I have filter attribute in ASP.NET core 2.0, See my code snippet below. Here the problem is I always get the status code is 200.
Even the actual status code is 500 then also I get a 200. How do I get the actual status code?
public void OnActionExecuted(ActionExecutedContext context)
{
try
{
var controller = context.Controller as APIServiceBase;
var statusCode = controller.Response.StatusCode;
..
..
}
catch { }
}
Quite an interesting question. Action filters are executed just after the action itself. The problem is that IActionResult
returned by the action is not yet executed at this stage. You could check it by returning your custom implementation of IActionResult
and checking that its ExecuteResultAsync
method is executed after OnActionExecuted()
of the action filter .
Since response is populated by IActionResult
(including status code), you shouldn't expect that Response.StatusCode
will be already set in action filter.
To solve this problem you should execute your logic later in ASP.Net Core pipeline, action filter is just not a proper place for it. You could add custom middleware in request pipeline (Startup.Configure()
method):
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async (context, next) =>
{
await next.Invoke();
var statusCode = context.Response.StatusCode;
// ...
});
app.UseMvc();
}
Make sure you add it before call to app.UseMvc()
. You could wrap delegate logic to separate class if required.
As raised by CodeFuller, your action may not have been executed yet.
However if you want to keep a filter-pattern to apply it only to specific methods, you may get use of the OnCompleted
method of the response:
// 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
});
}
This method should work for most types of filter, so you may use a any depending on the filter inputs you need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With