zoukankan      html  css  js  c++  java
  • 自定义MVC路由配置


    首先我用MVC4新增一个订单查看的功能


    1.创建控制器OrderController

    namespace MvcApplication3.Controllers
    {
        public class OrderController : Controller
        {
            public ActionResult OrderView()
            {
                return View();
            }
        }
    }

    2.创建视图 OrderView

    @{
        ViewBag.Title = "OrderView";
    }
    
    <h2>OrderView</h2>

    3.Global配置路由

     public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
                routes.MapRoute(
                  "OrderView", 
                  "OrderCenter/OrderView.html",
                  new { controller = "Order", action = "OrderView" },
                  new string[] { "MvcApplication3" }
                  );
    
            }

    我们在做MVC项目时,每次我们新增功能时,都要在golbal文件里注册下该视图的路由,当项目有10个,100个功能,那我们不配置死,而且都在一个文件里global里修改配置,维护起来非常费劲,有没有好的办法来解决这个问题尼,不用再修改global文件,就可自由的配置路由地址

    让我们接下来一步步分析

    首先我们看MVC路由类RouteCollection的扩展方法 MapRoute 的参数属性

            //
            // 摘要:
            //     Maps the specified URL route and sets default route values and namespaces.
            //
            // 参数:
            //   routes:
            //     A collection of routes for the application.
            //
            //   name:
            //     The name of the route to map.
            //
            //   url:
            //     The URL pattern for the route.
            //
            //   defaults:
            //     An object that contains default route values.
            //
            //   namespaces:
            //     A set of namespaces for the application.
            //
            // 返回结果:
            //     A reference to the mapped route.
            //
            // 异常:
            //   System.ArgumentNullException:
            //     The routes or url parameter is null.
            public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);

    再看下我们在Golbal里调用此方法

    routes.MapRoute(
                  "OrderView",  --对应name
                  "OrderCenter/OrderView.html", --对应url
                  new { controller = "Order", action = "OrderView" }, --对应object
                  new string[] { "MvcApplication3" } --对应namespaces
                  );

    看第三个参数 defaults 它包含了路由的Controller名称,Action名称,第四个参数namespaces表示这个Controller所在的命名空间,我们看看我们之前新建的控制器OrderController它的类型是class,而它下面的Action是一个返回类型是ActionResult的方法,再想到命名空间,由此我们是否可以利用反射技术来来循环读取当前应用程序下所有Controller,每个Controller的所有方法Action以及每个Controller所在命名空间

    下面我们写下面一段伪代码来分析我们的思路:

      var 控制器类集合=读取当前所有控制器类();
      foreach (var 控制器 in 控制器类集合)
      {
           var action方法数组=获取控制器所有Action方法();
           var namespance=获取当前控制器所在命名空间;
           var controllerName=获取控制器名称();
           foreach(var action in action方法数组)
           {
               var actionName=获取action名称();       
               var routerUrl="OrderCenter/OrderView.html";           
               //注册
               routes.MapRoute(
                      actionName, 
                      routerUrl,
                      new { controller =controllerName, action = actionName },
                      new string[] { namespance }
                      );
           }
      }  

    这段伪代码算是解决我们今天讲的主题问题的一部分,为什么尼,因为第二个参数url 我们无法识别或知道每个Controller路由的地址,这样问题还没有解决,我们继续苦逼的维护这我们的golbal路由文件,新增一个功能,来加个配置,如果每个Controller有个属性URL,我们可以设置这个属性,那问题不就解决了嘛,那如何给Controller添加属性尼,这里我们可以利用到C# 特性 Attribute

    关于特性MSDN给的定义: 

    特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性

    特性具有以下属性:

    • 特性可向程序中添加元数据。元数据是有关在程序中定义的类型的信息。所有的 .NET 程序集都包含指定的一组元数据,这些元数据描述在程序集中定义的类型和类型成员。可以添加自定义特性,以指定所需的任何附加信息。

    • 可以将一个或多个特性应用到整个程序集、模块或较小的程序元素(如类和属性)。

    • 特性可以与方法和属性相同的方式接受参数。

    • 程序可以使用反射检查自己的元数据或其他程序内的元数据。有关更多信息。

    所以我们定义一个特性类

     [AttributeUsage(AttributeTargets.All, Inherited = true)]
        public class RouteAddressAttribute : Attribute
        {
            public RouteAddressAttribute() 
            { }
            public RouteAddressAttribute(string name, string address)
            {
                this.Name = name;
                this.Address = address;
            }
            /// <summary>
            /// 地址 【正是我们想要的URL】
            /// </summary>
            public string Address { get; set; }
            /// <summary>
            /// 名称
            /// </summary>
            public string Name { get; set; }
        }

    定义了特性类,看我们怎么用它,此时我们再看我的Controller

    namespace MvcApplication3.Controllers
    {
        public class OrderController : Controller
        {
           [RouteAddress(Name = "订单查看", Address = "OrderCenter/OrderView.html")]
            public ActionResult OrderView()
            {
                return View();
            }
        }
    }

    再把我们之前的伪代码编程成真实代码,代码实现如下

    namespace MvcApplication3
    {
        public class RouteMap
        {
    
            public static void Redirection(RouteCollection routes, string assemblyName)
            {
                Assembly assembly = Assembly.Load(assemblyName);
                Type[] types = assembly.GetTypes();
                List<string> ListAdress = new List<string>();
                foreach (Type type in types)
                {
                    #region 读取所有Controller
                    if (type.Name.Contains("Controller"))
                    {
                        string nameSpace = type.Namespace;
                        string controller = type.Name.Replace("Controller", "");
                        string action = "";
                        string address = "";
                        string routeName = "";
    
                        MemberInfo[] memberInfos = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
                        #region 读取每个Controller的Action
                        foreach (var item in memberInfos)
                        {
                            action = item.Name;
                            routeName = type.Name + action;
    
                            var objAttr = item.GetCustomAttributes(typeof(RouteAddressAttribute), false);
                            if (objAttr != null && objAttr.Length > 0)
                            {
                                #region 获取特性RouteAdress
                                RouteAddressAttribute temp = (RouteAddressAttribute)objAttr.First();
                                if (temp != null)
                                {
                                    address = temp.Address;
    
                                    if (!ListAdress.Contains(address))
                                    {
                                        //实现注册
                                        routes.MapRoute(routeName, address, new { controller = controller, action = action }, new string[] { nameSpace });
                                        ListAdress.Add(address);
                                    }
                                    else
                                        throw new Exception("存在相同路由地址:" + address);
                                } 
                                #endregion
                            }
                            else
                            {
                                #region 没加特性的则显示默认地址 Controller/Action
                                address = string.Format("{0}/{1}", controller, action);
                                if (!ListAdress.Contains(address))
                                {
                                    //实现注册
                                    routes.MapRoute(routeName, address, new { controller = controller, action = action }, new string[] { nameSpace });
                                    ListAdress.Add(address);
                                }
                                else
                                    throw new Exception("存在相同路由地址:" + address); 
                                #endregion
                            }
                        } 
                        #endregion
                    } 
                    #endregion
                }
            } 
    
    
        }
    }

    这样Golbal文件里我们添加一行代码就行了。

     public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
                //调用
                RouteMap.Redirection(routes, "MvcApplication3");
    
            }

    综上所述,利用特性,利用反射,解决了开发人员繁琐的路由配置工作。

    关于特性和反射技术,大家可以看下MSDN,本文不做详细介绍。

    关于分享和转载:本文是由作者本人原创,如需分享或转载请备注原文出处!
  • 相关阅读:
    本地安装了flash,前台浏览器还显示需要安装flash?是因为版本需要对应
    关于jsp:include 动态引入的值传递问题(数据共享问题)
    java异常
    理解定义类
    泛型
    SSM配置
    markdown基本语法
    xadmin下设置“use_bootswatch = True”无效的解决办法
    django.db.utils.DataError: (1406, "Data too long for column 'gender' at row 1")
    【转】pycharm使用中的一些快捷键
  • 原文地址:https://www.cnblogs.com/Ryan2012/p/5006560.html
Copyright © 2011-2022 走看看