'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType

P. G. Choudhury 146 Reputation points
2025-01-24T17:31:46.3366667+00:00

I am trying to implement global exception handling in a .NetCore 9 webAPI project.
I created a ExceptionMiddlewareExtensions class like so:

ExceptionMiddlewareExtensions.cs -

public static class ExceptionMiddlewareExtensions
{
    public static void ConfigureExceptionHandler(this WebApplication app, Microsoft.Extensions.Logging.ILogger logger)
    {
        app.UseExceptionHandler(appError =>
        {
            appError.Run(async context =>
            {
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                context.Response.ContentType = "application/json";
                var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
                if(contextFeature!=null)
                {
                    await context.Response.WriteAsync(new ErrorDetails
                    {
                        StatusCode = context.Response.StatusCode,
                        Message = "Backend Internal Server Error"
                    }.ToString());
                }
            });
        });
    }
    public static void ConfigureCustomExceptionMiddleware(this WebApplication app)
    {
        app.UseMiddleware<ExceptionMiddleware>();
    }
}

where ExceptionMiddleware.cs -

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;
    public ExceptionMiddleware(RequestDelegate next, ILogger logger)
    {
        _logger = logger;
        _next = next;
    }
    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception exp)
        {
            _logger.LogError($"An unhandled exception has occurred:{exp.GetBaseException}");
            await HandleExceptionAsync(httpContext, exp);
        }
    }
    private async Task HandleExceptionAsync(HttpContext httpContext, Exception exp)
    {
        httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        httpContext.Response.ContentType = "application/json";
        await httpContext.Response.WriteAsync(new ErrorDetails
        {
            StatusCode = httpContext.Response.StatusCode,
            Message = "Internal Server Error from Custom Middleware"
        }.ToString());
    }
}

In my controller class -

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

In the Startup.cs -

builder.Services.AddSingleton<ExceptionMiddleware>();
var app = builder.Build();  <--- this is where it throws exception

var logger = app.Services.GetRequiredService<ExceptionMiddleware>();
app.ConfigureCustomExceptionMiddleware();

Can you tell me where did I commit the error in configuring the middleware pipeline? Why that exception is being thrown? The scenario should be fairly easy to reproduce at your end with the code I provided.

Looking for some help on this. Any kind of guidance will be a massive boost.

Thanks,

Developer technologies | ASP.NET | ASP.NET Core
{count} votes

4 answers

Sort by: Most helpful
  1. Anonymous
    2025-01-27T04:11:38.5566667+00:00

    Hi @P. G. Choudhury, what you are creating now is a middleware but not an interface, but you are trying to add lifecycle for this middleware which should only be appliable for interface and the implementation.

    Middleware is constructed once at application startup when the middleware pipeline is being built. This makes the middleware looks like singleton. But middleware is executed per request. Each request flows through the middleware pipeline, invoking the Invoke or InvokeAsync method of each middleware component in sequence and this makes the middleware looks like scoped.

    If you want to use middleware to do custom exception dealation, you can use code below and in Program.cs, pls use this middleware by app.UseMiddleware<ExceptionMiddleware>(); .By the way, please use ILogger<ExceptionMiddleware> instead of ILogger.

    public class ExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        //private readonly ILogger _logger;
        private readonly ILogger<ExceptionMiddleware> _logger;
        public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
        {
            _logger = logger;
            _next = next;
        }
        public async Task InvokeAsync(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception exp)
            {
                _logger.LogError($"An unhandled exception has occurred:{exp.GetBaseException}");
                await HandleExceptionAsync(httpContext, exp);
            }
        }
        private async Task HandleExceptionAsync(HttpContext httpContext, Exception exp)
        {
            httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            httpContext.Response.ContentType = "application/json";
            await httpContext.Response.WriteAsync(new ErrorDetails
            {
                StatusCode = httpContext.Response.StatusCode,
                Message = "Internal Server Error from Custom Middleware"
            }.ToString());
        }
    }
    

    And I also find you create ConfigureExceptionHandler method in your codes, you might want to use IExceptionHandler to handle known exceptions. You can follow the Microsoft document to drive it.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Tiny

    0 comments No comments

  2. Raymond Huynh (WICLOUD CORPORATION) 620 Reputation points Microsoft External Staff
    2025-07-09T08:23:02.2966667+00:00

    Hello Choudhury,

    You’re running into that annoying error because you’re registering your ExceptionMiddleware as a singleton with AddSingleton<ExceptionMiddleware>(). Middleware in ASP.NET Core isn’t meant to be registered like a regular service. When you do that, you can run into lifetime issues, especially if your middleware depends on things like loggers or database contexts that aren’t singletons themselves. That’s why you’re seeing the error at var app = builder.Build();.

    Here is the solutions:

    1. Don’t register your middleware as a singleton.

    Just remove this line:

    builder.Services.AddSingleton<ExceptionMiddleware>();
    

    2. Let ASP.NET Core handle the middleware.

    Add your middleware to the pipeline like this:

    app.UseMiddleware<ExceptionMiddleware>();
    

    Or, if you have an extension method:

    app.ConfigureCustomExceptionMiddleware();
    

    3. Use the right logger type in your middleware.

    Change your constructor to use the generic logger:

       public class ExceptionMiddleware
       {
           private readonly RequestDelegate _next;
           private readonly ILogger<ExceptionMiddleware> _logger;
     
           public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
           {
               _logger = logger;
               _next = next;
           }
     
           public async Task InvokeAsync(HttpContext httpContext)
           {
               try
               {
                   await _next(httpContext);
               }
               catch (Exception exp)
               {
                   _logger.LogError($"An unhandled exception has occurred: {exp.GetBaseException()}");
                   await HandleExceptionAsync(httpContext, exp);
               }
           }
     
           private async Task HandleExceptionAsync(HttpContext httpContext, Exception exp)
           {
               httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
               httpContext.Response.ContentType = "application/json";
               await httpContext.Response.WriteAsync(new ErrorDetails
               {
                   StatusCode = httpContext.Response.StatusCode,
                   Message = "Internal Server Error from Custom Middleware"
               }.ToString());
           }
       }
    

    That’s it! No need to mess with service lifetimes for middleware, just add it to the pipeline, and ASP.NET Core will take care of the rest. If you want to handle known exceptions in a more advanced way, you can look into using IExceptionHandler as well, but for most custom error handling, this middleware approach is perfect.

    Hope that helps!


  3. Raymond Huynh (WICLOUD CORPORATION) 620 Reputation points Microsoft External Staff
    2025-07-09T08:29:14.85+00:00

    Hello Choudhury,

    You’re running into that annoying error because you’re registering your ExceptionMiddleware as a singleton with AddSingleton<ExceptionMiddleware>(). Middleware in ASP.NET Core isn’t meant to be registered like a regular service. When you do that, you can run into lifetime issues, especially if your middleware depends on things like loggers or database contexts that aren’t singletons themselves. That’s why you’re seeing the error at var app = builder.Build();.

    What should you do instead?:

    1. Don’t register your middleware as a singleton.

    Just remove this line:

    builder.Services.AddSingleton<ExceptionMiddleware>();
    

    2. Let ASP.NET Core handle the middleware.

    Add your middleware to the pipeline like this:

    app.UseMiddleware<ExceptionMiddleware>();
    

    Or, if you have an extension method:

    app.ConfigureCustomExceptionMiddleware();
    
    

    3. Use the right logger type in your middleware.

    Change your constructor to use the generic logger:

       public class ExceptionMiddleware
       {
           private readonly RequestDelegate _next;
           private readonly ILogger<ExceptionMiddleware> _logger;
     
           public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
           {
               _logger = logger;
               _next = next;
           }
     
           public async Task InvokeAsync(HttpContext httpContext)
           {
               try
               {
                   await _next(httpContext);
               }
               catch (Exception exp)
               {
                   _logger.LogError($"An unhandled exception has occurred: {exp.GetBaseException()}");
                   await HandleExceptionAsync(httpContext, exp);
               }
           }
     
           private async Task HandleExceptionAsync(HttpContext httpContext, Exception exp)
           {
               httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
               httpContext.Response.ContentType = "application/json";
               await httpContext.Response.WriteAsync(new ErrorDetails
               {
                   StatusCode = httpContext.Response.StatusCode,
                   Message = "Internal Server Error from Custom Middleware"
               }.ToString());
           }
       }
    

    If you want to handle known exceptions in a more advanced way, you can look into using IExceptionHandler as well, but for most custom error handling, this middleware approach is perfect.

    Hope that helps!

    0 comments No comments

  4. Raymond Huynh (WICLOUD CORPORATION) 620 Reputation points Microsoft External Staff
    2025-07-09T08:39:57.37+00:00

    Hi,

    The error you’re encountering is happening because you’re registering your ExceptionMiddleware as a singleton using AddSingleton<ExceptionMiddleware>(). In ASP.NET Core, middleware isn’t meant to be registered like a typical service. Doing so can cause issues with service lifetimes, especially if your middleware depends on services like loggers or database contexts that aren’t singletons. That’s why you’re seeing the error at var app = builder.Build().

    Here’s how you can resolve this:

    1. Remove the singleton registration for your middleware.

    You can simply remove this line:

    builder.Services.AddSingleton<ExceptionMiddleware>();
    

    2. Let ASP.NET Core manage the middleware.

    Add your middleware to the pipeline like this:

    app.UseMiddleware<ExceptionMiddleware>();
    

    Or, if you have an extension method:

    app.ConfigureCustomExceptionMiddleware();
    

    3. Update your middleware to use the correct logger type.

    Change your constructor to use the generic logger:

       public class ExceptionMiddleware
       {
           private readonly RequestDelegate _next;
           private readonly ILogger<ExceptionMiddleware> _logger;
     
           public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
           {
               _logger = logger;
               _next = next;
           }
     
           public async Task InvokeAsync(HttpContext httpContext)
           {
               try
               {
                   await _next(httpContext);
               }
               catch (Exception exp)
               {
                   _logger.LogError($"An unhandled exception has occurred: {exp.GetBaseException()}");
                   await HandleExceptionAsync(httpContext, exp);
               }
           }
     
           private async Task HandleExceptionAsync(HttpContext httpContext, Exception exp)
           {
               httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
               httpContext.Response.ContentType = "application/json";
               await httpContext.Response.WriteAsync(new ErrorDetails
               {
                   StatusCode = httpContext.Response.StatusCode,
                   Message = "Internal Server Error from Custom Middleware"
               }.ToString());
           }
       }
    

    If you’d like to handle specific exceptions in a more advanced way, you might also want to look into using IExceptionHandler. But for most custom error handling, this middleware approach should work well.

    Hope this helps!


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.