Search code examples
asp.net-coreasp.net-core-mvcasp.net-core-1.0

Custom 404 response model


I want to provide a custom reponse for all 404s on our API. For example:

{
  "message": "The requested resource does not exist. Please visit our documentation.."
}

I believe the following result filter works for all cases within the MVC pipeline:

public class NotFoundResultFilter : ResultFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        var result = context.Result as NotFoundResult;

        if (result != null)
        {
            context.Result = new HttpNotFoundResult(); // My custom 404 result object
        }
    }
}

But, when a URL requested does not match an action route, the above filter is not hit. How could I best intercept these 404 responses? Would this require middleware?


Solution

  • Yes, you need to use middleware, as filter is only for MVC.

    1. You may, as always, write your own middleware

      app.Use(async (context, next) =>
      {
          await next();
          if (context.Response.StatusCode == 404)
          {
              context.Response.ContentType = "application/json";
      
              await context.Response.WriteAsync(JsonConvert.SerializeObject("your text"), Encoding.UTF8);
          }
      });
      
    2. Or use built-in middlware StatusCodePagesMiddleware, but as you want to handle only one status, this is an extra functionality. This middleware can be used to handle the response status code is between 400 and 600 .You can configure the StatusCodePagesMiddleware adding one of the following line to the Configure method (example from StatusCodePages Sample):

      app.UseStatusCodePages(); // There is a default response but any of the following can be used to change the behavior.
      
      // app.UseStatusCodePages(context => context.HttpContext.Response.SendAsync("Handler, status code: " + context.HttpContext.Response.StatusCode, "text/plain"));
      // app.UseStatusCodePages("text/plain", "Response, status code: {0}");
      // app.UseStatusCodePagesWithRedirects("~/errors/{0}"); // PathBase relative
      // app.UseStatusCodePagesWithRedirects("/base/errors/{0}"); // Absolute
      // app.UseStatusCodePages(builder => builder.UseWelcomePage());
      // app.UseStatusCodePagesWithReExecute("/errors/{0}");