Asp.net Mvc 请求是如何到达 MvcHandler的——UrlRoutingModule、MvcRouteHandler分析,并造个轮子
这个是转载自:http://www.cnblogs.com/keyindex/archive/2012/08/11/2634005.html(那个比较容易忘记,希望博主不要生气的)
前言
本文假定读者对 HttpModule 、HttpHandler和IIS的处理流程有一定的了解,如果为了解可以参考以下链接。文中大部分代码通过Reflector反编译 System.Web.dll 得到,.net 版本为4.0
IIS 5.0 和 6.0 的 ASP.NET 应用程序生命周期概述
Asp.net MVC 程序虽然开发的模式不同,但是其本质上还是 Asp.net。其利用了HttpModule 和 HttpHandler 做了扩展,可以参考博客园里的大牛——Artech 相关系列文章。
本文主要关注UrlRoutingModule 、MvcRouteHandler 两个类的源代码,进而分析客户的请求是如何到达MvcHandler 的。
Asp.net MVc 程序启动流程 需要关注的行为
- 1、Application启动时先通过RouteTable把URL映射到Handler
- 2、通过UrlRouting Module 这个HttpModule 拦截用户请求。
我们知道,HttpModule 是注册在 Web.config 中的,可是当你打开Asp.net MVc 程序的Web .Config 时 却没有发现该配置节,原因是:"它已经默认的写在全局的中"。应此 你可以在 “$\Windows\Microsoft.NET\Framework\版本号\Config\Web.config“ 中找到 " <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />”
UrlRoutingModule 源码
UrlRoutingModule 位于 System.web.dll 文件中,利用Reflector 可以查看到其源码:
UrlRoutingModuel
UrlHttpModule 实现了 IHttpModule 接口
HTTP Module在应用程序发出请求时被调用的并进行特定的事件处理。 HTTP Module作为请求管道的一部分调用,它们能够访问请求过程中请求周期中的各种管线事件。
Http Module必须经过注册才能从请求管道接收通知。 注册 HTTP 模块的最常用方法是在应用程序的 Web.config 文件中进行注册。 在 IIS 7.0 中,统一的请求管道使您还可以通过其他方式注册模块,其中包括通过 IIS 管理器和 Appcmd.exe 命令行工具。
当 ASP.NET 创建表示您的应用程序的 HttpApplication 类的实例时,将创建已注册的任何模块的实例。 在创建模块时,将调用它的 Init 方法,并且模块会自行初始化。在模块的 Init 方法中,可以注册各种应用程序事件的处理程序(如 BeginRequest 或 EndRequest)。
可以看到 UrlHttpModule 在 init 方法中注册了PostResolveRequestCache 事件的处理程序。
关于Asp.net的生命周期事件可以参考:
http://msdn.microsoft.com/zh-cn/library/ms178472
http://msdn.microsoft.com/zh-cn/library/bb470252
http://msdn.microsoft.com/zh-cn/library/ms178473
PostResolveRequestCache
该事件在完成缓存解析并投递时触发。
在UrlRoutingModule中它主要是进行上下文的初始化,同时根据传递过来的路由信息获取指定IHttpHandler (其实就是我们的MvcHandler类)
最后通过 context.RemapHandler() 代码将HttpHandler 处理程序映射到 管线处理中。
在 PostResolveRequestCache 之前分别触发的事件有:
引发 BeginRequest 事件。
引发 AuthenticateRequest 事件。
引发 PostAuthenticateRequest 事件。
引发 AuthorizeRequest 事件。
引发 PostAuthorizeRequest 事件。
引发 ResolveRequestCache 事件。
http://i.msdn.microsoft.com/dynimg/IC5405.png
核心逻辑代码:
1 //获取路由信息
2 RouteData routeData = this.RouteCollection.GetRouteData(context);
3 IRouteHandler routeHandler = routeData.RouteHandler;
4 //构建请求上下文
5 RequestContext requestContext = new RequestContext(context, routeData);
6 context.Request.RequestContext = requestContext;
7 IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
8 //将MvcHandler 实例 映射到管线中(通常我们是利用web.config 进行配置的,但是MvcHandler 没有默认无参构造函数,所以直接通过向其传递一个实例
9 //进行映射)
10 context.RemapHandler(httpHandler);
如何获取到MvcRouteHandler?
MvcRouteHandler 实现了 IRouteHandler接口。 上文的 IRouteHandler routeHandler=routeData.RouteHandler; 在Asp.net MVc 程序中实际上获取的是MvcRouteHandler实例。
RouteData 类中包含了 IRouteHandler实例的引用,它通过 RouteData 的构造函数:
public RouteData(RouteBase route, IRouteHandler routeHandler);
或者 属性
public IRouteHandler RouteHandler { get; set; }
进行注入。
我们再往回搜索,RouteData实例是通过 RouteCollection.GetRouteData(Context) 方法获取的。查看该方法的主要逻辑实现:
using (this.GetReadLock())
{
foreach (RouteBase base2 in this)
{
RouteData routeData = base2.GetRouteData(httpContext);
if (routeData != null)
{
return routeData;
}
}
}
可以看到通过 RouteBase 类的 GetRouteData(HttpContext)获取了 RouteData实例,并且将第一个部位Null的值返回。 我们需要深入查看RouteBase GetRouteData方法。 RouteBase 是抽象类,其方法是在 Route上具体实现的。(这里又引出一个问题,程序是何时将 Route实例绑定到了 RouteBase上)。
Route类
深入到Route 类中 发现其和 RouteData 一样, IRouteHandler 也是通过 构造参数 或 属性对 IRouteHandler 进行了注入。
public override RouteData GetRouteData(HttpContextBase httpContext)
{
string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
RouteValueDictionary values = this._parsedRoute.Match(virtualPath, this.Defaults);
if (values == null)
{
return null;
}
RouteData data = new RouteData(this, this.RouteHandler);
if (!this.ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest))
{
return null;
}
foreach (KeyValuePair<string, object> pair in values)
{
data.Values.Add(pair.Key, pair.Value);
}
if (this.DataTokens != null)
{
foreach (KeyValuePair<string, object> pair2 in this.DataTokens)
{
data.DataTokens[pair2.Key] = pair2.Value;
}
}
return data;
}
关于Asp.net Mvc 中的 MapRoute() 方法
在Asp.net MVc 程序Global 文件的RegisterRoutes 方法里,RouteCollection 类使用的是MapRoute 方法添加的路由,该方法是一个扩展方法。它位于System.Web.Mvc 的RouteCollectionExtensions类中。
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
if (routes == null) {
throw new ArgumentNullException("routes");
}
if (url == null) {
throw new ArgumentNullException("url");
} Route route = new Route(url, new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
}; if ((namespaces != null) && (namespaces.Length > 0)) {
route.DataTokens["Namespaces"] = namespaces;
} routes.Add(name, route); return route;
}
查看上面的关键行:
Route route = new Route(url, new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
可以清楚看到,当我们在Asp.net MVc 程序里使用MapRoute()添加路由时,会生成一个 Route 类的实例,并且该实例在生成时会被注入 MvcRouteHandler 实例。 最后被添加到 RouteCollection的集合里(Route 和 MvcRouteHandler 都是以多态形式存在于 RouteCollection中的),这样就建立了一个关系映射表,只有请求的上下文通过该上下文的验证,就可以返回对应MvcRouteHandler实例。
- MvcRouteHandler 实现了 IRouteHandler接口
- Route 继承了 RouteBase 抽象类。
- RouteCollection 中维护着一个 RouteBase 集合。
如何根据路由信息获取MvcHandler
在Asp.net Mvc 程序 启动时,会触发 Appliction_start 方法,该方法调用了 RouteTable,生成一个全局RouteCollection(单件模式),并将其作为参数传递到RegisterRoutes 方法中。
registerRoutes 方法里通过MapRoute 向 RouteCollection添加路由。 添加的路由是包含MvcRouteHandler实例的Route。
当用户的请求到达IIS后,由于Asp.net MVC 注册了一个HttpModule(UrlRoutingModule) ,应此会触发对应的管线事件处理方法。
1、根据上下文获取RouteData方法, 其内部 实现是:从RouteCollection中遍历RouteBase(实际为Route)实例,并调用RouteBase的GetRouteData() 方法,如果上下文与路由匹配
该方法就会构造一个 RouteData实例,并将 this.IRouteHandler的实例 注入(在Application映射路由时,每个Route实例都包含一个MvcRouteHandler实例的引用)。
2、从 RouteData中 获取IRouteHandler 实例,即 MvcRouteHandler
3、构建上下文,创建RequestContext 该类仅包含 HttpContextBase 和 RouteData 。调用MvcHandler的构造函数需要传递该参数(可以知道请求的Controller、action名等信息),MvcHandler 实现了 IHttpHandler,注意它与MvcHttpHandler 是不相同的:
MvcHandler . 此处理程序负责启动用于 MVC 应用程序的 ASP.NET 管道。 它从 MVC 控制器工厂接收 Controller 实例;此控制器处理请求的进一步处理。 注意,即使 MvcHandler 实现 IHttpHandler,也不能将其映射为处理程序(例如,.mvc 文件扩展名),因为该类不支持无参数构造函数。 (它唯一的构造函数需要一个 RequestContext 对象。)
因此 在 UrlRoutenModule 中 是 通过 HttpContext.RemapHttp(HttpHandler) 。 直接将 一个实例 映射到处理程序上 。(不需要通过系统对其实例化)。
MvcHttpHandler . 此处理程序用于在不通过路由模块的情况下帮助直接处理程序映射。 如果您希望一个文件的扩展名(如 .mvc)直接映射到一个 MVC 处理程序,这很有用。 在内部,MvcHttpHandler 执行 ASP.NET 路由通常执行的相同任务(通过 MvcRouteHandler 和 MvcHandler)。 但是,它将这些任务作为处理程序而不是模块来执行。 UrlRoutingModule 为所有请求启用时,通常不使用此处理程序。
)
4、调用IRouteHandler的 GetHttpHandler 方法 获取 IHttpHandler实例。(即调用了MvcRouteHandler实例的GetHttpHandler 方法,生成了一个 MvcHandler 实例)
5、向当前上下文注册 IHttpHandler 实例,进入 Controller 处理。
经过以上步骤,我们就大致了解到了Asp.net Mvc程序启动后,用户的请求是如何到达HttpHandler的。
RouteTable 类
这个类很简单只包含一个静态的RouteCollection 属性,是一个单件类。
在Asp.net MVc 中application_start 方法里 调用了RouteTable来获取唯一的RouteCollection实例,
所以在UrlRouteModuel中可以通过RouteTable.Routes获取所配置的路由集合。
RouteCollection类
是一个集合类,内部维护着一个RouteBase 以路由名作为Key的字典集合, 所以我们可以给路由命名。主要的属性和方法有:
RouteData GetRouteData(HttpContextBase httpContext)
该方法遍历集合内部的RouteBase实体,并返回第一个非Null的RouteData ,具体的RouteData实例,是由所遍历的RouteBase 通过调用 RouteBase.GetRouteData(HttpContext)方法获取的 。
返回的RouteData 中包含一个 IRouteHandler 对象,该接口的只有一个方法,GetHttpHandler,用于获取IHttpHandler 对象。
VirtualPathData GetVirtualPath(...)
该方法具有多个重载,当您使用 ASP.NET 路由框架生成 URL 时,GetVirtualPath 方法将返回 VirtualPathData 类的一个实例。 VirtualPathData 类包含与所提供的上下文匹配路由的相关信息。
Route MapPageRoute(...)
该方法用于向路由集合中添加路由,提供此方法是为了方便编码, 它等效于调用 Add 方法。其内部实现的主要代码为:
Route item = new Route(routeUrl, defaults, constraints, dataTokens, new PageRouteHandler(physicalFile, checkPhysicalUrlAccess));
注册使用 PageRouteHandler 类创建的 Route 对象。
在Asp.net Mvc 方法中,并没有利用该方法向集合中添加路由而是通过了了 MapRoute()方法 这是一个扩展方法,定义在了 RouteCollectionExtensions 类中。
static Route MapRoute(this RouteCollection routes, ......)
这是一个扩展方法,并且具有多个重载,目的是方便编码,用于向RouteCollection中 添加路由。其内部主要是 生成了一个 以 MvcRouteHandler 为 路由处理的Route 并将其加入到集合中。
Route route = new Route(url, new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
IRouteHandler 接口
接口的定义很简单,只有一个 GetHttpHandler 方法用于返回 一个 IHttpHandler 对象。在 Route 对象,及 RouteData对象中 都包含该对象的引用。该接口定义了一种协议, 指定了 Route 即路由应该有哪一个处理对象进行处理。 它是 Route 到 Handler的 重要桥梁。
RouteBase 类
这是一个抽象类,RouteBase 类用于定义应用程序中的路由。 在定义路由时,通常使用 Route 类,Route 类是从 RouteBase 类派生的。 但是,如果要提供与 Route 类所提供的功能不同的功能,则可以创建一个从 RouteBase 派生的类,并实现所需的属性和方法。
主要方法有:GetRouteData 在派生类中重写时,会返回有关请求的路由信息。
GetVirtualPath 在派生类中重写时,会检查路由是否与指定值匹配,如果匹配,则生成一个 URL,然后检索有关该路由的信息。
Route 类
可以通过 Route 类指定 ASP.NET 应用程序中路由的处理方式。 可以为要映射的每个 URL 模式创建一个 Route 对象,该类可处理与该模式相对应的请求。 当应用程序收到请求时,ASP.NET 路由会循环访问 Routes 集合中的路由,以查找与该 URL 模式匹配的第一个路由。
可将 Url 属性设置为 URL 模式。 该 URL 模式包含某些分段,这些分段位于 HTTP 请求中应用程序名称之后。 例如,在 URL http://www.contoso.com/products/show/beverages 中,该模式应用于 products/show/beverages。 包含三个分段的模式(如 {controller}/{action}/{id})与 URL http://www.contoso.com/products/show/beverages 匹配。 每个分段由 / 字符分隔。 如果分段位于大括号({ 和 })内,则表明该分段是一个 URL 参数。 ASP.NET 路由会检索请求中的值并将其分配给 URL 参数。 在上面的示例中,URL 参数 action 被赋予值 show。 如果该分段不在大括号内,则该值被视为文本值。将 Defaults 属性设置为 RouteValueDictionary 对象,该对象包含当 URL 中缺少某个参数时所使用的值,或者包含用于设置 URL 中未参数化的其他值的值。 将 Constraints 属性设置为 RouteValueDictionary 对象,该对象包含的值为正则表达式或 IRouteConstraint 对象。 这些值用于确定参数值是否有效。
public override RouteData GetRouteData(HttpContextBase httpContext)
{
string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
RouteValueDictionary values = this._parsedRoute.Match(virtualPath, this.Defaults);
if (values == null)
{
return null;
}
RouteData data = new RouteData(this, this.RouteHandler);
if (!this.ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest))
{
return null;
}
foreach (KeyValuePair<string, object> pair in values)
{
data.Values.Add(pair.Key, pair.Value);
}
if (this.DataTokens != null)
{
foreach (KeyValuePair<string, object> pair2 in this.DataTokens)
{
data.DataTokens[pair2.Key] = pair2.Value;
}
}
return data;
}
该方法重写了父类的方法,返回一个RouteData 作。方法一开始 首先通过 ParsedRoute 类的 Match 方法进行路由匹配,匹配成功后则生成一个RouteData对象实例。
ParsedRoute 类
该类是一个内部类,用于匹配、绑定URL,大家可以参考:
http://www.cnblogs.com/JeffreyZhao/archive/2009/08/24/more-on-ParsedRoute.html
http://www.cnblogs.com/JeffreyZhao/archive/2009/08/19/use-the-internal-feature.html
http://www.cnblogs.com/JeffreyZhao/archive/2009/08/24/domain-parser-based-on-parsedroute.html
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
BoundUrl url = this._parsedRoute.Bind(requestContext.RouteData.Values, values, this.Defaults, this.Constraints);
if (url == null)
{
return null;
}
if (!this.ProcessConstraints(requestContext.HttpContext, url.Values, RouteDirection.UrlGeneration))
{
return null;
}
VirtualPathData data = new VirtualPathData(this, url.Url);
if (this.DataTokens != null)
{
foreach (KeyValuePair<string, object> pair in this.DataTokens)
{
data.DataTokens[pair.Key] = pair.Value;
}
}
return data;
}
该方法返回与路由相关联的URL信息。其内部是通过ParsedRoute 类的Bind 把RouteData 绑定到一个BoundUrl 对象中。 如果有约束在则进行验证,最后返回一个 VirtualPathData 对象。
protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
object obj2;
IRouteConstraint constraint2 = constraint as IRouteConstraint;
if (constraint2 != null)
{
return constraint2.Match(httpContext, this, parameterName, values, routeDirection);
}
string str = constraint as string;
if (str == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("Route_ValidationMustBeStringOrCustomConstraint"), new object[] { parameterName, this.Url }));
}
values.TryGetValue(parameterName, out obj2);
string input = Convert.ToString(obj2, CultureInfo.InvariantCulture);
string pattern = "^(" + str + ")$";
return Regex.IsMatch(input, pattern, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
这是一个路由约束的处理方法,可以看到如果传递的 object constraint 是一个 IRouteConstraint 类型 则直接调用 其Match 方法。
如果正则表达式字符串,利用正则表达式进行验证,否则抛出异常。
造一个简陋的轮子
不要再造轮子是软件设计的一个准则,但是在学习研究时,造一个简单的轮子能更好的帮我们了解其原理。
创建一个HttpHandler 类,让Asp.net程序通过路由,运行我们指定的HttpHandler,同时在Handler中能够获取路由信息。
1、创建一个类库项目,在项目里创建一个WheelHandler类并实现IHttpHandler接口,这个类只有一个构造函数构造函数需要传递一个 RequestContext
public class WheelHandler : IHttpHandler
{
public WheelHandler(RequestContext requestContext)
{ this.RequestContext = requestContext;
} #region IHttpHandler Members public bool IsReusable
{
get { return true; }
} public void ProcessRequest(HttpContext context)
{
context.Response.Write(String.Format("this is a Wheel for {0}Controller and {1}action "
, this.RequestContext.RouteData.Values["Controller"]
, this.RequestContext.RouteData.Values["Action"]));
context.Response.End();
} #endregion public RequestContext RequestContext { get; private set; }
}
WheelHandler没有默认的无参构造函数,所以不能直接在Web.config 中注册。ProcessRequest对象很简单,就是输出传入的路由信息。
我们需要定义一个IRouteHandler对象,当路由被捕获时,返回一个WheelHandler,然后将其映射到Http处理中。
2.定义WheelRouteHandler
public class WheelRouteHandler : IRouteHandler
{ public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new WheelHandler(requestContext);
} IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
return this.GetHttpHandler(requestContext);
}
}
3、映射路由和WheelRouteHandler。
我们可以自定义一个派生自RouteBase 的类,进行特定的路由处理,但是本例是一个简单的"轮子",因此继续使用Route类,只需要在生成Route时 向其注入 WheelRouteHandler即可。
因此我们需要修改添加路由的方式,这里模仿MVc 利用扩展方法。当然你也可以不用扩展方法,在添加路由是直接使用Add方法,记得注入WheelRouteHandler便行。
public static Route MapWheelRoute(this RouteCollection routes, string name, string url, object defaults)
{
return MapWheelRoute(routes, name, url, defaults, null, null);
} public static Route MapWheelRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (url == null)
{
throw new ArgumentNullException("url");
}
// 在这里注册 Route 与 WheelRouteHandler的映射关系
Route route = new Route(url, new WheelRouteHandler())
{
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
}; if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens["Namespaces"] = namespaces;
} routes.Add(name, route); return route;
}
MapWheelRoute 方法里 调用了Route构造函数,并传入一个WheelRouteHandler对象。
4、创建HttpModule 对象
自定义的HttpModule的责任是,构建上下文,创建HttpHandler对象并将它映射到Http处理程序里去。
public void Init(HttpApplication context)
{
context.PostResolveRequestCache += new EventHandler(context_PostResolveRequestCache);
} void context_PostResolveRequestCache(object sender, EventArgs e)
{
HttpContextBase context = new HttpContextWrapper(((HttpApplication)sender).Context);
this.PostResolveRequestCache(context); } private void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = RouteTable.Routes.GetRouteData(context); if (routeData == null)
{
throw new InvalidOperationException();
} IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException();
} RequestContext requestContext = new RequestContext(context, routeData);
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null)
{
throw new InvalidOperationException("无法创建对应的HttpHandler对象");
}
context.RemapHandler(httpHandler); }
这里我们也是模仿Mvc 捕获的是PostResolveRequestCache事件进行处理,处理时首先将 包装HttpContext对象为 HttpContextBase对象。然后通过GetRouteData 获取RouteData对象,它包含有IRouteHandler对象。获取到IRouteHandler对象后,需要构造 一个RequestContext 对象(该对象很简单就是包含上下文和路由信息)因为 创建WheelHandler 需要该对象。
创建好IHttpHandler对象后,利用RemapHandler方法将其映射为处理程序。
5、注册路由 和Module
新建一个空的Asp.net 项目,移除里面所有的Aspx文件,事实上只要保留Global和 Web.Config文件即可。在Global 里注册路由:
完成最后我们还需要组成自定义的HttpModule
在Web.Config 中添加如下配置:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="WheelRouting" type="WheelRouting.WheelRoutingModule,WheelRouting"/>
</modules> </system.webServer>
关于 HttpModule的介绍 可以参考:演练:创建和注册自定义 HTTP 模块
下面是运行结果:
Controller默认值为 Home Action 默认值为 index
源码:点击下载
Asp.net Mvc 请求是如何到达 MvcHandler的——UrlRoutingModule、MvcRouteHandler分析,并造个轮子的更多相关文章
- Asp.Net MVC 请求原理分析
分析Asp.Net MVC的请求过程,我们从以下几方面看: 配置:IIS网站的配置可以分为两个块:全局 Web.Config 和本站 Web.Config . Asp.Net Routing属于全局性 ...
- 【MVC】ASP.NET MVC 请求生命周期
当一个asp.net mvc应用程序提出请求,为了响应请求,包含一些请求执行流程步骤! 在asp.net mvc应用程序Http request和Http response 过程中,主要包含8个步骤: ...
- ASP.NET MVC 请求流程
一.应用程序启动 1.Application_Start方法,程序启动 2.RegisterRoutes方法,注册路由 3.System.Web.Mvc.RouteCollectionExtensio ...
- asp.net mvc请求流程
收对应用程序的第一个请求 > 执行路由 > 创建 MVC 请求处理程序 > 创建控制器 > 执行控制器 > 调用操作 > 执行结果
- asp.net mvc请求响应模型原理回顾
根据讲师所讲总结了一下(可能存在些描述错误) -------------mvc进入asp.net管道原理: (在执行httpapplication管道之前mvc和asp.net是相同的,不同之处在于管 ...
- ASP.NET MVC 请求流程:Controller
1.请求进入时,.NET Framework就找出所有的HttpModule,以此调用它们的Init方法,如下图所示,我们重点关注"UrlRoutingModule-4.0"的Ht ...
- ASP.NET MVC 请求流程:Route
1.RouteTable RouteTable翻译过来的意思就是路由表,一个Web应用程序具有一个全局的路由表,该路由表通过System.Web.Routiing.RouteTable的静态只读属性R ...
- ASP.NET MVC请求参数字符串之区分空与NULL
开发中经常会写增删改查的功能,这里记录下在更新操作时遇到的一个问题. 假设一个模型对应数据库中某一张表,在更新时便需要区分是一次性更新全部字段还是仅更新部分字段.希望能做到传递某个参数时便更新,未传递 ...
- ASP.NET MVC请求特殊静态文件返回404 Not Found
今天在请求静态的json档案以及woff2档案,会返回404错误,需要在Web.Config里修改: <system.webServer> <modules> <remo ...
随机推荐
- asp.net事件委托易理解实例
比如说一个公司(场景),你是老板,手下有两个员工,小张和小王. 你命令小王,如果小张玩游戏,则小王扣去小张500元钱.这就是现实中的委托.实际上,在写程序中,程序员就是老板,小张和小王就是两个对象.小 ...
- asp.net 实现 tts
之前用WinForm实现tts已经成功,就调用了下系统的类库.但我把相同的代码搬到asp.net上时却碰到了许多问题,查了好多网站.试过了很多方法,到现在算是做出了一部分吧. 之前调用微软的TTS是用 ...
- UTF8转GB2312(UTF8解码)
小弟C++上手没多久,代码不严谨之处敬请见谅.英语也不是很好,有的是直接使用的拼音. string MyUTF_8toGB2312(string str) { ,,str.c_str(),-,NULL ...
- 关于毕设WiFi选型
毕设做基于WiFi的家庭灯光影音控制,现在主要是WiFi模块上的选型,自己选了ESP8266. 一开始是看到了机智云的内容,想尝试机智云.但是目前没有母版,不知道怎么下手. 接下来就先尝试通过通用类型 ...
- ZigZag-LeetCode
题目: The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows l ...
- 保存BASE64编码图片
1.前端上传用户图片时,一些K数较小图片,头像图标等 .以bass64编码后的字符串传到服务器. 2.服务器接收并保留到本地. // 页面上点击保存 $.post('/imgupload/save', ...
- MooTools 异步请求验证
http://www.chinamootools.com/ 问题 MooTools 异步请求例子 <{foreach from=array('0','1','2','3','4') item=c ...
- django的model对象转化成dict
今天发现一个掉渣天的方法,Django的forms包里面有一个方法:model_to_dict(),它可以将一个model对象转化成dict. In [1]: from apps.dormitory. ...
- yii 的mvc工作流
Yii 使用了 Web 开发中广泛采用的模型-视图-控制器(MVC)设计模式. MVC的目标是将业务逻辑从用户界面的考虑中分离,这样开发者就可以更容易地改变每一部分而不会影响其他. 在 MVC中,模型 ...
- 4Sum 解答
Question Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c ...