Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 27 de septiembre de 2016
ASP.NET Core
En más de una ocasión me he topado con artículos que sugerían que ASP.NET Core MVC es un middleware y de hecho, incluso en algunos momentos yo también he tenido la sensación de que podía serlo.

Sin embargo, y esta es la respuesta corta si quieres ahorrar tiempo de lectura, estrictamente hablando no lo es.

La respuesta larga

Está claro que el framework MVC está presente de alguna u otra forma en el pipeline de ASP.NET Core, lo que hace pensar que sí podría existir una especie de "middleware MVC" capaz de engancharse al pipeline para poder participar en el proceso de peticiones.

La respuesta la encontramos fácilmente buceando en el código del framework. Si echamos un vistazo al fuente del extensor UseMvc() que utilizamos para insertar MVC en el pipeline encontramos lo siguiente (he limpiado un poco el código para que se entienda mejor):

/// <summary>
/// Adds MVC to the <see cref="IApplicationBuilder"/> request 
/// execution pipeline.
/// </summary>
public static IApplicationBuilder UseMvc(
    this IApplicationBuilder app,
    Action<IRouteBuilder> configureRoutes)
{
    [...]

    // Verify if AddMvc was done before calling UseMvc
    // We use the MvcMarkerService to make sure if all the services were added.
    if (app.ApplicationServices.GetService(typeof(MvcMarkerService)) == null)
    {
        throw new InvalidOperationException(
            Resources.FormatUnableToFindServices(
               nameof(IServiceCollection),
               "AddMvc",
               "ConfigureServices(...)")
        );
    }

    var routes = new RouteBuilder(app)
    {
        DefaultHandler = app.ApplicationServices
                            .GetRequiredService<MvcRouteHandler>(),
    };

    configureRoutes(routes);

    routes.Routes.Insert(0, 
        AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices)
    );

    return app.UseRouter(routes.Build());
}

Lo que se hace aquí es lo siguiente:
  1. Primero, se verifica que los servicios de MVC fueron añadidos al sistema solicitando una instancia de MvcMarkerService. Si no existe, es que se ha llamado a AddMvc() en la configuración de servicios, por lo que se lanza una excepción.
     
  2. Se crea un RouteBuilder al que se asocia por defecto el handler MvcRouteHandler. En otras palabras, se comienza a preparar un grupo de rutas cuyo proceso será delegado al framework MVC.
     
  3. Se invoca el delegado suministrado por el desarrollador para que añada las rutas al builder que estamos definiendo. Este delegado es el que suele configurar las convenciones de rutas, como en el siguiente código:
    app.UseMvc(routes =>
    {
        // Delegado de configuración de rutas
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{id?}");
    });
  4. Se insertan en primera posición las rutas definidas por atributos, de forma que tengan prioridad sobre el resto. Por cierto, CreateAttributeMegaRoute(), vaya pedazo de nombre para un método, ¿verdad? ;D
     
  5. Por último, se añade el middleware de routing de ASP.NET Core que hemos configurado.
Este punto es el que andábamos buscando y que da respuesta a la pregunta que nos hacíamos al principio. Por tanto, MVC no se añade al pipeline como un middleware, simplemente configura un RouterMiddleware de forma que las peticiones dirigidas a las rutas configuradas sean procesadas por MvcRouteHandler, que será el encargado de seleccionar la acción e invocarla.

Publicado en Variable not found.

Aún no hay comentarios, ¡sé el primero!