• [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 > 12return false;
                        
    if(day<1)return false;
                        
    switch (month)
                        {
                            
    case 1:
                            
    case 3:
                            
    case 5:
                            
    case 7:
                            
    case 8:
                            
    case 10:
                            
    case 12:
                                
    if (day< 32return true;
                                
    break;
                            
    case 2:
                                
    if (day < 29return true;
                                
    break;
                            
    case 4:
                            
    case 6:
                            
    case 9:
                            
    case 11:
                                
    if(day<31return 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源代码

  • 相关阅读:
    外部排序
    oceanbase tpcc 关键总结
    TPCC测试
    最简单的oracle 19c安装教程
    unix进程环境
    tars以docker方式安装
    异常安全的赋值运算符函数
    linux 定时器setitimer使用
    libevent学习-reactor设计模式及代码示例
    linux中可执行程序搜索动态链接库的顺序
  • 原文地址:https://www.cnblogs.com/jasenkin/p/mvc_custom_contraints.html
Copyright © 2020-2023  润新知