我已经经历了mvc请求的生命周期,我仍然没有弄清楚请求在哪里根据注册的路由路由到处理程序。
我们用一个url放置mvc请求,然后找到控制器并交付正确的cshtml页面。
由于url没有任何资源类型,因此http模块事件或http处理程序如何区分mvc请求并将其传递给正确的控制器。

最佳答案

您已经从微软的asp.net站点获得了this document,详细描述了mvc 5请求生命周期以及如何将其集成到asp.net生命周期中。pdf中的一些图表部分本身链接到msdn中的相关页面。
另一个好的资源是lukasz lysic的this set of slides,它详细解释了mvc 4中的请求生命周期。
编辑:我不喜欢只链接的答案,所以我在下面增加了一些细节。
在您的机器级web.config中,您将看到注册为UrlRoutingModuleIHttpModule。例如,在我的电脑上,我有:

<system.web>
   <httpModules>
      ...
      <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
      ...
   </httpModules>
<system.web>

PostResolveRequestCache应用程序事件中,路由模块遍历RouteCollection属性中的所有路由,并搜索具有与http请求格式匹配的url模式的路由。当模块找到匹配的路由时,它将检索该路由的IRouteHandler对象。从路由处理程序中,该模块获取一个IHttpHandler对象,并将其用作当前请求的http处理程序(调用其ProcessRequest方法或异步对应的BeginProcessRequestEndProcessRequest)。
您可以在Microsoft.NET引用源站点上检查urlRoutingmodule代码here
对于mvc应用程序,当使用global.asax扩展方法在MapRoute中添加路由时,将创建MVCRouteHandler
检查MapRoute类中的RouteCollectionExtensions方法:
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
    if (routes == null)
    {
        throw new ArgumentNullException("routes");
    }
    if (url == null)
    {
        throw new ArgumentNullException("url");
    }

    Route route = new Route(url, new MvcRouteHandler())
    {
        Defaults = CreateRouteValueDictionaryUncached(defaults),
        Constraints = CreateRouteValueDictionaryUncached(constraints),
        DataTokens = new RouteValueDictionary()
    };

    ConstraintValidation.Validate(route);

    if ((namespaces != null) && (namespaces.Length > 0))
    {
        route.DataTokens[RouteDataTokenKeys.Namespaces] = namespaces;
    }

    routes.Add(name, route);

    return route;
}

因此,当请求与mvc路由匹配时,它将由MvcRouteHandler处理。如上所述,路由的IRouteHandler的目的是获取应用程序将用于继续处理请求的IHttpHandlerMvcRouteHandler将返回一个MvcHandler,它是mvc特定管道的入口点。
检查GetHttpHandler类的MvcRouteHandler方法:
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
    requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
    return new MvcHandler(requestContext);
}

MVC特定的管道基本上以ProcessRequest方法(或异步BeginProcessRequest/EndProcessRequest方法)开始。MvcHandler将获得IControllerFactory(默认情况下,将使用DefaultControllerFactory,除非您在global.asax application_start中使用ControllerBuilder.Current.SetDefaultControllerFactory注册自己的),使用它基于当前路由值创建控制器实例并启动控制器执行。
检查ProcessRequest类的MvcHandler方法:
protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
    IController controller;
    IControllerFactory factory;
    ProcessRequestInit(httpContext, out controller, out factory);

    try
    {
        controller.Execute(RequestContext);
    }
    finally
    {
        factory.ReleaseController(controller);
    }
}

private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
    // If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
    // at Request.Form) to work correctly without triggering full validation.
    // Tolerate null HttpContext for testing.
    HttpContext currentContext = HttpContext.Current;
    if (currentContext != null)
    {
        bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(currentContext);
        if (isRequestValidationEnabled == true)
        {
            ValidationUtility.EnableDynamicValidation(currentContext);
        }
    }

    AddVersionHeader(httpContext);
    RemoveOptionalRoutingParameters();

    // Get the controller type
    string controllerName = RequestContext.RouteData.GetRequiredString("controller");

    // Instantiate the controller and call Execute
    factory = ControllerBuilder.GetControllerFactory();
    controller = factory.CreateController(RequestContext, controllerName);
    if (controller == null)
    {
        throw new InvalidOperationException(
            String.Format(
                CultureInfo.CurrentCulture,
                MvcResources.ControllerBuilder_FactoryReturnedNull,
                factory.GetType(),
                controllerName));
    }
}

这应该解释如何将传入的请求与mvc中的控制器匹配。对于MVC管道的其余部分,请查看帖子中的链接!

关于asp.net-mvc - MVC路由发生在哪个请求事件中。,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23308804/

10-16 20:16