Search code examples
exceptionasp.net-core-webapimiddlewareasp.net-core-middleware

'InvalidOperationException: Unable to resolve service for type' exception thrown while trying to implement exception handling Middleware


I am trying to implement a custom middleware to globally handle exceptions in my ASP.NET Core Web API project. My .NET Core version is 9.0. I created a custom class by extending from IMiddleware.

My middleware class is as follows:

public class GlobalExceptionHandlingMiddleware:IMiddleware
{
    private readonly ILogger<GlobalExceptionHandlingMiddleware> _logger;
    public GlobalExceptionHandlingMiddleware(ILogger<GlobalExceptionHandlingMiddleware> logger)
    {
        _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);

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

            await context.Response.WriteAsync(json);
        }
    }
}

To use this, I modified Startup.cs like this:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddTransient<GlobalExceptionHandlingMiddleware>();

builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

builder.Services.AddScalarExplorer()
                .InjectDbContext(builder.Configuration)
                .AddApplicationServices();

var app = builder.Build();

// Configure the HTTP request pipeline.
app.ConfigureScalarExplorer()
    .ConfigureCORS(builder.Configuration);

app.UseHttpsRedirection();

app.UseAuthorization();

app.UseMiddleware<GlobalExceptionHandlingMiddleware>();

app.MapControllers();

app.Run();

I am using ILogger in my controller as such:

private readonly ILogger _logger;
public MyController(ILogger<MyController> logger)
{
    _logger = logger;
}

As AddTransient() did not work, I tried with AddSingleton() also. That didn't work either.

As a last resort I also tried:

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

None of these tweaks worked. It is still throwing the same exception on that marked line.

So where is it going wrong? If you study THIS LINK--> Why do I get this InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.RequestDelegate'?

the marked answer is saying that it is due to the fact that I am registering too many classes. That is definitely not my case. Also that answer is for a much older version of .NET Core.

Do you have any idea what's wrong here?

***Have added builder.Services.AddLogging(); to Startup.cs but code still throws exception.


Solution

  • I finally managed to resolve the issue. I was implementing the IMiddleware interface wrongly. Need not inject any RequestDelegate in the constructor of the custom middleware class. When implementing the InvokeAsync method, simply use RequestDelegate directly in the method signature to process incoming requests.

    I have updated the code block for GlobalExceptionHandlingMiddleware in the question I posted. Also have updated the code block for Startup.cs with the correct and functional code block. No need to add services for ILogger explicitly. Everything working like a charm!

    For detailed understanding pl see these two links, everything will be clear:

    1. https://www.youtube.com/watch?v=H3EbflpXVmo
    2. https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/extensibility?view=aspnetcore-9.0