c# - route - Diferencia entre app, servicios y middleware en mvc6.
httpcontext session asp net core (3)
Hay dos fases en la construcción del oleoducto:
- Registro de servicios para DI
- Añadiendo el middleware al pipeline.
AddMvc
registra los servicios que necesita MVC (por ejemplo, el motor de visualización, el formateador JSON, etc.) pero no agrega nada a la canalización.
UseMiddleware<T>
es un método genérico para agregar middleware a la canalización. Este método utilizará el sistema DI para inyectar dependencias a través del constructor de la clase de middleware.
UseMvc
y similares son métodos de extensión que hacen que sea más fácil pasar las opciones de configuración. Si escribe un middleware personalizado, puede simplemente llamar a UseMiddleware<T>
o proporcionar un método de extensión, según cómo necesite configurar el middleware.
Puede encontrar más información aquí: https://docs.asp.net/en/latest/fundamentals/middleware.html
Estoy tratando de entender el concepto de middleware en MVC6. Todavía es un poco vago para mí. Realmente no veo las diferencias entre algunas variables "estándar" que obtienes en la clase de Startup
.
Hasta donde puedo decir, hay 3 formas diferentes de decirle a la aplicación que debería usar un middleware específico.
Puede llamar a middleware a través de servicios usando. Pero esto parece solo para "agregar" middleware?
services.AddMvc();
// Add other services
services.AddScoped<IMyCountriesRepository, MyCountriesRepository>();
services.AddScoped<IEmailer, Emailer>();
Entonces tienes la IApplicationBuilder app
. ¿Esto es para usar realmente el middleware cargado en los servicios? Así que puedes llamarlo como:
app.UseMvc();
app.UseErrorPage(...);
app.UseIdentity(); // cookie authentication
Y luego hay una manera de cargar y usar middleware como este:
app.UseMiddleware<MyCustomMiddleware>();
¿Cuál es el beneficio de tener tres tipos de registro / uso de middleware? ¿Cuál es la diferencia exacta entre ellos?
Me gusta agregar a la respuesta de Daniel un ejemplo práctico. (Su respuesta es muy detallada y correcta, mira esto primero).
TL; DR:
services.Add
no está directamente relacionado con el middleware. Se trata de registrar dependencias en el contenedor de inyección de dependencias.
app.Use
se refiere a la selección de app.Use
qué código se ejecutará en la canalización (lógica), en qué orden, y si permite que la tubería continúe procesándose o no. La imaginación es el límite aquí, un ejemplo sería escribir un middleware que, dependiendo de la dirección IP, puede mostrar una página que dice: ''el servicio de servicio no está disponible en su país'')
app.UseMiddleware
es lo mismo que app.Use
pero en lugar de declarar el código en línea, especifique una clase que tendrá un método Invoke al que se llamará.
Ahora, vamos a ver un código de ejemplo:
Supongamos que desea que su aplicación procese su salida o parte de su salida, como miniar su HTML.
Puede agregar un middleware que intercepte la respuesta antes de que se escriba en la salida y lo minimice.
Así que puedes usar:
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);
});
Si desea compartir su middleware en varias aplicaciones u otras, puede crear un middleware y usarlo más como:
app.UseMiddleware<HtmlMinifierMiddleware>();
que hará todo el trabajo por usted con una sola línea de código en el método de configuración. Es una práctica común enviar métodos de extensión como app.UseHtmlMinifier()
y devolver objetos específicos que se pueden encadenar para la configuración o para admitir parámetros de configuración. El uso de extensiones proporciona mucha flexibilidad, legibilidad y capacidad de descubrimiento de API: D
ahora imagina que tu middleware esta deleced algo como esto:
public class HtmlMinifierMiddleware {
public HtmlMinifier(IHtmlMinifier minifier) {
// ...
}
public string Minify(string content) {
return minifier.Minify(content);
}
// ...
}
Como puede ver, debe pasar un IHtmlMinifer, por lo que necesita registrarlo para el DI.
Esto se logra en ConfigureService como:
services.AddScoped<IHtmlMinifier, MyCoolHtmlMinifier>();
ahora imagine que no necesita 1, sino muchas dependencias; dependerá del desarrollador / consumidor del middleware conocer cada una de las dependencias que deben registrarse.
Los autores de middleware normalmente envían una extensión para facilitar el uso de desarrolladores como: services.AddHtmlMinifier()
que es exactamente eso, un método de extensión para registrar servicios en el contenedor DI.
Incluso si no está utilizando un middleware, puede aprovechar la dependencia de su propia aplicación utilizando el mismo patrón.
Por ejemplo, si su aplicación es un comercio electrónico, puede crear métodos de extensión que registren sus dependencias: services.AddProductManagement()
, services.AddPriceCalculator()
, services.AddSearching()
, etc, O solo services.AddMyCoolApplication()
para proporcionar un Una forma limpia de agregar (registrar) sus servicios (dependencias) que se encuentran en el contenedor de DI para su aplicación.
Yo distinguiría entre agregar los servicios y agregar el middleware.
Añadiendo los servicios.
Básicamente, esto es registrar las clases que necesita su función en el contenedor de inyección de dependencias integrado en ASP .Net 5. (La interfaz IServiceCollection
)
Lo más simple que puede hacer es agregarlos manualmente uno por uno como en:
services.AddScoped<IMyCountriesRepository, MyCountriesRepository>();
services.AddScoped<IEmailer, Emailer>();
Si está creando una aplicación más compleja o un marco autónomo, es posible que desee crear una función que registre todos los servicios necesarios. Una buena manera de hacerlo es creando un método de extensión:
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();
Eso es exactamente lo que services.AddMvc();
está haciendo.
De una manera más flexible, ya que le permite pasar un lambda para personalizar aún más los servicios predeterminados como los modelos de enlaces (como
services.AddMvc(opts => opts.ModelBinders ...)
) y está devolviendo un IMvcBuilder que puede usar para personalizar aún más cosas como los motores de vista (comoservices.AddMvc().AddViewOptions(opts => opts.ViewEngines ...)
).
- Compruebe la implementación de
MvcServiceCollectionExtensions
yMvcCoreServiceCollectionExtensions
Añadiendo middleware
ASP .Net 5 no se basa en módulos y controladores HTTP, sino que se basa en la idea OWIN de middleware. Hay una bonita entrada de blog de Andrei Dzimchuk que describe el middleware que lo resume muy bien:
Middleware : pase a través de componentes que forman una tubería entre un servidor y una aplicación para inspeccionar, enrutar o modificar los mensajes de solicitud y respuesta para un propósito específico.
Y esta definición se aplica también a ASP.NET 5. El middleware puede considerarse como módulos y controladores HTTP que hemos tenido en ASP.NET clásico. Algún middleware implementaría varias tareas intermedias al procesar solicitudes como la autenticación, la recuperación y la persistencia del estado de la sesión, el registro, etc. Algunos de ellos serían los controladores de solicitudes finales que producirían respuestas.
Así que ahora desea agregar su propio comportamiento a la tubería de ASP.
Lo más simple es definir un middleware en línea:
app.Use(async (context, next) =>
{
//do something before passing the request to the next middleware
await next.Invoke();
});
También puede crear su propia clase de middleware y registrarla:
app.UseMiddleware<MyMiddleware>();
Finalmente, podría definir nuevamente los métodos de extensión para encapsular la lógica de configuración compleja.
Esto es lo que hace
app.UseMvc()
. Le permite definir sus rutas y luego agrega el middleware de enrutamiento llamando aapp.UseRouter()
. Como puede ver, la implementación deapp.UseRouter
agrega elRouterMiddleware
a la tubería con la llamada albuilder.UseMiddleware<RouterMiddleware>(router);
Cualquier servicio requerido por su middleware habría sido registrado previamente. Esto significa que estarán disponibles para su middleware a través del contenedor DI incorporado.
El resultado final es que el marco hace que sea más fácil mezclar y combinar los componentes (servicios) y el comportamiento (middleware) que necesita su aplicación, incluidos solo los bits que necesita.