白话学习MVC,mvc中路由的照射和兑现IHttpHandler挂载

率先大家精通一下貌似的方式

    我们只必要在web.config配置文件中做映射处理即可。

 1、概要

当大家新建三个MVC项目时,打开她的Web.Config文件能够窥见

    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 我们知道ScriptModule 类就是管理用于 ASP.NET 中 AJAX 功能的 HTTP 模块,在此我们不做介绍
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> //这个UrlRoutingModule类才是重点
    </httpModules>

这一个HttpModule,拦截全数请求,对请求进行处理,最终成立和推行合适的拍卖请求的HttpHandler(MVC三之后,那些UrlRoutingModule集成到MVC程序集中了)。

 

  当客户端在该地浏览器上输入网站来呼吁大家的3个MVC程序时,服务端接收到请求…..此处省略N个字(和asp.net处理一样)…..

  HttpApplication的事件注册,即将 UrlRoutingModule
注册到HttpApplication的风浪中

public class UrlRoutingModule : IHttpModule
{
    protected virtual void Init(HttpApplication application)
    {   //开始只是把要执行的具体方法注册到事件中,等待事件被触发时,在执行已被注册的方法。
        application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache); 
        application.PostMapRequestHandler += new EventHandler(this.OnApplicationPostMapRequestHandler);
    }
}

  注册完事件过后,那么快要开头实践HttpApplication事件。

1、执行Global.asax文件中Application_Start方法。
即:在此间将一个本身定义的路由规则注册到路由集合中。这几个路由集合可以由RouteTable.Routes得到。

 protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RegisterRoutes(RouteTable.Routes);
        }

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Default", // 路由名称
                "{controller}/{action}/{id}", // 带有参数的 URL
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
            ); //在路由表里添加一条路由规则
        }

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

ASP.NET路由[ASP.NET Routing]

  ASP.NET路由允许你在应用UTiguanL时不必相称到网址中切实的公文,因为这些U悍马H2L不必相配到二个文书,你选取了描述用户作为且更便于被用户领会的URAV四L。

  ASP.NET MVC框架和ASP.NET动态数据(Dynamic
Data)扩充路由为MVC应用和动态数据应用扩展了特点。

  在不选拔路由的ASP.NET应用中,一个新的哀告会被映射到二个物理文件并由该文件处理那一个请求,例如三个.aspx文件。例如,如下请求会题映射到3个富含代码和标签来向浏览器渲染响应的Products.aspx文件。Web页面人士利用id=4的查询字符来明确呈现的始末。

  使用ASP.NET路由,你能够定义映射请求-处理程序(request-handler)文件的U锐界L情势,但没须求在将这一个文件的名字蕴含在这几个U奥德赛L中。除此而外,你还能通过在U奥迪Q3L形式中运用占位符来向请求处理程序传输变量数据,而不用选取查询字符串。

  例如,如下请求 ,路由分析器会向页面处理器传入Products,show,beverages那么些值。在这么些例子中,借使运用server/application/{area}/{action}/{category}U兰德酷路泽L格局定义路由,页面处理器将会收到八个字典集合,那一个集合中富含以下键值对,area:Products,action:show,category:beverages。借使是在2个不被U大切诺基L路由管理的央求中,/Products/show/beverages片断将会被当作应用中的2个文书路径解释施行。

第1种样式:

 <system.web>
    <urlMappings enabled="true">

      <add url="~/d" mappedUrl="SmackBio.WebSocketSDK.GenericHandler"/>

    </urlMappings>

申明:那里的url便是我们供给在伏乞的具体写法,然后mappedUrl则是大家其实项目中的处理地方。

其次种形式:

 <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>    
      <add path="/socket" verb="*" name="GenericHandler" type="SmackBio.WebSocketSDK.GenericHandler"/>
    </handlers>
  </system.webServer>

评释:那里的path就是大家呼吁的入口地址,type则是大家的实际上项目中的方法类职位。

2、依次执行HttpApplication的轩然大波。  

BeginRequest
AuthenticateRequest
PostAuthenticateRequest
AuthorizeRequest
PostAuthorizeRequest
ResolveRequestCache
PostResolveRequestCache 在UrlRoutingModule类中,在此事件中注册了一个执行方法,即:OnApplicationPostResolveRequestCache
PostMapRequestHandler                                                       OnApplicationPostMapRequestHandler
AcquireRequestState
PostAcquireRequestState
PreRequesHandlerExecute
PostRequeshandlerExecute
ReleaseRequesState
PostReleaseRequestState
UpdateRequestCache
PostUpdateRequestCach
LogRequest
PostLogRequest
EndRequest

OnApplicationPostResolveRequestCache方法

private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
{
    HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context);
    this.PostResolveRequestCache(context);
}
//这里用HttpContextWrapper类包装当前的HttpContext,实质上也是一个请求的上下文。他可以使用诸如Typemock Isolator或Rhino Mocks的Mock对象框进行模拟变得更简单。
//并把这个包装之后的上下文作为PostResolveRequestCache的参数

------------------------------------------------------------------------------------------------------------------

public virtual void PostResolveRequestCache(HttpContextBase context)
{
    RouteData routeData = this.RouteCollection.GetRouteData(context);
//GetRouteData方法内部遍历路由集合中的每个路由对象去和上下文中指定的请求URL去匹配。如成功,就返回当前的路由对象RouteData,如不成功,返回null
//this.RouteCollection就是RouteTable.Routes,即:路由集合。

    if (routeData != null)----这里便是判断是否匹配成功
    {
        IRouteHandler routeHandler = routeData.RouteHandler;----//获取一个处理当前匹配成功的路由的对象
     //这个routeHandler其实就是一个MvcRouteHandle类
     ----因为在第一句中执行的GetRouteData方法中,为RouteData的RouteHandler属性赋值为MvcRouteHandler
        if (routeHandler == null)
        {
            throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoRouteHandler, new object[0]));
        }
        if (!(routeHandler is StopRoutingHandler))
        {
            RequestContext requestContext = new RequestContext(context, routeData);//把当前的请求的信息和与当前请求匹配成功的路由信息再包装起来。
            IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
            //根据包装后的请求信息,最终得到一个MvcHandler
       ---MvcRouteHandler中只有一个方法,GetHttpHandler方法,返回MvcHandler,Mvc中处理请求的类。
       ---PageRouteHandler中也只有一个方法,GetHttpHandler方法,返回的是Page,asp.net中处理请求的类。 

美高梅开户网址 1美高梅开户网址 2MvcRouteHandler

    public class MvcRouteHandler : IRouteHandler
    {

        protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new MvcHandler(requestContext);
        }

        IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
        {
            return this.GetHttpHandler(requestContext);
        }
    }

白话学习MVC,mvc中路由的照射和兑现IHttpHandler挂载。 

          if (httpHandler == null)

            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.UrlRoutingModule_NoHttpHandler, new object[] { routeHandler.GetType() }));
            }
            //RequestData类是UrlRoutingModule类中嵌套的一个私有类,把处理请求的类和当前请求的虚拟路径
            RequestData data2 = new RequestData {
                OriginalPath = context.Request.Path,
                HttpHandler = httpHandler
            };
            context.Items[_requestDataKey] = data2;
            //把封装的处理类MvcHandler和请求的虚拟路径,赋值到 HttpContextWrapper类中。(这样在用到处理类时,就需要实例化,直接取值即可)
            //HttpContextWrapper类包装当前的HttpContext,实质上也是一个请求的上下文。
            context.RewritePath("~/UrlRouting.axd");

context.RemapHandler(httpHandler);//博客是里这里是这么一句,但是我反编译没找到,可能是版本的问题吧!
//将MvcHandler 实例 映射到管线中(通常我们是利用web.config 进行配置的,但是MvcHandler 没有默认无参构造函数,所以直接通过向其传递一个实例进行映射)

} } } 

OnApplicationPostMapRequestHandler方法
该方法做的事情很简单,就是重写下请求路径,让输出的路径和输入的路径相同,在这里用来记忆输入路径的是context.Items[],从上下两段代码中可以看到.
这个事件负责根据文件扩展名映射到具体的httphandle处理类,而MVC的URL信息没有具体的文件后缀名 为了使处理模块能够在iis7中实现路由,则采取了这么一种简单的解决办法。先把路径指向~/UrlRouting.axd,在此事件中会设置一个UrlRouting.axd类型的Handler避免报错,并在下一步事件中替换掉此处的Handler再把~/UrlRouting.axd这个路径给改回来。

美高梅开户网址 3美高梅开户网址 4View Code

private void OnApplicationPostMapRequestHandler(object sender, EventArgs e)
{
    HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context);
    this.PostMapRequestHandler(context);
}



 public virtual void PostMapRequestHandler(HttpContextBase context)
{
    RequestData data = (RequestData) context.Items[_requestDataKey];
    if (data != null)
    {
        context.RewritePath(data.OriginalPath);
        context.Handler = data.HttpHandler;
    }
}

 

上文中拿走了贰个MvcHandler类实例,MvcHandler继承完成了IHttpAsyncHandler,
IHttpHandler,
IRequiresSessionState多少个接口。而那多少个接口借使都落实了,在MVC框架下是还是不是其它http请求就足以通吃了呢?从MSDN我们深知,事实不是如此的:只顾,固然MvcHandler 完结 IHttpHandler,也不可能将其映射为处理程序(例如.mvc
文件扩大名),因为此类不援救无参数构造函数。 (它唯一的构造函数须求2个RequestContext 对象)
可是,幸亏,大家还有MvcHttpHandler。

如您所知,MvcHttpHandler能够“弥补”MvcHandler的供不应求,为何如此说吧?因为MvcHandler未有无参的构造函数,由此就算MvcHandler达成了
IHttpHandler接口,在IIS中也不能够将其映射为某类文件扩充名的处理程序,而MvcHttpHandler就提供了不经过路由模块的情况下直接处理映射的处理程序。

  • MvcHttpHandler.使用此处理程序可方便落实直接处理程序映射(不通过路由模块)。假诺要将文件扩充名(如
    .mvc)直接照射到三个 MVC
    处理程序,此处理程序将十二分管用。在里边,MvcHttpHandler 将实行 ASP.NET
    路由普通执行(通过
    MvcRouteHandler

    MvcHandler)的天职。不过,它是用作处理程序而不是用作模块来推行这几个职务的。对负有请求启用
    UrlRoutingModule
    时,经常不接纳此处理程序。

  • MvcHandler.此处理程序负责运行MVC 应用程序的 ASP.NET 管道。它从
    MVC 控制器工厂接收
    Controller
    实例;此控制器处理请求的愈发处理。请注意,即使
    MvcHandler
    实现了
    IHttpHandler,它也无法映照为处理程序(例如,针对
    .mvc
    文件扩大名),因为此类不补助无参数构造函数(而处理程序供给是无参数构造函数)。(其唯1的构造函数须求
    RequestContext
    对象。)

总结点就是表达:为何MVC在浏览器输入地点就能访问到类(或类中的方法)?那是如何是好到的?笔者要好能够通过.NET写出二个友好的MVC框架吗?

一、      路由[Routes]

  路由是被处理程序映射的UENCOREL情势。处理程序能够是三个大体文件,例如Web
Form应用中的.aspx文件。处理也足以是处理请求的类,例如MVC应用中的控制器。为了定义一个路由,你要求成立贰个Route类的实例来钦命U逍客L情势,处理程序和可选的路由名称。

  你须求给RouteTable类的Routes静态属性添加Route对象来为使用添加路由。Routes属性是2个RouteCollection对象,其中存放着应用中全部路由规则。

  你平凡未有须要为MVC应用编写代码添加来添加路由规则。Visual
Studio的MVC项目模板包括了预配置的URAV肆L路由规则。他们定义在MvcApplication类,那些类在Global.asax文件中。

mvc路由安插方式

这是我们分化接纳的炫耀格局。不过在mvc路由中大家挂起壹般处理程序却发现不行了,上面大家就要安插路由艺术实行映射。

在mvc中我们分为三步:

    1.兑现拍卖代码程序(完毕一般处理程序继承类IHttpHandler)

美高梅开户网址 5美高梅开户网址 6

 1   public class GenericHandler : IHttpHandler
 2     {
 3         public void ProcessRequest(HttpContext context)
 4         {
 5             if (context.IsWebSocketRequest || context.IsWebSocketRequestUpgrading)
 6             {
 7                 context.AcceptWebSocketRequest(new SBWebSocketHandler());
 8             }
 9             else
10             {
11                 context.Response.ContentType = "text/plain";
12                 context.Response.Write("Service running");
13             }
14         }
15 
16         public bool IsReusable
17         {
18             get
19             {
20                 return false;
21             }
22         }
23     }

View Code

   
2.概念三个类路由规则(实现路由IRouteHandler接口然后针对处理代码程序类)

美高梅开户网址 7美高梅开户网址 8

 public class PlainRouteHandler : IRouteHandler
    {

        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new GenericHandler();
        }
    }

 public static void RegisterHandler(RouteCollection routes)
        {

            RouteTable.Routes.Add("socket",
                 new Route("socket", new MvcZodiac.Controllers.PlainRouteHandler()));
        }

View Code

 

    3.注册到程序中(在Global.asax中的Application_Start方法注册)

 RegisterHandler(RouteTable.Routes);

 那里补充一下,那句话肯定要写在路由注册此前,不然不会起功用。例如:

美高梅开户网址 9

 

 三、HttpApplication事件继续执行

BeginRequest
AuthenticateRequest
PostAuthenticateRequest
AuthorizeRequest
PostAuthorizeRequest
ResolveRequestCache
PostResolveRequestCache 
PostMapRequestHandler                                                       
AcquireRequestState
PostAcquireRequestState
PreRequesHandlerExecute
PostRequeshandlerExecute
ReleaseRequesState
PostReleaseRequestState
UpdateRequestCache
PostUpdateRequestCach
LogRequest
PostLogRequest
EndRequest

在1壹-11个事件的时候获得第十三个事件的时候创造的MVCHandler对象执行他的ProcessRequest方法。

public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
{
    protected virtual void ProcessRequest(HttpContext httpContext)
    {
        //使用HttpContextWrapper对HttpContext进行封装,封装的目的是为了解耦以获得可测试性.然后从RequestContext.RouteData中提取Controller名称.
        HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
        this.ProcessRequest(httpContext2);
    }

    protected internal virtual void ProcessRequest(HttpContextBase httpContext)
    {
        IController controller;
        IControllerFactory controllerFactory;
        this.ProcessRequestInit(httpContext, out controller, out controllerFactory); //获取到Controler实例       ----下节详细介绍
        try
        {
                controller.Execute(this.RequestContext); //当前Controler对象的Action的创建与执行                   ----下节详细介绍   
                执行包括:加载TempData, 创建及执行Action,处理Action返回的ActionResult ,保存TempData数据。
        }
        finally
        {
            controllerFactory.ReleaseController(controller); //释放当前Controler对象
        }
    }
}

流程如下图,MvcHandler实例来拍卖请求,他做为处理的基本,当成功之后,释放当前的Controler实例,继续执行HttpApplication事件

美高梅开户网址 10

 此图摘自:

答案是:可以。

二、      URL模式[URL Patterns]

  一个U揽胜极光L形式能够分包字面值(literal)和可变的占位符(参考U福特ExplorerL参数)。那么些字面值和占位符在UPRADOL片断中通过斜线(/)字符来分别和永恒。

  当3个呼吁到达,那个U宝马X3L被分析成片断和占位符,这个变量会提供给请求处理器。这一个进度和将数据通过查询字符串(query
strings)中分析和传导至请求处理器很类似。那三种意况下变量消息都会包括在UKugaL中并传播处理程序的键值对的表单中。对于查询字符串而言,全体键(keys)和值(values)都包括在UKugaL中。对于路由艺术,全数键就是在U悍马H2L情势中定义的占位符名称,只有值蕴涵中ULX570L中。

  在三个U大切诺基L方式中,你定义的占位符被大括号包裹起来({and})。你能够在二个片断中定义多少个占位符,不过它们必须被字面值分隔离。例如,{language}-{country}/{action}正是1个合法的路由格局。但是{language}{country}/{action}不是四个官方的路由格局,因为它们的占位符之间缺少字面值或分隔符。由此,路由不恐怕分明language和country占位符的值是何方分隔。

  下表给出了合法的路由方式,以及其个别能正确相配的UTiggoL请求。

路由定义

匹配URL示例

{controller}/{action}/{id}

/Products/show/beverages

{table}/Details.aspx

/Products/Details.aspx

blog/{action}/{entry}

/blog/show/123

{reporttype}/{year}/{month}/{day}

/sales/2008/1/5

{locale}/{action}

/US/show

{language}-{country}/{action}

/en-US/show

模拟URL映射

先来看2个德姆o,在价值观的.NET WebForms项目中,达成U奥德赛L的阻止。

打开VS201三,新建二个“ASP.NET
Web窗体应用程序”项目,并取名称为德姆o4U陆风X8LRouting。

美高梅开户网址 11

为了便利测试,注释掉Default.aspx页面包车型客车剧情和模板引用。那样做今后,看起来是这么

美高梅开户网址 12

然后新建3个ControllerFactory类,完毕IHttpHandler接口。

美高梅开户网址 13美高梅开户网址 14

 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配置

美高梅开户网址 15

代码如下:

美高梅开户网址 16美高梅开户网址 17

<!--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

此布局的用意是:拦截站点UTucsonL中带有Account关键字的整整U猎豹CS陆L地址。

按F五运维品种,在地方栏站点后,输入account,发现已成功被ControllerFactory类拦截。

美高梅开户网址 18

连续,输入/account/login。发现地址未被拦截。而是跳转到了暗中同意项指标登6页面。

美高梅开户网址 19

怎么回事呢?

原先,是种类下的Global.asax文件中的内容引起,注释掉RouteConfig注册的路由。

美高梅开户网址 20

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

美高梅开户网址 21

目前大家修改下ControllFactory类中ProcessRequest方法的代码,达成U普拉多L和类及类中艺术的炫耀。(注意,代码做了相当简单的拍卖,大家只要忽略大小写因素,路由格式也和观念MVC类似)

美高梅开户网址 22美高梅开户网址 23

 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,代码如下

美高梅开户网址 24美高梅开户网址 25

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()。然后我们经过浏览器举行走访

美高梅开户网址 26

美高梅开户网址 27

能够见到,通过在浏览器地址中,输入/Account,完结对AccountController类中Index方法的走访;输入/Account/HelloWorld达成对AccountController类中的HelloWorld方法的访问。

到此,大家开头达成了在WebForms环境下,U智跑L到类的投射。此进程的主干是handlers的安排和选择反射原理调用类中的方法。德姆o的缺乏是从未有过去破除大小写标题,未有更加灵敏的路由配置等。

那便是说难题来了,MVC中那1整套URL映射的编写制定,是怎么着兑现的啊?

MVC应用中标准的U索罗德L形式[Typical URL Patterns in MVC Applications]

  在MVC应用中,路由专业的USportageL格局涵盖{controller}和 {action}占位符。

  当接过到1个伸手时,它先被发送到UrlRoutingModule对象,再发送到MvcHandler
HTTP处理程序。MvcHandler
HTTP处理程序鲜明须求举办的控制器,通过给U凯雷德L中的controller值添加”Controller”后缀从而明确将拍卖此番请求的控制器类型名称。U途观L中的action值明确调用的拍卖方法。

  例如,UOdysseyL路径 /Products会被映射成ProductsController控制器。action参数的值是被调用的处理格局的称谓。U奥迪Q叁L路径/Products/show的照射结果将会是调用类ProductsController 的秘诀Show。

  下表给出了暗中认可的UPAJEROL格局和它们能处理的U汉兰达L请求示例。

默认URL模式

匹配URL示例

{controller}/{action}/{id}

http://server/application/Products/show/beverages

{resource}.axd/{*pathInfo}

http://server/application/WebResource.axd?d=…

  路由使用模式 {resource}.axd/{*pathInfo} 来阻止对网络文件的呼吁,例如WebReource.axd,ScriptResource.axd被传送给三个控制器。

  对于IIS七.0,能够毫无扩张名。对于IIS陆.0,你不能够不将扩充名.mvc添加到URAV四L格局,如下所示:{controller}.mvc/{action}/{id}

MVC5 UPAJEROL映射机制

实际上,在写本篇作品在此之前,笔者翻看了大气网上关于MVC的素材,发现多数对MVC映射机制(也叫MVC路由体制)的描述都分外笼统。

好像不懂装懂,大概让您去领略Model-View-Controller的三层,什么业务分别,可能说了半天说一群废话。。。笔者是讨厌的。假如唯有是解释微软MSDN上能查到的东西?那您的表明意义在何地?不说了,泡沫新闻太多了。

在打听MVC U猎豹CS陆L映射机制这一套原理此前,你首先要打听ASP.NET Routing。
ASP.NET Routing是.NET的一套独立组件。总的来说,它可以做两件事情:

壹. 将UPRADOL请求地址的1对转交到handler处理;

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

Routing近日的音信实在太少,感兴趣的能够在MSDN.aspx)上做始发询问。总的来说,Routing做了大家眼下模拟做的装有事情,而且不要置疑,做的越来越好越来越强硬。

在MVC中,从UOdysseyL到Controller,简要进度大概是那般:

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

以此进程很复杂,要详细阐释其经过,估算要三篇小说以上的字数。那里就不再演讲。

MVC框架中,RouteConfig类中那段代码已经做了UOdysseyL到Controller映射的保有工作。你所需求做的,只是相配Controller了。

美高梅开户网址 28美高梅开户网址 29

    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

三、      为Web Forms应用程序添加路由[Add Routes to a Web Forms Application]

  在Web
Form应用中,你能够行使类RouteCollection的方法MapPageRoute(String,
String,
String) 成立路由。方法MapPageRoute创建Route对象并将其增加RouteCollection对象中。你须求为Route对象在参数在钦赐一些性子,用来传给方法MapPageRoute。

  经常情状下,你在艺术中增进的路由会被Global.asax文件中Application_Start 方法处理器调用。那种艺术确定保障了这么些路由在应用程序运行时能够符合规律调用。它也同意你在为应用程序做单元测试时可直接调用该方法。当你在做单元测试时要是想要直接调用三个情势,该措施在登记时就不可能不是静态(Visual
Basic中Shared)且有叁个RouteCollection参数。

  下例中示范了Global.asax文件中添加一个Route目的,该指标定义了action和categoryName多个参数。URL中还定义了多个被定向到名称为Categories.aspx的大体页面。

美高梅开户网址 30美高梅开户网址 31

protected void Application_Start(object sender, EventArgs e)
{
    RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapPageRoute("",
        "Category/{action}/{categoryName}",
        "~/categoriespage.aspx");
}

View Code

总结

本篇小说首要讲述了ASP.NET
MVC中的UCRUISERL映射机制。先是通过在WebForms中模仿U科雷傲L映射,让初专家有八个直观的认识。然后简短的牵线了MVC中U君越L映射的编写制定。由于篇幅所限,在介绍UWranglerL映射机制时,只做了回顾的阐发。因为知识量相当大,而且提议读者要有ASP.NET
Routing组件的根基。关于Routing组件,今后有空的话,俺再独自写文章来讲。

在下壹篇小说中,小编将讲述Controller的其实使用及扩展,项目中Controller扮演的剧中人物。敬请期待。

正文原始地址。

肆、      为MVC应用程序添加路由[Adding Routes to an MVC Application]

  在MVC应用程序中,假如你选用MVC落成控制器的约定,即派生自类ControllerBase且以“Controller”结尾命名,那么您根本不须要搬运添加路由。预配置的路由将会执行你达成的控制器类中的处理形式。

  借使你指望在MVC应用程序中添加自定义的路由,你能够采纳办法美高梅开户网址 ,MapRoute(RouteCollection,
String,
String) 来取代方法MapPageRoute(String,
String,
String)。

  上边示例中示范在Global.asax文件中开创私下认可MVC路由的代码,就是Visual
Studio中MVC应用程序的门类模板。

美高梅开户网址 32美高梅开户网址 33

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",                                              // Route name 
            "{controller}/{action}/{id}",                           // URL with parameters 
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );

    }

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
    }
}

View Code

伍、      为U奥迪Q三L参数设置默许值[Setting Default Values for URL Parameters]

  当您定义贰个路由时,你可以为参数内定三个暗许值。假如一个参数的值不在U陆风X8L中,则接纳私下认可值。给路由设置私下认可值时是给类Route的属性Defaults点名1个字典对象。下例演示了什么使用办法MapPageRoute(String,
String, String, Boolean,
RouteValueDictionary)加上二个包涵私下认可值的路由。

美高梅开户网址 34美高梅开户网址 35

void Application_Start(object sender, EventArgs e) 
{
    RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapPageRoute("",
        "Category/{action}/{categoryName}",
        "~/categoriespage.aspx",
        true,
        new RouteValueDictionary 
            {{"categoryName", "food"}, {"action", "show"}});
}

View Code

  下图中示范了ASP.NET路由拍卖U奥迪Q⑤L请求,路由定义(categoryName的默许值为food,action暗中认可为show)和分析结果:

URL

Parameter values

/Category

action = "show" (default value)

categoryName = "food" (default value)

/Category/add

action = "add"

categoryName = "food" (default value)

/Category/add/beverages

action = "add"

categoryName= "beverages"

  对于MVC应用程序,方法RouteCollectionExtensions.MapRoute的重载版本,如MapRoute(RouteCollection,
String, String, Object,
Object),允许你内定默许值。

6、      U悍马H二L形式中处理可变多少片断[Handling a Variable Number of Segments in a URL Pattern]

  有时候你必须处理包蕴可变个数的U奥迪Q伍L片断的U大切诺基L请求。当您定义3个路由时,你能够钦赐当三个UQashqaiL拥有比形式中还要多的片断时,额外的片断会被看做最终二个片断对待。你要求为最后二个参数添加多个星号(*)来用那种办法处理额外的片断。那被称作全相称(catch-all)参数。蕴含全相配参数也将相当最终参数不带任何值的U奥迪Q五L。下例展现1个可以相配不恐怕分明片断长度的路由形式。

  query/{queryname}/{*queryvalues}

  下图中示范了ASP.NET路由拍卖U翼虎L请求,路由定义和分析结果。

URL

Parameter values

/query/select/bikes/onsale

queryname = "select"

queryvalues = "bikes/onsale"

/query/select/bikes

queryname = "select"

queryvalues = "bikes"

/query/select

queryname = "select"

queryvalues = Empty string

柒、      为路由添加封锁[Adding Constraints to Routes]

  路由方式中除了定义了可匹配UBMWX3L请求的参数个数,还足以钦赐那一个参数的值须要知足的少数约束。假设叁个UBMWX三L中的参数值不相符八个路由的约束,那么此路由不会处理该请求。你添加的束缚原则是为了确定保证ULacrosseL参数中隐含的值能在您的应用程序中央银行事。

  约束规范是用正则表达式或促成了接口IRouteConstraint的靶子来定义。当您将一条路由添加进Routes 集合时,你能够增三元含验证测试的对象RouteValueDictionary自律规范。字典中的键唯1标识符合约束原则的参数。字典中的值既能够是切合正则表明式的字符串,也能够是落到实处接口IRouteConstraint的对象。

  假诺您提供三个字符串,路由会将它当做符合正则表明式的值,并调用Regex类的IsMatch()方法检查该参数值是不是切合规则。正则表达式总是不区分轻重缓急写检讨。

  假如你提供了二个IRouteConstraint对象,ASP.NET路由调用IRouteConstraint目的的Match()方法来检查参数值是还是不是合法。Match()方法重临布尔值来申明参数值是还是不是合法。

  下例中示范怎样选择格局MapPageRoute 添加一条路由,并为参数locale和year添加约束。(MVC应用程序中,使用格局MapRoute。)

美高梅开户网址 36美高梅开户网址 37

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapPageRoute("",
        "Category/{action}/{categoryName}",
        "~/categoriespage.aspx",
        true,
        new RouteValueDictionary 
            {{"categoryName", "food"}, {"action", "show"}},
        new RouteValueDictionary 
            {{"locale", "[a-z]{2}-[a-z]{2}"},{"year", @"\d{4}"}}
       );
}

View Code

  当路由拍卖U凯雷德L请求时,例子中路由的概念和剖析后的结果如下表所示:

URL

Result

/US

No match. Both locale and year are required.

/US/08

No match. The constraint on year requires 4 digits.

/US/2008

locale = "US"

year = "2008"

八、      路由不起功用的情状[Scenarios When Routing Is Not Applied]

  在壹些意况下,ASP.NET路由尽管可用也不会处理请求。那节将介绍三种路由不会处理请求的状态。

UBMWX伍L方式相配多少个有效的大体文件[A Physical File is Found that Matches the URL Pattern]

  默许情状下,路由不会处理请求时,将其映射到Web服务器上3个已存在的物理文件。例如,借使存在多少个大体文件Products/Beverages/Coffee.aspx,路由就不会处理请求

  假使你希望路由能处理全体请求,尽管请求指向3个文本,你能够通过安装对象RouteCollection的属性RouteExistingFiles为true来重写暗中认可行为。当你将那个值设置为true则全体与定义路由形式匹配的央浼都会被路由拍卖。

显式禁止使用路由[Routing Is Explicitly Disabled for a URL Pattern]

  你也足以指明路由不处理有个别UHummerH二L请求。定义多少个路由并指明由类StopRoutingHandler拍卖该形式,以阻挡路由拍卖有些请求。当三个呼吁被StopRoutingHandler指标处理时,StopRoutingHandler对象块会为呼吁添加一些额外的消息。相反,那个请求会被用作一个ASP.NET页面、Web服务大概别的ASP.NET终端处理。你能够使用方法RouteCollection.Ignore(MVC应用程序中RouteCollectionExtensions.IgnoreRoute)来成立使用类 StopRoutingHandler的路由。下边演示如何堵住对WebResource.axd文件的乞求。

美高梅开户网址 38美高梅开户网址 39

public static void RegisterRoutes(RouteCollection routes)
{
  routes.Ignore("{resource}.axd/{*pathInfo}");
}

View Code

  U汉兰达L是怎么样被路由格外的[How URLs Are Matched to Routes]

  当路由先河拍卖U途达L请求时,它为尝试着将请求相配到一条路由规则上。一条路由规则能还是不能够般配U汉兰达L请求取决与以下标准:

    • 在您的种类中是还是不是含有自定义的路由规则恐怕暗许路由。
    • 集合Routes中添加路由规则的各种。
    • 为路由规则添加的默许值。
    • 为路由规则添加的牢笼。
    • 是还是不是定义了分外对物理文件请求的路由。

  为了防止不确切的路由处理了请求,在定义路由规则时肯定要思量全体这个原则。集合 Routes中Route目的出现的逐条也应仔细思忖。路由集合中从第二项到最终一项依次尝试的路由相配。当有1个1二分成功,不再对继续路由尝试匹配。平时,添加路由时应先添加最具体的,最终添加最不明朗的条条框框。

  例如你添加了如下路由规则:

    •   路由规则一,{controller}/{action}/{id}
    •   路由规则二, products/show/{id}

  路由2绝不会处理请求,因为路由一会初阶尝试相配,并且与路由2一双两好的伸手在它上面也再3再四能够干活。例如请求

    •   controller is products.
    •   action is show.
    •   id is bikes.

  当呼吁的参数贫乏时,暗中认可值就能起效果。不过,它们或然会合营到不要你所愿的乞求。例如,借使添加如下两条路由规则:

    •   路由1:{report}/{year}/{month},year,month带有暗中认可值。
    •   路由二:{report}/{year},year有暗许值。

  路由二将绝无处理请求的火候。路由1目的在于能按月度相称,而路由二则盼望是按年度。不过,路由第11中学的暗中同意值会让具有相称路由二的乞求在路由第11中学也能干活。

  你能够在路由中涵盖常量来幸免那种歧义,例如annual/{report}/{year}和monthly/{report}/{year}/{month}。

  若是三个UEscortL无法相配到在RouteTable集合中的别样1个Route对象,ASP.NET路由将不会处理该请求。

9、      从路由成立U冠道L[Creating URLs from Routes]

  假诺你想要创设二个链接到您站点页面包车型大巴超链接,你能够行使U奥迪Q7L格局编制程序创建符合路由的ULANDL。当你改改了路由方式,U奔驰M级L会自动相配到新的形式上。

10、      在路由页面访问U奥迪Q五L参数[Accessing URL Parameters in a Routed Page]

参见:

10一、      配置路由环境[Configuration Settings for Routing]

  ASP.NET中,要让应用程序接济路由成效,须要加上如下配置:

美高梅开户网址 40美高梅开户网址 41

<configuration>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <!-- more -->
    </modules>
  </system.webServer>
</configuration>

View Code

  当runAllManagedModulesForAllRequests为true时,如下URL

  然则,IIS七的换代导致不必添加配置项runAllManagedModulesForAllRequests,因为它自然就支持ASP.NET路由成效。

  若是你的站点运营在IIS7且IIS已履新,你就不要安装该配置项为true。事实上,并不推荐设置它,因为它为具备请求扩大了不须要的操作。假设设置该配置为true,全部请求,包涵.htm,.jpg和其他静态文件都会通过ASP.NET请求通道。

  默认runAllManagedModulesForAllRequests为false。如若网址配置文件中一直不强烈将其设置为true,而你又在未设置SP一的Windows
柒,不包罗须求更新的IIS柒中运作你的网址。
结果就是,你会晤到路由不会工作的不当提醒。即使路由中留存有的标题,你能够试试上边的措施:

    •   将Windows 柒更新到SP一,因为它添加了IIS七的翻新。
    •   安装微软件在从前小说中的描述的更新。
    •  
      在Web.Config文件中装置runAllManagedModulesForAllRequests为true。注意那会添加1些额外开销。

102、      ASP.NET路由与安全性[ASP.NET Routing and Security]

  授权规则可利用于独立映射的路由USportageL或同时映射的路由UHummerH二L和物理U奥迪Q5L。例如,授权规则能够评释全体用户都足以访问以伊始Category的UENCOREL,不过唯有管理员才能访问Categories.aspx页面。假诺路由UOdysseyL方式contoso.com/Category/{controller}/{action} 映射到大体地址contoso.com/Categoriespage.aspx,你不得不为路由地址添加授权规则,当用多个路由地址请求过之后,全数用户都被允许可访问Categoriespage.aspx。可是,当使用物理地址请求之后,唯有管理才有权力访问。

  默许意况下,授权规则应用于路由地址和情理地址。

十三、      ASP.NET Web Form和路由安全性[ASP.NET Web Forms and Route Security]

  在ASP.NET
Web窗体应用程序中,你不应该将站点的安全性全寄托在路由授权规则,因为它们只怕留下一些未爱护处理的情理地址。

104、      ASP.NET MVC和路由安全性[ASP.NET MVC and Route Security]

  你不可能使用路由或web.config文件有限支持MVC应用程序的安全性。唯1能确定保证MVC应用安全的做法是给持有控制器采取本性 AuthorizeAttribute ,并在签到和登记的方式(action)上使用天性AllowAnonymousAttribute 。

  增加请查看:

十五、      参考类[Class Reference]

Class

Description

Route

Represents a route in a Web Forms or MVC application.

DynamicDataRoute

Represents a route in a Dynamic Data application.

RouteBase

Serves as the base class for all classes that represent an ASP.NET route.

RouteTable

Stores the routes for an application.

RouteCollection

Provides methods that enable you to manage a collection of routes.

RouteCollectionExtensions

Provides additional methods that enable you to manage a collection of routes in MVC applications.

RouteData

Contains the values for a requested route.

RequestContext

Contains information about the HTTP request that corresponds to a route.

StopRoutingHandler

Provides a way to specify that ASP.NET routing should not handle requests for a URL pattern.

PageRouteHandler

Provides a way to define routes for Web Forms applications.

RouteValueDictionary

Provides a way to store route ConstraintsDefaults, and DataTokensobjects.

VirtualPathData

Provides a way to generate URLs from route information.

十六、      ASP.NET路由VS URL重写[ASP.NET Routing versus URL Rewriting]

  ASP.NET路由与U卡宴L重写分裂。ULANDL重写格局处理到达的央求时,先修改其U中华VL再将请求发送至Web页面。例如,3个应用程序中恐怕选拔URubiconL重写将/Products/Widgets/修改为/Products.aspx?id=肆。同时,UHummerH二L重写的风味是从未依照你的格局开创U奇骏L的API。使用U途达L重写,假若您要求脾气U逍客L规则,你不得不手动更新具有相关联的超链接。

  使用ASP.NET路由,在拍卖到达的伏乞时U中华VL不会暴发变化,因为路由作用也许从UEscortL中领到值。当你必要创建1个U途睿欧L时,给三个措施传入参数值就能为您生成U奇骏L。修改URL规则,只需求调动1个地方,你在应用程序中创造的兼具链接都会自行使用新规则。

 

  源地址:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图