Search code examples
c#asp.net-coreasp.net-core-mvc.net-6.0asp.net-core-6.0

Is it possible to return a 404 from ASP.NET Core 6 MVC middleware


I have an ASP.NET Core 6 MVC application with both view-based controllers and API controllers. I'd like to be able to disable certain controllers through configuration, and I have a middleware that works:

public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
        context.Request.RouteValues.TryGetValue("controller", out var controller);

        if (controller != null)
        {
            if (!_allowControllers.IsMatch(controller as string))
                context.Abort();
            else if (_denyControllers.IsMatch(controller as string))
                context.Abort();
        }

        await next(context);
}

However when triggered, the client gets a broken connection. Is it possible to return a "404" instead? I've tried

context.Response.Redirect("/notfound");

instead of Abort, but it doesn't seem to work for the API controllers.


Solution

  • You want so called short-circuiting/terminal middleware i.e. one which does not invoke (or does not always invoke) next. Something like the following:

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        context.Request.RouteValues.TryGetValue("controller", out var controller);
    
        if (controller is string str 
            && (!_allowControllers.IsMatch(str) || _denyControllers.IsMatch(str)))
        {
            context.Response.StatusCode = (int)HttpStatusCode.NotFound;
        }
        else
        {
            await next(context);    
        }
    }
    

    Read more: