• MVC路由机制


         传统的ASP.NET web form 是假想,用户请求的URL和服务器上面的文件之间有某种关联,这里,服务器的工作就是根据接收到的用户请求,检索到对应的文件给用户。这种方式在web form时代很适合,因为ASP.NET页面是aspx页面,并且能够独立的回复用户的浏览器请求。 但是这中方式在MVC中不合适,在MVC中用户请求是通过控制器里面的方法来处理的,在MVC中没有ASP.NET,一对一的文件关联关系;为了解决这个问题,我们要学会MVC路由机制。

     路由机制有两个功能:

    1.检查收到的URL请求,来判断这个请求是要请求哪个控制器哪个方法的;

    2.生成外部URL(用户点击某个链接的时候,会有一个请求,通过视图展现在浏览器上面的URL)

    现在我们来开始学MVC路由配置吧:

    在MVC 框架中,有两种方式创建路由:

    1.基于约定的路由配置

    2.特定的路由配置

    你可能已经很熟悉了基于约定的路由配置,但是特定的路由配置是MVC5中新增加的。我们在这里都会学习

    路由机制不知道,什么是(Controller)控制器,什么是(Actions)方法,它只是提取URL片段,路由的请求处理在后面的处理中,当满足路由配置的时候,才能得到请求的页面;

    默认的,路由会匹配拥有正确的片段的URL,例如{controller}/{action},会匹配有两个片段的URL

    URL模式是保守的,只会匹配拥有同样的片段的URL,但是URL模式又是包容的,只要URL有正确的片段,就会检查片段的值,但不论值是啥。

    路由配置是在RouteConfig.cs文件中的;

    public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.MapRoute(
                    name: "Default",
                    url: "{controller}/{action}/{id}",
                    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                   
                    
                );
                routes.MapRoute(
                    name: "Student",
                    url: "student/{id}",
                    defaults: new { controller = "Student", action = "Index"},
                      constraints: new { id = @"d+" }
    ); }

     

    RegisterRoutes这个静态方法在Global.asax文件中被调用,程序每次运行的时候,会执行Global文件中的Application_Start()方法,进行路由注册;
      protected void Application_Start()
            {
                
                AreaRegistration.RegisterAllAreas();
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }
      按照传统,在很多Web框架中(如经典的ASP、JSP、PHP、ASP.NET等之类的框架),URL代表的是磁盘上的物理文件。例如,当看到请求http://example.com/albums/list.aspx时,我们可以确定该站点目录结构中含有一个albums文件夹,并且在该文件夹下还有一个list.aspx文件。
      URL和文件系统之间这种一一对应的关系并不适用于大部分基于MVC的Web框架,如ASP.NET MVC.一般来说,这些框架采用不同的方法将URL映射到某个类上的方法调用,而不是映射到磁盘上的物理文件。
      另外,对于MVC应用程序,URL 请求到达的第一个组件是控制器而不是视图,而控制器是没有物理路径的

    路由机制概述 

    1.匹配传入的请求(该请求不匹配服务器文件系统中文件),并将这些请求映射到控制器操作(Controller中的action方法)

    MVC基本的处理流程:来了一个URL请求, 从中找到Controller和Action的值, 将请求传递给Controller处理. Controller获取Model数据对象, 并且将Model传递给View, 最后View负责呈现页面。(说白了,就是来了一个URL,找到一个控制器中的方法)(路由是模式,有参数,通过URL中的参数,就可以对应找到符合这种路由模式的方法)

    Routing的作用:

    ´URL: localhost/home/index
    ´localhost是域名, 所以首先要去掉域名部分: home/index
    ´对应了上面代码中的这种URL结构: {controller}/{action}/{id}
    ´因为我们建立了这种URL结构的识别规则, 所以能够识别出 Controller是home, action是index, id没有则为默认值"".
    路由机制一般是由路由名称,路由模式和默认值构成的
    Defaults属性
    最一般的路由情况
    routes.MapRoute(
                    name: "Default",
                    url: "{controller}/{action}/{id}",
                    defaults: new { controller = "Home", action = "GlobalIndex", id = UrlParameter.Optional }
                );

    路由URL模式

    默认值

    匹配URL模式的实例

    {controller}/{action}/{id}

    New {id=“”}

    /albums/display/123

    /albums/display

    {controller}/{action}/{id}

    New {controller=“home”,

    action=“index”,

    id=“”}

    /albums/display/123

    /albums/display

    /albums

    /

    如果一条URL能够匹配就会出错
    比如
    Test的控制器里有两个action
    public ActionResult Index()
    public ActionResult Index(int id)

    在页面中有一个请求
    Test/Index 或者Test/Index/3 都会出错:
      对控制器类型“TestController”的操作“Index”的当前请求在下列操作方法之间不明确:
      类型 MVCDemo.Controllers.TestController 的 System.Web.Mvc.ActionResult Index()
      类型 MVCDemo.Controllers.TestController 的 System.Web.Mvc.ActionResult Index(Int32)
    因为在这种最一般的情况下,这条URL能够匹配两条路由,用两个方法都行。也就是说,来了一个URL,到控制器里找到两个方法都可以用。
          这就是控制器方法不能重载的原因
     
    注册路由的顺序
        当一个URL请求到达应用程序时,路由引擎将遍历所有已注册的路由,检查请求URL是否和URL模式相匹配,然后根据指定的约束验证检索到的URL参数是否有效。一旦路由引擎找到第一个匹配的路由,就会停止遍历。
    ´
       因此,路由的注册顺序非常重要,必须按照从最特殊到最通用的顺序注册。
    routes.MapRoute("showBlogRoute",
                   "blog/post/{id}",
                    new { controller =“CMS”,action = “Show”,id=“”});   
           
      routes.MapRoute("blogRoute", 
                    “blog/{action}/{id}",
                    new { controller = "CMS", action = “Index", id = “”});
    
    routes.MapRoute(“DefaultRoute”, // 路由名称 
                    "{controller}/{action}/{id}", // 带有参数的 URL
                    new { controller = "Home", action = "Index", id =“”} // 参数默认值
                );
                    
        当URL    /blog/post/3  到达应用程序时,路由引擎开始对路由列表进行评估,由于URL和第一个参数路由相匹配,因而停止评估路由。如果按照相反的顺序注册路由,URL将匹配默认的路由,从而调用BlogController中的Post方法,显然就得不到想要的结果
         当路由模式的控制器部分写的是{controller} 时,可以匹配任何URL中的控制器部分,当是blog时,只能匹配 blog/... 的路由
     
    Constraints属性
     
     Constraints属性是一个包含针对URL参数的验证规则的字典,就是说,它是用来限定每个参数的规则或Http请求的类型的
     使用正则表达式来定义约束,比如下面的例子,如果希望以正确的格式(只允许数字值)指定年月日
    routes.MapRoute("simple",
                    "archive/{year}/{month}/{day}",
                    new{controller="blog",action="search",year="2009",month="10",day="10"},
                    new{
                       year=@"d{2}|d{4}",//只能是两位或四位数字
                       month=@"d{1,2}",//只能使用一位或两位数字
                       day=@"d{1,2}"//只能使用一位或两位数字
                  });

    2.构造传出的URL,用来响应控制器中的操作

        在视图中调用一个方法如Html.ActionLink或Url.Action的方法。 这方法会调用RouteCollection. GetVirtualPath方法,传入参数用于选择正确的路线生成的URL。
    <div>
            @Html.ActionLink("点击","Click","Home");
        </div>

    RouteCollection. GetVirtualPath方法

     返回值类型为VirtualPathData,包含路由关联的 URL 路径的相关信息。
     定义了两个重载函数

    方法

    说明

    GetVirtualPath(RequestContextRouteValueDictionary)

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

    GetVirtualPath(RequestContext, String, RouteValueDictionary)

    如果具有指定的上下文、路由名称和参数值,则返回与命名路由关联的 URL 路径的相关信息。

              第一个方法获得了当前路由的一些信息和用户指定的路由值(字典)去选择目标路由。 

              1.  路由系统然后会循环整个路由表,通过GetVirtualPath方法向每一个路由发问:“Can you generate a URL given  these parameters?”

               2.  如果答案是Yes,那么就会返回一个VirtualPathData实例,包括URL和与匹配相关的一些其他信息。如果答案是NO,则返回一个Null,路由系统会转向下一条路由,直到遍历整个路由表。

    举例:

    如果我们在路由机制中定义了一个

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

    在视图中写:

    <div>
            @Html.ActionLink("测试","look","test");
        </div>
    
       <div>
            @Html.ActionLink("点击","Click","Home");
        </div>

    最终的结果是 不管点击哪一个按钮,都会触发方法Click

    public class HomeController : Controller
        {
            //
            // GET: /Home/
    
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult Click()
            {
                return View();
            }
    
        }

    但是显示的URL都是

    如果我们在地址栏中直接输入 test/look或者Home/Click 都是正确的。

  • 相关阅读:
    解题:POI 2006 Periods of Words
    解题:NOI 2014 动物园
    1483. 最高平均分
    1438. 较大分组的位置(回顾)
    1258. 漂亮子数组
    1903. 部门统计(回顾)
    1509. 柠檬水找零
    1451. 到最近的人的最大距离
    1425. 比较含退格的字符串
    1394. 山羊拉丁文
  • 原文地址:https://www.cnblogs.com/weihengblogs/p/8877339.html
Copyright © 2020-2023  润新知