4.路由学习

1.路由学习

2.路由源码解读

3.自定义路由

在MVC的项目中有一个Global.asax.cs 文件,里面有一个 Application_Start 方法,代码如下:

public class MvcApplication : System.Web.HttpApplication
    {
        /// <summary>
        ///不是每次请求都调用
        ///在Web应用程序的生命周期里就执行一次
        ///在应用程序第一次启动和应用程序域创建时被调用
        ///适合处理应用程序范围的初始化代码
        /// </summary>
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);//注册路由
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

这个地方就是开启路由的地方,它把url包装成Route对象,然后把我们注册的路由规则用name---route键值对的方式存入RouteCollection中(注册的路由写在App_Start 文件加下面的 RouteConfig 里面),当请求来了后,会在RouteCollection进行路由解析,就会根据自定义的路由规则从上到下进行匹配

路由解析:

  1.如果没有匹配上我们定义的路由,那么就走原始流程,就等于MVC中路由完全没有生效

  2.如果请求能够找到物理文件,那么就不再匹配路由(支持WebForm的原因)

  3.匹配路由是从上到下进行匹配的,如果第一个匹配上了,那么就不会继续往下匹配了,如果匹配不上,那么就走原始流程

WebForm请求:

  WebForm请求的是一个具体的页面,当用户请求具体的aspx页面时,服务器会对该页面中的内容一行一行的解析(碰到服务器脚本语言还会执行),最后形成响应流重新写回到浏览器,再由浏览器对该响应流进行解析(依照W3C标准),最终将用户请求的页面呈现出来

注册路由的几种方式如下:

  1.在RouteConfig 里面注册路由

    参数说明:

      name:          路由名称
      url:     url参数
      defaults:    参数默认值
      constraints:  参数约束(常用的是正则表达式)

/*
                默认路由规则
                这个表示只匹配所有控制器下面的动作,如果不指定控制器和动作,那么默认访问Home控制器下的Index动作,如果指定了,那么就访问指定的控制器下的动作
            */
            routes.MapRoute(
                name: "Default1",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

            /*
               指定控制器(就是把控制器写死)
               这个表示只匹配Home控制器下面的动作,如果不指定动作,那么默认访问Index动作,如果指定了,那么就访问指定的动作
           */
            routes.MapRoute(
                name: "Default2",
                url: "Home/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

            /*
               指定控制器和动作(就是把控制器和动作写死)
               这个表示只匹配Home控制器下面Index动作
            */
            routes.MapRoute(
                name: "Default3",
                url: "Home/Index/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

            /*
                 给路由定义约束(constraints)
                 这个表示只能匹配Home和Index控制器下面的Index方法
            */
            routes.MapRoute(
                name: "Default4",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                constraints: new { controller = "Home|Index", action = "Index" }
            );


            /*
                 给路由定义约束(constraints)
                 这个表示只能匹配Home和Index控制器下面的Index方法,并且一定要带一个参数 id,不管动作是否需要参数,不带访问不到啊(例如:localhost:8955/Index/Index_100)
                 这样写的好处是GET请求的时,让别人不知到你这参数是干什么的,是什么字段
                 注意:
                    这个地方可以随意拼接例如:{controller}_{id}/{action}   {controller}/{action}/_{id} 
            */
            routes.MapRoute(
                name: "Default4",
                url: "{controller}/{action}/_{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                constraints: new { controller = "Home|Index", action = "Index" }
            );


            /*
                 给路由定义约束(constraints)----正则表达式
                 这个表示
                    1.只能匹配Home和Index控制器下面的Index方法,并且一定要带一个参数 id,
                    2.并且id的值是五个数字组成 (例如:localhost:8955/Home/Index_10000)
                    3.此路有之匹配GET请求 
            */
            routes.MapRoute(
                name: "Default4",
                url: "{controller}/{action}_{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                constraints: new { controller = "Home|Index", action = "Index",id=@"d{5}",httpMethod = new HttpMethodConstraint("GET") }
            );
View Code

  2.使用特性注册路由(RouteAttribute)

    使用:

      首先我们在RouteConfig 里面启动特性路由,将特性 RouteAttribute 标记到控制器或控制器操作上。

public static void RegisterRoutes(RouteCollection routes)
{
    /*
        IgnoreRoute为RouteCollection 的扩展方法,作用是忽略指定样式的路由。 
        上面routes.IgnoreRoute("{resource}.axd/{*pathInfo}");中的{resource}代表一个路由参数,
        上面routes.IgnoreRoute("{resource}.axd/{*pathInfo}");中的{resource}代表一个路由参数,
        { resource}.axd代表以.axd结尾的字符串;{*pathInfo}也是一个路由参数,*代表匹配任何字符串,
        那么以pathInfo结尾的串都会匹配到。这条语句完整含义是:以axd结尾的任何字符串,不论斜杠后是何种字符串都不执行路由行为。
    */
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapMvcAttributeRoutes();//启动路由
}

    使用特性的三个属性或构造函数:

       public RouteAttribute(string template):template是路由匹配模式

       Name:获取或设置路由名称

       Order:获取或设置路由应用顺序

       Template:获取路由匹配模式

public class HomeController : Controller
    {
        /// <summary>
        /// url:localhost:8955/Home/Index
        /// </summary>
        [RouteAttribute("Home/Index")]
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// url:localhost:8955/Home-Index
        /// </summary>
        [RouteAttribute("Home-Index")]
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// url:localhost:8955/Home/aaa
        /// </summary>
        [RouteAttribute("Home/aaa")]
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// url:localhost:8955/Home/10-10
        /// 注意:
        ///     如果动作里面有2个参数,此参数是无任何类型的 a b(public ActionResult Index(int a, int b)),那么参数a为10,参数b为10
        ///     不管动作是否有参数,都需要传递值进来(不能 localhost:8955/Home)
        /// </summary>
        [RouteAttribute("Home/{a}-{b}")]
        public ActionResult Index(int a, int b)
        {
            return View();
        }


        /// <summary>
        /// url:localhost:8955/Home/10-10
        /// 注意:
        ///     不管动作是否有参数,都需要传递值进来(不能 localhost:8955/Home)
        ///     a 无任何类型   b 只接受int类型的值(如果要接受时间类型:{b:datetime})
        /// </summary>
        [RouteAttribute("Home/{a}-{b:int}")]
        public ActionResult Index()
        {
            return View();
        }

        

        [RouteAttribute("Home/Main")]
        public ActionResult Main()
        {
            return View();
        }
    }
View Code

当然,因为在同一个控制器中,所有动作的控制器的名称都是一样的,所以我们可以在控制器上面使用RoutePrefix定义公共路由

当然需要更加了解可以访问:https://www.cnblogs.com/ITusk/p/7677001.html

namespace WebApplication1.Controllers
{
    [RoutePrefixAttribute("Home/{id}")]
    public class HomeController : Controller
    {
        /// <summary>
        /// url:localhost:8955/Home/15/Index
        /// </summary>
        [RouteAttribute("Index")]
        public ActionResult Index()
        {
            return View();
        }
    }
}

我们可以使用 ? 将一个路由参数标记为 可选参数(optional parameter),如果一个路由参数被标记为可选的,则必须为其设置默认值

[Route("api/product/{id:int?}")]
public IHttpActionResult GetProduct(int id =1){
}

 可以同时使用多个约束条件,每个条件之间通过 进行分割,例如

[Route("api/product/{id:int:min(1)}")]
public IHttpActionResult GetProduct(int id){}

 

课外补充:

 URL与搜索引擎优化
            1)URL越短越好

            2)用破折号而不是下划线

            3)使用小写字母。根据HTTP规范,URL区分大小写,一般的搜索引擎遵循HTTP规范

        Glimpse:
        使用Glimpse观察路由
            安装:打开VS->工具->NuGet程序包管理器->搜索Glimpse.MVC5,然后回车,执行安装
            使用:

      1.运行web应用,输入地址格式为:网站根目录/glimpse.axd,例如   localhost:8955/glimpse.axd

      2.点击页面中的Turn Glimpse On 按钮

      3.运行你要测试页面地址

 

 

原文地址:https://www.cnblogs.com/zjdbk/p/10617280.html