【asp.net core 系列】2 控制器與路由的恩怨情仇

0. 前言

在上一篇文章中,咱們初步介紹了asp.net core,以及如何建立一個mvc項目。從這一篇開始,我將爲你們展現asp.net core 的各類內容,而且嘗試帶領你們來挖掘其中的內在邏輯。mvc

固然,那是之後的事情。這一篇將經過自定義一個控制器來爲你們介紹asp.net core mvc 中控制器和路由的相關知識。app

圖片

1. 控制器

先在Controllers目錄下添加一個類,名叫:asp.net

public class DemoController
{
   public string Index()
   {
       return "你好";
   }
}

訪問地址:ide

http://localhost:5006/demo/index

若是不出意外的話,你應該能看到網頁上的"你好"兩個字。測試

再新建一個類:ui

using Microsoft.AspNetCore.Mvc;
public class NoContrl : Controller
{
   public IActionResult Index()
   {
       return Content("Test");
   }
}

結合兩個不常規的控制器類,讓咱們初窺asp.net core MVC是如何識別控制器的。這正是我以前說的,約定優於配置最好的體現。這個哲學最先也是爲MVC提出來的,後來被.net framework引伸到各個方面。this

asp.net core mvc識別控制器,會在項目中發現 以Controller結尾的公開類或者繼承自Controller的公開類,並將這些類標記爲控制器。當接到用戶或者界面轉交的請求時,程序從請求路徑中解析出控制器名稱,而後尋找 <控制器>Controller 或者 <控制器> : Controller 的類。spa

在默認狀況下,一個訪問URL會在程序中解析成以下格式:.net

http://<HOST>:<PORT>/<Controller>/<Action>[其餘參數]

在上文中,咱們知道了控制器的解析規則,那麼如今看一下Action的解析規則:code

在DemoController中添加以下方法:

public int TestInt()
{
   return 10;
}

public object TestObject()
{
   return new
   {
       Name = "TestObject",
       Age = 1
   };
}

public string TestPublic()
{
   return "成功訪問 TestPublic";
}

   protected string TestProtect()
{
   return "成功訪問 TestProtect";
}

private string TestPrivate()
{
   return "成功訪問 TestPrivate";
}

從新啓動,後依次訪問以下地址:

http://localhost:5006/Demo/TestInt
http://localhost:5006/Demo/TestObject
http://localhost:5006/Demo/TestPublic
http://localhost:5006/Demo/TestProtect
http://localhost:5006/Demo/TestPrivate

而後能夠看到,TestInt、TestObject以及TestPublic均能正常訪問,但TestProtect和TestPrivate都提示找不到網頁或沒法訪問。

能夠看到,對於程序而言,Action就是控制器類裏的公開類方法,與方法的返回值無關。也就是說,程序會找到 XXXController 或者名爲XXX但繼承了Controller的類做爲XXX的控制器,而後繼續在這個類裏尋找到Action,若是沒有找到就會返回404的請求。

2. 路由

在第一節中,咱們介紹了一下asp.net core mvc如何尋找控制器和Action,那這一節將介紹程序如何從請求連接中解析出控制器和Action的名稱,也就是路由映射。

路由(Routing)負責匹配傳入的HTTP請求,而後將這些請求發送給應用的可執行終結點。終結點是應用的可執行請求處理代碼單元,也就是咱們控制器裏的方法(Action)。

2.1 路由的配置

對於全部的asp.net core模板都包括生成在代碼中的路由。一般,咱們要求路由在Startup.Configure方法中進行配置。

注意,Startup類裏有且只有一個Configure方法,不能出現其重載版本。

該方法的聲明通常狀況以下:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env);

若是想要設置路由,須要先註明項目啓用路由:

app.UseRouting();

而後使用以下方法配置路由:

app.UseEndpoints(endpoints =>
{
   // 配置路由
});

一般對於mvc項目而言,咱們通常使用以下方式配置路由:

endpoints.MapControllerRoute(
   name: "default",
   pattern: "{controller=Home}/{action=Index}/{id?}");

這行代碼的意思是:建立一個名字爲 default 的映射控制器的路由,映射規則爲 {controller}/{action}/{id?},也就是第一個爲控制器,第二個爲Action,第三個是ID,其中ID能夠不存在,當Action沒法從請求地址中解析出來時默認爲Index,控制器默認爲Home。

經過這個解析,咱們能夠得知 咱們以前訪問的

http://localhost:5000/

是哪一個控制器裏的什麼方法來處理了——HomeController.Index。

那麼咱們修改一下HomeController.Index來驗證一下,咱們理解是否有誤:

public IActionResult Index()
{
   return View();
}
//  修改成
public IActionResult Index()
{
   return Content("測試");
}

從新運行程序,訪問

http://localhost:5000/

而後看到頁面出現:測試字樣,能夠看到路由系統自動爲咱們補全了控制器名和action名。若是方法中出現參數,則自動按照參數名1=值1&參數名2=值2這種形式查看參數。Id爲特殊的,會自動按照目錄去映射。因此:

http://localhost:5000/控制器1/方法1/id值
http://localhost:5000/控制器1/方法1?id=id值

是一個請求連接。

2.2 添加路由配置

那麼,咱們回過頭來看一下聲明路由的方法:

public static ControllerActionEndpointConventionBuilder MapControllerRoute(this IEndpointRouteBuilder endpoints, string name, string pattern, object defaults = null, object constraints = null, object dataTokens = null);

默認狀況下,咱們不會設置 defaults、constraints、dataTokens,這三個參數都有含義,這裏不對後兩個作介紹,簡單介紹一下第一個:

在路由配置的方法裏,添加如下內容:

endpoints.MapControllerRoute(
                   name : "test",
                   pattern: "DemoTest/{action=Index}/{id?}",
                   defaults : new
                   {
                       Controller = "Demo",

                   });

至此,咱們沒有建立名爲DemoTest的控制器,可是咱們在訪問:

http://localhost:5006/DemoTest

仍然能獲得響應,並且控制器被解析爲Demo。

這就是defaults的意義,路由在解析的時候,系統會把defaults中的值自動填充到路由鏈接中沒有設置的值裏。

當咱們設置多個路由的時候,路由系統會優先嚐試匹配最容易解析的配置。好比說,當咱們訪問:

http://localhost:5000/DemoTest/

的時候,路由系統會優先從名爲test的配置表中解析,只有當沒法從這裏找到時纔會從其餘路由中解析。

3. 總結

這一篇咱們簡單介紹了控制器與路由映射,能夠訪問咱們本身添加的路由。在開發中,一般狀況下,建立的控制器都是以Controller結尾並繼承Controller類。這是由於Controller類有不少有用的屬性和方法供咱們使用,以Controller結尾是爲了統一規則,可讓咱們一眼看出哪些是控制器。

相關文章
相關標籤/搜索