[ASP.NET MVC2 系列] ASP.NET MVC 之如何创建自定义路由约束

 [ASP.NET MVC2 系列] 
     [ASP.NET MVC2 系列] ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》 
     [ASP.NET MVC2 系列] ASP.Net MVC教程之《ASP.NET MVC 概述》
     [ASP.NET MVC2 系列] 理解MVC应用程序的执行过程
     [ASP.NET MVC2 系列] ASP.NET MVC Routing概述 
     [ASP.NET MVC2 系列] ASP.NET MVC 之如何创建自定义路由约束 
     [ASP.NET MVC2 系列] Action要求与View本质
     [ASP.NET MVC2 系列] Action Filters以及自定义OutputCache ActionFilterAttribute事件发生次序

 

创建一个路由约束(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对象处理。

 

如何创建一个ASP.NET 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之间,此处不再叙述,详见源代码。

 

(四)最后一步是将所有的联系在一起,使ASP.NET MVC 应用程序能够运行。这里仅仅是定义一个routes。


namespace  MvcAppRouting
{
    
//  注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
    
//  请访问  http://go.microsoft.com/?LinkId=9394801

    
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设置了默认的值,并且增加了一个约束对象。这个约束对象将模式中的参数映射至它的约束实例中,因此这些值能够被验证。

现在我用一个验证的请求模式来运行这个应用程序,展示的页面如下。

 

 

同样,发送一个archive/2000/2/30这个请求,它是不能通过验证,并且得到一个错误。

 

总结:
应该注意约束条件必须继承IRouteConstraint,并且实现Match方法。

 

源代码下载: MvcAppRouting源代码

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值