`
北极的。鱼
  • 浏览: 150536 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】Asp.Net MVC4 系列-- 进阶篇之路由(1)

    博客分类:
  • MVC
 
阅读更多

转自: http://blog.csdn.net/lan_liang/article/details/22993839?utm_source=tuicool

 

创建一个路由  

打开 RouteConfig.cs  ,发现已经创建了一个默认路由 :

 

routes.MapRoute(  
        name:"Default",  
        url:"{controller}/{action}/{id}"  
       //defaults: new { controller ="Home", action = "Index", id = UrlParameter.Optional }
);  

 为了说明路由的url匹配过程,暂时comment掉default参数。

 

 

打开Global.cs ,可以看到路由配置文件已经注册:

 

protected void Application_Start()  
{  
           AreaRegistration.RegisterAllAreas();  
   
           WebApiConfig.Register(GlobalConfiguration.Configuration);  
           FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);  
           RouteConfig.RegisterRoutes(RouteTable.Routes);  
           BundleConfig.RegisterBundles(BundleTable.Bundles);  
} 

 

 

关于路由工作方式

Asp.net MVC Framework 的路由部分,是插入在http pipeline中的,当接受到http请求,会寻找注册的路由表(在ApplicationStart时候注册,就是应用启动时候),找到路由规则,获取每个路由规则的pattern,试图匹配当前请求合适的那个route,匹配成功,则解析出controller和action,从controllerfactory找到相应的controller,把请求传递给action,如果请求中传参,路由还会解析出参数,给action。

下面是几种url匹配的例子:

http://mysite/Admin/Index

Controller =Admin,Action=Index

http://mysite/Index/Admin

Controller=Index,Action=Admin

http://mysite/Apples/Oranges

Controller=Apples,Action=Oranges

http://mysite/Admin

匹配失败,Segment太少

http://mysite/Admin/Index/Soccer

匹配失败,Segment太多

 

路由会调用route handler来完成路由过程,默认的,mvc应用会使用MVCRouteHandler.手动添加一个Route,就可以体现出来:

 

routes.Add("MyRoute",newRoute("{controller}/{action}", new MvcRouteHandler()));

 

 

指定默认(default)

刚才说明url匹配时候,拿掉了default参数,这时我们一起看看default参数的作用。

 

routes.MapRoute(  
       name:"Default",  
       url:"{controller}/{action}/{id}",  
       defaults: new { controller = "Home", action ="Index", id = UrlParameter.Optional }  
);

 可以看到最后一个参数,指定了一个默认的controller和action。

 

 

Mydomain.com

Controller = Home ,action=Index

Mydomain.com/Customer

Controller=Customer ,action=Index

Mydomain.com/Customer/List

Controller=Customer, action=List

Mydomain.com/Customer/List/All

匹配失败,segment太多

 

定值Segment

场景1,所有请求中第一个Segment为”public”的,需要统一处理,因此定义一个路由:

 

routes.MapRoute(name: "PublicReqRoute", url:"Public/{controller}/{action}",  
                      defaults: new {controller = "PublicHome", action ="Index"});

 示例url:http://mysite/Public

匹配结果:controller = PublicHome,action=Index

 

场景2,请求中以public开始的,需要统一处理,定义路由:

示例url: Http:/mysite/PublicX/

匹配结果:controller=X,action=Index

routes.MapRoute(name: "PublicReqRoute", url:"Public{controller}/{action}",  
                      defaults: new {controller = "PublicHome", action ="Index"});  

 

 

场景3:有个controller或action不工作,需要改个bug,把所有原来指向这个controller的请求暂时路由到首页:

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

 注意:路由是按着添加顺序依次解析的,因此把最特殊的那个路由放在前面,避免先fall 到相对generall的那个。

 

获取参数

对于Route:

routes.MapRoute(  
        name:"Default",  
        url:"{controller}/{action}/{id}",  
        defaults: new { controller = "Home", action ="Index", id = UrlParameter.Optional } );  

 请求:http://mysite/Home/Index/15

 

Action 中使用RouteData.Values获取传入的id:

public ActionResult CustomVariable() {  
    ViewBag.Controller = "Home";  
    ViewBag.Action = "CustomVariable";  
    ViewBag.CustomVariable = RouteData.Values["id"];  
    return View();  
}  

 

使用mvcframework Route System自动传参机制

 

除了使用RouteData.Values取出传入的参数,可以更简单的定义个参数在action,但是参数名要和route定义的相同(id)

Public  ActionResult  CustomVariable(string id) {  
    ViewBag.Controller = "Home";  
    ViewBag.Action = "CustomVariable";  
    ViewBag.CustomVariable = id;  
    return View();  
}  

 对于url:http://mysite/Home/Index/15,id就会自动被赋值为15传入action

定义可选参数

依然对于url:

routes.MapRoute(  
       name:"Default",  
       url:"{controller}/{action}/{id}",  
       defaults: new { controller = "Home", action ="Index", id = UrlParameter.Optional }  
); 

 Id=UrlParameter.Optional,此时id就是可选参数

Mydomain.com

Controller=home ,action=Index

Mydomain.com/customer

Controller=customer, action=Index

Mydomain.com/customer/List

Controller=customer, action=List

Mydomain.com/customer/List/All

Controller=customer , action=List, Id=All

Mydomain.com/customer/List/All/Delete

url 匹配失败

 

如果没有传参,action提供了id参数,那么id此时就为null;

public  ActionResultCustomVariable(string id) {  
    ViewBag.Controller = "Home";  
    ViewBag.Action = "CustomVariable";  
    ViewBag.CustomVariable = id == null ? "<novalue>" : id;  
    return View();  
}  

 作为另一个选择,可以指定一个默认参数,如果没url没传值,默认参数值就会被使用。

Public  ActionResultCustomVariable(string id = "DefaultId") {  
    ViewBag.Controller = "Home";  
    ViewBag.Action = "CustomVariable";  
    ViewBag.CustomVariable = id;  
    return View();  
}  

 

使用{*catchall}捕捉超出数量的segment

例如,对于这条route:

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

 由于使用了{*catchall},对于url:

http://mysite/Home/Index/All/More/More/More

此时,controller=Home,Action=Index, catchall=”All/More/More/More”

这样,就把解析剩下segment的工作交给了自己处理

 

解决在不同namespace的同名controller

例如现在有两个controller,在不同的命名空间:

namespace UrlsAndRoutes.Controllers {  
    public class HomeController : Controller {  
        public ActionResult Index() {  
            ViewBag.Controller = "Additional Controllers - Home";  
            ViewBag.Action = "Index";  
            return View("ActionName");  
        }  
    }  
} 

 和

namespace UrlsAndRoutes.AdditionalControllers {  
    public  classHomeController : Controller {  
        public  ActionResultIndex() {  
            ViewBag.Controller = "Additional Controllers -Home";  
            ViewBag.Action = "Index";  
            return View("ActionName");  
        }  
    }  
}  

 对于这种情况,可能希望路由先在一个指定的命名空间里找,找到了返回:

routes.MapRoute("MyRoute","{controller}/{action}/{id}/{*catchall}",  
new { controller = "Home", action ="Index",  
id = UrlParameter.Optional  
},  
new[] { "URLsAndRoutes.AdditionalControllers" }); 

 关键在于最后的那个命名空间参数,mvc framework会优先找 “URLsAndRoutes.AdditionalControllers”里面的controller,如果没找到,会搜索其余的命名空间。

注意,这个new []{}数字里的参数是平行的,也就是说,如果mvc framework在这些命名空间里找到多个同名controller,不会找到第一个就返回,依然会抛出异常,例如:

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

 对于url:

http://mysite/home/Index/15

mvc framework会在指定的命名空间数组里找,由于找到了多个homecontroller,因此抛出异常。

如果希望这样:指定多个命名空间,找到了第一个就返回,怎么做?

可以配置多条route:

routes.MapRoute("AddContollerRoute","Home/{action}/{id}/{*catchall}",  
new { controller = "Home", action ="Index",  
id = UrlParameter.Optional },  
new[] { "URLsAndRoutes.AdditionalControllers" });  
   
routes.MapRoute("MyRoute","{controller}/{action}/{id}/{*catchall}",  
new { controller = "Home", action ="Index",  
id = UrlParameter.Optional },  
new[] { "URLsAndRoutes.Controllers" });  

 mvc framework就会按着添加的顺序依次查找匹配的controller和action,找到了把解析好的参数(如果有)传递给action就返回了。

只允许mvc framework在指定的 namespace里找,如何做?

Route myRoute=routes.MapRoute("AddContollerRoute",  
"Home/{action}/{id}/{*catchall}",  
new { controller = "Home", action ="Index",  
id = UrlParameter.Optional },  
new[] { "URLsAndRoutes.AdditionalControllers" });   
  
myRoute.DataTokens["UseNamespaceFallback"] = false;

 由于把DataTokens[“UseNamespaceFallback”] 设为false,因此mvcframework在指定的命名空间:URLsAndRoutes.AdditionalControllers"里面找完了,就不去其他地方找了。

 

给路由加限制

 

正则限制

可以加正则限制在controller和action:

routes.MapRoute("MyRoute","{controller}/{action}/{id}/{*catchall}",  
new { controller = "Home", action ="Index", id = UrlParameter.Optional },  
new { controller = "^H.*"},  
new[] { "URLsAndRoutes.Controllers"}); 

 由于给controller加上了正则表达式:”^H.*”的限制,因此对于url匹配了urlpattern,解析出controller,如果不是以H开头的,也会被过滤掉。

类似的,也可以使用给action加正则限制:

new { controller = "^H.*", action ="^Index$|^About$"}  

 这样,就限制了action必须是Index和About。

 

使用Http Method限制

可以限制请求是Get ,Post亦或是Put ,Delete等类型的。

new { controller = "^H.*", action ="Index|About",  
httpMethod = new HttpMethodConstraint("GET") } ,  

 这样,就限制了请求必须是Get方式的。

 

注意,给route加httpmethod限制,和给controller还有action加httpmethod区别在于,route在httppipeline很早的位置就被处理了,而到controller和action的时候,已经是httppipeline很晚的时候了,controller和action已经被解析了,参数也已经被解析了(如果有)。

 

自定义限制

Mvc 提供了IRouteConstranit 接口,可以自己定义限制,通过实现这个接口:

public class UserAgentConstraint : IRouteConstraint {  
    private string requiredUserAgent;  
    public UserAgentConstraint(string  agentParam) {  
        requiredUserAgent = agentParam;  
    }  
    Public  boolMatch(HttpContextBase  httpContext, Routeroute, string  parameterName,  
RouteValueDictionary  values,RouteDirection routeDirection) {  
        return httpContext.Request.UserAgent != null &&  httpContext.Request.UserAgent.Contains(requiredUserAgent);  
    }  
}  

 以上代码,实现了一个限制,必须Request对象中的代理对象不为空,也就是必须使用代理才能访问,并且代理名称包含指定的名称。

使用自定义限制:

routes.MapRoute("ChromeRoute","{*catchall}",  
new { controller = "Home", action ="Index" },  
new {  
customConstraint = newUserAgentConstraint("Chrome")  
},  
new[] { "UrlsAndRoutes.AdditionalControllers" });

 这样,就实现了,必须使用chrome才能访问的限制。

 

让访问物理文件目录的请求也参与路由

默认情况下,route system会先检查url是否指向了一个物理文件目录,如果是,返回找到这个文件,返回;否则,执行注册到路由表里面的每一条route。也就是说,指向物理文件目录的请求实际在mvc路由机制之前已经被处理掉了,默认没有参与路由。

 

如果要改变这个行为,例如访问

http://mysite/resource/pic/  ,不希望route去找resource/pic物理目录,而希望route找resourcecontroller ,pic action,那么:

在注册路由时,加上

routes.RouteExistingFiles = true;

这样,本地文件的检测 就会在路由机制执行之后了。

在路由前后,httppipeline的示意图

 

 其中,httpmodule 1和 httpmodule2 在pipeline上面routesystem前后的两个module。

加上route.RouteExistingFiles=true

Route system中,就会先执行MVC Route,后执行CheckDisk Files .最后,为物理文件指定一个route:

routes.MapRoute("DiskFile","Content/StaticContent.html",  
new {  
controller = "Resource",  
action = "List",  
}); 

 

By Passing Route System

有些访问资源文件的请求,是需要ignore的,这种需求直接用ignoreRoute就可以了:

 

routes.IgnoreRoute("Content/{filename}.html");  

 这样,对于url:http://mysite/Content.test.html 的请求就被route忽略了,访问页面,就会出现资源无法找到和404错误:

HTTP Error 404.0 - Not Found

The resource you are looking for has beenremoved, had its name changed, or is temporarily unavailable.

 

  • 大小: 23.6 KB
分享到:
评论

相关推荐

    ASP.NET MVC 5入门指南(中文PDF+源码)

    ASP.NET MVC 5入门指南 (中文PDF+源碼) 1. ASP.NET MVC 5 - 开始MVC 5之旅 2. ASP.NET MVC 5 - 控制器 3. ASP.NET MVC 5 - 视图 4. ASP.NET MVC 5 - 将数据从控制器传递给视图 5. ASP.NET MVC 5 - 添加一个模型 6. ...

    ASP.NET MVC学习笔记-Controller与View传值.

    ASP.NET MVC学习笔记-Controller与View传值.

    ASP.NET MVC 身份验证-利用cookie记录登录用户

    ASP.NET MVC 身份验证-利用cookie记录登录用户

    asp.net MVC4 CMS

    asp.net MVC4 CMS 完整的源代码,学习和提高asp.net mvc4可以参考一下。

    ASP.NET MVC5.pdf

    本系列共11篇文章,翻译自ASP.NET MVC 5 官方教程,由于本系列文章言简意赅,篇幅适中,从一个web网站示例开始讲解,全文最终完成了一个管理影片的小系统,非常适合新手入门ASP.NET MVC 5 (新增、删除、查询、更新) ...

    ASP.NET MVC3.0实例-Movies

    ASP.NET MVC3.0实例-Movies

    ASP.NET MVC 4高级编程(第4版)清晰完整PDF版

    MVC专家“梦之队”对ASP.NET MVC 4的全新诠释 由Microsoft专家和极受敬重的软件开发社区负责人撰写的《ASP.NET MVC 4高级编程(第4版)》将带您学习最前沿的Web框架:ASP.NET MVC 4。本书开篇简要介绍ASP.NET MVC框架...

    asp.net mvc demo[25-day]

    asp.net mvc demo 2015-08-25

    ASP.NET MVC MSDN 文档 CHM

    ASP.NET MVC 1.0 MSDN Reference CHM Version ASP.NET MVC 1.0 MSDN 参考及类库,CHM版本,从MSDN 官方网站下载并编译。源分支URL: http://msdn.microsoft.com/en-us/library/dd394709.aspx 内容列表: ASP.NET MVC...

    [ASP.NET MVC] ASP.NET MVC 4 实战 (英文版)

    ASP.NET MVC 4 in Action is a hands-on guide that shows you how to apply ASP.NET MVC effectively. After a high-speed ramp up, this thoroughly revised new edition explores each key topic with a self-...

    ASP.NET MVC 4高级编程 第4版PDF.rar

    《ASP.NET MVC 4高级编程(第4版)》主要有以下核心内容: 解释ASP.NET MVC框架与“文件页”Web框架的不同之处; 介绍控制器、视图、模型、表单、HTML辅助方法、数据注解、验证、成员资格、授权、安全和路由; ...

    ASP.NET MVC4 Web编程

    asp.net mvc4

    Asp.Net MVC案例教程

    Asp.Net MVC案例教程 Asp.Net MVC案例教程 Asp.Net MVC案例教程 Asp.Net MVC案例教程 Asp.Net MVC案例教程 Asp.Net MVC案例教程

    【全网首发】ASP.NET MVC4开发指南(附带源码)

    全网首发:ASP.NET MVC4 开发指南(附带源码)版本,ASP.NET MVC4 开发指南 PDF + ASP.NET MVC4 开发指南源码,让你学习起来再也不费劲,轻松高效!

    ASP.NET MVC4

    ASP.NET MVC4,全英文的教程,大家英语好的可以原汁原味的看看

    Adam Freeman-Pro ASP.NET Core MVC 2-Apress (2017)

    Adam Freeman-Pro ASP.NET Core MVC 2-Apress (2017) 一如既往的好书!

    ASP.NET MVC企业实战源代码Chapter12.rar

    本书共分为12章,以符合初学者思维的方式系统地介绍ASP.NET MVC的应用技巧,并结合实际项目详细地介绍如何基于ASP.NET MVC构建企业项目。通过本书的学习,读者可以全面掌握ASP.NET MVC的开发,并从代码中获取软件...

    ASP.NET MVC in Action - Jeffrey Palermo.pdf

    ASP.NET MVC in Action is a comprehensive guide to MVC-based development using this powerful framework. It offers a clearly-written introduction both to the ASP.NET MVC Framework and to the MVC ...

    ASP.NET MVC4 中文版.rar

    本书介绍了微软最新的ASP.NET MVC4框架,包括如何使用ASP.NET MVC4框架构建Web应用程序,ASP.NET MVC4框架的运行原理,如何在真实开发场景中使用ASP.NET MVC4框架新特性来解决不同的需求,如何使用HTML、JavaScript...

    ASP.NET MVC4 教程(完整版).pdf

    ASP.NET MVC 4 is a framework for building scalable, standards-based web applications using well-established design patterns and the power of ASP.NET and the .NET Framework. It installs side-by-side ...

Global site tag (gtag.js) - Google Analytics