ASP.NET MVC 之如何创建自定义路由约束
本文将讲解如何创建一个路由约束以及创建一个自定义路由约束创建一个路由约束(C#)
你能够使用路由约束来限制匹配一个特殊路径的浏览器请求。你能够使用一个正则表达式来制定一个路由约束。
例如,假设你已经定义路由如下:
Listing 1 - Global.asax.cs
程序代码:
routes.MapRoute( "Product", "Product/{productId}", new {controller="Product", action="Details"} );
Listing 1 包含一个命名为Product的路由. 你能够使用这个 Product route来将将浏览器请求映射到ProductController,如下:
Listing 2 - Controllers\ProductController.cs
程序代码:
using System.Web.Mvc; namespace MvcApplication1.Controllers { public class ProductController : Controller { public ActionResult Details(int productId) { return View(); } } }
注意:Details() action 接收一个命名为 productId的单一参数. 这个参数是整型参数.
在Listing 1 will中定义的route将匹配一下的任何一个URLs:
?/Product/23
?/Product/7
遗憾的,这个route也同样匹配以下的URLs:
?/Product/blah
?/Product/apple
因为Details() action预期接收一个整型的参数,当请求中包含的内容不同于整数时,它将导致一个错误。
你真正想要做的,仅仅是匹配包含一个的整数productId的URLs。当你定义一个route时,你能够使用一个限制条件来限制URLs,使它匹配这个route。在Listing 3中,这个route包含一个只匹配整数的正则表达式约束。
Listing 3 - Global.asax.cs
程序代码:
routes.MapRoute( "Product", "Product/{productId}", new {controller="Product", action="Details"}, new {productId = @"\d+" } );
这个真正表达式约束\d+ 匹配一个或多个整数. 这个约束导致Product route匹配如下的URLs:
?/Product/3
?/Product/8999
但不是如下的URLs:
?/Product/apple
?/Product
这个浏览器请求将被另一个route处理。或者,如果没有匹配的routes, “The resource could not be found ”错误将被返回.
创建一个自定义路由约束 (C#)
演示如何创建一个自定义的路由约束.约束接口中的Match方法如下:
程序代码:
IRouteConstraint.Match Method bool Match( HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection )
你可以通过实现IRouteConstraint接口来创建一个路径约束,并且通过几个步骤把它添加到你的路径中。IRouteConstraint仅有一个Match方法,它返回一个布尔值。这个布尔值决定该请求是否应该被route对象处理。
如何创建一个 MVC应用程序来模拟一个仅仅在视图中显示年份,月份,日期的文章系统,类似于博客系统的路径?
(一)首先,创建一个ArchiveController,它包含一个仅仅显示年份,月份,日期值的Index action 方法。
程序代码:
namespace MvcAppRouting.Controllers { public class ArchiveController : Controller { // // GET: /Archive public ActionResult Index(int year, int month, int day) { ViewData["Year"] = year; ViewData["Month"] = month; ViewData["Day"] = day; return View(); } } }
(二)创建一个显示数据的view。
程序代码:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Index </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>Index</h2> <fieldset> <legend>Fields</legend> <p>Year: <%= ViewData["Year"] %> </p> <p> Month: <%= ViewData["Month"]%> </p> <p> Day: <%= ViewData["Day"]%></p> </fieldset> </asp:Content>
(三)最主要的步骤,需要创建年份,月份,日期验证的三个分离的约束。它们将在路径定义中应用。以创建一个DayConstraint来开始。
程序代码:
using System.Web.Routing; using System.Globalization; namespace MvcAppRouting.RouteConstraints { public class DayConstraint:System.Web.Routing.IRouteConstraint { public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { if ((routeDirection == RouteDirection.IncomingRequest) && (parameterName.ToLower(CultureInfo.InvariantCulture) == "day")) { try { int month = int.Parse(values["Month"].ToString()); int day = int.Parse(values["Day"].ToString()); if (month <= 0 || month > 12) return false; if(day<1)return false; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: if (day< 32) return true; break; case 2: if (day < 29) return true; break; case 4: case 6: case 9: case 11: if(day<31) return true; break; } } catch { return false; } } return false; } } }
年份数据限制为1950-2010。同样,月份的值在1-12之间,此处不再叙述。
(四)最后一步是将所有的联系在一起,使 MVC 应用程序能够运行。这里仅仅是定义一个routes。
程序代码:
namespace MvcAppRouting { // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明, // 请访问 <span style="color: #008000; text-decoration: underline;">http://go.[/color] public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // 路由名称 "{controller}/{action}/{id}", // 带有参数的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值 ); routes.MapRoute( "Archive", "archive/{year}/{month}/{day}", new { controller = "Archive", action = "Index", year = "", month = "", day = "" }, new { year = new RouteConstraints.YearConstraint(), month = new RouteConstraints.MonthConstraint(), day = new RouteConstraints.DayConstraint() } ); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); } } }
实例中的“archive/{year}/{month}/{day}”模式,像正常的routes一样,同样为route设置了默认的值,并且增加了一个约束对象。这个约束对象将模式中的参数映射至它的约束实例中,因此这些值能够被验证。
现在我用一个验证的请求模式来运行这个应用程序,展示的页面如下。
总结:
应该注意约束条件必须继承IRouteConstraint,并且实现Match方法。
《转自独上高楼》