InvalidOperationException: Unable to resolve service while trying to implement middleware for handling global exceptions -

P. G. Choudhury 146 Reputation points
2025-01-25T12:37:22.15+00:00

Hello,

I am trying to implement middleware to handle exceptions globally in a .NetCore WebAPI project. My .NetCore version is 9.0. Full details of the exception that is being thrown when I'm trying to launch my webAPI is as:

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate' while attempting to activate 'Stack9Backend.CustomExceptionMiddleware.GlobalExceptionHandlingMiddleware'.

What I did was, create a custom middleware class extending from IMiddleware. The implementation is as:

public class GlobalExceptionHandlingMiddleware:IMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<GlobalExceptionHandlingMiddleware> _logger;
    public GlobalExceptionHandlingMiddleware(RequestDelegate next, ILogger<GlobalExceptionHandlingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, ex.Message);
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            ProblemDetails problem = new()
            {
                Status = (int)HttpStatusCode.InternalServerError,
                Type = "Backend Server Error",
                Title = "Backend Server Error",
                Detail = "An unexpected server error occurred"
            };

            string json=JsonSerializer.Serialize(problem);

            await context.Response.WriteAsync(json);

            context.Response.ContentType = "application/json";
        }
    }
}

Here ILogger comes from Microsoft.Extensions.Logging. To use this middleware I applied it in my Program.cs as:

builder.Services.AddTransient<GlobalExceptionHandlingMiddleware>();

var app = builder.Build();   <------ exception thrown on this line

app.UseMiddleware<GlobalExceptionHandlingMiddleware>();

I tried AddSingleton also in place of AddTransient. That didn't work.
I thought since my middleware implements IMiddleware, so I also tried -->

builder.Services.AddScoped<IMiddleware, GlobalExceptionHandlingMiddleware>();

But no. None of the above tweaks worked. Been stuck with this for a considerable amount of time now. Looking for some help on this.

Thanks

Developer technologies ASP.NET ASP.NET Core
Developer technologies C#
0 comments No comments
{count} votes

Accepted answer
  1. AgaveJoe 30,126 Reputation points
    2025-01-25T21:54:37.35+00:00

    I think part of the problem is you are not following the official middleware reference documentation. Try Inheriting from IMiddleware and implement the InvokeAsync() method. Don't use a constructor to inject the RequestDelegate. See the middleware factory pattern.

    https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/extensibility?view=aspnetcore-9.0

    The official documentation also has coding patterns for handling exceptions in Core API.

    https://learn.microsoft.com/en-us/aspnet/core/web-api/handle-errors?view=aspnetcore-9.0


1 additional answer

Sort by: Most helpful
  1. Robert Virnau 26 Reputation points
    2025-01-26T20:05:47.33+00:00

    It looks like 2 examples might have been mixed up :) ... For the code in the example given, the IMiddleware interface is not needed. With the interface removed, the "GlobalExceptionHandlingMiddleware" does not need to be registered as a service. The middleware will get added directly to the request pipeline using "app.UseMiddleware<GlobalExceptionHandlingMiddleware>();",

    The global "_next" variable set via the constructor should be used by InvokeAsync, also InvokeAsync should only have HttpContext as a parameter. More complex scenarios can implement the IMiddleware interface, however it looks like this is not needed given your example.
    User's image

    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.