整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          ASP.NET實戰008:MVC路由實現詳解

          ASP.NET實戰008:MVC路由實現詳解

          RL定義

          URL是Uniform Resource Locator的首字母縮寫,名為統一資源定位符,主要負責定位查找Internet中的信息資源,是Internet上標準的資源地址。資源是個抽象的概念,既可以指某個文件也可以指某方法調用的結果,所以URL不僅可以包含了文件的信息,也可以攜帶參數。

          URL組成

          URL主要由四部分組成,他們分別是傳輸協議、服務器地址、端口號、路徑名,中間用“/”符號拼接:

          傳輸協議指的是要訪問的服務器的傳輸類型,如FTP(文件傳輸協議)、SMTP(電子郵件協議)、HTTP(超文本傳輸協議)、HTTPS(超文本傳輸安全協議)、DNS(域名系統協議)、TELNET(會話協議)等等,當然這里我們WEB指的是一般都是HTTP或者HTTPS。

          服務器地址用來定位資源所存在的機器,在公網中每臺服務器會分配一個唯一的IP地址,我們可以通過IP找到對應的服務器。

          端口號連接時所使用的通信端口號,這是Internet用來辨別信息服務用的一種軟件標識。因為一臺服務器上可能部署多個服務,為了能更精準的當問到指定的服務我們就可以通過指定端口來區分。

          路徑名指的是指定資源的具體文件路徑或者方法調用,由于資源不一定是文件,所以路徑中常常會攜帶參數,在方法調用的時候進行傳參。

          ASP.NET MVC 路由

          ASP.NET MVC 路由是建立在Asp.NetFramework之上的組件,路由機制同樣也可以應用在WebForms應用中,對于ASP.NET Web Forms來說,路由定位的是一個有效的文件。這個文件可以是靜態的圖片、視頻等文件,也可以是.aspx動態頁面。而對于ASP.NET MVC來說,路由則是指向了某個Controller類型中的Action方法,同時支持URL參數傳遞,這讓路由屬性更加靈活多變,可控性也強。

          MVC路由特點

          1,安全性高,避免直接訪問物理資源,提高了系統的安全性;

          2,靈活性強,URL不會因為物流資源的改變而改變;

          3,可讀性好,通過定義URL可以直觀的知道訪問的資源類型;

          4,SEO優化,良好的URL規范容易被搜索引擎識別收錄;

          5,易重寫,可以在不同的路由模式的操作上重寫默認路由。


          Global.asax.cs

          在創建一個新的ASP.NET MVC項目時在項目的根目錄中生成一個Global.asax文件,它是一個全局文件也是項目運行時的初始函數,它的作用是全局注冊組件,比如申明全局注冊、Filters注冊、 Route注冊、Bundle注冊等。項目啟動時會自動調用Global.asax文件中的Application_Start方法,該方法中默認申明了全局注冊及路由注冊。

          RouteCOnfig.cs

          Application_Start方法則調用了RegisterRoutes的方法(這個方法在~/App_Start/RouteCOnfig.cs中被定義),用來向ASP.NET MVC 注冊了路由規則,通過RouteCollection 的MapRoute方法(MVC提供MapRoute、MapPageRoute、IgnoreRoute三種方式)向系統增加一條路由規則,這個路由規則適用于所有的控制器。

          name:路由的名稱;

          url:這是個路由匹配規則,告訴系統請求資源的路徑,也就是我們URL中的路徑名,這里每個部分用{}括起來,相當于占位符,是變量,用來申明URL中的每個組成部分;

          defaults:這是個默認的對象,{}中的變量指向了固定的參數表示執行匹配,這里是告訴系統去Home Controller控制器中找Index方法并且傳入id這個參數,因此我們必須保證在項目的Controllers文件夾中必須有一個叫做HomeController的對象且對象中必須有Index這個方法,否則在訪問該路由時就會提示資源不存在,而Optional 是可選沒有也可以。

          有了以上配置就可以滿足大部分的路由配置了,我們可以把更多的時間用在Model、View和Controller模塊開發上,MVC 會自動去匹配每一個路由,直到找到匹配的路由并將請求映射到對應的action上,如果沒有找到指定的路由就會彈出404錯誤提示。比如RouteCOnfig.cs中的defaults: new { controller="Home", action="Index", id=UrlParameter.Optional }就告訴我們當我們啟動程序時默認執行HomeController控制器中的Index方法,向用戶展示index.cshtml頁面。如果Controller中不存在對應的控制器和方法時就會報“/”應用程序中的服務器錯誤。

          ?路由特性

          特性路由就是利用特性去定義路由讓你在應用程序中能更好的控制URL,特性路由可以簡化URL和Action之間的映射關系。添加了特性路由后只能通過特性路由設置的路徑訪問,一般我們可以在一個項目中同時使用特性路由和傳統路由兩種技術。要啟用特性路由只需要在RouteConfig.cs路由配置中調用方法:MapMvcAttributeRoutes()即可。

          如何定義特性路由

          特性路由可以通過[Route]和[RoutePrefix]特性來自定義路由,[RoutePrefix]只作用于Controller,當定義了[RoutePrefix]特性時必須定義[Route]特性,此時的接口路由是“協議+IP+Port+RoutePrefix特性+Route特性”,如圖:http://localhost:54639/Test/TestView

          注意:當Action定義了Router特性時Controller中定義的Route特性中的action指向的是Action中的Route特性,而不是Action方法名,也就是說下圖中通過http://localhost:54639/Test/index路由是訪問不到資源的。

          [Route]主要作用于Action路由重寫,當在Action前定義了Route特性時,路由只能通過Route特性中的路由進行資源訪問,如果希望當前Action支持多路由訪問則可以定義多個Route特性。如下圖該方法即可以通過http://localhost:54639/home/test訪問,也可以通過http://localhost:54639/test訪問。

          ? 當[Route]作用于Controller時RouteData 必須包含名為“action”且值為非空的字符串,此時Acion中就可以不用再單獨定義Route特性了。如[Route("Home/{action}")],當我們請求http://localhost:54639/Home/index時系統會自動去尋找符合特性路由[Route("Home/{action}")]下的index方法。

          路由約束

          通過前面的路由配置我們可以實現大部分路由配置了,但仔細查看還是會發現問題,作為路由參數匹配時路由參數會匹配任何非空字符,所以不管是int類型還是string類型都能匹配到當前路由。此時系統發現滿足路由的Acion方法有兩個,這時系統就會將參數作為方法參數傳遞給Action并試圖執行兩個Action方法,此時系統會報錯:當前請求在以下操作方法之間不明確。

          ? 這時我們就可以通過路由約束來進行控制,當路由參數滿足路由約束條件時才匹配該路由并執行相應的Acion方法,當路由參數為int類型時則執行第一條路徑,否則則選擇第二條路線。通過在參數約束后面添加一個問號表示URI參數是可選的,也可以添加等號為其指定默認值。 當然也可以將多個約束應用于一個參數,只要用冒號分隔開即可。

          ? .Net提供了大量的路由約束且默認加載了這些路由約束,當我們使用約束時會去驗證路由參數,通過TryParse()方法對參數嘗試轉換變量并提取參數字符串,返回ture則通過,false則跳過。除了通過使用類型和值約束來約束也可以用正則表達式來約束路由,只有與正則指定的類型匹配才能通過該路由。?

          更多ASP.NET MVC實戰技巧可以參考專欄:ASP.NET MVC實戰系列

          TML 幫助器用于修改 HTML 輸出。


          HTML 幫助器

          通過 MVC,HTML 幫助器類似于傳統的 ASP.NET Web Form 控件。

          就像 ASP.NET 中的 Web Form 控件,HTML 幫助器用于修改 HTML。但是 HTML 幫助器是更輕量級的。與 Web Form 控件不同,HTML 幫助器沒有事件模型和視圖狀態。

          在大多數情況下,HTML 幫助器僅僅是一個返回字符串的方法。

          通過 MVC,您可以創建您自己的幫助器,或者直接使用內建的 HTML 幫助器。


          標準的 HTML 幫助器

          MVC 包含了大多數常用的 HTML 元素類型的標準幫助器,比如 HTML 鏈接和 HTML 表單元素。


          HTML 鏈接

          呈現 HTML 鏈接的最簡單的方法是使用 HTML.ActionLink() 幫助器。

          通過 MVC,Html.ActionLink() 不連接到視圖。它創建一個連接到控制器操作。

          Razor 語法:

          @Html.ActionLink("About this Website", "About")

          ASP 語法:

          <%=Html.ActionLink("About this Website", "About")%>

          第一個參數是鏈接文本,第二個參數是控制器操作的名稱。

          上面的 Html.ActionLink() 幫助器,輸出以下的 HTML:

          <a href="/Home/About">About this Website</a>

          Html.ActionLink() 幫助器的一些屬性:

          屬性描述
          .linkTextURL 文本(標簽),定位點元素的內部文本。
          .actionName操作(action)的名稱。
          .routeValues傳遞給操作(action)的值,是一個包含路由參數的對象。
          .controllerName控制器的名稱。
          .htmlAttributesURL 的屬性設置,是一個包含要為該元素設置的 HTML 特性的對象。
          .protocolURL 協議,如 "http" 或 "https"。
          .hostnameURL 的主機名。
          .fragmentURL 片段名稱(定位點名稱)。

          注釋:您可以向控制器操作傳遞值。例如,您可以向數據庫 Edit 操作傳遞數據庫記錄的 id:

          Razor 語法 C#:

          @Html.ActionLink("Edit Record", "Edit", new {Id=3})

          Razor 語法 VB:

          @Html.ActionLink("Edit Record", "Edit", New With{.Id=3})

          上面的 Html.ActionLink() 幫助器,輸出以下的 HTML:

          <a href="/Home/Edit/3">Edit Record</a>


          HTML 表單元素

          以下 HTML 幫助器可用于呈現(修改和輸出)HTML 表單元素:

          • BeginForm()

          • EndForm()

          • TextArea()

          • TextBox()

          • CheckBox()

          • RadioButton()

          • ListBox()

          • DropDownList()

          • Hidden()

          • Password()

          ASP.NET 語法 C#:

          <%=Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>

          <% using (Html.BeginForm()){%>

          <p>

          <label for="FirstName">First Name:</label>

          <%=Html.TextBox("FirstName") %>

          <%=Html.ValidationMessage("FirstName", "*") %>

          </p>

          <p>

          <label for="LastName">Last Name:</label>

          <%=Html.TextBox("LastName") %>

          <%=Html.ValidationMessage("LastName", "*") %>

          </p>

          <p>

          <label for="Password">Password:</label>

          <%=Html.Password("Password") %>

          <%=Html.ValidationMessage("Password", "*") %>

          </p>

          <p>

          <label for="Password">Confirm Password:</label>

          <%=Html.Password("ConfirmPassword") %>

          <%=Html.ValidationMessage("ConfirmPassword", "*") %>

          </p>

          <p>

          <label for="Profile">Profile:</label>

          <%=Html.TextArea("Profile", new {cols=60, rows=10})%>

          </p>

          <p>

          <%=Html.CheckBox("ReceiveNewsletter") %>

          <label for="ReceiveNewsletter" style="display:inline">Receive Newsletter?</label>

          </p>

          <p>

          <input type="submit" value="Register" />

          </p>

          <%}%>

          . 概述

          介紹asp.net core路由時,我初步想了下,分幾篇來說明。 路由的知識點很多,參考了官方文檔提取出一些重要的知識點來說。 在ASP.NET Core中是使用路由中間件來匹配傳入請求的 URL 并將它們映射到操作(action方法)。路由是在程序啟動時進行傳統路由或屬性路由定義。 路由描述如何將 URL 路徑與操作相匹配。 它還用于在響應中生成送出的 URL(用于鏈接)。

          路由操作既支持傳統路由,也支持屬性路由。也可混合使用。通常傳統路由用于為瀏覽器處理 HTML 頁面的控制器。屬性路由用于處理 web API 的控制器。

          1.1設置路由中間件

          要使用傳統路由,必須在UseMVC中間件中配置實現IRouteBuilder接口,在asp.net core mvc 2.2 框架下,應用程序Startup的Configure 方法中,默認路由設置如下:

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

          在對 UseMvc調用中,MapRoute 用于創建單個路由,亦稱 default 路由。 大多數 MVC 應用使用帶有模板的路由。對于default路由簡便的方法可以使用:

          app.UseMvcWithDefaultRoute();
          

          UseMvc 和 UseMvcWithDefaultRoute 可向中間件管道添加 RouterMiddleware 的實例。 MVC 不直接與中間件交互,而是使用路由來處理請求。 MVC 通過 MvcRouteHandler 實例連接到路由。

          UseMvc 不直接定義任何路由,它向屬性路由的路由集合添加占位符{controller=Home}/{action=Index}/{id?} 。通過重載 UseMvc(Action<IRouteBuilder>) 則允許用戶添加自己的路由,并且還支持屬性路由。

          1.2 傳統路由

          傳統路由是:具有描述性的路由方案,這樣URL具有可讀性。傳統路由格式:{controller=Home}/{action=Index}/{id?}這樣的url路徑是設定了一個約定: 第一段映射到控制器名稱, 第二段映射到操作名稱,第二段映射到可選ID。

          (1) 使用默認路由:

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

          使用此默認路由時: url路徑/Products/List 將映射到程序ProductsController(控制器).List(action)中。 url路徑/Blog/Article/17將映射到程序BlogController(控制器).Article(action)中。

           (2) 多個路由:

          通過添加對 MapRoute 的多次調用,可以在 UseMvc 內添加多個路由。 這樣做可以定義多個約定,或添加專用于特定操作的傳統路由,比如:

          app.UseMvc(routes=>
             {
              routes.MapRoute("blog", "blog/{*article}",
           defaults: new { controller="Blog", action="Article" });
             routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
             });
          

          這里的blog路由是一個專用的傳統路由,這表示blog使用傳統路由系統,但專用于特定的操作,也就是對于BlogController控制器的Article操作,此專用路由將始終映射。對于多個路由的路由集合會進行排序,并按添加順序進行處理,因此,在此示例中,將先嘗試 blog 路由,再嘗試 default 路由。

           (3) action操作的區分

          在處理url請求時,當通過路由匹配到一個控制器內兩項相同的action名稱時,mvc必須進行區分,以選擇最佳候選項,否則會引發異常(AmbiguousActionException)。

          public class ProductsController : Controller
           {
           public IActionResult Edit(int id) { ... }
           [HttpPost]
           public IActionResult Edit(int id, Product product) { ... }
           }
          

          此Products控制器定義了二項操作,這兩項操作均與 URL 路徑的 /Products/Edit/17 匹配相同。解決方案是將要提交的action加上 Http 謂詞為 POST。這樣post過來時,就會選擇Edit(int, Product)

          1.3 屬性路由

          通過在控制器(Controller)或操作(Action)上放置路由可實現屬性路由。 不能通過傳統路由訪問定義屬性路由的操作,反之亦然。 控制器上的任何路由屬性,都會使控制器中的所有操作使用屬性路由。

          屬性路由使用一組屬性將action直接映射到路由模板。在下面的示例中,Configure 方法使用 app.UseMvc();,不傳遞任何路由。 HomeController 將匹配一組 URL,這組 URL 與默認路由 {controller=Home}/{action=Index}/{id?} 匹配的 URL 類似:

          當去掉default默認路由模板后,只使用app.UseMvc()時。運行程序時,頁面報404錯誤:找不到 localhost 的網頁。

           app.UseMvc();
          

          (1) 屬性路由基本使用 

          如果定義了屬性路由的操作,此時就是啟動屬性路由功能。Home控制器的屬性路由示例如下:

          public class HomeController : Controller
           {
           [Route("")]
           [Route("Home")]
           [Route("Home/Index")]
           public IActionResult Index()
           {
           return View();
           }
           }
          

          在index的action上加[Route("")]屬性路由。 瀏覽器可以使用下面三種url來訪問,也是程序啟動時的默認加載頁面:

          http://localhost:30081/

          http://localhost:30081/Home/

          http://localhost:30081/Home/index

          (2) 屬性路由精確控制

          屬性路由需要更多輸入來指定路由;傳統的默認路由處理路由的方式則更簡潔。 但是,屬性路由允許(并需要)精確控制應用于每項操作的路由模板。下面示例是精確控制每項操作的路由模板,比如url訪問/home/index時,即是調用MyIndex的action方法。

          public class MyDemoController : Controller
           {
           [Route("")]
           [Route("Home")]
           [Route("Home/Index")]
           public IActionResult MyIndex()
           {
           return View("Index");
           }
           }
          

          1.4 使用 Http[Verb] 屬性的屬性路由

          屬性路由還可以使用 Http[Verb] 屬性,比如 HttpPostAttribute。 所有這些屬性都可采用路由模板。 此示例展示,同一路由模板匹配的兩項操作:

          [HttpGet("/products")]
           public IActionResult ListProducts()
           {
           // ...
           }
           [HttpPost("/products")]
           public IActionResult CreateProduct(...)
           {
           // ...
           }
          

          當 Http 謂詞為 GET 時將執行ProductsApi.ListProducts 操作, 當 Http 謂詞為 POST 時將執行 ProductsApi.CreateProduct。生成 REST API 時,很少會在操作方法上使用 [Route(...)]。 建議使用更特定的 Http*Verb*Attributes 來明確 API 所支持的操作。 REST API 的客戶端需要知道映射到特定邏輯操作的路徑和 Http 謂詞。

          例如下面一個web api訪問路由,使用Http*Verb*Attributes 來明確定義如下:

           public class ProductsApiController : Controller
           {
           [HttpGet("/products/{id}", Name="Products_List")]
           public IActionResult GetProduct(int id) { ... }
           }
          

          上面定義只有針對如訪問url如: /products/3(而非 /products)之類的 URL才會執行 ProductsApi.GetProduct(int) 操作。

          1.5 路由合并

          若要使屬性路由減少重復,可將控制器Controller上的路由屬性與各個操作Action上的路由屬性合并。 控制器上定義的所有路由模板均作為操作上路由模板的前綴。 在控制器上放置路由屬性會使控制器中的所有操作都使用屬性路由。

          下面是一個web api的路由合并,訪問Get的方法的訪問路徑為: http://localhost:30081/api/Products/1

          [Route("api/Products")]
           public class ProductsApiController : Controller
           {
           // GET api/values/5
           [HttpGet("{id}")]
           public string Get(int id)
           {
           return "value";
           }
           }
          

          下面是一個控制器的路由合并。訪問index頁面的訪問路徑為: http://localhost:30081/home/index

           [Route("Home")]
            public class HomeController : Controller
            {
           [Route("")] // Combines to define the route template "Home"
           [Route("Index")] // Combines to define the route template "Home/Index"
           [Route("/")] // Doesn't combine, defines the route template ""
           public IActionResult Index()
           {
           //...
           }
            }
          

          1.6 指定屬性路由參數約束

           [HttpGet("Home/{id:int}",Name="Pri")]
           public IActionResult Privacy(int id)
           {
           return View();
           }
          

          如果輸入非整數類型的參數,瀏覽器提示:找不到與以下網址對應的網頁:http://localhost:30081/home/dd

          1.7 自定義路由屬性

          該框架中提供的所有路由屬性([Route(...)]、[HttpGet(...)] 等)都可實現 IRouteTemplateProvider接口。 當應用啟動時,MVC 會查找控制器類和操作方法上的屬性,并使用可實現 IRouteTemplateProvider的屬性生成一組初始路由。

          下面使用IRouteTemplateProvider 來定義自己的路由屬性。每個 IRouteTemplateProvider 都允許定義一個包含自定義路由模板、順序和名稱的路由:

           public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider
           {
           //實現接口的三個屬性,這里的[controller]是一個標記替換。
           public string Template=> "api/[controller]/{action}/{id?}";
           public int? Order { get; set; }
           public string Name { get; set; }
           } 
           public class ProductsApiController : Controller
           {
           // GET api/values/5
           // [HttpGet("{id}")]
           [MyApiController()]
           public string Get(int id)
           {
           return "value";
           }
           }
          

          通過訪問url: http://localhost:30081/api/ProductsApi/get/1 來調用get方法。

          參考文獻

          官方資料:asp.net core routing

          歡迎添加個人微信號:Like若所思。

          歡迎關注我的公眾號,不僅為你推薦最新的博文,還有更多驚喜和資源在等著你!一起學習共同進步!


          主站蜘蛛池模板: 国产成人精品一区在线| 日本一区免费电影| 精品亚洲A∨无码一区二区三区 | 精品一区二区三区中文| 99精品一区二区免费视频| 78成人精品电影在线播放日韩精品电影一区亚洲 | 成人毛片无码一区二区| 日韩一区二区免费视频| 丝袜人妻一区二区三区网站| 在线播放精品一区二区啪视频| 精品日产一区二区三区手机| 一区二区免费视频| 久久免费国产精品一区二区| 国产精品99精品一区二区三区| 国产探花在线精品一区二区| 一区二区三区四区电影视频在线观看| 在线播放偷拍一区精品| 亚洲综合av一区二区三区| 国产人妖视频一区二区破除| 国产乱码精品一区二区三区四川人 | 国产精品合集一区二区三区| 国产精品福利区一区二区三区四区| 国语精品一区二区三区| 亚洲日韩一区精品射精| 成人区精品人妻一区二区不卡| 午夜视频在线观看一区二区| 国产日韩精品一区二区在线观看| 性色AV一区二区三区| 无码人妻一区二区三区在线 | 美女福利视频一区二区| 国产a久久精品一区二区三区| 国产激情无码一区二区app| 一区二区三区无码视频免费福利| 国产一区二区免费视频| 亚洲综合色一区二区三区| 日本一区午夜爱爱| 秋霞无码一区二区| 视频一区在线免费观看| 亚洲国产一区二区三区青草影视 | 99偷拍视频精品一区二区| 精品无人乱码一区二区三区|