.Net Core路由基础

路由负责将请求 URI 映射到终结点并向这些终结点调度传入的请求。 路由在应用中定义,并在应用启动时进行配置。 路由可以选择从请求包含的 URL 中提取值,然后这些值便可用于处理请求。 通过使用应用中的路由信息,路由还能生成映射到终结点的 URL。

要在 ASP.NET Core 2.2 中使用最新路由方案,请在 Startup.ConfigureServices 中为 MVC 服务注册指定兼容性版本:

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

EnableEndpointRouting 选项确定路由是应在内部使用 ASP.NET Core 2.1 或更早版本的基于终结点的逻辑还是使用其基于 IRouter 的逻辑。 兼容性版本设置为 2.2 或更高版本时,默认值为 true。 将值设置为 false 以使用先前的路由逻辑:

services.AddMvc(options => options.EnableEndpointRouting = false)
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

路由基础知识

大多数应用应选择基本的描述性路由方案,让 URL 有可读性和意义。 默认传统路由 {controller=Home}/{action=Index}/{id?}

  • 支持基本的描述性路由方案。
  • 是基于 UI 的应用的有用起点。

开发者通常在专业情况下使用特性路由或专用传统路由向应用的高流量区域添加其他简洁路由。 专用情况示例包括:博客和电子商务终结点。

Web API 应使用属性路由,将应用功能建模为一组资源,其中操作是由 HTTP 谓词表示。 也就是说,对同一逻辑资源执行的许多操作(例如,GET 和 POST)都使用相同 URL。 属性路由提供了精心设计 API 的公共终结点布局所需的控制级别。

借助 URL 生成支持,无需通过硬编码 URL 将应用关联到一起,即可开发应用。 此支持允许从基本路由配置入手,并在确定应用的资源布局后修改路由。

路由使用“终结点”(Endpoint) 来表示应用中的逻辑终结点。

终结点定义用于处理请求的委托和任意元数据的集合。 元数据用于实现横切关注点,该实现基于附加到每个终结点的策略和配置。

路由系统具有以下特征:

  • 路由模板语法用于通过标记化路由参数来定义路由。

  • 可以使用常规样式和属性样式终结点配置。

  • IRouteConstraint 用于确定 URL 参数是否包含给定的终结点约束的有效值。

  • 应用模型(如 MVC/Razor Pages)注册其所有终结点,这些终结点具有可预测的路由方案实现。

  • 路由实现会在中间件管道中任何所需位置制定路由决策。

  • 路由中间件之后出现的中间件可以检查路由中间件针对给定请求 URI 的终结点决策结果。

  • 可以在中间件管道中的任何位置枚举应用中的所有终结点。

  • 应用可根据终结点信息使用路由生成 URL(例如,用于重定向或链接),从而避免硬编码 URL,这有助于可维护性。

  • URL 生成是基于支持任意可扩展性的地址:

    • 可以使用依赖关系注入 (DI) 在任意位置解析链接生成器 API (LinkGenerator) 以生成 URL。
    • 如果无法通过 DI 获得链接生成器 API,则 IUrlHelper 会提供生成 URL 的方法。

 路由模板

在我们生成的项目中有一个默认的模板,来匹配路由访问到对的路径:

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

大多数应用通过 MapRoute 或 IRouteBuilder 上定义的一种类似扩展方法来创建路由。任何 IRouteBuilder 扩展方法都会创建 Route 的实例并将其添加到路由集合中。MapRoute 不接受路由处理程序参数。 MapRoute 仅添加由 DefaultHandler 处理的路由。

上面这个模板和URL的路径匹配类似,例如访问路径 /Product/Detail/17 对应 Controller = Product  、action = Detail 、 id = 17,这边 id 后面的问号表示可选参数是可空的,controller 和 action 等于= 后面表示默认值,访问路径为 / 即访问这个默认值路径,但是访问默认路径就不能传递 id 了,除非这样 /Home/Index/3 。

 如果我们系统中的 id 为整数,我们要求不能为字符串,那么我们可以用如下约束(约束有很多种可以按自己情况设置),也可以进行多个约束用冒号隔开,有多个约束存在需要满足所有约束的哦:

{id:int} // {id:int:min(1)}

路由的匹配也可以用正则表达式匹配:

routeBuilder.MapRoute(
    "Track Package Route",
    "package/{operation:regex(^track|create$)}/{id:int}");

我们设置多个路由规则,自上而下以第一个匹配成功为准。

使用RouteBuilder

必须在 Startup.Configure 方法中配置路由:

services.AddRouting();

设置如下路由规则:

var trackPackageRouteHandler = new RouteHandler(context =>
{
    var routeValues = context.GetRouteData().Values;
    return context.Response.WriteAsync(
        $"Hello! Route values: {string.Join(", ", routeValues)}");
});

var routeBuilder = new RouteBuilder(app, trackPackageRouteHandler);

routeBuilder.MapRoute(
    "Track Package Route",
    "package/{operation:regex(^track|create$)}/{id:int}");

routeBuilder.MapGet("hello/{name}", context =>
{
    var name = context.GetRouteValue("name");
    // The route handler when HTTP GET "hello/<anything>" matches
    // To match HTTP GET "hello/<anything>/<anything>, 
    // use routeBuilder.MapGet("hello/{*name}"
    return context.Response.WriteAsync($"Hi, {name}!");
});

var routes = routeBuilder.Build();
app.UseRouter(routes);

下表显示了具有给定 URI 的响应。

 
URI响应

/package/create/3

Hello! Route values: [operation, create], [id, 3]

/package/track/-3

Hello! Route values: [operation, track], [id, -3]

/package/track/-3/

Hello! Route values: [operation, track], [id, -3]

/package/track/

请求失败,不匹配。

GET /hello/Joe

Hi, Joe!

POST /hello/Joe

请求失败,仅匹配 HTTP GET。

GET /hello/Joe/Smith

请求失败,不匹配。

Map[Verb] 方法将使用约束来将路由限制为方法名称中的 HTTP 谓词,像是 MapGet 表示匹配 Get 请求。RouteBuilder 不限于上面演示的,还有 MapDelete 等方法。

保留的路由名称

以下关键字是保留的名称,它们不能用作路由名称或参数:

    • action
    • area
    • controller
    • handler
    • page

路由的数据令牌

URL 匹配是路由向终结点调度传入请求的过程。 此过程基于 URL 路径中的数据,但可以进行扩展以考虑请求中的任何数据。 向单独的处理程序调度请求的功能是缩放应用的大小和复杂性的关键。

终结点路由中的路由系统负责所有的调度决策。 由于中间件是基于所选终结点来应用策略,因此任何可能影响调度或安全策略应用的决策都应在路由系统内部制定,这一点很重要。

执行终结点委托时,将根据迄今执行的请求处理将 RouteContext.RouteData 的属性设为适当的值。

RouteData.Values 是从路由中生成的路由值的字典。 这些值通常通过标记 URL 来确定,可用来接受用户输入,或者在应用内作出进一步的调度决策。

RouteData.DataTokens 是一个与匹配的路由相关的其他数据的属性包。 提供 DataTokens 以支持将状态数据与每个路由相关联,以便应用可根据所匹配的路由作出决策。 这些值是开发者定义的,不会影响通过任何方式路由的行为。 此外,存储于 RouteData.DataTokens 中的值可以属于任何类型,与 RouteData.Values 相反,后者必须能够转换为字符串,或从字符串进行转换。

RouteData.Routers 是参与成功匹配请求的路由的列表。 路由可以相互嵌套。 Routers 属性可以通过导致匹配的逻辑路由树反映该路径。 通常情况下,Routers 中的第一项是路由集合,应该用于生成 URL。 Routers 中的最后一项是匹配的路由处理程序。

routes.MapRoute(
    name: "us_english_products",
    template: "en-US/Products/{id}",
    defaults: new { controller = "Products", action = "Details" },
    constraints: new { id = new IntRouteConstraint() },
    dataTokens: new { locale = "en-US" });

可以看到RouteData的数据为:

原文地址:https://www.cnblogs.com/xwc1996/p/13621284.html