从.Net Core 2.0中的IActionFilter获取HttpStatus代码

blu*_*lue 5 c# asp.net-core asp.net-core-webapi asp.net-core-2.0

我在ASP.NET核心2.0中有过滤器属性,请参阅下面的我的代码片段.这里的问题是我总是得到状态码是200.

即使实际状态代码是500,那么我也得到200.如何获得实际状态代码?

public void OnActionExecuted(ActionExecutedContext context)
{
    try
    {
        var controller = context.Controller as APIServiceBase;
        var statusCode = controller.Response.StatusCode;
        ..
        ..
    }
    catch { }

}
Run Code Online (Sandbox Code Playgroud)

Cod*_*ler 5

非常有趣的问题。动作过滤器在动作本身之后执行。问题在于,该IActionResult操作返回的操作在此阶段尚未执行。您可以通过返回您的自定义实现IActionResult并检查其方法是否在操作过滤器ExecuteResultAsync之后执行来检查它。OnActionExecuted()

由于响应是由IActionResult(包括状态代码)填充的,因此您不应期望它Response.StatusCode已在操作过滤器中设置。

要解决此问题,您应该稍后在 ASP.Net Core 管道中执行逻辑,操作过滤器不适合它。Startup.Configure()您可以在请求管道(方法)中添加自定义中间件:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Use(async (context, next) =>
    {
        await next.Invoke();
        var statusCode = context.Response.StatusCode;
        // ...
    });

    app.UseMvc();
}
Run Code Online (Sandbox Code Playgroud)

确保在调用 之前添加它app.UseMvc()。如果需要,您可以将委托逻辑包装到单独的类中。


Jea*_*ean 5

正如 CodeFuller 提出的,您的操作可能尚未执行。但是,如果您想保留过滤模式以仅将其应用于特定方法,您可以使用OnCompleted响应的方法:

// Called on incoming request
public void OnActionExecuting(ActionExecutedContext context)
{
    context.HttpContext.Response.OnCompleted(async () => {
        // Executed once the response is sent

        var status = context.HttpContext.Response.StatusCode;

        // Work here
        // Be careful on Transient or Scoped injections, they may already be disposed
        // If you need a DbContext, instanciate it by injecting 
        //    DbContextOptions<MyDbContext> earlier in the code

    });
}
Run Code Online (Sandbox Code Playgroud)

此方法应该适用于大多数类型的过滤器,因此您可以根据需要的过滤器输入使用 any 。