路由用于映射请求到路由处理程序。路由会在应用程序一启动时进行配置,并且可以从URL中提取值用于请求处理。路由还负责使用ASP.NET应用中定义的路由来生成链接。

路由基础

路由是用来把请求映射到路由处理程序。应用程序一启动就配置了路由,并且可以从URL中提取值用于处理请求。它还负责使用 ASP.NET 应用程序中定义的路由来生成链接。

路由使用Routes类(IRouter的实现)来:

  • 映射传入的请求到路由处理程序
  • 生成用于响应中的URL

通常一个应用有一个路由集合。路由集合会按顺序进行处理。请求会在路由集合按照URL matching来进行查找。响应使用路由生成URL。

路由通过RouterMiddleware类连接到中间件管道。ASP.NET MVC添加路由到中间件管道作为配置的一部分。

URL匹配

URL匹配是指路由调度传来的请求到一个处理程序的一个过程。这个过程通常是基于URL路径中的数据,但也可以扩展到请求中的任何数据。调度请求到不同的处理程序的能力是调节应用大小和复杂度的关键。

传入的请求会进入RouterMiddleware,它会按顺序调用每个路由上的RouteAsync方法。IRouter实例通过设置RouteContext Handler为一个不为空的RequestDelegate来选择是否处理请求。如果一个处理程序已经设置了路由,那么它将被调用来处理这个请求,并且没有其它的路由再去处理。如果所有的路由都执行了,请求还没有找到处理程序,那么中间件会调用next,从而下一个在请求管道中的中间件被会调用。

RouteAsync的主要输入是和当前请求相关联的RouteContext HttpContext。在成功匹配之后,RouteContext.HandlerRouteContext RouteData会作为输出。

RouteAsync执行期间,一个成功的匹配会基于一个已经完成的请求处理设置RouteContext.RouteData的属性为一个适当的值。当一个路由成功匹配了一个请求时,RouteContext.RouteData包含关于路由结果的重要的状态信息

RouteData Values是一个从路由产生的路由值的字典。这些值通常由标记化的URL由确定的,可以用于接受用户的输入,或者用于应用内部更深层次的调度决定。

RouteData DataTokens是一个与相关匹配路由的附加数据的属包。DataTokens提供与每个路由相关联的状态数据的支持。这样应用可以基于匹配的路由延迟作为决定。这个值都是由开发人员定义的,也不会对路由行为产生影响。而且,数据令牌中的数据可以是任何类型。与路由值相比之下,它可以很方便地在字符串之间进行互转。

RouteData Routers是一个参与成功匹配请求的路由的列表。路由可以彼此嵌套,而且Routers属性反映了通过导致匹配的路由的逻辑树的路径。通常,Routers中的第一项是路由集合,并且应该用来生成URL。Routers中的最后一项就是已经匹配的路由。

URL生成

URL生成(URL Generation)是指路由可以基于一组路由值创建一个URL路径的过程。这允许你的处理程序和访问它们的URL之间有一个逻辑分离。

URL生成遵循一个类似于迭代的过程,但以用户或者框架代码调用到路由集合的GetVirtualPath方法开始。然后,每一个路由将按顺序调用其GetVirtualPath方法,直到返回一个非空的VirtualPathData

GetVirtualPath主要输入有:

  • VirtualPathContext HttpContext
  • VirtualPathContext Values
  • VirtualPathContext AmbientValues

路由主要使用ValuesAmbientValues提供的路由值来决定在哪生成一个URL以及包含什么值。AmbientValues是随着路由系统当前请求而产生的一组路由值。相比,Values是指定怎么去为当前操作生成所期望的URL的路由值。提供HttpContext是以防路由需要获取一个服务或者与当前上下文关联的额外数据。

GetVirtualPath的输出是一个VirtualPathData。它包含输出URL的VirtualPath以及应当由路由设置的额外属性。

VirtualPathData VirtualPath属性包含一个路由产生的虚拟路径。根据你的需求,你可以需要对该路径作进一步处理。例如,如果你想要在HTML中呈现生成的URL,你需要去预先设置好应用的基本路径。

VirtualPathData Router是一个成功生成URL路由的参考。

VirtualPathData DataTokens属性是生成URL的路由的一个附加数据的字典集合。

创建路由

路由提供了Route类作为IRouter的标准实现。当调用RouteAsync调用时,Route使用路由模板语法来定义匹配URL路径的模式。当调用GetVirtualPath方法时,Route会使用相同的路由模板去生成URL。

大多数的应用会通过调用MapRoute或者在IRouteBuilder上定义的类似的扩展方法来创建路由。所有的这些方法会创建一个Route实例并添加到路由集合中。

ASP.NET MVC通常配置了一个默认处理程序,它只处理匹配一个可用的控制器和动作方法的请求。

这个一个用于典型的ASP.NET MVC路由定义MapRoute调用的例子:

routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id?}");

该模板会匹配类似于/Products/Details/17这样的URL路径,并提取出路由值:{ controller = Products, action = Details, id = 17 }。路由值通过将URL路径拆分为段来确定的,在路由模板中通过路由参数名称来匹配每个段。路由参数被命名。它们是通过在大括号{}中包含参数名来定义的。

上面的模板也能匹配/URL路径,还会产生值{ controller = Home, action = Index }。这是因为{controller}{action}都定义了默认值。并且id路由参数是可选的。在路由参数名称后面跟随在等号=后的值是该参数的默认值。路由参数后面的问号?表示该参数是可选的。带有默认值的路由参数总是会在路由匹配的时候产生一个路由值 - 而如果没有相应的URL路径段,则可选参数将不会产生一个值。

这是一个路由约束的例子:

routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id:int}");

这个模板将会匹配/Products/Details/17,当不会匹配/Products/Details/Apples。路由参数通过{id:int}id路由参数定义了一个路由约束。路由参数实现于IRouteConstraint接口,并会检查路由值是否符合约束。在这个例子中,id必须可以转换为一个整数。

另外,MapRoute的重载接受constraints,dataTokensdefaults。这些另外的参数都被定义为object类型。这些参数的典型用法是传递一个匿名类型的对象,匿名类型的属性名称必须与路由参数名称相匹配。

下面的两个例子创建了两个等效的路由:

routes.MapRoute(
    name: "default_route",
    template: "{controller}/{action}/{id?}",
    defaults: new { controller = "Home", action = "Index" });

routes.MapRoute(
    name: "default_route",
    template: "{controller=Home}/{action=Index}/{id?}");