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 }

下一步,打开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-->

此配置的意图是:拦截站点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         }

在代码中,进行了简单的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.";
        }

    }
}

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 }
            );
        }
    }

总结

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

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

本文原始地址

时间: 2024-12-09 21:37:16

ASP.NET MVC 5 Web编程2 -- URL映射(路由原理)的相关文章

ASP.NET MVC 5 Web编程1 -- 入门

开篇引言 说起ASP.NET MVC,我想作为WebForms开发者第一点要问的是:为什么要使用它?我的理解是:MVC是更细节化的框架,“细节可控”意味着你的系统更精致.具体体现在应用上.MVC的出现,可能正是迎合Web开发越来越精致的需求.就我了解的一个大型投资管理电商平台,所用的架构就是ASP.NET MVC.MVC将来在系统应用的趋势,很可能就是大型电子商务平台.当然,WebForms并不是被“抛弃”,在快速开发,控件复用上,WebForms依然走在前面.有时候,根据需要,我们可以在同一项

ASP.NET MVC 5 Web编程4 -- Razor视图引擎

Razor简介 Razor是ASP.NET新增的一个视图引擎,由微软全球最年轻的副总裁,有着"ASP.NET之父"称呼的Scott Guthrie主导的团队开发. 主导Razor开发的Scott Guthrie,毕业于美国杜克大学.现任微软云计算与企业级产品工程部执行副总裁. Razor对传统aspx页面的写法和页面渲染能力提出了反思,所以它在代码书写和HTML生成方面都进行了优化.Rzaor的设计目标遵循以下几点: a). 尽量减少代码 b). 上手快,只需要现有的编程语言和基本的H

ASP.NET MVC 5 Web编程5 -- 页面传值的方式

本篇文章将讲述MVC的页面传值方式,具体包括:后端向前端传值(Controller向View传值):前端向后端传值(View向Controller传值):Action与Action之间的传值. 回顾 我们回顾下在ASP.NET WebForms中,页面之间最常用的传值方式,有以下几种: a). QueryString(也叫URL传值) b). Session c). Cookie d). Application e). Server.Transfer 这里不再讲述这几种传值方式的用法和利弊,在本

ASP.NET MVC 5 Web编程3 -- Controller的应用及扩展

http://www.midifan.com/moduleuser-index-420934.htmhttp://www.midifan.com/moduleuser-index-420949.htmhttp://www.midifan.com/moduleuser-index-421026.htmhttp://www.midifan.com/moduleuser-index-420782.htmhttp://www.midifan.com/moduleuser-index-421061.htm

ABP示例程序-使用AngularJs,ASP.NET MVC,Web API和EntityFramework创建N层的单页面Web应用

本片文章翻译自ABP在CodeProject上的一个简单示例程序,网站上的程序是用ABP之前的版本创建的,模板创建界面及工程文档有所改变,本文基于最新的模板创建.通过这个简单的示例可以对ABP有个更深入的了解,每个工程里应该写什么样的代码,代码如何组织以及ABP是如何在工程中发挥作用的. 源文档地址:https://www.codeproject.com/Articles/791740/Using-AngularJs-ASP-NET-MVC-Web-API-and-EntityFram 源码可以

[Asp.Net] MVC 和Web API 的区别

Asp.net MVC 和web api 的action 在获取从前台传入的数据是有很大不同 前台使用ajax的方式向后台发起post的请求 Content-Type:application/json 使用以下json对象 { "user": { "Username":"xxx", "Password":"xxxx" } } { "Username":"xxx", &

Asp.Net MVC 4 Web API 中的安全认证-使用OAuth

Asp.Net MVC 4 Web API 中的安全认证-使用OAuth 各种语言实现的oauth认证: http://oauth.net/code/ 上一篇文章介绍了如何使用基本的http认证来实现asp.net web api的跨平台安全认证. 这里说明一个如何使用oauth实现的认证.oauth大家可能不陌生.那么这里需要注意的是我们使用的是.net平台一个比较好的开源oauth库. DOTNETOPENAUTH. 就像上图所示,我们需要一个ISSSUE Server来给我们一个token

在ASP.NET MVC控制器中获取链接中的路由数据

在ASP.NET MVC中,在链接中附加路由数据有2种方式.一种是把路由数据放在匿名对象中传递: <a href="@Url.Action("GetRouteData","Home",new { ReturnUrl = Request.Url.PathAndQuery, x = 10})">走你</a> 一种是放在RouteValueDictionary对象中传递: <a href="@Url.Action

asp.net mvc vs web form

译者介绍 小小.NET学童,滴答…滴答…的雨…… 正文如下======================================================= 原文示例(VS2012): 1.  Download Simple WebForm demo - 6.7 KB 2.  Download Simple MVC Demo demo - 1.5 MB 介绍 我做为一名ASP.NET开发人员已经有很长时间了,并且我非常乐意使用ASP.NET Web Forms开发web应用程序. 在