asp.net mvc路由篇 如何找到 IHttpHandler方法介紹
我們來看看它里面主要的核心代碼吧:
protected virtual void Init(HttpApplication application)
{
if (application.Context.Items[_contextKey] == null)
{
application.Context.Items[_contextKey] = _contextKey;
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
}
}
private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
{
HttpContextBase context = new HttpContextWrapper(((HttpApplication) sender).Context);
this.PostResolveRequestCache(context);
}
public virtual void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = this.RouteCollection.GetRouteData(context);
if (routeData != null)
{
IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
}
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)
{
throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3"));
}
UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
}
else
{
context.RemapHandler(httpHandler);
}
}
}
}
在IHttpModule.Init中注冊(cè)了一個(gè)PostResolveRequestCache事件,而該事件主要是調(diào)用PostResolveRequestCache這個(gè)方法,在這個(gè)方法里面有幾句很重要的代碼是
RouteData routeData = this.RouteCollection.GetRouteData(context);
IRouteHandler routeHandler = routeData.RouteHandler;
RequestContext requestContext = new RequestContext(context, routeData);
context.Request.RequestContext = requestContext;
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
context.RemapHandler(httpHandler);
讓我們來分析第一句RouteData routeData = this.RouteCollection.GetRouteData(context) ,這句我們猜測(cè)是獲取路由信息。要想理解這句代碼又得回到我們程序中來,我們?cè)贕lobal.asax.cs文件中的RegisterRoutes方法中,默認(rèn)有這么一句
routes.MapRoute(
"Default", // 路由名稱
"{controller}/{action}/{id}", // 帶有參數(shù)的 URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數(shù)默認(rèn)值
);
這句代碼主要是注冊(cè)一個(gè)路由,這里的url要注意不能隨便寫,需要有controller和action。具體是怎么實(shí)現(xiàn)的了?
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
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;
}
各參數(shù)如下
routeName="Default", // 路由名稱
routeUrl= "{controller}/{action}/{id}", // 帶有參數(shù)的 URL
defaults=new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 參數(shù)默認(rèn)值
constraints=null
namespaces=null
在這里創(chuàng)建了一個(gè)Route實(shí)例并且把它加入到RouteCollection中了。
現(xiàn)在又讓我們回到 RouteData routeData = this.RouteCollection.GetRouteData(context);這句代碼中來,GetRouteData的主要代碼如下:
public RouteData GetRouteData(HttpContextBase httpContext)
{
using (this.GetReadLock())
{
foreach (RouteBase base2 in this)
{
RouteData routeData = base2.GetRouteData(httpContext);
if (routeData != null)
{
return routeData;
}
}
}
return null;
}
在這里的base2就是我們先前調(diào)用MapRoute是添加的Route的。而Route的GetRouteData的方法如下:
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;
}
這個(gè)方法很復(fù)雜,有許多驗(yàn)證和檢查,我們主要關(guān)心一句 RouteData data = new RouteData(this, this.RouteHandler);
當(dāng)然剩下 RequestContext requestContext = new RequestContext(context, routeData);
context.Request.RequestContext = requestContext;這2句沒什么特別了。
現(xiàn)在讓我們來看看IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);這句究竟干了些什么,意思很明白獲取Httphandler。
那么MvcRouteHandler是如何獲取一個(gè)Httphandler的了,
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
return new MvcHandler(requestContext);
}
直接返回了一個(gè)MvcHandler實(shí)例。
最有一句context.RemapHandler(httpHandler); 很簡(jiǎn)單很好明白吧,在HttpContext的RemapHandler方法中有這么一句 this._remapHandler = handler;
在HttpContext中有這個(gè)屬性
internal IHttpHandler RemapHandlerInstance
{
get
{
return this._remapHandler;
}
}
那么這個(gè)東西又是什么時(shí)候調(diào)用的了,在HttpApplication的內(nèi)部類MaterializeHandlerExecutionStep中的 void HttpApplication.IExecutionStep.Execute()方法調(diào)用
if (httpContext.RemapHandlerInstance != null)
{
httpContext.Handler = httpContext.RemapHandlerInstance;
}
看到MaterializeHandlerExecutionStep這個(gè)了類名,我想大家都能猜到吧。在內(nèi)部類PipelineStepManager中BuildSteps方法有
HttpApplication.IExecutionStep step = new HttpApplication.MaterializeHandlerExecutionStep(app);
app.AddEventMapping("ManagedPipelineHandler", RequestNotification.MapRequestHandler, false, step);
我想大家看到這里對(duì)mvc整個(gè)路由應(yīng)該有個(gè)大致的理解了吧。
- ASP.NET?MVC實(shí)現(xiàn)區(qū)域路由
- ASP.NET Core MVC學(xué)習(xí)教程之路由(Routing)
- 詳解ASP.NET Core MVC 源碼學(xué)習(xí):Routing 路由
- ASP.NET Core中使用默認(rèn)MVC路由的配置
- ASP.NET Core MVC 配置全局路由前綴
- 解讀ASP.NET 5 & MVC6系列教程(11):Routing路由
- 為ASP.NET MVC及WebApi添加路由優(yōu)先級(jí)
- ASP.NET MVC3關(guān)于生成純靜態(tài)后如何不再走路由直接訪問靜態(tài)頁面
- ASP.NET?MVC中的路由原理與用法
相關(guān)文章
asp.net mvc路由篇 如何找到 IHttpHandler方法介紹
學(xué)習(xí)是使用asp.net已經(jīng)有很長(zhǎng)一段時(shí)間了,現(xiàn)在就來分析一下mvc的整過過程吧。個(gè)人計(jì)劃寫一個(gè)mvc系列的博文,僅從源代碼的角度來分析mvc。在接觸mvc時(shí)我們一定會(huì)經(jīng)歷路由,那么路由這東東是怎么搞出來的啊2012-11-11.NET??Smobiler的復(fù)雜控件的由來與創(chuàng)造
這篇文章主要介紹了.NET Smobiler的復(fù)雜控件的由來與創(chuàng)造,Smobiler的復(fù)雜控件即利用自定義控件的方式組合控件,來使控件成為一個(gè)有機(jī)整體,里面的控件可相互協(xié)作交互,并使其達(dá)到高可用2022-08-08為什么ASP.NET Core 數(shù)據(jù)庫連接串的值和appsettings.json配的不一樣?
這篇文章主要介紹了為什么數(shù)據(jù)庫連接串的值和appsettings.json配的不一樣?下面我們就帶著疑問閱讀下文,需要的小伙伴可以參考一下,希望對(duì)你有所幫助2022-02-02.Net 7函數(shù)Ctor與CCtor使用及區(qū)別詳解
這篇文章主要為大家介紹了.Net 7函數(shù)Ctor與CCtor使用及區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11ASP.NET通過Web.config實(shí)現(xiàn)驗(yàn)證賬號(hào)密碼是否正確進(jìn)行登錄
本文是通過authentication(認(rèn)證訪問者) 和 authorization( 訪問權(quán)限),來實(shí)現(xiàn)一個(gè)簡(jiǎn)單的判斷用戶賬號(hào)密碼是否正確,需要的朋友可以參考下2021-09-09.Net?Core?配置文件讀取IOptions,IOptionsMonitor,IOptionsSnapshot
這篇文章主要介紹了.Net?Core配置文件讀取IOptions,IOptionsMonitor,IOptionsSnapshot,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09.NET?中配置從xml轉(zhuǎn)向json方法示例詳解
這篇文章主要為大家介紹了.NET?中配置從xml轉(zhuǎn)向json方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11