ASP.NET Core 入門教程 三、ASP.NET Core MVC路由入門

1、前言

一、本文主要內容

  • ASP.NET Core MVC路由工做原理概述
  • ASP.NET Core MVC帶路徑參數的路由示例
  • ASP.NET Core MVC固定前/後綴的路由示例
  • ASP.NET Core MVC正則表達式匹配路由示例
  • ASP.NET Core MVC路由約束與自定義路由約束
  • ASP.NET Core MVC RouteAttribute綁定式路由使用介紹

二、本教程環境信息

軟件/環境 說明
操做系統 Windows 10
SDK 2.1.401
ASP.NET Core 2.1.3
IDE Visual Studio Code 1.27
瀏覽器 Chrome 69

本篇代碼基於上一篇進行調整:https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-02javascript

三、前置知識

你可能須要的前置知識css

  • MVC框架/模式介紹

https://baike.baidu.com/item/mvchtml

  • 正則表達式

http://www.runoob.com/regexp/regexp-tutorial.htmljava

2、ASP.NET Core MVC 路由簡介

一、ASP.NET Core MVC路由工做原理概述

ASP.NET Core MVC路由的做用就是將應用接收到請求轉發到對應的控制器去處理。git

應用啓動的時候會將路由中間件(RouterMiddleware)加入到請求處理管道中,並將咱們配置好的路由加載到路由集合(RouteCollection)中。當應用接收到請求時,會在路由管道(路由中間件)中執行路由匹配,並將請求交給對應的控制器去處理。github

另外,須要特別注意的是,路由的匹配順序是按照咱們定義的順序從上之下匹配的,遵循是的先配置先生效的原則。正則表達式

二、路由配置參數說明

參數名 說明
name 路由名稱,不可重複
template 路由模板,可在模板中以{name}格式定義路由參數
defaults 配置路由參數默認值
constraints 路由約束

在路由配置中,MVC框架內置了兩個參數,controller,action。
路由匹配經過後,須要根據這兩個參數將當前請求交由對應的Controller+Action去處理。因此,這兩個參數缺乏任何一個,都會致使路由沒法正常工做。
一般咱們有兩個選擇:瀏覽器

  • 在template中指定{controller},{action}參數
  • 在默認值中爲controller、action指定默認值

3、ASP.NET Core MVC 路由示例

一、準備工做

爲了方便咱們進行測試,咱們先準備好承接路由的Controller&Actionmvc

  • 建立TutorialController

在Controllers文件夾下新增控制器TutorialController.cs並繼承於Controller框架

using System; using Microsoft.AspNetCore.Mvc; namespace Ken.Tutorial.Web.Controllers { public class TutorialController : Controller { } } 
  • 增長Action:Index
public IActionResult Index() { return Content("ASP.NET Core Tutorial by ken from ken.io"); } 
  • 增長Action:Welcome
public IActionResult Welcome(string name, int age) { return Content($"Welcome {name}(age:{age}) !"); } 

二、帶路徑參數的路由

路由配置:

routes.MapRoute(
        name: "TutorialPathValueRoute", template: "{controller}/{action}/{name}/{age}" ); 

此路由適配URL:

  • /tutorial/welcome/ken/20

不適配URL:

  • /tutorial/welcome/ken

若是咱們但願不在路徑中設置age,也能夠被路由到,那麼能夠將age指定爲可選參數,將模板中的{age}修改成{age?}便可

routes.MapRoute(
        name: "TutorialPathValueRoute", template: "{controller}/{action}/{name}/{age?}" ); 

此路由適配URL:

  • /tutorial/welcome/ken/20
  • /tutorial/welcome/ken
  • /tutorial/welcome/ken?age=20

三、固定先後綴的路由

固定前綴路由配置:

routes.MapRoute(
    name: "TutorialPrefixRoute", template: "jiaocheng/{action}", defaults: new { controller = "Tutorial" } ); 

此路由適配URL:

  • /jiaocheng/index
  • /jiaocheng/welcome

因爲路徑參數中不包含controller參數,因此須要在默認值中指定。

固定後綴路由配置

routes.MapRoute(
    name: "TutorialSuffixRoute", template: "{controller}/{action}.html" ); 

此路由適配URL:

  • /tutorial/index.html
  • /tutorial/welcome.html
  • /home/index.html
  • /home/time.html

固定後綴的路由適用於僞靜態等訴求
固定先後綴能夠根據本身的需求結合起來使用。
固然,你也能夠在路由模板中間設定固定值。

4、ASP.NET Core MVC 路由約束

一、路由約束介紹

路由約束主要是用於約束路由參數,在URL格式知足路有模板要求以後,進行參數檢查。若是參數不知足路由約束,那麼依然會返回未匹配該路由。最經常使用的可能就是參數類型校驗、參數長度校驗、以及經過正則知足的複雜校驗。

在開始以前須要在Startup.cs中引用相關命名空間

using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Constraints; 

二、參數長度約束

路由配置:約束name長度不能>5

routes.MapRoute(
    name: "TutorialLengthRoute", template: "hello/{name}/{age?}", defaults: new { controller = "Tutorial", action = "Welcome", name = "ken" }, constraints: new { name = new MaxLengthRouteConstraint(5) } ); 

此路由適配

  • /hello
  • /hello/ken
  • /hello/ken/1000

次路由不適配

  • /hello/kenaaaa

咱們也能夠直接在模板中配置路由約束:

routes.MapRoute(
    name: "TutorialLengthRoute2", template: "hello2/{name:maxlength(5)}/{age?}", defaults: new { controller = "Tutorial", action = "Welcome", name = "ken" } ); 

三、參數範圍約束

路由配置:約束 1<=age<=150

routes.MapRoute(
    name: "TutorialLengthRoute", template: "hello/{name}/{age?}", defaults: new { controller = "Tutorial", action = "Welcome", name = "ken" }, constraints: new { age = new CompositeRouteConstraint(new IRouteConstraint[] { new IntRouteConstraint(), new MinRouteConstraint(1), new MaxRouteConstraint(150) }) } ); 

此路由適配:

  • /hello/ken/1
  • /hello/ken/150

此路由不適配

  • /hello/ken/1000

咱們也能夠直接在模板中配置路由約束:

routes.MapRoute(
    name: "TutorialLengthRoute2", template: "hello2/{name}/{age:range(1,150)?}", defaults: new { controller = "Tutorial", action = "Welcome", name = "ken" } ); 

四、帶有正則表達式約束的路由

路由配置:

routes.MapRoute(
    name: "TutorialRegexRoute", template: "welcome/{name}", defaults: new { controller = "Tutorial", Action = "Welcome" }, constraints: new { name = @"k[a-z]*" } ); 

此路由適配:

  • /welcome/k
  • /welcome/ken
  • /welcome/kevin

此路由不適配

  • /welcome/k1
  • /welcome/keN
  • /welcome/tom

這裏咱們用正則表達式約束了參數name,必須經過正則k[a-z]*匹配經過,即:以小寫字母k開頭,且後續可跟0到多個小寫字母

咱們也能夠直接在模板中配置路由約束:

routes.MapRoute(
    name: "TutorialRegexRoute2", template: "welcome2/{name:regex(@"k[a-z]*")}", defaults: new { controller = "Tutorial", Action = "Welcome" } ); 

五、自定義路由約束

一、建立自定義約束

在項目根目錄建立目錄Common,並在目錄建立類:NameRouteConstraint.cs,而後實現接口:IRouteConstraint

using System; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; namespace Ken.Tutorial.Web.Common { public class NameRouteConstraint : IRouteConstraint { public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { string name = values["name"]?.ToString(); if (name == null) return true; if (name.Length > 5 && name.Contains(",")) return false; return true; } } } 

這裏咱們約束當name長度>5時,name中不能包含,

二、路由配置

引入命名空間

using Ken.Tutorial.Web.Common; 

在ConfigureServices引入路由約束

public void ConfigureServices(IServiceCollection services) { //引入MVC模塊 services.AddMvc(); //引入自定義路由約束 services.Configure<RouteOptions>(options => { options.ConstraintMap.Add("name", typeof(NameRouteConstraint)); }); } 

配置路由

routes.MapRoute(
    name: "TutorialDiyConstraintRoute", template: "diy/{name}", defaults: new { controller = "Tutorial", action = "Welcome" }, constraints: new { name = new NameRouteConstraint() } ); 

此路由適配:

  • /diy/ken
  • /diy/ken,
  • /diy/kenny

此路由不適配

  • /diy/kenny,

固然,按照慣例,依然能夠在模板中配置路由約束

routes.MapRoute(
    name: "TutorialDiyConstraintRoute2", template: "diy2/{name:name}", defaults: new { controller = "Tutorial", action = "Welcome" } ); 

5、ASP.NET Core MVC 綁定式路由配置

一、路由配置風格

  • 集中式配置

前面章節提到的路由配置都是在Startup類中進行的集中式路由配置,集中配置的路由,除了template中沒有配置{controller}參數,默認都是對全部控制器(Controller)生效的。這種集中配置的方式通常咱們只要配置一個默認路由,其餘狀況咱們只須要不知足默認模板的狀況下進行配置便可。尤爲是對URL沒有友好度要求的應用,例如:後臺管理系統

  • 分散式配置/綁定式配置

對於集中式路由配置的方式,若是某個Controller/Action配置了特殊路由,對於代碼閱讀就會不太友好。不過不要緊,ASP.NET Core MVC也提供了RouteAttribute可讓咱們在Controller或者Action上直接指定路由模板。

不過要強調的是,一個控制器只能選擇其中一種路由配置,若是控制器標記了RouteAttribute進行路由配置,那麼集中式配置的路由將不對其生效。

二、綁定式路由配置

在項目Controllers目中新建TestController.cs繼承與Controller
並配置Action與路由

using System; using Microsoft.AspNetCore.Mvc; namespace Ken.Tutorial.Web.Controllers { [Route("/test")] public class TestController : Controller { [Route("")] [Route("/test/home")] public IActionResult Index() { return Content("ASP.NET Core RouteAttribute test by ken from ken.io"); } [Route("servertime")] [Route("/t/t")] public IActionResult Time(){ return Content($"ServerTime:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} - ken.io"); } } } 
配置項 說明
[Route("/test")] 表示該Controller訪問路由前綴爲/test,必須以/開頭
[Route("")] 表示以Controller的路由配置爲前綴訪問該Action;能夠經過/test路由到該Action
[Route("/test/home")] 表示忽略Controller的路由配置;能夠經過/test/home路由到該Action
[Route("servertime")] 表示以Controller的路由配置爲前綴訪問該Action;能夠經過/test/servertime路由到該Action
[Route("/t/t")] 表示忽略Controller的路由配置;能夠經過/t/t路由到該Action

RouteAttribute中配置的參數,就至關於咱們集中式配置中的路由模板(template),最終框架仍是幫咱們初始化成路由規則,以[Route("/test/home")]爲例,至關於生成了如下路由配置:

routes.MapRoute(
    name: "Default", template: "test/home", defaults: new { controller = "Test", action = "Index" } ); 

固然,咱們也能夠在[Route]配置中使用模板參數,並且依然能夠在模板中使用約束,自定義約束也沒問題。

[Route("welcome/{name:name}")] public IActionResult Welcome(string name){ return Content($"Welcome {name} !"); } 

最大的區別就是不能定義默認值了,可能也不須要了,你說是吧。_

6、備註

一、附錄

  • 本文代碼示例

https://github.com/ken-io/asp.net-core-tutorial/tree/master/chapter-03

  • 本文參考

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/routing?view=aspnetcore-2.1


本文首發於個人獨立博客: https://ken.io/note/asp.net-core-tutorial-mvc-route

相關文章
相關標籤/搜索