新建一个MVC项目启动后,首先访问的地址是http://localhost:xxx/Home/Index,这时候我们也明白因为在程序中有个叫做Home的控制器,并且在这个控制器下面有个叫做Index的方法,基于这种对应的关系,才有了这种结果,那么这种对应关系是如何产生,如何工作的了?

在我们网站在第一次启动的时候,会去访问一个全局的配置文件Global.asax下面的Application_Start()方法,代码如下

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing; namespace Test
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}

在这个方法中就注册了我们的路由配置,相关的注册文件都是在在App_Start目录下

路由配置文件RouteConfig.cs,内容如下

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace Test
{
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 }
);
}
}
}

首先是忽略路由,满足匹配会被忽略,如果没有特殊需求,这个地方就不需要更改,

name表示路由的名称,同一个路由集合中,路由名称必须唯一,不能够有重名,

url就是正则表达式,用于http://localhost:xxx/后路径地址的匹配,

defaults表示缺省路由,也就是默认的路由.这是一个路由规则增删的方法,并且默认的路由为home/index,

还有一个比较常用的参数是constraints,用于条件约束,简单实例如下:

     public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); //假若Home下有Test(int year,int month,int day)方法
//home/Test_2017_06_05可以访问至该方法
//home/Test_2017_6_05是无法访问
routes.MapRoute(
name: "Constraints",
url: "{controller}/{action}_{year}_{month}_{day}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
//条件参数,约束后面参数(此处简单正则:4位数字,2位数字,2位数字)
constraints: new { year = @"^\d{4}", month = @"^\d{2}", day = @"^\d{2}" }); routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
}

路由浅析

那么路由究竟是如何工作的,下面是2个与路由工作十分紧密的2个方法的源码,任何http请求进入后,都会先被它们处理

 public virtual void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = RouteCollection.GetRouteData(context);
if (routeData != null)
{
IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString("UrlRoutingModule_NoRouteHandler")));
}
if (!(routeHandler is StopRoutingHandler))
{
RequestContext requestContext = new RequestContext(context, routeData);
context.Request.RequestContext = requestContext;
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[]
{
routeHandler.GetType()
}));
}
if (httpHandler is UrlAuthFailureHandler)
{
if (FormsAuthenticationModule.FormsAuthRequired)
{
UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
return;
}
throw new HttpException(, SR.GetString("Assess_Denied_Description3"));
}
context.RemapHandler(httpHandler);
}
}
}

PostResolveRequestCache

 public RouteData GetRouteData(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
if (httpContext.Request == null)
{
throw new ArgumentException(SR.GetString("RouteTable_ContextMissingRequest"), "httpContext");
}
if (base.Count == )
{
return null;
}
bool flag = false;
bool flag2 = false;
if (!RouteExistingFiles)
{
flag = IsRouteToExistingFile(httpContext);
flag2 = true;
if (flag)
{
return null;
}
}
using (GetReadLock())
{
foreach (RouteBase item in this)
{
RouteData routeData = item.GetRouteData(httpContext);
if (routeData != null)
{
if (!item.RouteExistingFiles)
{
if (!flag2)
{
flag = IsRouteToExistingFile(httpContext);
flag2 = true;
}
if (flag)
{
return null;
}
}
return routeData;
}
}
}
return null;
}

GetRouteData

大致分析下这段源码,我们可以得出下列比较重要的结论

1在路由匹配之前,先一步检查了物理文件的存在,所以mvc和webform可以共存,如果存在满足路径条件的aspx文件,它会优先被访问

2路由是从上到下逐个匹配的,所以排列的顺序对于路由匹配是非常重要的

路由扩展

在上述基础下,我们对路由有了大概的了解,对此我们可以简单扩展一下

路由并不是只能够在路径规则上做文章,我们也可以继承路由的基类RouteBase自定义一些路由,然后把自定义的路由放入注册路由集合中,调准好顺序,实现我们想要的结果.因为能够得到HttpContext这个用户请求的上下文,我们可以完成很多扩展,例如检查ip,浏览器类型,参数等等,下面我们就简单的实现不同浏览器访问到不同路径的功能,如下:

     public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); //注意顺序
routes.Add("Agent",new Agent()); routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
} }
public class Agent : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
if (httpContext.Request.UserAgent.Contains("Chrome/63.0.3239.132"))
{
var data = new RouteData(this, new MvcRouteHandler());
data.Values.Add("controller", "Home");
data.Values.Add("action", "About");
return data;
}
else
{
return null;
}
} public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}

一定得注意路由排列的顺序,如果将上面的Agent路由放在Default路由后面,那么就直接会访问到Home/Index,而不会去判断.

我们也可以通过自定义继承了RouteBase的Route类,来完成特殊路径的扩展,如下

   public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.Add(new Route("Test",new TestRouteHandler())); routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
} public class TestRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new TestHandler();
}
}
public class TestHandler : IHttpHandler
{
public bool IsReusable => true; public void ProcessRequest(HttpContext context)
{
context.Response.Write("Test");
}
}

效果如下:

出自:博客园-半路独行

原文地址:https://www.cnblogs.com/banluduxing/p/9185159.html

本文出自于http://www.cnblogs.com/banluduxing 转载请注明出处。

.Net MVC5路由机制与扩展的更多相关文章

  1. MVC5路由系统机制详细讲解

    请求一个ASP.NET mvc的网站和以前的web form是有区别的,ASP.NET MVC框架内部给我们提供了路由机制,当IIS接受到一个请求时,会先看是否请求了一个静态资源(.html,css, ...

  2. ASP.NET MVC5路由系统机制详细讲解

    请求一个ASP.NET mvc的网站和以前的web form是有区别的,ASP.NET MVC框架内部给我们提供了路由机制,当IIS接受到一个请求时,会先看是否请求了一个静态资源(.html,css, ...

  3. MVC5之路由机制

    ---恢复内容开始--- MVC是一种模式,是基于asp.net上的一种设计.路由机制不属于MVC,路由机制属于asp.net.因此,mvc的路由机制就是基于asp.net路由机制上的一种“自定制”. ...

  4. typecho路由机制详解

    本文介绍的是typecho的路由机制,引自 不烦恼路由机制是typecho的核心,有很多功能都是基于路由功能设计的,理解并熟悉TE的路由机制将非常有助于插件的开发. 完整的路由表如下: array ( ...

  5. asp.net MVC 路由机制

    1:ASP.NET的路由机制主要有两种用途: -->1:匹配请求的Url,将这些请求映射到控制器 -->2:选择一个匹配的路由,构造出一个Url 2:ASP.NET路由机制与URL重写的区 ...

  6. asp.net MVC 路由机制 Route

    1:ASP.NET的路由机制主要有两种用途: -->1:匹配请求的Url,将这些请求映射到控制器 -->2:选择一个匹配的路由,构造出一个Url 2:ASP.NET路由机制与URL重写的区 ...

  7. MVC路由机制(转)

    今天我来缕一下MVC的路由机制,因为使用MVC已经快一年了,之前也只是上手,没有系统去理会.项目完了,结合实际使用,回过头来深入一下. MVC 学习索引(点击即可) 一个请求进入IIS后 传统ASP. ...

  8. 【C#】 WebApi 路由机制剖析

    C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转自:https://blog.csdn.net/wulex/article/details/71601478 2017年05月11日 10 ...

  9. C#进阶系列——WebApi 路由机制剖析:你准备好了吗?

    前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: ...

随机推荐

  1. snmp获取设备相关管理信息

    在本文中,作者将向我们展示如何用snmp代理监视网络设备,甚至发送软件警告. 网络上很多代理在为我们服务.只要我们开启UDP/161,162端口,这些代理就会以Management Informati ...

  2. Spring cloud Hystrix的配置属性优先级和详解

    Hystrix配置属性详解 Hystrix可以配置属性的有以下类型: Execution:控制HystrixCommand.run() 的如何执行 Fallback: 控制HystrixCommand ...

  3. 在C#里面获得应用程序的当前路径

    Environment.CurrentDirectory——获取应用程序的当前工作目录.System.IO.Directory.GetCurrentDirectory()AppDomain.Curre ...

  4. spring jpa sqls

    package com.example.repository; import java.util.List; import org.springframework.data.jpa.repositor ...

  5. Git----时光穿梭机之工作区和暂存区03

    Git和其他版本控制系统SVN的一个不同之处就是有暂存区的概念 先来看看名词解释 工作区(Working Directory) 就是你在我电脑里能看到的目录,比如我的learngittest文件夹就是 ...

  6. spring mvc请求参数中文乱码解决方案

    POST 请求 在web.xml中加上增加过滤器 <filter> <filter-name>encodingFilter</filter-name> <fi ...

  7. Glow Shader

    [Glow Shader] Glow Shader基于BlurShader来实现.总的来说分为2步: 1.利用BlurShader渲染出BlurTexture. 2.将BlurTexture与SrcT ...

  8. java.io.FileNotFoundException(系统找不到指定的路径。)

    报错:java.io.FileNotFoundException(系统找不到指定的路径.) 解决方法: 1.检查文件路径是否正确 2.另外,使用OutputStream时,如果文件不存在,会自动创建文 ...

  9. Python编程快速上手(七)Unsplash批量下载器

    首发于个人博客:http://rhinoc.top/post/python_7.html 程序描述 V1.0输入关键字搜索图片,模拟页面下拉获取更多图片,页面加载完成后获取图片链接并下载至指定文件夹. ...

  10. 用jquery实现html5的placeholder功能

    html5的placeholder功能在表单中经常用到,它主要用来提示用户输入信息,当用户点击该输入框之后,提示文字会自动消失. 我们用jquery实现类似的功能: 当输入框获得焦点时,清空输入框中的 ...