99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

ASP.NET Core 中的路由

2019-04-17 08:59 更新

路由負責將請求 URI 映射到終結點選擇器并向終結點調度傳入的請求。 路由在應用中定義,并在應用啟動時進行配置。 路由可以選擇從請求包含的 URL 中提取值,然后這些值便可用于處理請求。 通過使用應用中的路由信息,路由還能生成映射到終結點選擇器的 URL。

要在 ASP.NET Core 2.2 中使用最新路由方案,請在 Startup.ConfigureServices 中為 MVC 服務注冊指定兼容性版本

C#

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

EnableEndpointRouting 選項確定路由是應在內部使用 ASP.NET Core 2.1 或更早版本的基于終結點的邏輯還是使用其基于 IRouter 的邏輯。 兼容性版本設置為 2.2 或更高版本時,默認值為 true。 將值設置為 false 以使用先前的路由邏輯:

C#

// Use the routing logic of ASP.NET Core 2.1 or earlier:
services.AddMvc(options => options.EnableEndpointRouting = false)
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

有關基于 IRouter 的路由的詳細信息,請參閱本主題的 ASP.NET Core 2.1 版本。

 重要

本文檔介紹較低級別的 ASP.NET Core 路由。 有關 ASP.NET Core MVC 路由的信息,請參閱 在 ASP.NET Core 中路由到控制器操作。 有關 Razor Pages 中路由約定的信息,請參閱 ASP.NET Core 中 Razor 頁面的路由和應用約定

查看或下載示例代碼如何下載

路由基礎知識

大多數(shù)應用應選擇基本的描述性路由方案,讓 URL 有可讀性和意義。 默認傳統(tǒng)路由 {controller=Home}/{action=Index}/{id?}:

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

開發(fā)人員通常在專業(yè)情況下(例如,博客和電子商務終結點)使用屬性路由或專用傳統(tǒng)路由向應用的高流量區(qū)域添加其他簡潔路由。

Web API 應使用屬性路由,將應用功能建模為一組資源,其中操作是由 HTTP 謂詞表示。 也就是說,對同一邏輯資源執(zhí)行的許多操作(例如,GET、POST)都將使用相同 URL。 屬性路由提供了精心設計 API 的公共終結點布局所需的控制級別。

Razor Pages 應用使用默認的傳統(tǒng)路由從應用的“頁面”文件夾中提供命名資源。 還可以使用其他約定來自定義 Razor Pages 路由行為。 有關詳細信息,請參閱 ASP.NET Core 中的 Razor 頁面介紹 和 ASP.NET Core 中 Razor 頁面的路由和應用約定。

借助 URL 生成支持,無需通過硬編碼 URL 將應用關聯(lián)到一起,即可開發(fā)應用。 此支持允許從基本路由配置入手,并在確定應用的資源布局后修改路由。

路由使用“終結點”(Endpoint) 來表示應用中的邏輯終結點。

終結點定義用于處理請求的委托和任意元數(shù)據(jù)的集合。 元數(shù)據(jù)用于實現(xiàn)橫切關注點,該實現(xiàn)基于附加到每個終結點的策略和配置。

路由系統(tǒng)具有以下特征:

  • 路由模板語法用于通過標記化路由參數(shù)來定義路由。
  • 可以使用常規(guī)樣式和屬性樣式終結點配置。
  • IRouteConstraint 用于確定 URL 參數(shù)是否包含給定的終結點約束的有效值。
  • 應用模型(如 MVC/Razor Pages)注冊其所有終結點,這些終結點具有可預測的路由方案實現(xiàn)。
  • 路由實現(xiàn)會在中間件管道中任何所需位置制定路由決策。
  • 路由中間件之后出現(xiàn)的中間件可以檢查路由中間件針對給定請求 URI 的終結點決策結果。
  • 可以在中間件管道中的任何位置枚舉應用中的所有終結點。
  • 應用可根據(jù)終結點信息使用路由生成 URL(例如,用于重定向或鏈接),從而避免硬編碼 URL,這有助于可維護性。
  • URL 生成是基于支持任意可擴展性的地址:可以使用依賴關系注入 (DI) 在任意位置解析鏈接生成器 API (LinkGenerator) 以生成 URL。如果無法通過 DI 獲得鏈接生成器 API,則 IUrlHelper 會提供生成 URL 的方法。

 備注

在 ASP.NET Core 2.2 中發(fā)布終結點路由后,終結點鏈接的適用范圍限制為 MVC/Razor Pages 操作和頁面。 將計劃在未來發(fā)布的版本中擴展終結點鏈接的功能。

路由通過 RouterMiddleware 類連接到中間件管道。 ASP.NET Core MVC 向中間件管道添加路由,作為其配置的一部分,并處理 MVC 和 Razor Pages 應用中的路由。 要了解如何將路由用作獨立組件,請參閱使用路由中間件部分。

URL 匹配

URL 匹配是路由向終結點調度傳入請求的過程。 此過程基于 URL 路徑中的數(shù)據(jù),但可以進行擴展以考慮請求中的任何數(shù)據(jù)。 向單獨的處理程序調度請求的功能是縮放應用的大小和復雜性的關鍵。

終結點路由中的路由系統(tǒng)負責所有的調度決策。 由于中間件是基于所選終結點來應用策略,因此任何可能影響調度或安全策略應用的決策都應在路由系統(tǒng)內部制定,這一點很重要。

執(zhí)行終結點委托時,將根據(jù)迄今執(zhí)行的請求處理將 RouteContext.RouteData 的屬性設為適當?shù)闹怠?/p>

RouteData.Values 是從路由中生成的路由值的字典。 這些值通常通過標記 URL 來確定,可用來接受用戶輸入,或者在應用內作出進一步的調度決策。

RouteData.DataTokens 是一個與匹配的路由相關的其他數(shù)據(jù)的屬性包。 提供 DataTokens 以支持將狀態(tài)數(shù)據(jù)與每個路由相關聯(lián),以便應用可根據(jù)所匹配的路由作出決策。 這些值是開發(fā)者定義的,不會影響通過任何方式路由的行為。 此外,存儲于 RouteData.DataTokens 中的值可以屬于任何類型,與 RouteData.Values 相反,后者必須能夠轉換為字符串,或從字符串進行轉換。

RouteData.Routers 是參與成功匹配請求的路由的列表。 路由可以相互嵌套。 Routers 屬性可以通過導致匹配的邏輯路由樹反映該路徑。 通常情況下,Routers 中的第一項是路由集合,應該用于生成 URL。 Routers 中的最后一項是匹配的路由處理程序。

URL 生成

URL 生成是通過其可根據(jù)一組路由值創(chuàng)建 URL 路徑的過程。 這需要考慮終結點與訪問它們的 URL 之間的邏輯分隔。

終結點路由包含鏈接生成器 API (LinkGenerator)。 LinkGenerator 是可從 DI 檢索的單一實例服務。該 API 可在執(zhí)行請求的上下文之外使用。 MVC 的 IUrlHelper 和依賴 IUrlHelper 的方案(如 Tag Helpers、HTML Helpers 和 Action Results)使用鏈接生成器提供鏈接生成功能。

鏈接生成器基于“地址”和“地址方案”概念。 地址方案是確定哪些終結點用于鏈接生成的方式。 例如,許多用戶熟悉的來自 MVC/Razor Pages 的路由名稱和路由值方案都是作為地址方案實現(xiàn)的。

鏈接生成器可以通過以下擴展方法鏈接到 MVC/Razor Pages 操作和頁面:

這些方法的重載接受包含 HttpContext 的參數(shù)。 這些方法在功能上等同于 Url.Action 和 Url.Page,但提供了更大的靈活性和更多的選項。

GetPath* 方法與 Url.Action 和 Url.Page 最相似,因為它們生成包含絕對路徑的 URI。 GetUri*方法始終生成包含方案和主機的絕對 URI。 接受 HttpContext 的方法在執(zhí)行請求的上下文中生成 URI。 除非重寫,否則將使用來自執(zhí)行請求的環(huán)境路由值、URL 基本路徑、方案和主機。

使用地址調用 LinkGenerator。 生成 URI 的過程分兩步進行:

  1. 將地址綁定到與地址匹配的終結點列表。
  2. 計算每個終結點的 RoutePattern,直到找到與提供的值匹配的路由模式。 輸出結果會與提供給鏈接生成器的其他 URI 部分進行組合并返回。

對任何類型的地址,LinkGenerator 提供的方法均支持標準鏈接生成功能。 使用鏈接生成器的最簡便方法是通過擴展方法對特定地址類型執(zhí)行操作。

擴展方法說明
GetPathByAddress根據(jù)提供的值生成具有絕對路徑的 URI。
GetUriByAddress根據(jù)提供的值生成絕對 URI。

 警告

請注意有關調用 LinkGenerator 方法的下列含義:

  • 對于不驗證傳入請求的 Host 標頭的應用配置,請謹慎使用 GetUri* 擴展方法。 如果未驗證傳入請求的 Host標頭,則可能以視圖/頁面中 URI 的形式將不受信任的請求輸入發(fā)送回客戶端。 建議所有生產應用都將其服務器配置為針對已知有效值驗證 Host 標頭。
  • 在中間件中將 LinkGenerator 與 Map 或 MapWhen 結合使用時,請小心謹慎。 Map* 會更改執(zhí)行請求的基路徑,這會影響鏈接生成的輸出。 所有 LinkGenerator API 都允許指定基路徑。 始終指定一個空的基路徑來撤消 Map* 對鏈接生成的影響。

與早期版本路由的差異

ASP.NET Core 2.2 或更高版本中的終結點路由與 ASP.NET Core 中早期版本的路由之間存在一些差異:

  • 終結點路由系統(tǒng)不支持基于 IRouter 的可擴展性,包括從 Route 繼承。
  • 終結點路由不支持 WebApiCompatShim。 使用 2.1 兼容性版本 (.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)) 以繼續(xù)使用兼容性填充碼。
  • 在使用傳統(tǒng)路由時,終結點路由對生成的 URI 的大小寫具有不同的行為。請考慮以下默認路由模板:C#復制app.UseMvc(routes => { routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"); }); 假設使用以下路由生成某個操作的鏈接:C#復制var link = Url.Action("ReadPost", "blog", new { id = 17, }); 如果使用基于 IRouter 的路由,此代碼生成 URI /blog/ReadPost/17,該 URI 遵循所提供路由值的大小寫。 ASP.NET Core 2.2 或更高版本中的終結點路由生成 /Blog/ReadPost/17(“Blog”大寫)。 終結點路由提供 IOutboundParameterTransformer 接口,可用于在全局范圍自定義此行為或應用不同的約定來映射 URL。有關詳細信息,請參閱參數(shù)轉換器參考部分。
  • 在試圖鏈接到不存在的控制器/操作或頁面時,MVC/Razor Pages 通過傳統(tǒng)路由執(zhí)行的鏈接生成,其操作具有不同的行為。請考慮以下默認路由模板:C#復制app.UseMvc(routes => { routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"); }); 假設使用以下路由通過默認模板生成某個操作的鏈接:C#復制var link = Url.Action("ReadPost", "Blog", new { id = 17, }); 如果使用基于 IRouter 的路由,即使 BlogController 不存在或沒有 ReadPost 操作方法,結果也始終為 /Blog/ReadPost/17。 正如所料,如果操作方法存在,ASP.NET Core 2.2 或更高版本中的終結點路由會生成 /Blog/ReadPost/17。 但是,如果操作不存在,終結點路由會生成空字符串。 從概念上講,如果操作不存在,終結點路由不會假定終結點存在。
  • 與終結點路由一起使用時,鏈接生成環(huán)境值失效算法的行為會有所不同。環(huán)境值失效是一種算法,用于決定當前正在執(zhí)行的請求(環(huán)境值)中的哪些路由值可用于鏈接生成操作。 鏈接到不同操作時,傳統(tǒng)路由會使額外的路由值失效。 ASP.NET Core 2.2 之前的版本中,屬性路由不具有此行為。 在 ASP.NET Core 的早期版本中,如果有另一個操作使用同一路由參數(shù)名稱,則該操作的鏈接會導致發(fā)生鏈接生成錯誤。 在 ASP.NET Core 2.2 或更高版本中,鏈接到另一個操作時,這兩種路由形式都會使值失效。請考慮 ASP.NET Core2.1 或更高版本中的以下示例。 鏈接到另一個操作(或另一頁面)時,路由值可能會按非預期的方式被重用。在 /Pages/Store/Product.cshtml 中:CSHTML復制@page "{id}" @Url.Page("/Login") 在 /Pages/Login.cshtml 中:CSHTML復制@page "{id?}" 如果 ASP.NET Core 2.1 或更早版本中的 URI 為 /Store/Product/18,則由 @Url.Page("/Login")在 Store/Info 頁面上生成的鏈接為 /Login/18。 即使鏈接目標完全是應用的其他部分,仍會重用 id 值 18。 /Login 頁面上下文中的 id 路由值可能是用戶 ID 值,而非存儲產品 ID 值。在 ASP.NET Core 2.2 或更高版本的終結點路由中,結果為 /Login。 當鏈接的目標是另一個操作或頁面時,不會重復使用環(huán)境值。
  • 往返路由參數(shù)語法:使用雙星號 (**) catch-all 參數(shù)語法時,不對正斜杠進行編碼。在鏈接生成期間,路由系統(tǒng)對雙星號 (**) catch-all 參數(shù)(例如,{**myparametername})中捕獲的除正斜杠外的值進行編碼。 在 ASP.NET Core 2.2 或更高版本中,基于 IRouter 的路由支持雙星號 catch-all 參數(shù)。ASP.NET Core ({*myparametername}) 早期版本中的單星號 catch-all 參數(shù)語法仍然受支持,并對正斜杠進行編碼。路由鏈接生成方式為Url.Action(new { category = "admin/products" })…/search/{*page}/search/admin%2Fproducts(對正斜杠進行編碼)/search/{**page}/search/admin/products

中間件示例

在以下示例中,中間件使用 LinkGenerator API 創(chuàng)建列出存儲產品的操作方法的鏈接。 應用中的任何類都可通過將鏈接生成器注入類并調用 GenerateLink 來使用鏈接生成器。

C#

using Microsoft.AspNetCore.Routing;

public class ProductsLinkMiddleware
{
    private readonly LinkGenerator _linkGenerator;

    public ProductsLinkMiddleware(RequestDelegate next, LinkGenerator linkGenerator)
    {
        _linkGenerator = linkGenerator;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        var url = _linkGenerator.GetPathByAction("ListProducts", "Store");

        httpContext.Response.ContentType = "text/plain";

        await httpContext.Response.WriteAsync($"Go to {url} to see our products.");
    }
}

創(chuàng)建路由

大多數(shù)應用通過調用 MapRoute 或 IRouteBuilder 上定義的一種類似的擴展方法來創(chuàng)建路由。 任何 IRouteBuilder 擴展方法都會創(chuàng)建 Route 的實例并將其添加到路由集合中。

MapRoute 不接受路由處理程序參數(shù)。 MapRoute 僅添加由 DefaultHandler 處理的路由。 要了解 MVC 中的路由的詳細信息,請參閱 在 ASP.NET Core 中路由到控制器操作

以下代碼示例是典型 ASP.NET Core MVC 路由定義使用的一個 MapRoute 調用示例:

C#

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

此模板與 URL 路徑相匹配,并且提取路由值。 例如,路徑 /Products/Details/17 生成以下路由值:{ controller = Products, action = Details, id = 17 }。

路由值是通過將 URL 路徑拆分成段,并且將每段與路由模板中的路由參數(shù)名稱相匹配來確定的。 路由參數(shù)已命名。 參數(shù)通過將參數(shù)名稱括在大括號 { ... } 中來定義。

上述模板還可匹配 URL 路徑 /,并且生成值 { controller = Home, action = Index }。 這是因為 {controller} 和 {action} 路由參數(shù)具有默認值,且 id 路由參數(shù)是可選的。 路由參數(shù)名稱為參數(shù)定義默認值后,等號 (=) 后將有一個值。 路由參數(shù)名稱后面的問號 (?) 定義了可選參數(shù)。

路由匹配時,具有默認值的路由參數(shù)始終會生成路由值。 如果沒有相應的 URL 路徑段,則可選參數(shù)不會生成路由值。 有關路由模板方案和語法的詳細說明,請參閱路由模板參考部分。

在以下示例中,路由參數(shù)定義 {id:int} 為 id 路由參數(shù)定義路由約束

C#

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

此模板與類似于 /Products/Details/17 而不是 /Products/Details/Apples 的 URL 路徑相匹配。 路由約束實現(xiàn) IRouteConstraint 并檢查路由值,以驗證它們。 在此示例中,路由值 id 必須可轉換為整數(shù)。 有關框架提供的路由約束的說明,請參閱路由約束參考。

其他 MapRoute 重載接受 constraints、dataTokens 和 defaults 的值。 這些參數(shù)的典型用法是傳遞匿名類型化對象,其中匿名類型的屬性名匹配路由參數(shù)名稱。

以下 MapRoute 示例可創(chuàng)建等效路由:

C#

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?}");

 提示

定義約束和默認值的內聯(lián)語法對于簡單路由很方便。 但是,存在內聯(lián)語法不支持的方案,例如數(shù)據(jù)令牌。

以下示例演示了一些其他方案:

C#

routes.MapRoute(
    name: "blog",
    template: "Blog/{**article}",
    defaults: new { controller = "Blog", action = "ReadArticle" });

上述模板與 /Blog/All-About-Routing/Introduction 等的 URL 路徑相匹配,并提取值 { controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction }。 controller 和 action 的默認路由值由路由生成,即便模板中沒有對應的路由參數(shù)。 可在路由模板中指定默認值。 根據(jù)路由參數(shù)名稱前的雙星號 (**) 外觀,article 路由參數(shù)被定義為 catch-all。全方位路由參數(shù)可捕獲 URL 路徑的其余部分,也能匹配空白字符串。

以下示例添加了路由約束和數(shù)據(jù)令牌:

C#

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" });

上述模板與 /en-US/Products/5 等 URL 路徑相匹配,并且提取值 { controller = Products, action = Details, id = 5 } 和數(shù)據(jù)令牌 { locale = en-US }。

本地 Windows 令牌

路由類 URL 生成

Route 類還可通過將一組路由值與其路由模板組合來生成 URL。 從邏輯上來說,這是匹配 URL 路徑的反向過程。

 提示

為更好了解 URL 生成,請想象你要生成的 URL,然后考慮路由模板將如何匹配該 URL。 將生成什么值? 這大致相當于 URL 在 Route 類中的生成方式。

以下示例使用常規(guī) ASP.NET Core MVC 默認路由:

C#

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

使用路由值 { controller = Products, action = List },將生成 URL /Products/List。 路由值將替換為相應的路由參數(shù),以形成 URL 路徑。 由于 id 是可選路由參數(shù),因此成功生成的 URL 不具有 id 的值。

使用路由值 { controller = Home, action = Index },將生成 URL /。 提供的路由值與默認值匹配,并且會安全地省略與默認值對應的段。

已生成的兩個 URL 將往返以下路由定義 (/Home/Index 和 /),并生成用于生成該 URL 的相同路由值。

 備注

使用 ASP.NET Core MVC 應用應該使用 UrlHelper 生成 URL,而不是直接調用到路由。

有關 URL 生成的詳細信息,請參閱 Url 生成參考部分。

使用路由中間件

引用應用項目文件中的 Microsoft.AspNetCore.App 元包

將路由添加到 Startup.ConfigureServices 中的服務容器:

C#

public void ConfigureServices(IServiceCollection services)
{
    services.AddRouting();
}

必須在 Startup.Configure 方法中配置路由。 該示例應用使用以下 API:

C#

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|detonate$)}/{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/3Hello! Route values: [operation, create], [id, 3]
/package/track/-3Hello! Route values: [operation, track], [id, -3]
/package/track/-3/Hello! Route values: [operation, track], [id, -3]
/package/track/請求失敗,不匹配。
GET /hello/JoeHi, Joe!
POST /hello/Joe請求失敗,僅匹配 HTTP GET。
GET /hello/Joe/Smith請求失敗,不匹配。

框架可提供一組用于創(chuàng)建路由 (RequestDelegateRouteBuilderExtensions) 的擴展方法:

Map[Verb] 方法將使用約束來將路由限制為方法名稱中的 HTTP 謂詞。 有關示例,請參閱 MapGet和 MapVerb

路由模板參考

如果路由找到匹配項,大括號 ({ ... }) 內的令牌定義綁定的路由參數(shù)。 可在路由段中定義多個路由參數(shù),但必須由文本值隔開。 例如,{controller=Home}{action=Index} 不是有效的路由,因為 {controller} 和 {action} 之間沒有文本值。 這些路由參數(shù)必須具有名稱,且可能指定了其他屬性。

路由參數(shù)以外的文本(例如 {id})和路徑分隔符 / 必須匹配 URL 中的文本。 文本匹配區(qū)分大小寫,并且基于 URL 路徑已解碼的表示形式。 要匹配文字路由參數(shù)分隔符({ 或 }),請通過重復該字符({{ 或 }})來轉義分隔符。

嘗試捕獲具有可選文件擴展名的文件名的 URL 模式還有其他注意事項。 例如,考慮模板 files/{filename}.{ext?}。 當 filename 和 ext 的值都存在時,將填充這兩個值。 如果 URL 中僅存在 filename 的值,則路由匹配,因為尾隨句點 (.) 是可選的。 以下 URL 與此路由相匹配:

  • /files/myFile.txt
  • /files/myFile

可以使用星號 (*) 或雙星號 (**) 作為路由參數(shù)的前綴,以綁定到 URI 的其余部分。 這些稱為 catch-all 參數(shù)。 例如,blog/{**slug} 將匹配以 /blog 開頭且其后帶有任何值(將分配給 slug路由值)的 URI。 全方位參數(shù)還可以匹配空字符串。

使用路由生成 URL(包括路徑分隔符 (/))時,catch-all 參數(shù)會轉義相應的字符。 例如,路由值為 { path = "my/path" } 的路由 foo/{*path} 生成 foo/my%2Fpath。 請注意轉義的正斜杠。 要往返路徑分隔符,請使用 ** 路由參數(shù)前綴。 { path = "my/path" } 的路由 foo/{**path} 生成 foo/my/path。

路由參數(shù)可能具有指定的默認值,方法是在參數(shù)名稱后使用等號 (=) 隔開以指定默認值。 例如,{controller=Home} 將 Home 定義為 controller 的默認值。 如果參數(shù)的 URL 中不存在任何值,則使用默認值。 通過在參數(shù)名稱的末尾附加問號 (?) 可使路由參數(shù)成為可選項,如 id? 中所示。 可選值和默認路徑參數(shù)的區(qū)別在于具有默認值的路由參數(shù)始終會生成值 —,而可選參數(shù)僅當請求 URL 提供值時才會具有值。

路由參數(shù)可能具有必須與從 URL 中綁定的路由值匹配的約束。 在路由參數(shù)后面添加一個冒號 (:) 和約束名稱可指定路由參數(shù)上的內聯(lián)約束。 如果約束需要參數(shù),將以在約束名稱后括在括號 ((...)) 中的形式提供。 通過追加另一個冒號 (:) 和約束名稱,可指定多個內聯(lián)約束。

約束名稱和參數(shù)將傳遞給 IInlineConstraintResolver 服務,以創(chuàng)建 IRouteConstraint 的實例,用于處理 URL。 例如,路由模板 blog/{article:minlength(10)} 使用參數(shù) 10 指定 minlength 約束。 有關路由約束詳情以及框架提供的約束列表,請參閱路由約束引用部分。

路由參數(shù)還可以具有參數(shù)轉換器,用于在生成鏈接以及將操作和頁面匹配到 URI 時轉換參數(shù)的值。與約束類似,可以通過在路由參數(shù)名稱后面添加冒號 (:) 和轉換器名稱,將參數(shù)變換器內聯(lián)添加到路徑參數(shù)。 例如,路由模板 blog/{article:slugify} 指定 slugify 轉換器。 有關參數(shù)轉換的詳細信息,請參閱參數(shù)轉換器參考部分。

下表演示了示例路由模板及其行為。

路由模板示例匹配 URI請求 URI…
hello/hello僅匹配單個路徑 /hello。
{Page=Home}/匹配并將 Page 設置為 Home。
{Page=Home}/Contact匹配并將 Page 設置為 Contact。
{controller}/{action}/{id?}/Products/List映射到 Products控制器和 List 操作。
{controller}/{action}/{id?}/Products/Details/123映射到 Products控制器和 Details 操作(id 設置為 123)。
{controller=Home}/{action=Index}/{id?}/映射到 Home 控制器和 Index 方法(忽略 id)。

使用模板通常是進行路由最簡單的方法。 還可在路由模板外指定約束和默認值。

 提示

啟用日志記錄以查看內置路由實現(xiàn)(如 Route)如何匹配請求。

保留的路由名稱

以下關鍵字是保留的名稱,它們不能用作路由名稱或參數(shù):

  • action
  • area
  • controller
  • handler
  • page

路由約束參考

路由約束在傳入 URL 發(fā)生匹配時執(zhí)行,URL 路徑標記為路由值。 路徑約束通常檢查通過路徑模板關聯(lián)的路徑值,并對該值是否可接受做出是/否決定。 某些路由約束使用路由值以外的數(shù)據(jù)來考慮是否可以路由請求。 例如,HttpMethodRouteConstraint 可以根據(jù)其 HTTP 謂詞接受或拒絕請求。 約束用于路由請求和鏈接生成。

 警告

請勿將約束用于“輸入驗證”。 如果將約束用于“輸入約束”,那么無效輸入將導致“404 - 未找到”響應,而不是含相應錯誤消息的“400 - 錯誤請求”。 路由約束用于消除類似路由的歧義,而不是驗證特定路由的輸入。

下表演示示例路由約束及其預期行為。

約束示例匹配項示例說明
int{id:int}123456789, -123456789匹配任何整數(shù)
bool{active:bool}true, FALSE匹配 true或 false(區(qū)分大小寫)
datetime{dob:datetime}2016-12-31, 2016-12-31 7:32pm匹配有效的 DateTime值(位于固定區(qū)域性中 - 查看警告)
decimal{price:decimal}49.99, -1,000.01匹配有效的 decimal 值(位于固定區(qū)域性中 - 查看警告)
double{weight:double}1.234, -1,001.01e8匹配有效的 double 值(位于固定區(qū)域性中 - 查看警告)
float{weight:float}1.234, -1,001.01e8匹配有效的 float 值(位于固定區(qū)域性中 - 查看警告)
guid{id:guid}CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638}匹配有效的 Guid 值
long{ticks:long}123456789, -123456789匹配有效的 long 值
minlength(value){username:minlength(4)}Rick字符串必須至少為 4 個字符
maxlength(value){filename:maxlength(8)}Richard字符串不得超過 8 個字符
length(length){filename:length(12)}somefile.txt字符串必須正好為 12 個字符
length(min,max){filename:length(8,16)}somefile.txt字符串必須至少為 8 個字符,且不得超過 16 個字符
min(value){age:min(18)}19整數(shù)值必須至少為 18
max(value){age:max(120)}91整數(shù)值不得超過 120
range(min,max){age:range(18,120)}91整數(shù)值必須至少為 18,且不得超過 120
alpha{name:alpha}Rick字符串必須由一個或多個字母字符(a-z,區(qū)分大小寫)組成
regex(expression){ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}123-45-6789字符串必須匹配正則表達式(參見有關定義正則表達式的提示)
required{name:required}Rick用于強制在 URL 生成過程中存在非參數(shù)值

可向單個參數(shù)應用多個由冒號分隔的約束。 例如,以下約束將參數(shù)限制為大于或等于 1 的整數(shù)值:

C#

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }

 警告

驗證 URL 的路由約束并將轉換為始終使用固定區(qū)域性的 CLR 類型(例如 int 或 DateTime)。 這些約束假定 URL 不可本地化。 框架提供的路由約束不會修改存儲于路由值中的值。 從 URL 中分析的所有路由值都將存儲為字符串。 例如,float 約束會嘗試將路由值轉換為浮點數(shù),但轉換后的值僅用來驗證其是否可轉換為浮點數(shù)。

正則表達式

ASP.NET Core 框架將向正則表達式構造函數(shù)添加 RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant。 有關這些成員的說明,請參閱 RegexOptions

正則表達式與路由和 C# 計算機語言使用的分隔符和令牌相似。 必須對正則表達式令牌進行轉義。要在路由中使用正則表達式 ^\d{3}-\d{2}-\d{4}$,表達式必須在字符串中提供 \(單反斜杠)字符,正如 C# 源文件中的 \\(雙反斜杠)字符一樣,以便對 \ 字符串轉義字符進行轉義(除非使用字符串文本)。 要對路由參數(shù)分隔符進行轉義({、}、[、]),請將表達式({{、}、[[、]])中的字符數(shù)加倍。 下表展示了正則表達式和轉義版本。

正則表達式轉義后的正則表達式
^\d{3}-\d{2}-\d{4}$^\\d{{3}}-\\d{{2}}-\\d{{4}}$
^[a-z]{2}$^[[a-z]]{{2}}$

路由中使用的正則表達式通常以脫字號 (^) 開頭,并匹配字符串的起始位置。 表達式通常以美元符號 ($) 字符結尾,并匹配字符串的結尾。 ^ 和 $ 字符可確保正則表達式匹配整個路由參數(shù)值。如果沒有 ^ 和 $ 字符,正則表達式將匹配字符串內的所有子字符串,而這通常是不需要的。 下表提供了示例并說明了它們匹配或匹配失敗的原因。

表達式String匹配注釋
[a-z]{2}hello子字符串匹配
[a-z]{2}123abc456子字符串匹配
[a-z]{2}mz匹配表達式
[a-z]{2}MZ不區(qū)分大小寫
^[a-z]{2}$helloNo參閱上述 ^ 和 $
^[a-z]{2}$123abc456No參閱上述 ^ 和 $

有關正則表達式語法的詳細信息,請參閱 .NET Framework 正則表達式。

若要將參數(shù)限制為一組已知的可能值,可使用正則表達式。 例如,{action:regex(^(list|get|create)$)} 僅將 action 路由值匹配到 list、get 或 create。 如果傳遞到約束字典中,字符串 ^(list|get|create)$ 將等效。 已傳遞到約束字典(不與模板內聯(lián))且不匹配任何已知約束的約束還將被視為正則表達式。

自定義路由約束

除了內置路由約束以外,還可以通過實現(xiàn) IRouteConstraint 接口來創(chuàng)建自定義路由約束。IRouteConstraint 接口包含一個方法 Match,當滿足約束時,它返回 true,否則返回 false。

若要使用自定義 IRouteConstraint,必須在應用的服務容器中使用應用的 ConstraintMap 注冊路由約束類型。 ConstraintMap 是將路由約束鍵映射到驗證這些約束的 IRouteConstraint 實現(xiàn)的目錄。 應用的 ConstraintMap 可作為 services.AddRouting 調用的一部分在 Startup.ConfigureServices 中進行更新,也可以通過使用 services.Configure<RouteOptions> 直接配置 RouteOptions 進行更新。 例如:

C#

services.AddRouting(options =>
{
    options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});

然后,可以使用在注冊約束類型時指定的名稱,以常規(guī)方式將約束應用于路由。 例如:

C#

[HttpGet("{id:customName}")]
public ActionResult<string> Get(string id)

參數(shù)轉換器參考

參數(shù)轉換器:

  • 在為 Route 生成鏈接時執(zhí)行。
  • 實現(xiàn) Microsoft.AspNetCore.Routing.IOutboundParameterTransformer。
  • 使用 ConstraintMap 進行配置。
  • 獲取參數(shù)的路由值并將其轉換為新的字符串值。
  • 在生成的鏈接中使用轉換后的值的結果。

例如,路由模式 blog\{article:slugify}(具有 Url.Action(new { article = "MyTestArticle" }))中的自定義 slugify 參數(shù)轉換器生成 blog\my-test-article。

若要在路由模式中使用參數(shù)轉換器,請先在 Startup.ConfigureServices 中使用 ConstraintMap 對其進行配置:

C#

services.AddRouting(options =>
{
    // Replace the type and the name used to refer to it with your own
    // IOutboundParameterTransformer implementation
    options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
});

框架使用參數(shù)轉化器來轉換進行終結點解析的 URI。 例如,ASP.NET Core MVC 使用參數(shù)轉換器來轉換用于匹配 area``controller``action 和 page 的路由值。

C#

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

使用上述路由,操作 SubscriptionManagementController.GetAll() 與 URI /subscription-management/get-all 匹配。 參數(shù)轉換器不會更改用于生成鏈接的路由值。 例如,Url.Action("GetAll", "SubscriptionManagement") 輸出 /subscription-management/get-all。

對于結合使用參數(shù)轉換器和所生成的路由,ASP.NET Core 提供了 API 約定:

  • ASP.NET Core MVC 還具有 Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention API 約定。該約定將指定的參數(shù)轉換器應用于應用中的所有屬性路由。 在替換屬性路徑令牌時,參數(shù)轉換器將轉換這些令牌。 有關詳細信息,請參閱使用參數(shù)轉換器自定義標記替換。
  • Razor Pages 具有 Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention API 約定。此約定將指定的參數(shù)轉換器應用于所有自動發(fā)現(xiàn)的 Razor Pages。 參數(shù)轉換器轉換 Razor Pages.路由的文件夾和文件名段。 有關詳細信息,請參閱使用參數(shù)轉換器自定義頁面路由。

URL 生成參考

以下示例演示如何在給定路由值字典和 RouteCollection 的情況下生成路由鏈接。

C#

app.Run(async (context) =>
{
    var dictionary = new RouteValueDictionary
    {
        { "operation", "create" },
        { "id", 123}
    };

    var vpc = new VirtualPathContext(context, null, dictionary, 
        "Track Package Route");
    var path = routes.GetVirtualPath(vpc).VirtualPath;

    context.Response.ContentType = "text/html";
    await context.Response.WriteAsync("Menu<hr/>");
    await context.Response.WriteAsync(
        $"<a href='{path}'>Create Package 123</a><br/>");
});

上述示例末尾生成的 VirtualPath 為 /package/create/123。 字典提供“跟蹤包路由”模板 package/{operation}/{id} 的 operation 和 id 路由值。 有關詳細信息,請參閱使用路由中間件部分或示例應用中的示例代碼。

VirtualPathContext 構造函數(shù)的第二個參數(shù)是環(huán)境值的集合。 由于環(huán)境值限制了開發(fā)人員在請求上下文中必須指定的值數(shù),因此環(huán)境值使用起來很方便。 當前請求的當前路由值被視為鏈接生成的環(huán)境值。 在 ASP.NET Core MVC 應用 HomeController 的 About 操作中,無需指定控制器路由值即可鏈接到使用 Home 環(huán)境值的 Index 操作—。

忽略與參數(shù)不匹配的環(huán)境值。 在顯式提供的值會覆蓋環(huán)境值的情況下,也會忽略環(huán)境值。 在 URL 中將從左到右進行匹配。

顯式提供但與路由片段不匹配的值將添加到查詢字符串中。 下表顯示使用路由模板 {controller}/{action}/{id?} 時的結果。

環(huán)境值顯式值結果
控制器 =“Home”操作 =“About”/Home/About
控制器 =“Home”控制器 =“Order”,操作 =“About”/Order/About
控制器 = “Home”,顏色 = “Red”操作 =“About”/Home/About
控制器 =“Home”操作 =“About”,顏色 =“Red”/Home/About?color=Red

如果路由具有不對應于參數(shù)的默認值,且該值以顯式方式提供,則它必須與默認值相匹配:

C#

routes.MapRoute("blog_route", "blog/{*slug}",
    defaults: new { controller = "Blog", action = "ReadPost" });

當提供 controller 和 action 的匹配值時,鏈接生成僅為此路由生成鏈接。

復雜段

復雜段(例如,[Route("/x{token}y")])通過非貪婪的方式從右到左匹配文字進行處理。 請參閱此代碼以了解有關如何匹配復雜段的詳細說明。 ASP.NET Core 無法使用代碼示例,但它提供了對復雜段的合理說明。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號