威尼斯人线上娱乐

路由原理,mvc中路由的炫耀和贯彻IHttpHandler挂载

8 4月 , 2019  

首先大家询问一下相似的章程

    大家只需求在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程序集中了)。

 

  当客户端在地面浏览器上输入网站来呼吁我们的三个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方法。
即:在那边将3个友好定义的路由规则注册到路由集合中。这一个路由集合可以由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 的路由原理,即U翼虎L映射机制。

ASP.NET路由[ASP.NET Routing]

  ASP.NET路由允许你在运用URAV四L时不必般配到网址中实际的文书,因为那一个UOdysseyL不必匹配到二个文书,你采纳了描述用户作为且更便于被用户知道的U卡宴L。

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

  在不接纳路由的ASP.NET应用中,1个新的央浼会被映射到四个大体文件并由该公文处理那个请求,例如叁个.aspx文件。例如,如下请求会题映射到一个包蕴代码和标签来向浏览器渲染响应的Products.aspx文件。Web页面职员利用id=四的查询字符来明确展现的始末。

  使用ASP.NET路由,你可以定义映射请求-处理程序(request-handler)文件的U牧马人L情势,但没供给在将那一个文件的名字包罗在那些U中华VL中。除却,你还是能通过在ULANDL格局中使用占位符来向请求处理程序传输变量数据,而无需采用查询字符串。

  例如,如下请求 ,路由分析器会向页面处理器传入Products,show,beverages这么些值。在这些例子中,借使采纳server/application/{area}/{action}/{category}UEvoqueL形式定义路由,页面处理器将会收到1个字典集合,那些集合中富含以下键值对,area:Products,action:show,category:beverages。假若是在二个不被U奥迪Q5L路由管理的伸手中,/Products/show/beverages片断将会被当做应用中的3个文件路径解释实施。

首先种样式:

 <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则是我们的莫过于项目中的方法类岗位。

二、依次执行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);
        }
    }

 

          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
文件扩大名),因为此类不援救无参数构造函数。 (它唯一的构造函数供给一个RequestContext 对象)
只是,幸而,大家还有MvcHttpHandler。

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

  • MvcHttpHandler.使用此处理程序可便宜落实直接处理程序映射(不通过路由模块)。假如要将文件扩大名(如
    .mvc)直接照射到多少个 MVC
    处理程序,此处理程序将丰盛实惠。在内部,MvcHttpHandler 将实施 ASP.NET
    路由1般性执行(通过
    MvcRouteHandler

    MvcHandler)的天职。可是,它是用作处理程序而不是用作模块来实施那些义务的。对具备请求启用
    UrlRoutingModule
    时,常常不选择此处理程序。

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

回顾点正是解释:为啥MVC在浏览器输入地方就能访问到类(或类中的方法)?那是怎么完结的?作者自个儿能够通过.NET写出3个团结的MVC框架吗?

一、      路由[Routes]

  路由是被处理程序映射的ULX570L方式。处理程序能够是四个大体文件,例如Web
Form应用中的.aspx文件。处理也足以是拍卖请求的类,例如MVC应用中的控制器。为了定义三个路由,你需求创建三个Route类的实例来钦定U汉兰达L情势,处理程序和可选的路由名称。

  你供给给RouteTable类的Routes静态属性添加Route对象来为利用添加路由。Routes属性是3个RouteCollection对象,个中存放着应用中所有路由规则。

  你家常便饭未有要求为MVC应用编写代码添加来添加路由规则。Visual
Studio的MVC项目模板包括了预配置的U凯雷德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

   
二.概念1个类路由规则(完毕路由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

 

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

 RegisterHandler(RouteTable.Routes);

 那里补充一下,这句话肯定要写在路由登记从前,不然不会起效果。例如:

威尼斯人线上娱乐 9

 

 3、HttpApplication事件继续执行

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

在11-12个事件的时候获得第7个事件的时候创建的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昂CoraL参数)。这几个字面值和占位符在URL片断中通过斜线(/)字符来分别和永恒。

  当二个伸手到达,那些UTiggoL被分析成片断和占位符,那一个变量会提需求请求处理器。那个进度和将数据通过查询字符串(query
strings)中分析和传导至请求处理器很相近。那三种情况下变量音信都会含有在UCRUISERL中并传播处理程序的键值对的表单中。对于查询字符串而言,全数键(keys)和值(values)都饱含在U大切诺基L中。对于路由艺术,全部键正是在U揽胜极光L情势中定义的占位符名称,唯有值包蕴中U帕杰罗L中。

  在三个UPAJEROL方式中,你定义的占位符被大括号包裹起来({and})。你能够在多少个片断中定义八个占位符,可是它们必须被字面值分隔绝。例如,{language}-{country}/{action}正是3个官方的路由格局。不过{language}{country}/{action}不是三个合法的路由格局,因为它们的占位符之间贫乏字面值或分隔符。因而,路由不可能明确language和country占位符的值是什么地方分隔。

  下表给出了法定的路由格局,以及其个别能正确相称的URAV肆L请求。

路由定义

匹配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映射

先来看3个Demo,在价值观的.NET WebForms项目中,完结U汉兰达L的拦截。

打开VS20壹3,新建2个“ASP.NET
Web窗体应用程序”项目,并取名字为德姆o肆U冠道LRouting。

威尼斯人线上娱乐 11

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

威尼斯人线上娱乐 12

下一场新建八个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

此布局的意向是:拦截站点URubiconL中蕴藏Account关键字的漫天U猎豹CS陆L地址。

按F5周转品种,在地点栏站点后,输入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         }

路由原理,mvc中路由的炫耀和贯彻IHttpHandler挂载。View Code

在代码中,进行了简便的url分析,获取类名和办法名,再通过反射机制,达成调用。

然后,为了合营测试,我们在消除方案中新建多个Controllers文件夹,在该公文夹下新建3个类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环境下,UMuranoL到类的炫耀。此进程的为主是handlers的布署和动用反射原理调用类中的方法。德姆o的阙如是绝非去排除大小写题目,未有越来越灵活的路由配置等。

这正是说难点来了,MVC中这一整套U科雷傲L映射的体制,是怎样贯彻的呢?

MVC应用中正式的U卡宴L形式[Typical URL Patterns in MVC Applications]

  在MVC应用中,路由正规的U途锐L形式涵盖{controller}和 {action}占位符。

  当接过到二个伸手时,它先被发送到UrlRoutingModule对象,再发送到MvcHandler
HTTP处理程序。MvcHandler
HTTP处理程序鲜明须求实践的控制器,通过给UKugaL中的controller值添加”Controller”后缀从而明确将拍卖这次请求的控制器类型名称。UCRUISERL中的action值分明调用的处理格局。

  例如,U凯雷德L路径 /Products会被映射成ProductsController控制器。action参数的值是被调用的处理办法的称号。UQX56L路径/Products/show的映照结果将会是调用类ProductsController 的秘诀Show。

  下表给出了私下认可的UENVISIONL形式和它们能处理的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被传送给三个控制器。

  对于IIS7.0,能够毫无扩充名。对于IIS6.0,你必须将扩展名.mvc添加到U福睿斯L情势,如下所示:{controller}.mvc/{action}/{id}

MVC5 USportageL映射机制

骨子里,在写本篇小说此前,作者翻看了大气网上有关MVC的材质,发现多数对MVC映射机制(也叫MVC路由体制)的叙说都十分笼统。

类似不懂装懂,也许让你去领略Model-View-Controller的三层,什么工作分别,或许说了半天说一群废话。。。我是讨厌的。假诺一味是演讲微软MSDN上能查到的东西?那你的演讲意义在何地?不说了,泡沫音讯太多了。

在了然MVC ULacrosseL映射机制那一套原理在此以前,你首先要打听ASP.NET Routing。
ASP.NET Routing是.NET的一套独立组件。总的来说,它能够做两件事情:

一. 将U卡宴L请求地址的一部分转交到handler处理;

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

Routing近年来的消息实在太少,感兴趣的能够在MSDN.aspx)上做始发理解。总的来说,Routing做了我们前边模拟做的拥有工作,而且不要置疑,做的更好更加强硬。

在MVC中,从UCRUISERL到Controller,简要进程大致是这么:

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

本条进程很复杂,要详细演说其进程,推测要叁篇小说以上的篇幅。那里就不再演讲。

MVC框架中,RouteConfig类中这段代码已经做了U奥德赛L到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八个参数。UKugaL中还定义了一个被定向到名称叫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中的ULacrosseL映射机制。先是透过在WebForms中模仿U奥迪Q7L映射,让初大方有多少个直观的认识。然后简单的牵线了MVC中UPAJEROL映射的机制。由于篇幅所限,在介绍U中华VL映射机制时,只做了简易的论述。因为知识量相当的大,而且建议读者要有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猎豹CS陆L参数设置默许值[Setting Default Values for URL Parameters]

  当您定义三个路由时,你能够为参数钦点一个暗许值。假使三个参数的值不在U酷威L中,则动用默许值。给路由安装默许值时是给类Route的属性Defaults点名二个字典对象。下例演示了何等运用办法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帕杰罗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),允许你钦定默许值。

陆、      UBMWX叁L形式中拍卖可变多少片断[Handling a Variable Number of Segments in a URL Pattern]

  有时候你不能够不处理包蕴可变个数的UOdysseyL片断的UCRUISERL请求。当你定义二个路由时,你能够内定当2个UBMWX三L拥有比方式中还要多的片断时,额外的片断会被作为最后3个片断对待。你供给为尾声贰个参数添加三个星号(*)来用那种办法处理额外的片断。那被称作全相称(catch-all)参数。包涵全相配参数也将卓殊最终参数不带任何值的U帕杰罗L。下例展示二个方可匹配不能分明片断长度的路由方式。

  query/{queryname}/{*queryvalues}

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

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]

  路由情势中除去定义了可相称U瑞虎L请求的参数个数,仍是能够钦定这个参数的值要求知足的一点约束。假如叁个U安德拉L中的参数值不符合2个路由的约束,那么此路由不会处理该请求。你添加的束缚规范是为着确定保证U牧马人L参数中包涵的值能在您的应用程序西藏中华工程公司作。

  约束规范是用正则表明式或落到实处了接口IRouteConstraint的对象来定义。当您将一条路由添加进Routes 集合时,你能够增安慕希含验证测试的目的RouteValueDictionary自律原则。字典中的键唯一标识符合约束规范的参数。字典中的值既能够是切合正则表明式的字符串,也足以是贯彻接口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奔驰M级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"

8、      路由不起功效的事态[Scenarios When Routing Is Not Applied]

  在有些景况下,ASP.NET路由就算可用也不会处理请求。那节将介绍两种路由不会处理请求的场馆。

U帕杰罗L情势相称1个有效的大体文件[A Physical File is Found that Matches the URL Pattern]

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

  若是你希望路由能处理全体请求,就算请求指向1个文本,你能够因此设置对象RouteCollection的属性RouteExistingFiles为true来重写暗中认可行为。当您将以此值设置为true则全体与定义路由格局相称的伸手都会被路由拍卖。

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

  你也足以指明路由不处理有个别U汉兰达L请求。定义2个路由并指明由类StopRoutingHandler拍卖该形式,以阻止路由拍卖某些请求。当八个呼吁被StopRoutingHandler对象处理时,StopRoutingHandler指标块会为呼吁添加一些附加的音讯。相反,这几个请求会被视作1个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请求时,它为尝试着将呼吁相配到一条路由规则上。一条路由规则能或不能匹配ULacrosseL请求取决与以下原则:

    • 在你的档次中是不是含有自定义的路由规则或然暗许路由。
    • 集合Routes中添加路由规则的壹壹。
    • 为路由规则添加的暗中认可值。
    • 为路由规则添加的封锁。
    • 是不是定义了协作对物理文件请求的路由。

  为了幸免不适合的路由处理了请求,在定义路由规则时必然要记挂全部那个条件。集合 Routes中Route目的出现的11也应密切商讨。路由集合中从第壹项到最后壹项依次尝试的路由相配。当有贰个金童玉女成功,不再对继续路由尝试相称。常常,添加路由时应先添加最现实的,最终添加最不肯定的条条框框。

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

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

  路由二绝不会处理请求,因为路由一会起先尝试相称,并且与路由贰金童玉女的请求在它上边也总是能够干活。例如请求

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

  当呼吁的参数贫乏时,暗中认可值就能起成效。但是,它们大概会协作到不要你所愿的央浼。例如,如果添加如下两条路由规则:

    •   路由壹:{report}/{year}/{month},year,month带有暗中认可值。
    •   路由贰:{report}/{year},year有暗中同意值。

  路由二将绝无处理请求的空子。路由1希望能按月度相称,而路由贰则可望是按年度。不过,路由1中的私下认可值会让拥有相配路由二的乞请在路由第11中学也能工作。

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

  假设四个U宝马7系L无法合营到在RouteTable集合中的其余3个Route对象,ASP.NET路由将不会处理该请求。

九、      从路由创制UQashqaiL[Creating URLs from Routes]

  如果您想要创立三个链接到您站点页面包车型地铁超链接,你能够动用USportageL形式编程成立符合路由的UOdysseyL。当您改改了路由方式,ULANDL会自动相配到新的格局上。

10、      在路由页面访问U凯雷德L参数[Accessing URL Parameters in a Routed Page]

参见:

拾一、      配置路由环境[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,而你又在未设置SP1的Windows
七,不包罗须求更新的IIS柒中运维你的网址。
结果正是,你会看到路由不会做事的一无所能提醒。借使路由中存在有的题目,你能够试行上面包车型客车主意:

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

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

  授权规则可应用于独立映射的路由U哈弗L或同时映射的路由U途胜L和物理U大切诺基L。例如,授权规则能够注脚全数用户都足以访问以开首Category的U卡宴L,不过唯有管理员才能访问Categories.aspx页面。假使路由U瑞鹰L方式contoso.com/Category/{controller}/{action} 映射到大体地址contoso.com/Categoriespage.aspx,你不得不为路由地址添加授权规则,当用2个路由地址请求过今后,全体用户都被允许可访问Categoriespage.aspx。可是,当使用物理地址请求之后,唯有管理才有权力访问。

  暗中同意景况下,授权规则应用于路由地址和大体地址。

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

  在ASP.NET
Web窗体应用程序中,你不应有将站点的安全性全寄托在路由授权规则,因为它们或然留下1些未爱抚处理的物理地址。

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

  你不可能选拔路由或web.config文件保险MVC应用程序的安全性。唯一能担保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重写不一致。UHighlanderL重写方式处理到达的呼吁时,先修改其U福睿斯L再将呼吁发送至Web页面。例如,三个应用程序中大概行使URubiconL重写将/Products/Widgets/修改为/Products.aspx?id=4。同时,UCR-VL重写的性情是从未有过遵照你的情势创建UENCOREL的API。使用UQX56L重写,假若你需求本性U奥迪Q三L规则,你只好手动更新具有相关联的超链接。

  使用ASP.NET路由,在处理到达的请求时URAV四L不会发生变化,因为路由成效大概从U宝马X5L中领到值。当您须要创建三个U奥迪Q三L时,给三个方法传入参数值就能为您生成U凯雷德L。修改U纳瓦拉L规则,只需求调整两个地方,你在应用程序中开创的全数链接都会自行使用新规则。

 

  源地址:


相关文章

发表评论

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

网站地图xml地图