2016-04-19 80 views
3

我的中间件类在不同的类库项目中,而控制器在不同的项目中。我试图做的,如果特定条件不符合然后重定向到中间件的自定义控制器/操作方法。来自中间件的呼叫控制器的操作方法

但是,我不能用Response.Redirect方法做到这一点。

我该如何在中间件类中做到这一点?

对此有任何帮助表示赞赏!

Rohit

+1

条件是什么?它是认证/授权,还是其他?如果它是auth,你可能想要返回'401'或'403'(取决于它是认证还是授权失败),如果是别的东西,你可能不想首先在中间件中执行它。你可以再详细一点吗? –

+0

@TomasLycken是的,它与认证/授权无关,如果没有找到特定的客户端/租户,则重定向到某些控制器的操作方法以显示错误消息。要从httpcontext获取客户名称,逻辑是写在中间件 – Rohit

回答

5

看来你是因为错误的原因使用了中间件。

我建议你通过简单地将它写入响应流(而不是转发到Next())来让中间件返回一个(非常小的)404,或者不要在中间件中完成此操作,而是在在您的MVC应用程序中全球注册了IActionFilter


我已经解释了在评论上述建议的理由,但我认为要提升到实际的答案是足够重要:

在中间件管道,希望每个组件是为尽可能独立。几件事情启用OWIN此松耦合:

  • 的输入,并且输出从,每个组件具有相同的格式,是否有收到10个其他中间件组件,或者根本没有

  • 的约定是,该管道的每一部分都可以做的三件事情的一个或多个,顺序如下:

    1. 阅读(修改)传入的请求。

    2. 决定完全处理请求,或转发处理到下一个组件。

    3. 写入响应流。

当粘到这些约定,它变得非常容易编写,分解和重新组成从可重用中间件组件管线。 (希望请求日志记录?只需在管道的起始处连接一个中间件组件,想要在整个板上使用一些通用的身份验证逻辑?在管道的auth阶段添加一个组件。想要切换到不同的日志记录框架?要想在微服务的生态系统中应用相同的日志记录,可以重新使用组件Etcetera,ad infinum ...)这很有效,因为组件都在它们的边界之内,并且与Web服务器本身可以理解。

ASP.NET WebAPI看起来可能是一个不同的野兽,但实际上它只是另一个OWIN组件,它总是被配置为处理请求,并且永远不会转发到下一个组件(因此它们使它变得困难在管道中的WebApi之后注册一个组件......)。

你想要做什么,打破了第二点的合同 - 你想告诉下一个组件如何处理请求。 但这并不取决于你 - 它取决于下一个组件。

+0

能否请你提供一个404和IActionFilter的小例子?谢谢 ! – Rohit

+0

要写入回复,请参阅[这个Q/A](http://stackoverflow.com/questions/32532058/how-do-i-ask-owin-katana-to-write-headers-to-the-output-stream)。对于'IActionFilter'的例子,看看[这里](https://damienbod.com/2014/01/04/web-api-2-using-actionfilterattribute-overrideactionfiltersattribute-and-ioc-injection/) –

+0

你能解释一下为什么他的用例不适合中间件。 –

5

这是检查请求并重定向的中间件。它适用于嵌入式中间件或中间件类。

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(); 
} 

这里是中间件类。

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); 
     } 
    } 
} 

有关更多信息,请参阅Docs » Fundamentals » Middleware

+1

你似乎已经提供了启动类的配置方法?如果发生错误,我怎么能从中间件返回? – Rohit

+0

'app.Use'是中间件。 :-)我添加了另一种方式。 –

+1

@ShaunLatin谢谢你的帮助!它的工作! – Rohit