Mvc3(3)

摘录于Pro ASP.NET MVC3 Framework一书:

路由匹配:

(一)

1.会预先定义些路由模式,当一个请求路由过来时,路由系统会把这个路由和我们预先定义的这些模式做匹配,只要匹配成功,路由系统就处理这个URL

2.每个URL中除了主机名和查询字符串,其他的部分是用"/"来分成片断的,路由系统一但匹配成功,就会为解析URL中每个片断的值,然后将其赋给与其匹配成功的模式中的片断

3.路由默认情况下:  

A.只和含有相同个数片断的模式匹配【多一个或少一个都不行】  

B.只要URL和模式匹配上,就为模式中相应片断赋值,而不管这些值具体是什么

4.要改变路由的这种默认情况,采用的办法就是在模式中为片断设置默认值,如

routes.MapRoute("MyRoute", "{controller}/{action}",                 

                                             new { controller = "Home", action = "Index" });

  //这样就可以匹配含0到2个片断的路由,URL中若没有值,就为其采用默认值

  //在请求RUL中我们收到的片断越少,那我们就越多依赖于模式中的默认值

 Number of Segments             Example                                   Maps To
         0                    mydomain.com                                   controller = Home     action = Index
         1                    mydomain.com/Customer                     controller = Customer action = Index
         2                    mydomain.com/Customer/List               controller = Customer action = List
         3                    mydomain.com/Customer/List/All          No match—too many segments

(二)定义静态的URL

  1)URL模式中每个片断不一定都要是变量(参数),也可以是指定的静态量(不需要赋值)     

      Suppose we want to match a URL like this to support URLs that are prefixed with Public     

      eg:  http://mydomain.com/Public/Home/Index

      routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });     

      ---这个URL只会匹配带3个片断的URL,且第一个片断必须是Public

  2)还可以定义一个片断里同时包含静态量和变量          

      routes.MapRoute("", "X{controller}/{action}");     

      ---The pattern in this route matches any two-segment URL where the first segment starts with the letter X. The value for controller is taken from the first segment, excluding the X.

     eg: http://mydomain.com/XHome/Index

   3)public static void RegisterRoutes(RouteCollection routes)        

       {            

             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

             routes.MapRoute(            

                                         "Default", // Route name            

                                        "{controller}/{action}/{id}", // URL with parameters 

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

                                     );

        }

   //在这个方法里定义的路由是有顺序的,依次从上往下匹配,所以应该把更明确的路由放在前面,例如:
   routes.MapRoute("", "X{controller}/{action}");//这个更明确
   routes.MapRoute("MyRoute", "{controller}/{action}", new { controller = "Home", action = "Index" });
   routes.MapRoute("", "Public/{controller}/{action}", new { controller = "Home", action = "Index" });

(三)为已经存在的路由创建一个别名

之前发布出去的程序已经有了一个路由,且这个路由已被用户熟悉;后面如果又对该程序进行了重构了的话,产生了一个新的路由,但又不想改变原先已存在的路由,这时可以用静态片断和默认路由来建一个别名,这样用户还是用旧的路由,不需要改变,当用户输入旧的路由时,就会自动跳转到我们建的那个别名路由。     

eg:   routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });   

这样,当用户请求Shop Controller中的action时,路由系统就会自动转换成请求Home controller中的action

甚至还可以对action取别名,例如:routes.MapRoute("ShopSchema2", "Shop/OldAction", new { controller = "Home", action = "Index" });   

//当用户请求Shop/OldAction时,就会转换成请求Home中的Index

 

(四)Defining Custom Segment Variables(自定义片断变量)  

不仅仅局限于定义Controller和action,还可以定义自己想要的变量片断

routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" })    

//This route will match any zero-to-three-segment URL. The contents of the third segment will be assigned to the id variable, and if there is no third segment, the default value will be used.

获取id的值有两个方法   We can access any of the segment variables in an action method by using the RouteData.Values property.

例如:1.public ViewResult CustomVariable() {

           ViewBag.CustomVariable = RouteData.Values["id"];      

           return View();  

}

       2.方法中的参数名一定要和Route中定义的参数名相同,否则路由系统会找不到拥有这样参数名的方法,从而传不了值  

       public ViewResult CustomVariable(string id) {      

          ViewBag.CustomVariable = id;      

          return View();  

       }

(五)Defining Optional URL Segments(定义可选的URL片断)  

 一个可选的URL片断指的是用户不需要指定,且不需要指定默认值的片断

 routes.MapRoute("MyRoute", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });      

  Number of Segments                   Example URL                            Maps To
        0                            mydomain.com                                       controller = Home         action = Index
        1                        mydomain.com/Customer                            controller = Customer     action = Index
        2                        mydomain.com/Customer/List                      controller = Customer     action = List
        3                        mydomain.com/Customer/List/All                 controller = Customer     action = List     id = All
        4                        mydomain.com/Customer/List/All/Delete       No match—too many segments

(六)Defining Variable-Length Routes(定义可变长的路由)

        方法:用{*catchall}
 
        routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
  
        //前面三个片断依次是为{controller}/{action}/{id}赋值,从第四个开始传过来的所有的片断全部赋给{*catchall},
        //也就是说这个路由可以匹配任意长度URL

 

(七)通过命名空间(Namespace)来指定使用哪个空间里的Controller

  如果程序里引用了多个命名空间,不同的空间里可能存在相同的Controller名,这样在匹配路由时就必须指定匹配哪个空间里的Controller,不然就会报错

  1.routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",            

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

                                                 new[] { "URLsAndRoutes.Controllers"});//指定命名空间,

  //指定了命名空间后,MVC Framework 会先在URLsAndRoutes.Controllers命名空间里找相应的Controller,如果没找着,MVC Framework接着会在所有可用的命名空间里找

   2.routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",             n

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

                                                new[] { "URLsAndRoutes.Controllers", "AdditionalControllers"});

//一个路由里添加了多个命名空间,这些命名空间具有相同的优先级,没有先后顺序     

//这样,MVC Framework会试图解析这两个命名空间里的所有控制器类,如果这两个命名空间里存在相同名字的控制器类,那么就会报错,所以就不能把这两个命名空间同时放在一个路由里面,应该把它们拆开,单独成一个路由,

例如:3.routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",            

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

                                          new[] { "AdditionalControllers" });

           routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",            

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

                                          new[] { "URLsAndRoutes.Controllers"});

4.我们也可以指定MVC Framework在我们指定的命名空间里找,如果没有找到就终止,不会再去另外的命名空间里找          

Route myRoute = routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}",                            

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

                          new[] { "AdditionalControllers" });          

                         myRoute.DataTokens["UseNamespaceFallback"] = false;

//这个设置将会被传给负责寻找控制器类的控制器工厂,告诉它不用再去找控制器了

 

(八)约束路由

  (1)用正值表达式来约束路由
     routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },//默认路由
            new { controller = "^H.*"},//限制控制器类名是H或h开头的
            new[] { "URLsAndRoutes.Controllers"});       
     //约束限制也像默认路由一样,作为参数,但得放在默认路由的后面

  (2)Constraining a Route to a Set of Specific Values(通过设定值来限定路由)    
     routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new { controller = "^H.*", action = "^Index$ | ^About$"},
            new[] { "URLsAndRoutes.Controllers"});     
     //这个路由只匹配controller名是以H或h开头,action是Index或about

  (3)Constraining a Route Using HTTP Methods
     We can constrain routes so that they match a URL only when it is requested using a specific HTTP method    
     routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new { controller = "^H.*", action = "Index|About", httpMethod = new HttpMethodConstraint("GET") },
            new[] { "URLsAndRoutes.Controllers" });     
     //httpMethod这个属性名是可以随便取的,只要传一个HttpMethodConstraint对象即可
     //用HTTP方法来限制路由,跟用HttpGet,HttpPost来限制action中的method没有必然联系
     //路由限制的处理早于action的限制处理    
     //也可以  httpMethod = new HttpMethodConstraint("GET", "POST")

  (4)Defining a Custom Constraint(省略。。。)

  (5)Routing Requests for Disk Files (路由请求物理文件:such as images, static HTML files, JavaScript libraries, and so on)    
     不是所有的路由请求都是请求controller和action的,也可以请求一个物理文件
     默认情况下,路由系统会首先匹配对物理文件的请求,如果匹配成功,则物理文件被启用,其它路由则永远不会被启用;如果失败,则接着匹配其它路由

     eg:在Content文件夹里创建一个StaticContent.htm,然后在地址栏中输入 http://localhost:1892/content/StaticContent.htm,就跳到了这个html文件了


     我们可以先匹配其他路由,在没有匹配成功的情况下,会接着去匹配物理文件,也就是改变默认情况下的行为,只要设置:
     routes.RouteExistingFiles = true; 

     这样一来,当输入http://localhost:1892/content/StaticContent.htm,content就成了controller,StaticContent.htm就成了action, 这时在模式中得为controller及action填上其他值,否则是找不到页面的

  (6)Bypassing the Routing System(绕开路由系统)
     routes.IgnoreRoute("Content/{filename}.html");
     //第一个参数是content,第二个参数以.html为扩展名的路由都将被忽略

 

  (九)Generating Outgoing URLs(生成输出路由)      

   (1)

       A.The simplest way to generate an outgoing URL in a view is to call the Html.ActionLink method within a view,      

       @Html.ActionLink("About this application", "About")

       B.Targeting Other Controllers        

       The default version of the ActionLink method assumes that you want to target an action method in the same controller that has caused the view to be rendered. To create an outgoing URL that targets a different controller, you can use a different overload that allows you to specify the controller name

       //@Html.ActionLink该方法有好几个重载,可以传不同的参数,用的较多的为

      @Html.ActionLink("linkname", "Index", "Home", new { id = 12 }, new {@class="test"})

      //形成的html片断为:<a class="test" href="/Home/Index/12">linkname</a>

      //从各参数名和参数值上看就知道个大概,如果用@Html.ActionLink("About this application", "About"),这个没有说明是哪个Controller,默认是调用当前Controller里的About action

   (2)当为一个属性赋上值,且这个属性跟路由片断不匹配,那么这个属性值将会被追加在输出URL的后面作为查询串,

       例如:  @Html.ActionLink("About this application", "About", new { id = "MyID", myVariable = "MyValue" })          

       It generates the following HTML:

       <a href="/Home/About?id=MyID&myVariable=MyValue">About this application</a>     

       //相当于多传递了一个串

   (3)@Html.ActionLink("About this application", "Index", "Home")          

       如果路由如下:      routes.MapRoute("Default", // Route name                

                                                           "{controller}/{action}/{id}", // URL with parameters                

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

                                  );

     当Html.ActionLink中提供的action名和controller名与默认路由提供的相同时,那么在形成输出路由时,路由系统会忽略Html.ActionLink中提供的值,形成html片断为

     <a href="/">About this application</a>

   (4)Generating URLs (and Not Links)【用Url.Action方法】     

       生成一个URL,不带html标记,Html.ActionLink生成的URL是在<a>标记里面的          

       ---we can use the Url.Action method to generate just the URL and not the surrounding HTML

       eg:   My URL is: @Url.Action("Index", "Home", new { id = "MyId" })[调用Index方法]          

       生成的结果是:My URL is: /Home/Index/MyId

       //这种情况用在:只是想仅仅显示一个URL

      //The Url.Action method works in the same way as the Html.ActionLink method, except that it generates only the URL.

    (5)在action方法中生成输出路由

     public ViewResult MyActionMethod() {
             string myActionUrl = Url.Action("Index", new { id = "MyID" });
             string myRouteUrl = Url.RouteUrl(new { controller = "Home", action = "Index" });
             ... do something with URLs...
      }

      //最常见的情况是先生成一个路由,然后再进行跳转,可以用RedirectToAction方法实现      

     public ActionResult MyActionMethod() {              return RedirectToAction("Index");       }     

     public ActionResult MyOtherActionMethod() {       return RedirectToRoute(new { controller = "Home", action = "Index", id = "MyID" });       }  

     //这里换成RedirectToAction方法是同样的效果

 

posted on 2012-12-05 23:57  Gcam  阅读(332)  评论(0编辑  收藏  举报

导航