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.