Understanding RequestDelegate in Middleware class

Viewed 33

I have created a class (using tutorials) which serves as a global middleware class to catch and handle all errors in one place:

using System.Net;

namespace WebApi.Helpers
{
    public class ErrorHandlerMiddleware
    {
        private readonly RequestDelegate _next;

        public ErrorHandlerMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (Exception error)
            {
                var response = context.Response;
                string result = "";
                response.ContentType = "application/json";
                response.StatusCode = (int)HttpStatusCode.BadRequest;                
                await response.WriteAsync(result);
            }
        }

    }
}

The above code is invoked in the expected manner:

throw new AppException("error has occurred");

After reading several topics on the subject of middleware, I am understanding that the middleware class is acting upon a request in a pipeline of requests and then handing over to the next module in the pipeline to handle the request.

However in the Invoke method above, I do not understand the following:

    try
    {
        await _next(context);
    }

Is this calling the next request in the pipeline or the current one? I am basically having trouble understanding how throwing an exception elsewhere is being intercepted and processed in the Invoke method.

1 Answers

await _next(context); will call the next middleware (calling its Invoke method) and process the page.

It's simply an async method like all other methods, so when the page has been handled it returns and move to next code line.

Now if an exception occurs in other middleware or page handling, this exception will flow back to your middleware and be caught by your exception handler.

if you add code after await _next(context); like this:

await _next(context);
Console.WriteLine("Check");

It will write that line after you page has been processed, unless an exception occur (then it will obviously be skipped).

Normally calling _next is the last line of a middleware, but for global exception handling you want to run code when the method returns with an exception, like in your code.

Related