Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between app, services and middleware in mvc6

Tags:

I'm trying to understand the concept of middleware in MVC6. It is still kind of vague to me. I don't really see the differences between a few "standard" variables you get in the Startup class.

As far as I can tell there are 3 different ways to tell the application that it should use a specific middleware?

You can call middleware through services using. But this seems only for "adding" middleware?

services.AddMvc();  // Add other services services.AddScoped<IMyCountriesRepository, MyCountriesRepository>(); services.AddScoped<IEmailer, Emailer>(); 

Then you have IApplicationBuilder app. This is to actually use the middleware loaded in the services? So you can call it like:

app.UseMvc(); app.UseErrorPage(...); app.UseIdentity(); // cookie authentication  

And then there is a way to load and use middleware like this:

app.UseMiddleware<MyCustomMiddleware>(); 

What is the benefit having three types of registering / using middleware? What is the exact differences between them?

like image 215
Vivendi Avatar asked Oct 14 '15 13:10

Vivendi


People also ask

What is the difference between app use VS app run while adding middleware?

app. Run() will end the request, and app. Use() will pass the request to next middleware.

What is the difference between IApplicationBuilder use () and IApplicationBuilder run ()?

Run() is an extension method on IApplicationBuilder instance which adds a terminal middleware to the application's request pipeline. The Run method is an extension method on IApplicationBuilder and accepts a parameter of RequestDelegate.

What is the use of middleware in MVC?

Middleware are software components that are assembled into an application pipeline to handle requests and responses. Each component chooses whether to pass the request on to the next component in the pipeline, and can perform certain actions before and after the next component is invoked in the pipeline.

What is difference between middleware and filters in .NET Core?

Middleware only has access to the HttpContext and anything added by preceding middleware. In contrast, filters have access to the wider MVC context, so can access routing data and model binding information for example.


2 Answers

I would distinguish between adding the services and adding the middleware.

Adding the services

This is basically registering the classes needed by your feature into the dependency injection container built in ASP .Net 5. (The IServiceCollection interface)

The most simple thing you can do is manually add them one by one as in:

services.AddScoped<IMyCountriesRepository, MyCountriesRepository>(); services.AddScoped<IEmailer, Emailer>(); 

If you are building a more complex app, or a self contained framework, you might want to create a function that registers all the services needed. A good way of doing that is by creating an extension method:

public static void AddMyServices(this IServiceCollection services) {     services.AddScoped<IMyCountriesRepository, MyCountriesRepository>();     services.AddScoped<IEmailer, Emailer>();     ... }  //register all your services just by running the ext method: services.AddMyServices(); 

That is exactly what services.AddMvc(); is doing.

In a more flexible way as it allows you to pass a lambda to further customize default services like the model binders (Like services.AddMvc(opts => opts.ModelBinders ...)) and is returning an IMvcBuilder you can use to further customize it things like the view engines (Like services.AddMvc().AddViewOptions(opts => opts.ViewEngines ...)).

  • Check the implementation of MvcServiceCollectionExtensions and MvcCoreServiceCollectionExtensions

Adding middleware

ASP .Net 5 is not based in HTTP modules and handlers, and instead is based on the OWIN idea of middleware. There is a nice blog entry by Andrei Dzimchuk describing the middleware which nicely summarizes it:

Middleware – Pass through components that form a pipeline between a server and application to inspect, route, or modify request and response messages for a specific purpose.

And this definition applies to ASP.NET 5 as well. Middleware can be thought of as both HTTP modules and handlers that we've had in classic ASP.NET. Some middleware would implement various intermediate tasks when processing requests such as authentication, session state retrieval and persistence, logging and so on. Some of them would be the ultimate request handlers that would produce responses.

So now you want to add your own behavior into the ASP pipeline.

The most simple thing is define an inline middleware:

app.Use(async (context, next) => {     //do something before passing the request to the next middleware     await next.Invoke(); }); 

You can also create your own middleware class and register it:

app.UseMiddleware<MyMiddleware>(); 

Finally, you could again define extension methods to encapsulate complex setup logic.

This is what app.UseMvc() does. It lets you define your routes and it is then adding the routing middleware by calling app.UseRouter(). As you can see, the implementation of app.UseRouter adds the RouterMiddleware into the pipeline with the call to builder.UseMiddleware<RouterMiddleware>(router);

Any services needed by your middleware would have previously been registered. This means they will be available to your middleware through the built in DI container.


The end result is that the framework makes easier for you to basically mix and match the components(services) and behavior(middleware) needed by your application, including only the bits that you need.

like image 92
Daniel J.G. Avatar answered Sep 16 '22 15:09

Daniel J.G.


I like to add to the Daniel answer an practical example. (his answer is very detailed and correct, check this out first).

TL;DR:

services.Add is not directly related to middleware. It's about registering dependencies in the Dependency Injection Container.

app.Use is about cherry picking which code will run in the pipeline (do logic), in which order, and if allows the pipeline to keep processing or not. The imagination is the limit here, one example would be writting a middleware that depending on the IP Address, you can show a page that says: 'sorry service is not available in your country')

app.UseMiddleware it's the same as app.Use but instead of declaring the code inline, you specify a class that will have an Invoke method that will be called for you.

Now, let's get to some sample code:

Let's say you want your application to process your output or some of your output, like minifing your HTML.

You can add a middleware that intercepts the response before is written to the output and minify it.

So you can use:

app.Use(async (context, next) => {     await next(context);     context.Response // will have the response as processed by all the previous middleswares like mvc.     if IsMinifiable(context.Response)     MinifyResponse(context.Response);  }); 

If you want to share your middleware in various applications or by others, you may want to create a middleware and use it more like:

app.UseMiddleware<HtmlMinifierMiddleware>();  

that will do all the work for you with a single line of code in the configure method. It's common practice to ship extension methods like app.UseHtmlMinifier() and return specific objects that can be chained for configuration or support configuration parameters. Using extensions gives a lot of flexibility, readability and api discoverability :D

now imagine your middleware is delcared something like this:

public class HtmlMinifierMiddleware {     public HtmlMinifier(IHtmlMinifier minifier) {         // ...     }     public string Minify(string content) {         return minifier.Minify(content);     }     // ... } 

as you can see, you need to pass a IHtmlMinifer, so you need to register it for the DI.

this is accomplished on ConfigureService like:

services.AddScoped<IHtmlMinifier, MyCoolHtmlMinifier>(); 

now imagine you need not 1, but many dependencies, it will be up to the developer/consumer of the middleware to know every single dependency that needs to be registered.

Authors of middleware normally ships an extension to ease the use of developers like: services.AddHtmlMinifier() which is exactly that, an extension method for register services into the DI Container.

Even if you are not using a middleware, you can leverage the dependency of your own application using the same pattern.

For example, if your app is an ecommerce, you can create extension methods that register your dependencies: services.AddProductManagement(), services.AddPriceCalculator(), services.AddSearching(), etc, OR just services.AddMyCoolApplication() to provide a clean way of adding (registering) your services (dependencies) to be found by the DI Container for your application.

like image 38
Bart Calixto Avatar answered Sep 17 '22 15:09

Bart Calixto