理解預設路由表
當你建立一個新的ASP.NET MVC應用程式時,應用程式已經被設定為使用ASP.NET路由.ASP.NET路由在兩個地方設定。
第一點,在你的應用程式的Web設定檔(Web.config檔檔)中啟用ASP.NET路由在設定檔中有四個節點與路由有關: sytem.web.httpModules節,system.web.httpHandlers節,system.webserver.modules節,以及system.webserver.handlers節。特別要小心不要刪除了這些節點,因為沒有它們路由將無法運作。
第二點,也是更重要的一點,在應用程式的Global.asax中檔案中建立了一個路由表.Global.asax檔案是一個特殊的文件,它包含了作用於ASP. NET應用程式生命週期事件的事件處理程序。路由表在應用程式開始事件期間建立。
程式碼清單1中的檔案包含了一個ASP.NET MVC應用程式的預設Global.asax檔。
程式碼清單1 - Global.asax.cs
使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Web; 使用 System.Web.Mvc; 使用 System.Web.Routing; 命名空间 MvcApplication1 { //注意:有关启用IIS6或IIS7经典模式的说明, 请访问http://go.microsoft.com/?LinkId=9394801 public class MvcApplication:System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection路由) { routes.IgnoreRoute( “{resource} .axd / {* pathInfo}”); 路线。 MapRoute( “Default”, // Route name “{controller} / {action} / {id}”, //具有参数 的URL new {controller = “Home”,action =“Index”,id =“” } //参数默认值 ); } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } } } //具有参数的URL new {controller = “Home”,action =“Index”,id =“” } //参数defaults); } protected void Application_Start(){RegisterRoutes(RouteTable.Routes); }}} //具有参数的URL new {controller = “Home”,action =“Index”,id =“” } //参数defaults); } protected void Application_Start(){RegisterRoutes(RouteTable.Routes); }}} } protected void Application_Start(){RegisterRoutes(RouteTable.Routes); }}} } protected void Application_Start(){RegisterRoutes(RouteTable.Routes); }}}
當一個MVC應用程式首次執行時,會呼叫的Application_Start()方法。這個方法隨後調用了的RegisterRoutes()方法.RegisterRoutes()方法創建了路由表。
預設的路由表包含了一個路由(名叫預設).DEFAULT路由將URL的第一部分對應到控制器名,URL的第二部分對應到控制器動作,第三個部分映射到一個叫做ID的參數。
假設你在瀏覽器的網址列輸入了下面的網址:
/首頁/索引/ 3
#預設的路由將這個URL對應為下面的參數:
控制器=首頁
Action = Index
id = 3
當你要求URL /首頁/索引/ 3時,將會執行下面的程式碼:
HomeController.Index(3)
預設路由包含了所有三個參數的預設值。如果你不提供控制器,那麼控制器參數預設值為首頁。如果你不提供動作,動作參數預設為值指標。最後,如果你不提供ID,ID參數預設為空字串。
讓我們來看看幾個例子,預設路由是如何將URL對應到控制器動作的設想你在瀏覽器網址列輸入了下面的網址:
/家
由於預設路由參數的預設值,輸入這個網址將會呼叫代碼清單2中的HomeController的類別的指數()方法。
程式碼清單2 - HomeController.cs
使用 System.Web.Mvc; 命名空间 MvcApplication1.Controllers { [HandleError] public class HomeController:Controller { public ActionResult Index(string id) { return View(); } } }
在程式碼清單2中,HomeController類別包含了一個叫做Index()的方法,它接受一個叫做Id的參數.URL / Home將會導致呼叫Index()方法,並使空字串作為Id參數的值。
出於MVC框架呼叫控制器動作的方式,URL / Home也符合程式碼清單3中HomeController類別的索引()方法。
程式碼清單3 - HomeController.cs(不含參數的索引動作)
使用 System.Web.Mvc; 命名空间 MvcApplication1.Controllers { [HandleError] public class HomeController:Controller { public ActionResult Index() { return View(); } } }
程式碼清單3中的Index()方法不接受任何的參數.URL / Home將會導致調用這個Index()方法.URL / Home / Index / 3也會呼叫這個方法(Id被忽略)。
URL / Home也會符合程式碼清單4中HomeController類別的索引()方法。
程式碼清單4 - HomeController.cs(使用可空參數的索引動作)
使用 System.Web.Mvc; 命名空间 MvcApplication1.Controllers { [HandleError] public class HomeController:Controller { public ActionResult Index(int?id) { return View(); } } }
在程式碼清單4中,索引()方法擁有一個整數參數。因為這個參數是一個可空參數(可以擁有空值),因此可以呼叫指數()而不會引發錯誤。
最後,使用URL / Home呼叫程式碼清單5中的Index()方法將會引發一個異常,因為Id參數並非一個可空參數。如果你試著呼叫Index()方法,那麼你將會得到一個圖1所示的錯誤。
程式碼清單5 - HomeController.cs(含有Id參數的索引動作)
使用 System.Web.Mvc; 命名空间 MvcApplication1.Controllers { [HandleError] public class HomeController:Controller { public ActionResult Index(int id) { return View(); } } }
#圖01:呼叫一個期望參數值的控制器動作
另一方面,URL / Home / Index / 3能夠與程式碼清單5中的索引控制器動作很好地工作./Home/Index/3請求將會引發呼叫含有一個Id的索引()方法,且該Id值為3。
這篇教學的目的是要為你提供一個ASP.NET路由的簡短介紹。我們仔細查看了預設的路由表,它在你建立新的ASP.NET MVC應用程式時獲得。你學習了預設的路由表如何將URL映射到控制器動作。
2.创建自定义路由
在这篇教程中,你会学习到如何为ASP.NET MVC应用程序添加自定义路由。你会学习如何将Global.asax文件中的默认路由表修改为自定义路由。
对于简单的ASP.NET MVC应用程序,默认的路由表已经可以很好的完成工作了。然而,你可以发现会存在特定的路由需求在这种情况下,你可以创建一个自定义路由。
设想一下,举个例子,你正在创建一个博客应用程序你可能想要像这样处理即将到来的请求:
/存档/ 2009年12月25日
当用户输入这一请求,你想要返回对应于日期2009年12月25日的博客条目。为了处理这种类型的请求,你需要创建一个自定义路由。
代码清单1中的Global.asax包含了一个新的自定义路由,命名为了博客,它处理了类似/存档/条目日期这样的请求。
代码清单1 - Global.asax(含有自定义路由)
使用 System.Web.Mvc; 使用 System.Web.Routing; 命名空间 MvcApplication1 { public class MvcApplication:System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute(“{resource} .axd / {* pathInfo}”); routes.MapRoute( “Blog”, //路由名称 “Archive / {entryDate}”, //具有参数 的URL new {controller = “Archive”,action =“ } //参数defaults ); routes.MapRoute( “Default”,//路由名称 “{controller} / {action} / {id}”,//具有参数 的URL new {controller = “Home”,action =“Index”,id =“” } //参数defaults ); } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } } } } //参数defaults); routes.MapRoute(“Default”,//路由名称“{controller} / {action} / {id}”,//具有参数的URL new {controller = “Home”,action =“Index”,id =“” } //参数defaults); } protected void Application_Start(){ RegisterRoutes(RouteTable.Routes); } } } ,//路由名称“{controller} / {action} / {id}”,//具有参数的URL new {controller = “Home”,action =“Index”,id =“” } //参数defaults); } protected void Application_Start(){ RegisterRoutes(RouteTable.Routes); } } } , //路由名称“{controller} / {action} / {id}”, //具有参数的URL new {controller = “Home”,action =“Index”,id =“” } //参数defaults); } protected void Application_Start(){ RegisterRoutes(RouteTable.Routes); } } } //具有参数的URL new {controller = “Home”,action =“Index”,id =“” } //参数defaults); } protected void Application_Start(){ RegisterRoutes(RouteTable.Routes); } } } //具有参数的URL new {controller = “Home”,action =“Index”,id =“” } //参数defaults); } protected void Application_Start(){ RegisterRoutes(RouteTable.Routes); } } }
添加到路由表中的路由顺序非常重要。我们的新自定义博客路由在现有的默认路由前面。如果你将这个顺序颠倒过来,那么默认路由将总是被调用,而不是自定义路由。
自定义博客路由匹配任何以/存档/作为开始的请求因此,它匹配所有下面的网址:
/存档/ 2009年12月25日
/存档/ 2004年10月6日
/存档/苹果
自定义路由将即将到来的请求映射到名为存档的控制器,并且调用了条目()动作。当调用项()方法时,条目日期作为entryDate参数进行了传递。
代码清单2 - ArchiveController.cs
使用系统; 使用 System.Web.Mvc; 命名空间 MvcApplication1.Controllers { public class ArchiveController:Controller { public string Entry(DateTime entryDate) { return “您从” + entryDate.ToString())请求了条目。 } } }
注意到代码清单2中的条目()方法接受一个日期时间类型的参数.MVC框架非常的聪明,足以自动地将URL中的条目日期转换为日期时间值。如果URL中的条目日期参数不能转换为日期时间,将会引发错误(如图1)。
图1 - 转换参数时的错误
这篇教程的目的是演示如何创建自定义路由。你学习了如何在Global.asax中文件的路由表中添加自定义路由,该路由代表着博客条目。我们讨论了如何将对博客条目的请求映射到名为ArchiveController的控制器,和名为项()的控制器动作上。
3.创建路由约束
你可以使用路由约束来限制匹配特定路由的浏览器请求。可以使用正则表达式来指定一个路由约束。
举个例子,假设你已经在Global.asax中文件中定义了一个路由。
代码清单1 - Global.asax.cs
routes.MapRoute( “Product”, “Product / {productId}”, new {controller =“Product”,action =“Details”} );
代码清单1包含一个叫做产品的路由。你可以使用产品路由将浏览器请求映射到代码清单2中的ProductController的。
代码清单2 - Controllers \ ProductController.cs
使用 System.Web.Mvc; 命名空间 MvcApplication1.Controllers { public class ProductController:Controller { public ActionResult Details(int productId) { return View(); } } }
注意到产品控制器公布的详细信息()动作接受一个叫做的productId的参数。这个参数是一个整数参数。
定义在代码清单1中的路由将会匹配下面的任意网址:
/产品/ 23 /产品/ 7 不幸的是,路由也会匹配下面的网址: /产品/嗒嗒 /产品/苹果
因为详细()动作期望的是一个整数值,发起一个含有非整数值的请求将会导致错误。举个例子,如果你在浏览器中输入/产品/苹果网址,那么你将会得到图1所示的错误页。
图1:错误页
你实际想做的是只匹配包含合适整数productId参数的URL。当定义路由来限制与路由相匹配的网址时,你可以使用约束。代码3中的修改后的产品路由包含了一个正则表达式,它限制了只匹配数字。
代码清单3 - Global.asax.cs
routes.MapRoute( “Product”, “Product / {productId}”, new {controller =“Product”,action =“Details”}, new {productId = @“\ d +”} )
正则表达式\ D +匹配一个或多个整数这个限制使得产品路由匹配了下面的网址:
/产品/ 3 /产品/ 8999 但是不匹配下面的网址: /产品/苹果 /产品
这些浏览器请求将自由另外的路由处理,或者,如果没有匹配的路由,将会返回一个“资源找不到”错误。
创建一个自定义路由约束
这篇教程的目标是演示如何创建一个自定义路由约束。自定义路由约束允许你阻止某个路径被匹配,除非满足一些自定义的条件。
在这篇教程中,我们创建了一个本地主机路由约束.Localhost路由约束只匹配本地计算机发出的请求。通过互联网发出的远程请求不会被匹配。
。你可以通过实现IRouteConstraint接口来实现一个自定义路由这是一个极其简单的接口,它只描述了一个方法:
bool Match( HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary值, RouteDirection routeDirection )
这个方法返回一个布尔值。如果返回了假,与约束相关联的路由将不会匹配浏览器请求。
本地主机约束包含在了代码清单1中。
代码清单1 - LocalhostConstraint.cs
使用 System.Web; 使用 System.Web.Routing; 命名空间 MvcApplication1.Constraints { public class LocalhostConstraint:IRouteConstraint { public bool Match ( HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection ) { return httpContext.Request.IsLocal; } } }
代码清单1中的约束利用了HttpRequest的类公布的IsLocal属性。当发出请求的IP地址是127.0.0.1或者与服务器的IP地址相同时,这个属性返回真。
你在定义于Global.asax中的路由中使用了自定义约束。代码清单2中的Global.asax中文件使用了本地主机约束来阻止任何人请求管理员页面,除非他们从本地服务器发出请求。举个例子,当请求来自远程服务器时,对于/管理/ DeleteAll的请求将会失败。
代码清单2 - Global.asax
使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Web; 使用 System.Web.Mvc; 使用 System.Web.Routing; 使用 MvcApplication1.Constraints; 命名空间 MvcApplication1 { public class MvcApplication:System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes){ routes.IgnoreRoute( “{resource} .axd / {* pathInfo}”); routes.MapRoute( “Admin”, “Admin / {action}”, isLocal = new LocalhostConstraint()} ); //routes.MapRoute( // “默认”,//路线名称 // “{控制器} / {行动} /(编号)”,// URL与参数 // 新 {控制器= “主页”,动作=“索引“,id =”“ } //参数defaults //); } protected void Application_Start(){ RegisterRoutes(RouteTable.Routes); } } }
本地主机约束使用在了管理路由的定义中这个路由不会被远程浏览器请求所匹配然而,应该意识到定义在Global.asax中中的其他路由可能会匹配相同的请求理解这一点很重要。:约束阻止了特定路由匹配某一请求,而不是所有定义在Global.asax中文件中的路由。
注意到默认路由在代码清单2中的Glabal.asax文件中被注释掉了。如果你包含默认路由,那么默认路由将会匹配对管理控制器的请求。在这种情况下,远程用户仍然可以调用管理控制器的动作,即使他们的请求不匹配管理路由。
【相关推荐】
1. 什么是ASP.NET MVC ?总结ASP.NET MVC
2. 详细介绍ASP.NET MVC--控制器(controller)
5. 通过asp.net mvc开发微信自定义菜单编辑工具的代码示例
以上是詳細介紹ASP.NET MVC--路由的詳細內容。更多資訊請關注PHP中文網其他相關文章!