這篇關於MVC路由及視圖規則本來是昨天要發的,但是本人真的有點懶,終於今天忍無可忍了。初學MVC的時候比現在還菜一點(現在也很菜),想著會用就行,但是有時還是會好奇,為什麼它能找到控制器?為什麼控制器return View();就能找到視圖,而為什麼視圖一定要建在Views文件下?好像說的有點多了, ...
這篇關於MVC路由及視圖規則本來是昨天要發的,但是本人真的有點懶,終於今天忍無可忍了。初學MVC的時候比現在還菜一點(現在也很菜),想著會用就行,但是有時還是會好奇,為什麼它能找到控制器?為什麼控制器return View();就能找到視圖,而為什麼視圖一定要建在Views文件下?好像說的有點多了,接下來一邊上例子,一邊分析!
MVC路由自定義
相信對於MVC路由的配置大家也都瞭解過一些,其實,這也不是本章的重點。
創建MVC項目的時候,根目錄下>>App_Start>>RouteConfig,這個類就是用來配置路由的,開始會有個預設路由。
簡單介紹下:第一個參數:路由名稱(唯一),第二個參數url:需要註意的是{controller}、{action}都是相當於占位符。第三個參數則是預設路由了。
場景:當你的控制器需要根據不同功能來分類時,假如你需要做不同產品,希望把同一產品的控制器放在一起。你可以這樣做:
添加一條路由規則:
1 public static void RegisterRoutes(RouteCollection routes) 2 { 3 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 4 routes.MapRoute( 5 name: "Product", 6 url: "Product/AboutPrice/{controller}/{action}/{id}", 7 defaults: new { controller = "Sale", action = "Index", id = UrlParameter.Optional } 8 ); 9 10 routes.MapRoute( 11 name: "Default", 12 url: "{controller}/{action}/{id}", 13 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 14 ); 15 }
註意點:路由規則匹配是從上到下的,優先匹配的路由一定要寫在最上面。因為路由匹配成功以後,它就不會繼續匹配下去。當然我們創建的控制器目錄也得符合才能匹配。
結果:
MVC視圖找尋規則
在上面那部分即使我們自定義了路由,但是視圖創建的位置還是得乖乖放在Views文件夾下,(不然的話,結果肯定是找不到視圖)我們同樣也希望View位置是可配。
希望控制器返回的視圖能在這個目錄下:
①首先,需要寫一個類來自定義我們視圖的映射規則,這裡我就建在App_Start文件夾下,跟其他配置類一起。
1 public sealed class MyViewRule:RazorViewEngine 2 { 3 public MyViewRule() { 4 5 ViewLocationFormats = new string[] { 6 //我們定義的視圖找尋規則,和路由配置一樣,它是從上往下匹配,如果兩個路徑下都有著視圖,它會展示第一個。 7 "~/ProductViews/AboutPrice/{1}/{0}.cshtml", 8 //這是預設設置的,覺得用不到可以刪掉,{1}表示控制器名稱,{0}表示視圖名稱 9 "~/Views/{1}/{0}.cshtml", 10 "~/Views/Shared/{0}.cshtml" 11 }; 12 }
13 }
②然後,需要在全局Global.asax.cs裡面註冊我們的規則,代碼如下:
1 public class MvcApplication : System.Web.HttpApplication 2 { 3 protected void Application_Start() 4 { 5 AreaRegistration.RegisterAllAreas(); 6 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 7 RouteConfig.RegisterRoutes(RouteTable.Routes); 8 BundleConfig.RegisterBundles(BundleTable.Bundles); 9 //上面是項目創建預設註冊的,下麵兩條:先把原來的規則清空,再把我們設置加上() 10 ViewEngines.Engines.Clear(); 11 ViewEngines.Engines.Add(new MyViewRule()); 12 } 13 }
測試結果:
錯誤:The view at '~/ProductViews/AboutPrice/Sale/Index.cshtml' must derive from WebViewPage, or WebViewPage<TModel>.
大概意思是:沒有繼承這個WebViewPage類,在編譯的時候,這個視圖頁面也是會生成一個類的,解決的辦法有兩種:
①直接讓它繼承那個類(@inherits System.Web.Mvc.WebViewPage)
1 @{ 2 Layout = null; 3 } 4 @inherits System.Web.Mvc.WebViewPage 5 <!DOCTYPE html> 6 7 <html> 8 <head> 9 <meta name="viewport" content="width=device-width" /> 10 <title>Index</title> 11 </head> 12 <body> 13 <div> 我視圖位置不一樣的哦! 14 </div> 15 </body> 16 </html>
當然,上面這個辦法,有個不好的地方就是每次添加一個視圖就得寫一次,視圖多的話極不方便。我們還可以通過配置文件讓它繼承WebViewPage
②添加配置文件(web.config),在pages節點下繼承WebViewPage。或者在預設創建Views文件夾下有個Web.config複製到/ProductViews/AboutPrice下。(局部配置文件,就近原則)
<pages pageBaseType="System.Web.Mvc.WebViewPage"> </pages>
結果:
總結
關於MVC怎麼找到控制器,控制器怎麼匹配視圖希望能給有需要的小伙伴一點幫助,也是自己的一個總結,不妥之處,歡迎指正。
程式員在學習的路上永遠不要怕遇到問題,這是成長,也是一種鍛煉,在這個極其需要經驗的行業,倒下的是那些渾渾噩噩度。遇到問題,努力解決,總有柳暗花明時,那時是滿足的喜悅,共勉!