43

As known, IApplicationBuilder of the method Configure (class Startup) in ASP.NET Core requires specific semantics (to have method 'Invoke' with input parameter of HttpContext type and Task as return value). But why it's not implemented as interface? I can write something like it:

public class FakeMiddleware
{

}

and register it:

    app.UseMiddleware<FakeMiddleware>();

and we'll get an runtime error. Of course, it's trivial thing and easy to be found and fix, but it's implemented so rough, without interface?

Oleg Sh
  • 8,496
  • 17
  • 89
  • 159

2 Answers2

37

The Invoke method is flexible and you can ask for additional parameters. ASP.NET will inject the additional parameters using the application's service configuration.

public async Task Invoke(HttpContext ctx, 
                         IHostingEnvironment host,
                         ISomethingElse service)
{
    // ...
}

C# interface definitions can't provide this flexibility in a nice way.

OdeToCode
  • 4,906
  • 23
  • 18
  • so, with DI we can think about disadvantages interfaces in current "version"? :) Because this situation (with additional parameters and resolving it automatically) can be more distributed than this place – Oleg Sh Nov 30 '16 at 22:13
  • 20
    Oh gosh, that should be constructor injected. If it's a per-request dependency then a factory pattern would work nicely – Robert Cutajar May 18 '17 at 09:21
  • Using a factory pattern would mean creating a factory for each transient type you would inject and make an explicit call to `someFactory.Create()` method. Doing so would probably make your code less adhering to the KISS principle. But that's maybe just a matter of taste ? – bN_ Jul 26 '21 at 11:03
  • But, if the idea is to inject any service, wouldn't be easier to inject the `IServiceProvider` instead? Then a interface would be possible. – Victor Coll May 06 '22 at 21:16
5

Since AspNetCore2.0 you can set middleware which implements interface IMiddleware.

public class InterfaceMiddleware : IMiddleware
{
    private InterfaceMiddlewareOptions _opts;

    public InterfaceMiddleware(IOptions<InterfaceMiddlewareOptions> opts)
    {
        _opts = opts.Value;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        await context.Response.WriteAsync(_opts.Message);
    }
}

In addition to app.UseMiddleware<InterfaceMiddleware>(). You need to register your middleware in DI(singleton lifetime is not required).

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<InterfaceMiddlewareOptions>(opts =>
    {
        opts.Message = "IMiddleware interface is implemented";
    });

    services.AddSingleton<InterfaceMiddleware>();
}