路由

http://www.cnblogs.com/artech/archive/2012/03/20/aspnet-routing-02.html

RouteTable<System.Web.Routing.RouteTable>

        Routes<RouteCollection>

               MapPageRoute()(其实就是添加一个Route:RouteBase对象)//可将一个ASPX页面映射到路由虚拟路径

               GetRouteData()//返回有关集合中与指定值匹配的路由的信息。

               GetVirtualPath()//如果具有指定的上下文和参数值,则返回与路由关联的 URL 路径的相关信息。

               Ignore()       //定义不需检查是否匹配路由的 URL 模式。

               RouteExistingFiles  //对已存在的文件和文件夹是否启用路由,大家千万不要忘记还有文件夹这个检查,同时文件和文件夹的检查结果默认是启用了缓存的。

               AppendTrailingSlash    //获取或设置指示的 value 尾部的反斜杠是否添加,在虚拟路径进行规范化时。

               LowercaseUrls  //获取或设置指示的 value URL 是否转换为小写,在虚拟路径进行规范化时。

RouteBase  //匹配路由表类的基类  子类Route

        GetRouteData   //匹配成功返回一个RouteData

        GetVirtualPath //如果匹配成功返回一个 替换了URL模板 的封装对象VirtualPathData

RouteData      (Page.RouteData只读对象)

        Values<RouteValueDictionary>//保存路由变量的字典  一般有"controller"和"action"KEY

        DataTokens  //附加到路由对象上的自定义变量   额外变量 , 一般用于存取命名空间   对应的Key为"Namespace" 

               /{filename}/{*pathinfo}

               /abc/ccc/ddd           DataTokens  (ccc/ddd)

        IRouteHandler

               GetHttpHandler

约束  正则表达式/IRouteConstraint 接口

IRouteConstraint  实现类HttpMethodConstraint

ASP.NET路由系统的应用编程接口中定义了如下一个实现了IRouteConstraint接口的HttpMethodConstraint类型。顾名思义,HttpMethodConstraint提供针对HTTP方法(GET、POST、PUT、DELTE等)的约束。我们可以通过HttpMethodConstraint为路由对象设置一个允许的HTTP方法列表,只有方法名称在这个指定的列表中的HTTP请求才允许被路由。这个被允许被路由的HTTP方法列表对于HttpMethodConstraint的只读属性AllowedMethods,并在构造函数中初始化。

   1: public class Global : System.Web.HttpApplication

   2: {

   3:     protected void Application_Start(objectsender, EventArgs e)

   4:     {

   5:         var defaults = newRouteValueDictionary { { "areacode", "010" }, {"days", 2 } };

   6:         var constaints = newRouteValueDictionary { { "areacode", @"0\d{2,3}" }, {"days", @"[1-3]{1}" }, { "httpMethod", newHttpMethodConstraint("POST") } };

   7:         var dataTokens = newRouteValueDictionary { { "defaultCity", "BeiJing" }, {"defaultDays", 2 } };

   8:         

   9:        RouteTable.Routes.MapPageRoute("default","{areacode}/{days}", "~/weather.aspx", false, defaults,constaints, dataTokens);

  10:     }

  11: }

对现有文件的路由

var defaults = new RouteValueDictionary { { "areacode","010" }, { "days", 2 }};

var dataTokens = new RouteValueDictionary { { "defaultCity","BeiJing" }, { "defaultDays", 2 } };

RouteTable.Routes.MapPageRoute("default","{areacode}/{days}", "~/weather.aspx", false, defaults,null, dataTokens);

注册路由忽略地址

如果将代表全局路由表的RouteTable的静态属性Routes的RouteExistingFiles属性设置为True,意味着ASP.NET针对所有抵达的请求都一视同仁,都按照注册的路由表进行注册。都按照注册的路由表进行注册,但这会代码一些问题。CSS文件的请求也被路由  直接请求文件变成了 请求weather.aspx的路由。

我们可以通过调用RouteCollection的Igore方法来注册一些需要让路由系统忽略的URL模板

RouteTable.Routes.RouteExistingFiles = true;

RouteTable.Routes.Ignore("{filename}.js/{*pathInfo}");

直接添加路由对象

var defaults = new RouteValueDictionary { { "areacode","010" }, { "days", 2 }};

var dataTokens = new RouteValueDictionary { { "defaultCity","BeiJing" }, { "defaultDays", 2 } };

1.

RouteTable.Routes.MapPageRoute("default","{areacode}/{days}", "~/weather.aspx", false, defaults,null, dataTokens);

2.

Route route = new Route("{areacode}/{days}", defaults,constaints, dataTokens, new PageRouteHandler("~/weather.aspx",false));

RouteTable.Routes.Add("default", route);

根据路由规则生成URL   GetVirtualPath()

   1: public partial class Weather : Page

   2: {

   3:     protected void Page_Load(object sender,EventArgs e)

   4:     {

   5:         RouteData routeData = newRouteData();

   6:        routeData.Values.Add("areaCode","0512");

   7:        routeData.Values.Add("days","1");

   8:         RequestContext requestContext= new RequestContext();

   9:         requestContext.HttpContext =new HttpContextWrapper(HttpContext.Current);

  10:         requestContext.RouteData =routeData;

  12:         RouteValueDictionary values = newRouteValueDictionary();

  13:         values.Add("areaCode","028");

  14:         values.Add("days","3");

     

  16:        Response.Write(RouteTable.Routes.GetVirtualPath(null,null).VirtualPath +"<br/>");

  17:        Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,null).VirtualPath + "<br/>");

  18:        Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,values).VirtualPath + "<br/>");

  19:     }

  20: }

从上面的代码片断我们可以看到:第一次调用GetVirtualPath方法传输的requestContext和values参数均为Null;第二次则指定了一个手工创建的RequestContext对象,其RouteData的Values属性具有两个变量(areaCode=0512;days=1),而values参数依然为Null;第三次我们同时为参数requestContext和values指定了具体的对象,而后者包含两个参数(areaCode=028;days=3)。在浏览器上访问Weather.aspx页面会得到如下图所示的3个URL。这充分证实了上面提到的关于变量选择优先级的结论。

路由映射

我们手工创建了一个HttpRequest和HttpResponse对象,HttpRequest的请求的地址为“http://localhost:3721/0512/3”(3721是本Web应用对应的端口号)。根据这两个对象创建了HttpContext对象,并以此创建一个HttpContextWrapper对象。最终我们将其作为参数调用RouteTable的Routes属性的GetRouteData方法并返回。这个方法实际上就是模拟注册的路由表针对相对地址为“/0512/3”的HTTP请求的路由处理。

   1: public partial class Default : System.Web.UI.Page
    2: {
    3:     private RouteData routeData;
    4:     public RouteData GetRouteData()
    5:     {
    6:         if (null != routeData)
    7:         {
    8:             return routeData;
    9:         }
   10:         HttpRequest request = new HttpRequest("default.aspx", "http://localhost:3721/0512/3", null);
   11:         HttpResponse response = new HttpResponse(new StringWriter());
   12:         HttpContext context = new HttpContext(request, response);
   13:         HttpContextBase contextWrapper = new HttpContextWrapper(context);
   14:         return routeData = RouteTable.Routes.GetRouteData(contextWrapper);
   15:     }
   16: }

我们通过调用RouteTable的Routes属性的MapRoute方法注册了一个采用“ {areacode}/{days}”作为URL模板的路由对象,并指定了默认变量、约束和命名空间列表。

   1: public class Global : System.Web.HttpApplication
    2: {
    3:     protected void Application_Start(object sender, EventArgs e)
    4:     {
    5:         object defaults = new { areacode = "010", days = 2, defaultCity="BeiJing", defaultDays=2};
    6:         object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}"};
    7:         string[] namespaces = new string[] { "Artech.Web.Mvc", "Artech.Web.Mvc.Html" };
    8:         RouteTable.Routes.MapRoute("default", "{areacode}/{days}", defaults, constraints, namespaces);
    9:     }               
   10: }

  • 与调用RouteCollection的MapPateRoute方法进行路由映射不同的是,这个得到的RouteData对象的RouteHandler属性是一个System.Web.Mvc.MvcRouteHandler对象。
  • 在MapRoute方法中通过defaults参数指定的两个与URL匹配无关的变量(defaultCity=BeiJing;defaultDays=2)体现在RouteData的Values属性中。这意味着如果我们没有在URL模板中为Controller和Action的名称定义相应的变量({controller}和{action}),也可以将它们定义成默认变量。
  • DataTokens属性中包含一个Key值为Namespaces值为字符数组的元素,我们不难猜出它对应着我们指定的命名空间列表。

clip_image002

缺省URL参数

UrlParameter.Optional

在此默认路由中,controller 设置为“Home”,action 设置为“Index”,而 id 设置为 Optional。 如果没有为 id 传递任何值,则 MvcHandler 类将忽略 id 参数(RouteData.Values中不包含ID参数)。

Area的路由映射

 *     1、新建 Area:右键 -> Add -> Area...
 *     2、继承 AreaRegistration,配置对应此 Area 的路由
 *     3、在 Global 中通过 AreaRegistration.RegisterAllAreas(); 注册此 Area
 *     4、有了 Area,就一定要配置路由的命名空间

AreaRegistration与AreaRegistrationContext

AreaRegistration定义了两个抽象的静态RegisterAllAreas方法重载,参数state用于传递给具体AreaRegistration的数据。当RegisterAllArea方法执行的时候,它先 遍历通过BuildManager的静态方法GetReferencedAssemblies方法得到的编译Web应用所使用的程序集,通过反射得到所有实现了接口IController的类型,并通过反射创建相应的AreaRegistration对象。对于每个AreaRegistration对象,一个 AreaRegistrationContext对象被创建出来并作为参数调用它们的RegisterArea方法。

AreaRegistration是一个抽象类,抽象只读属性AreaName返回当前Area的名称,而抽象方法RegisterArea用于实现基于当前Area的路由注册。

   1: public abstract class AreaRegistration
   2: {    
   3:     public static void RegisterAllAreas();
   4:     public static void RegisterAllAreas(object state);
   5:  
   6:     public abstract void RegisterArea(AreaRegistrationContext context);
   7:     public abstract string AreaName { get; }
   8: }

AreaRegistration定义了两个抽象的静态RegisterAllAreas方法重载,参数state用于传递给具体AreaRegistration的数据。当RegisterAllArea方法执行的时候,它先遍历通过BuildManager的静态方法GetReferencedAssemblies方法得到的编译Web应用所使用的程序集,通过反射得到所有实现了接口IController的类型,并通过反射创建相应的AreaRegistration对象。对于每个AreaRegistration对象,一个AreaRegistrationContext对象被创建出来并作为参数调用它们的RegisterArea方法。

如下面的代码片断所示,AreaRegistrationContext的只读属性AreaName表示Area的名称,属性Routes是一个代表路由表的RouteCollection对象,而State是一个用户自定义对象,它们均通过构造函数进行初始化。具体来说,对于最初通过调用AreaRegistration的静态方法RegisterAllAreas创建的AreaRegistrationContext对象,AreaName来源于当前AreaRegistration对象的同名属性,Routes则对应着RouteTable的静态属性Routes表示的全局路由表,而在调用RegisterAllAreas方法指定的参数(state)作为AreaRegistrationContext对象的State参数。

   1: public class AreaRegistrationContext
   2: {    
   3:     public AreaRegistrationContext(string areaName, RouteCollection routes);
   4:     public AreaRegistrationContext(string areaName, RouteCollection routes, object state);
   5:  
   6:     public Route MapRoute(string name, string url);
   7:     public Route MapRoute(string name, string url, object defaults);
   8:     public Route MapRoute(string name, string url, string[] namespaces);
   9:     public Route MapRoute(string name, string url, object defaults, object constraints);
  10:     public Route MapRoute(string name, string url, object defaults, string[] namespaces);
  11:     public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces);
  12:  
  13:     public string AreaName { get; }
  14:     public RouteCollection Routes { get; }
  15:     public object State { get; }
  16:     public ICollection<string> Namespaces { get; }
  17: }

AreaRegistrationContext的只读属性Namespaces表示一组优先匹配的命名空间(当多个同名的Controller类型定义在不同的命名空间中)。当针对某个具体AreaRegistration的AreaRegistrationContext被创建的时候,如果AreaRegistration类型具有命名空间,那么会在这个命名空间基础上添加“.*”后缀并添加到Namespaces集合中。换言之,对于多个定义在不同命名空间中的同名Controller类型,会优先选择包含在当前AreaRegistration命名空间下的Controller

AreaRegistrationContext定义了一系列的MapRoute用于进行路由映射注册,方法的使用以及参数的含义与定义在RouteCollectionExtensions类型中的同名扩展方法一致。在这里需要特别指出的是,如果MapRoute方法没有指定命名空间,则通过属性Namespaces表示的命名空间列表会被使用;反之,该属性中包含的命名空间被直接忽略

当我们通过Visual Studio的ASP.NET MVC项目模版创建一个Web应用的时候,在的Global.asax文件中会生成如下的代码通过调用AreaRegistration的静态方法RegisterAllAreas实现对所有Area的注册,也就是说针对所有Area的注册发生在应用启动的时候。

        public override void RegisterArea(AreaRegistrationContext context)

        {

            // 在 Area 中配置路由的时候,要设置命名空间(即本例中的第 4 个参数)

            context.MapRoute(

                "AsynchronousController_default",

                "AsynchronousController/{controller}/{action}/{id}",

                new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults

                new string[] { "MVC20.Areas.AsynchronousController.Controllers" }

            );

        }

   1: public class MvcApplication : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start()
   4:     {
   5:         AreaRegistration.RegisterAllAreas();
   6:     }
   7: }

如果调用AreaRegistrationContext的MapRoute方法是显式指定了命名空间,或者说对应的AreaRegistration定义在某个命名空间下,这个名称为“UseNamespaceFallback”的DataToken元素的值为False;反之为True。进一步来说,如果在调用MapRoute方法时指定了命名空间列表,那么AreaRegistration类型所示在命名空间会被忽略。也就是说,后者是前者的一个后备,前者具有更高的优先级。

系统自动生成的 AdminAreaRegistration 类继承至抽象类 AreaRegistration,并重写了 AreaName 属性和 RegisterArea 方法。在 RegisterArea 方法中它为我们定义了一个默认路由,我们也可在这个方法中定义专属于Admin Area的的其他路由。但有一点要注意,在这如果要给路由起名字,一定要确保它和整个应用程序不一样。

AreaRegistrationContext 类的 MapRoute 方法和 RouteCollection 类的 MapRoute 方法的使用是一样的,只是 AreaRegistrationContext 类限制了注册的路由只会去匹配当前 Area 的 controller,所以,如果你把在 Area 中添加的 controller 的默认命名空间改了,路由系统将找不到这个controller 。

namespace MvcApplication1.Areas.Admin //系统自动生成
http://www.cnblogs.com/willick/p/3331519.html

Areas之间的调用

  ASP.NET MVC中,经常需要在控制层的不同方法之间进行互相调用。如果没特别指定,则默认为同一个area中的action方法和控制器之间的调用。如果需要在不同的area之间进行互相调用,可以使用如下方法:

<%= Html.ActionLink("Main Area", "Index", "Home", new { area = "" }, null)%>
<br /><br />
<%= Html.ActionLink("Blog Area", "Index", "Home", new { area = "Blog" }, null)%>
<br /><br />
<%= Html.ActionLink("Help Desk Area", "Index", "Home", new { area = "HelpDesk" }, null)%>
<br /><br />
<%= Html.ActionLink("Shopping Area", "Index", "Home", new { area = "Shopping" }, null)%

可以看到,上面使用了ActionLink()方法产生链接,注意其中的第4个参数,使用new {area=“Blog”}这样形式的参数,指出调用的是哪一个area中action方法。

  使用RedirectToAction

  同样,我们经常要在某个area中的action方法去调用另外一个area方法中的action,这个时候要如何做呢?代码如下:

  public ActionResult Index()
  {
  return RedirectToAction("Index", "Home", new { Area = "HelpDesk" });
  }

1.理解默认路由表

   1: public static class RouteCollectionExtensions

   2: {

   3:     //其他成员  

   4:    publicstaticvoid IgnoreRoute(this RouteCollection routes,string url);   

   5:     public static void IgnoreRoute(this RouteCollection routes,string url,object constraints);  

   6: 

   7:     public static Route MapRoute(this RouteCollection routes,string name,string url);   

   8:     public static Route MapRoute(this RouteCollection routes,string name,string url,object defaults);   

   9:     public static Route MapRoute(this RouteCollection routes,string name,string url,string[] namespaces);   

  10:     public static Route MapRoute(this RouteCollection routes,string name,string url,object defaults,object constraints);   

  11:     public static Route MapRoute(this RouteCollection routes,string name,string url,object defaults,string[] namespaces);   

  12:     public static Route MapRoute(this RouteCollection routes,string name,string url,object defaults,object constraints,string[] namespaces);

  13: }

一、 实例演示:注册路由映射与查看路由信息

   1: public partial class Default : System.Web.UI.Page

   2: {

   3:     private RouteData routeData;

   4:     public RouteData GetRouteData()

   5:     {

   6:         if (null != routeData)

   7:         {

   8:             return routeData;

   9:         }

  10:        HttpRequest request =new HttpRequest("default.aspx","http://localhost:3721/0512/3",null);

  11:        HttpResponse response =new HttpResponse(new StringWriter());

  12:        HttpContext context =newHttpContext(request, response);

  13:        HttpContextBase contextWrapper =new HttpContextWrapper(context);

  14:         return routeData =RouteTable.Routes.GetRouteData(contextWrapper);

  15:     }

  16: }

 

protected void Application_Start(object sender, EventArgse)

   4:     {

   5:         object defaults = new { areacode = "010", days = 2, defaultCity="BeiJing", defaultDays=2};

   6:         object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}"};

   7:         string[] namespaces = new string[] { "Artech.Web.Mvc", "Artech.Web.Mvc.Html" };

   8:        RouteTable.Routes.MapRoute("default","{areacode}/{days}", defaults, constraints, namespaces);

   9:     }             

*.asp

 <%foreach(var variable in GetRouteData().Values)
                         {%>
                       <li>
                           <%=variable.Key%>=<%=variable.Value%></li>
                       <% }%>

结果

Route:

System.Web.Routing.Route

RouteHandler:

System.Web.Mvc.MvcRouteHandler

Values:

  • areacode=0512
  • days=3
  • defaultCity=BeiJing
  • defaultDays=2

DataTokens:

  • Namespaces=System.String[]

 

routes.MapRoute(

                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller= "Home", action = "Index", id = "" }  // Parameter defaults

            );

/Home/Index/3

默认的路由将这个URL映射为下面的参数:

Controller= Home

Action= Index

id =3

/Home

由于Default路由参数的默认值,输入这个URL将会调用代码清单2中的HomeController类的Index()方法。



可空参数的Index动作

namespace MvcApplication1.Controllers
{
    [HandleError]
    
public class HomeController : Controller
    {
        
public ActionResultIndex(int? id)
        {
            
return View();
        }
    }
}

在代码清单4中,Index()方法拥有一个整数参数。因为这个参数是一个可空参数(可以拥有Null值),因此可以调用Index()而不会引发错误。

使用URL /Home 调用代码清单5中的Index()方法将会引发一个异常,因为Id参数并非一个可空参数。

2.创建自定义路由

 routes.MapRoute(
                
"Blog",                                           // Route name
                "Archive/{entryDate}",                            // URL with parameters
                new { controller= "Archive",action = "Entry" }  // Parameter defaults
            );

3.创建路由约束

 

  9        object defaults =new { areacode ="010", days = 2, defaultCity ="BeiJing", defaultDays = 2 };

  10:         object constraints = new { areacode = @"0\d{2,3}", days = @"[1-3]{1}" };

  11:        context.MapRoute("weatherDefault","weather/{areacode}/{days}", defaults, constraints);

 

你可以使用路由约束来限制匹配特定路由的浏览器请求。可以使用正则表达式来指定一个路由约束。

举个例子,假设你已经在Global.asax文件中定义了一个路由。

代码清单1 - Global.asax.cs

routes.MapRoute(
    
"Product",
    
"Product/{productId}",
    
new {controller="Product",action="Details"}
);

代码清单1包含一个叫做Product的路由。你可以使用Product路由将浏览器请求映射到代码清单2中的ProductController。

代码清单2 - Controllers\ProductController.cs

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    
public class ProductController : Controller
    {
        
public ActionResult Details(int productId)
        {
            
return View();
        }
    }
}

注意到Product控制器公布的Details()动作接受一个叫做productId的参数。这个参数是一个整数参数。

定义在代码清单1中的路由将会匹配下面的任意URL:

·        /Product/23

·        /Product/7

不幸的是,路由也会匹配下面的URL

·        /Product/blah

·        /Product/apple

因为Details()动作期望的是一个整数值,发起一个含有非整数值的请求将会导致错误。举个例子,如果你在浏览器中输入/Product/apple URL,那么你将会得到图1所示的错误页。


图1:错误页

你实际想做的是只匹配包含合适整数productId的URL。当定义路由来限制与路由相匹配的URL时,你可以使用约束。代码3中的修改后的Product路由包含了一个正则表达式,它限制了只匹配数字。

代码清单3 - Global.asax.cs

routes.MapRoute(
    
"Product",
    
"Product/{productId}",
    
new {controller="Product",action="Details"},
    
new {productId= @"\d+" }
 );

正则表达式\d+匹配一个或多个整数。这个限制使得Product路由匹配了下面的URL:

·        /Product/3

·        /Product/8999

但是不匹配下面的URL

·        /Product/apple

·        /Product

这些浏览器请求将由另外的路由处理,或者,如果没有匹配的路由,将会返回一个“The resource could not be found”错误。

 

4. 创建一个自定义路由约束

 

你可以通过实现IRouteConstraint接口来实现一个自定义路由。这是一个极其简单的接口,它只描述了一个方法:

bool Match(
    HttpContextBase httpContext,
    Route route,
    
string parameterName,
    RouteValueDictionary values,
    RouteDirection routeDirection
)

这个方法返回一个布尔值。如果返回了false,与约束相关联的路由将不会匹配浏览器请求。

Localhost约束包含在了代码清单1中。

代码清单1 - LocalhostConstraint.cs

using System.Web;
using System.Web.Routing;

namespace MvcApplication1.Constraints
{
    
public class LocalhostConstraint : IRouteConstraint
    {
        
public bool Match
            (
               HttpContextBase httpContext, 
               Route route, 
                
string parameterName, 
               RouteValueDictionaryvalues, 
               RouteDirection routeDirection
            )
        {
            
return httpContext.Request.IsLocal;
        }

    }
}

代码清单1中的约束利用了HttpRequest类公布的IsLocal属性。当发出请求的IP地址是127.0.0.1或者与服务器的IP地址相同时,这个属性返回true。

你在定义于Global.asax的路由中使用了自定义约束。代码清单2中的Global.asax文件使用了Localhost约束来阻止任何人请求Admin页面,除非他们从本地服务器发出请求。举个例子,当请求来自远程服务器时,对于/Admin/DeleteAll的请求将会失败。

 

 routes.MapRoute(
                
"Admin",
                
"Admin/{action}",
                
new {controller="Admin"},
                
new {isLocal=new LocalhostConstraint()}
           );
Localhost约束使用在了Admin路由的定义中。这个路由不会被远程浏览器请求所匹配。然而,应该意识到定义在Global.asax中的其他路由可能会匹配相同的请求。理解这一点很重要:约束阻止了特定路由匹配某一请求,而不是所有定义在Global.asax文件中的路由。

 

MVC区域

在路由没有指定名称空间的情况下,很容易产生二义性,即两个同名的控制器同时匹配一个路由,我们可以通过在项目中使用唯一的控制器名称来防止二义性,如下:对特定的路由指定一组用来定位控制器的名称空间

routes.MapRoute{"Default","{controller}/{action}/{id}",new{controller="Home",action="Index",id=""},new []{"AreasWeb.Controllers"});

第四个参数指定一个名称空间数组

9.2.5Catch-All 参数

Catch-all参数允许路由匹配具有任意数量的段的URL,参数中的值是不含查询字符串的URL剩余部分

如:

routes.MapRoute("CatchAllRoute","/query/{query-name}/{*extrastuff}");

匹配如下:

URL 参数值

/query/select/a/b/cextrastuff="a/b/c"

/query/select/a/b/c/extrastuff="a/b/c"

/query/select/extrastuff=""(路由仍然匹配,“catch-all捕获了空字符串

9.2.6 段中的多个URL参数

路由的URL中可以存在多个参数,如下:

l {title}-{artist}

l Album{title}and{artist}

l {filename}.{ext}

为避免二义性,参数不能临近,

如下:均为无效的URL

l {title}{atrist}

lDownLoad{filename}{ext}

路由URL在与传入的请求匹配时,它的字面值与请求精确匹配,而其中的URL参数是贪婪匹配,路由使每个URL参数尽可能的匹配更多的文本

如下:多参数路由匹配

路由URL 请求的URL 路由数据的结果

{finename}.{ext}/Foo.xml.aspx filename="Foo.xml" ext="aspx"

My{title}-{cat}/MyHouser-dwelling title="Houser" ext="dwelling"

{foo}xyz{bar}/xyzxyzxyzblah foo="xyzxyz" bar="blah"

9.2.7StopRoutingHandler和IgnoreRoute

默认情况下,路由机制将忽略那些映射到磁盘物理文件的请求。

方法如下:

public static voidRegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");//第一种方法

routes.Add(newRoute("{resource}.axd/{@pathInfo}",new StopRoutingHandler()));//第二种方法

}

溢出参数

指在URL生成过程中使用、但是在路由定义中却没有指定的路由值。具体指的是路由的URL、默认的字典和约束字典

如:路由定义如下:

routes.MapRoute(

"Default",// 路由名称

"{controller}/{action}/{id}",// 带有参数的 URL

new

{

controller ="Home",

action ="Index",

id =UrlParameter.Optional

} // 参数默认值

);

上面路由的定义中不包括名为“page”的URL参数,下面我们使用Url.RouteUrl方法渲染了URL,而不是生成连接:

@Url.RouteUrl(new{controller="Report",action="List",page="123"});

5、该行代码生成的URL是:/Request/List?Page=2,但是我们指定的参数比需要的参数还要多,这个时候额外的参数会作为查询字符串附加在生成的URL之后,路由机制在选择匹配的路由时并不是精确的匹配,它只是选择足够的匹配的路由,只要指定的参数满足路由需要,额外参数无关紧要

6、Route类生成URL的若干示例

routes.MapRoute("report","reports/{year}/{month}/{day}", new{day = 1});

则GetVirtualPath方法调用示例如下:

参数返回URL 说明

Year=2007,month=1,day=1 /reports/2007/1/1 直接匹配

Year=2007,month=1 /reports/2007/1 默认day=1

Year=2007,month=1, /reports/2007/1/1?Category=123 溢出参数进入生成的URL

day=1,category=123

Year=2007 返回空值 因为没有提供足够的匹配参数

9.3 揭秘路由如何绑定到操作

9.3.1 高层次请求的路由管道

主要由以下几步组成:

① UrlRoutingModule 尝试使用在RouteTable中注册的路由匹配当前请求

② 如果一个路由匹配成功,那么路由模块将从匹配成功的路由中获取IRouteHandler接口对象

③ 路由模块由IRouteHandler接口的GetHandler方法,并返回用来处理请求的IHttpHandler对象

④ 调用HTTP处理程序中的ProcessRequest方法,将要处理的值传给它

⑤ 在ASP.NET MVC 中,IRouteHandler是MvcRouteHandler类的一个实例,MvcRouteHandler转而返回一个实现了IHttpHandler接口的MvcHandler对象,返回的MvcHandler对象主要用来实例化控制器,并调用该实例化控制器上的方法

9.3.2 路由数据

调用GetRouteData方法将返回一个RouteData的实例,RouteData包含了关于匹配请求的路由的信息,如果匹配成功则会创建一个字典,其中包含从URL中解析出的信息,并且路由还会为URL中的每一个参数向字典中添加一个键,如:{controller}/{action}/{id},所在的字典中至少包含三个键分别为controller、action、id

9.4自定义路由约束

之前我们讲过可以使用正则表达式对路由进行细粒度的匹配控制,除此之前路由机制提供了一个具有单一Match方法的IRouteConstraint接口,该接口定义如下:

public interfaceIRouteConstraint

{

boolMatch(HttpContextBase httpContext, Route route, string parameterName,RouteValueDictionary values, RouteDirection routeDirection);

}

当路由机制评估路由约束时,如果约束值实现了IRouteConstraint接口,那么这将导致路由机制引擎调用路由约束上的IRouteConstraint.Match方法,以确定约束是否满足给定的请求。

路由机制本身以HttpMethodConstraint类的形式提供了IRouteConstraint接口的一个实现。如下:定义一个路由只相应GET请求,其他请求不响应

routes.MapRoute("name","{controller}", null, new

{

httpMethod = newHttpMethodConstraint("GET")

});

HttpMethodConstraint("POST/GET/PUT/DELETE")

自定义的约束没有必要关联URL参数,因此可以提供一个基于多个URL参数或一些其他约束

 

3、外界路由值

在一些情形中,URL生成程序还可以利用那些不是通过调用GetVirtualPath方法显示提供的值

 routes.MapRoute(
                
"controller",
                
"{controller}/{action}/{page}",
                
new {controller="Admin"},
                
new {action="index"}

            );

@Html.ActionLink("Page2","List",new{controller="tasks",action="List",page=2})

@Html.ActionLink("Page 2","List",new{page 2})//外界路由值

MapPageRoute指定页面

I realize I coulddo:我知道我可以做到:

routes.MapPageRoute("legacy-foo", "Foo.aspx","~/Legacy/Foo.aspx");

but I'm wonderingif there is a way to do that dynamically (using MVC routes)?但我想知道如果有一种方法做动态(使用MVC路由),? eg:例如:

 routes.MapPageRoute("legacyroutes","{filename}.aspx", "~/Legacy/{filename}.aspx");

在视图中生成指向路由的超链接如下:

@Html.RouteLink("Test",new

{

controller ="section",

action ="Index",

id = 123

});

@Html.RouteLink("Default",new

{

controller ="Home",

action ="Index",

id ="123"

});

该方法不能指定由哪个路由来生成链接

为此我们做如下修改:

@Html.RouteLink(linkText:"Route:Test", routeName: "Test", new

{

controller ="section",

action ="Index",

id ="123"

});

@Html.RouteLink(linkText:"Route:Default", routeName: "Default", new

{

controller ="Home",

action ="Index",

id ="123"

});

这样我们便可以为生成的URL指定路由名来生成相应的URL

路由调试

<appSettings>

<AddKey="RouteDebugger:Enabled" value="true" />

</appSettings>



到的关于变量选择优先级的结论。
到的关于变量选择优先级的结论。
将会得到图1所示
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值