• ASP.NET MVC 5 Web编程2 -- URL映射(路由原理)


    本章将讲述ASP.NET MVC5 的路由原理,即URL映射机制。

    简单点就是解释:为什么MVC在浏览器输入地址就能访问到类(或类中的方法)?这是怎么做到的?我自己可以通过.NET写出一个自己的MVC框架吗?

    答案是:可以。

    模拟URL映射

    先来看一个Demo,在传统的.NET WebForms项目中,实现URL的拦截。

    打开VS2013,新建一个“ASP.NET Web窗体应用程序”项目,并取名为Demo4URLRouting。

    为了方便测试,注释掉Default.aspx页面的内容和模板引用。这样做以后,看起来是这样

    然后新建一个ControllerFactory类,实现IHttpHandler接口。

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Web;
     5 
     6 namespace Demo4URLRouting
     7 {
     8     /// <summary>
     9     /// 自己写的ControllerFactory,试图扮演MVC5中的RouteConfig(路由配置)角色。
    10     /// </summary>
    11     public class ControllerFactory : IHttpHandler
    12     {
    13         ControllerFactory()
    14         { 
    15         }
    16 
    17         public bool IsReusable
    18         {
    19             get;
    20             set;
    21         }
    22 
    23         public void ProcessRequest(HttpContext context)
    24         {
    25             context.Response.Write(string.Format("ControllerFactory来拦截请求-> URL为: {0}",context.Request.RawUrl));
    26         }
    27     }
    28 }
    View Code

    下一步,打开Web.config配置文件,在system.webServer节点下添加一项handlers配置

    代码如下:

    <!--for url routing test Start-->
        <handlers>
          <add name="ControllerFactory" verb="*" path="*Account/*" type="Demo4URLRouting.ControllerFactory,Demo4URLRouting" preCondition="integratedMode"/>
        </handlers>
        <!--for url routing test End-->
    View Code

    此配置的意图是:拦截站点URL中包含Account关键字的全部URL地址。

    按F5运行项目,在地址栏站点后,输入account,发现已成功被ControllerFactory类拦截。

    继续,输入/account/login。发现地址未被拦截。而是跳转到了默认项目的登陆页面。

    怎么回事呢?

    原来,是项目下的Global.asax文件中的内容引起,注释掉RouteConfig注册的路由。

    重新输入/account/login,发现已成功被ControllerFactory类拦截。

    现在我们修改下ControllFactory类中ProcessRequest方法的代码,实现URL和类及类中方法的映射。(注意,代码做了非常简单的处理,我们假定忽略大小写因素,路由格式也和传统MVC类似)

     1 public void ProcessRequest(HttpContext context)
     2         {
     3             context.Response.Write(string.Format("ControllerFactory来拦截请求-> URL为: {0}",context.Request.RawUrl));
     4             context.Response.Write("<br/>");
     5 
     6             /**
     7              * 将拦截的URL地址分发给对应的Controller
     8              **/
     9             //简单处理,截取URL中第一个/和/之间的字符串做为要查找的Controller对象
    10             string url = context.Request.RawUrl;
    11             string actionURL = url.IndexOf('?') > 0 ? url.Substring(0, url.IndexOf('?')) : url.Substring(0);
    12             string[] strArray = actionURL.Split('/');
    13             //得到类名称
    14             string targetClassName = (strArray[1] + "Controller");
    15             string methodName = string.Empty;
    16             if (strArray.Length > 2 && !string.IsNullOrEmpty(strArray[2]))
    17                 methodName = strArray[2];//以'/'做分割,类名称后为方法名称
    18             /**
    19              * 从URL获取类名称之后,利用反射实现方法的调用。
    20              **/
    21             //获取Controller实例
    22             object instance = Activator.CreateInstance(Type.GetType(string.Format("Demo4URLRouting.Controllers.{0}", targetClassName)));
    23             if (instance != null)
    24             {
    25                 object outputObj = null;//方法输出内容
    26                 if (string.IsNullOrEmpty(methodName) || instance.GetType().GetMethod(methodName) == null)
    27                     methodName = "Index";//如果url没有输入方法或方法不存在,默认调用Index方法
    28                 try
    29                 {
    30                     //调用实例方法
    31                     outputObj = instance.GetType().GetMethod(methodName).Invoke(instance, null);
    32                     context.Response.Write(outputObj);
    33                 }
    34                 catch(MissingMethodException mme)
    35                 {
    36                     context.Response.Write(string.Format("<font color='red'>Error! Method not Found!</font>  {0}",mme.Message));
    37                 }
    38             }
    39         }
    View Code

    在代码中,进行了简单的url分析,获取类名和方法名,再通过反射机制,实现调用。

    然后,为了配合测试,我们在解决方案中新建一个Controllers文件夹,在该文件夹下新建一个类AccountController,代码如下

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace Demo4URLRouting.Controllers
    {
        public class AccountController
        {
            public string Index()
            {
                return "this is the AccountController,<b>Index</b> method.";
            }
    
            public string HelloWorld()
            {
                return "this is <font color='red'>HelloWorld method</font> which is in the Class named AccountController.";
            }
    
        }
    }
    View Code

    AccountController类中定义了两个方法,Index()和HelloWorld()。然后我们通过浏览器进行访问

    可以看到,通过在浏览器地址中,输入/Account,实现对AccountController类中Index方法的访问;输入/Account/HelloWorld实现对AccountController类中的HelloWorld方法的访问。

    到此,我们初步实现了在WebForms环境下,URL到类的映射。此过程的核心是handlers的配置和利用反射原理调用类中的方法。Demo的不足是没有去消除大小写问题,没有更灵活的路由配置等。

    那么问题来了,MVC中这一整套URL映射的机制,是如何实现的呢?

    MVC5 URL映射机制

    实际上,在写本篇文章之前,我翻看了大量网上有关MVC的资料,发现大多数对MVC映射机制(也叫MVC路由机制)的描述都非常笼统。

    类似不懂装懂,或者让你去理解Model-View-Controller的三层,什么业务分离,或者说了半天说一堆废话。。。我是深恶痛绝的。如果仅仅是解释微软MSDN上能查到的东西?那你的解释意义在哪里?不说了,泡沫信息太多了。

    在了解MVC URL映射机制这一套原理之前,你首先要了解ASP.NET Routing。 ASP.NET Routing是.NET的一套独立组件。总的来说,它可以做两件事情:

    1. 将URL请求地址的片段转交到handler处理;

    2. 构造(创建)URL地址。

    Routing目前的信息实在太少,感兴趣的可以在MSDN上做初步了解。总的来说,Routing做了我们前面模拟做的所有事情,而且毋庸置疑,做的更好更强大。

    在MVC中,从URL到Controller,简要过程大概是这样:

    URL -->  RouteData对象 --> MvcHandler对象 --> IControllerFactory接口 --> Controller 

    这个过程很复杂,要详细阐述其过程,估计要三篇文章以上的篇幅。这里就不再阐述。

    MVC框架中,RouteConfig类中这段代码已经做了URL到Controller映射的所有工作。你所需要做的,只是匹配Controller了。

        public class RouteConfig
        {
            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 }
                );
            }
        }
    View Code

    总结

    本篇文章重点讲述了ASP.NET MVC中的URL映射机制。先是通过在WebForms中模拟URL映射,让初学者有一个直观的认识。然后简要的介绍了MVC中URL映射的机制。由于篇幅所限,在介绍URL映射机制时,只做了简要的阐述。因为知识量很大,而且建议读者要有ASP.NET Routing组件的基础。关于Routing组件,以后有空的话,我再单独写文章来讲。

    在下一篇文章中,我将讲述Controller的实际应用及扩展,项目中Controller扮演的角色。敬请期待。

    本文原始地址

  • 相关阅读:
    cmd查看端口号是否占用
    重新安装安全狗以后,apchpe 启动不了。
    springcloud组件-eureka
    关于mybatis和spring整合后的一级缓存
    SpringCloud理解篇
    mycat的读写分离
    mycat的分库分表
    Linux下mysql服务器配置
    mycat理解
    linux配置mysql
  • 原文地址:https://www.cnblogs.com/hangwei/p/4276388.html
Copyright © 2020-2023  润新知