No service for type has been registered

Yeldar Kurmangaliyev picture Yeldar Kurmangaliyev · Jan 23, 2018 · Viewed 13k times · Source

I am trying to implement ASP.NET Core middleware, and this is the whole code I have in my project:

public class HostMiddleware : IMiddleware
{
    public int Count { get; set; }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        if (context.Request.Query.ContainsKey("hello"))
        {
            await context.Response.WriteAsync($"Hello World: {++Count}");
        }
        else
        {
            await next.Invoke(context);
        }
    }
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider provider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMiddleware<HostMiddleware>();

        app.Run(async context =>
        {
            context.Response.StatusCode = 400;
            await context.Response.WriteAsync("Bad request.");
        });
    }

However, when I run this server I get the following error:

InvalidOperationException: No service for type 'WebApplication4.HostMiddleware' has been registered.

developer exception page screenshot

Why do I get this error? Why would my middleware need to register any services if I don't use dependency injection in my project?

Update:

For some reason, this error does not occur when I stop using IMiddleware, rename InvokeAsync to Invoke and implement my middleware in the following way:

public class WmsHostMiddleware 
{
    private readonly RequestDelegate _next;

    public int Count { get; set; }

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

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Query.ContainsKey("hello"))
        {
            await context.Response.WriteAsync($"Hello World: {++Count}");
        }
        else
        {
            await _next.Invoke(context);
        }
    }
}

The question is still open - why does this happen? What is the difference? Why do I need to register services when I use IMiddleware.

Answer

davidfowl picture davidfowl · Jan 25, 2018

Today, when you use the IMiddleware interface, you also have to add it to the dependency injection container as a service:

services.AddTransient<HostMiddleware>();