Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call controller's action method from middleware

My middleware class is in different class library project and controller is in different project. What I am trying to do, if specific condition does not meet then redirect to the Custom Controller/Action method from middleware.

However, I am not able to do that with Response.Redirect method.

How can I do this in middleware class ?

Any help on this appreciated !

Rohit

like image 647
XamDev Avatar asked Apr 19 '16 07:04

XamDev


People also ask

How do you call an action from a controller?

You can specify an action via the MVC namespace. When given a Controller, such as HomeController : public class HomeController : Controller { public ActionResult Index() { ... } public ActionResult MyAction() { ... } public ActionResult MyActionWithParameter(int parameter) { ... } }

What is the use of middleware in MVC?

Middleware are software components that are assembled into an application pipeline to handle requests and responses. Each component chooses whether to pass the request on to the next component in the pipeline, and can perform certain actions before and after the next component is invoked in the pipeline.


2 Answers

Here is middleware that examines the request and redirects. It works with either inline middleware or with a middleware class.

public void Configure(IApplicationBuilder app)
{
    // use inline middleware
    app.Use(async (context, next) =>
    {
        // if specific condition does not meet
        if (context.Request.Path.ToString().Equals("/foo"))
        {
            context.Response.Redirect("path/to/controller/action");
        }
        else
        {
            await next.Invoke();
        }
    });

    // or use a middleware class
    app.UseMiddleware<RedirectMiddleware>();

    app.UseMvc();
}

Here is the middleware class.

public class RedirectMiddleware
{
    private readonly RequestDelegate _next;

    public RedirectMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        // if specific condition does not meet
        if (context.Request.Path.ToString().Equals("/bar"))
        {
            context.Response.Redirect("path/to/controller/action");
        }
        else
        {
            await _next.Invoke(context);
        }
    }
}

See Docs » Fundamentals » Middleware for more info.

like image 175
Shaun Luttin Avatar answered Sep 17 '22 23:09

Shaun Luttin


It seems you're using a middleware for the wrong reasons.

I recommend that you either have the middleware return a (very minimal) 404 by simply writing it to the response stream (instead of forwarding to Next()), or don't do this in a middleware at all but instead in a globally registered IActionFilter in your MVC app.


I've explained the rationale for the above advice in the comments, but I think it's important enough to lift into the actual answer:

In a middleware pipeline, you want each component to be as independent as possible. A couple of things enable this loose coupling in OWIN:

  • The input to, and output from, each component has the same format, whether there are 10 other middleware components before it, or none at all

  • The convention is that each part of the pipeline can do one or more of three things, in this order:

    1. Read (and modify) the incoming request.

    2. Decide to handle the request entirely, or forward handling to the next component.

    3. Write to the response stream.

When sticking to these conventions, it becomes very easy to compose, decompose and re-compose pipelines from reusable middleware components. (Want request logging? Just hook up a middleware component at the start of the pipe. Want some general authentication logic across the board? Add a component in the auth stage of the pipe. Want to switch to a different logging framework? Replace the logging component. Want to apply the same logging across an ecosystem of microservices? Re-use the component. Etcetera, ad infinum...) This works so well, because the components both stay within their boundaries, and work with a contract that the web server itself can understand.

ASP.NET WebAPI might seem to be a different beast, but in reality it's just another OWIN component which is always configured to handle the request, and never to forward to a next component (and thus they've made it difficult to register a component after WebApi in the pipeline...).

What you're trying to do, breaks the contract of the second point there - you want to tell the next component how to handle the request. But that's not up to you - it's up to the next component.

like image 25
Tomas Aschan Avatar answered Sep 20 '22 23:09

Tomas Aschan