ASP.NET MVC是基于ASP.NET之上的扩展框架,同样要通过HttpApplication管道去执行

ASP.NET MVC本质上就是换了一个HttpHandler来执行,而实现这个操作的就是UrlRoutingModule

public class UrlRoutingModule : IHttpModule
{
// Fields
private static readonly object _contextKey = new object();
private static readonly object _requestDataKey = new object();
private RouteCollection _routeCollection;

// Methods
protected virtual void Dispose()
{
}

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);
}

[Obsolete("This method is obsolete. Override the Init method to use the PostMapRequestHandler event.")]
public virtual void PostMapRequestHandler(HttpContextBase 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);
}
}
}
}

void IHttpModule.Dispose()
{
this.Dispose();
}

void IHttpModule.Init(HttpApplication application)
{
this.Init(application);
}

// Properties
public RouteCollection RouteCollection
{
get
{
if (this._routeCollection == null)
{
this._routeCollection = RouteTable.Routes;
}
return this._routeCollection;
}
set
{
this._routeCollection = value;
}
}
}

IRouteHandler routeHandler = routeData.RouteHandler;

此处的routeHandler是MvcRouteHandler

IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);

此处的httpHandler是MvcHandler

context.RemapHandler(httpHandler);

RemapHandler方法就是提供一个自定义的HttpHandler,覆盖系统默认的HttpHandler.

 

下面我们来讨论一下RouteCollection,RouteData对象

 在Global文件中有个Application_Start方法我们主要看的是RouteCollection的MapRoute方法,这个方法是个扩展方法在RouteCollectionExtensions扩展类中实现MapRoute的作用就是根据参数生成一个Route对象,并存到RouteCollection对象中。我们可以看到每个Route对象都包含了一个MvcRouteHandler对象

 RouteCollection.GetRouteData方法就是遍历集合,然后找到匹配的RouteData

        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 = UrlParameter.Optional } // Parameter defaults
);

}

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

 

public static class RouteCollectionExtensions
{
// Methods
private static RouteCollection FilterRouteCollectionByArea(RouteCollection routes, string areaName, out bool usingAreas)
{
if (areaName == null)
{
areaName = string.Empty;
}
usingAreas = false;
RouteCollection routes2 = new RouteCollection();
using (routes.GetReadLock())
{
foreach (RouteBase base2 in routes)
{
string a = AreaHelpers.GetAreaName(base2) ?? string.Empty;
usingAreas |= a.Length > 0;
if (string.Equals(a, areaName, StringComparison.OrdinalIgnoreCase))
{
routes2.Add(base2);
}
}
}
if (!usingAreas)
{
return routes;
}
return routes2;
}

public static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, RouteValueDictionary values)
{
return routes.GetVirtualPathForArea(requestContext, null, values);
}

public static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, string name, RouteValueDictionary values)
{
bool flag;
return routes.GetVirtualPathForArea(requestContext, name, values, out flag);
}

internal static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, string name, RouteValueDictionary values, out bool usingAreas)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (!string.IsNullOrEmpty(name))
{
usingAreas = false;
return routes.GetVirtualPath(requestContext, name, values);
}
string areaName = null;
if (values != null)
{
object obj2;
if (values.TryGetValue("area", out obj2))
{
areaName = obj2 as string;
}
else if (requestContext != null)
{
areaName = AreaHelpers.GetAreaName(requestContext.RouteData);
}
}
RouteValueDictionary dictionary = values;
RouteCollection routes2 = FilterRouteCollectionByArea(routes, areaName, out usingAreas);
if (usingAreas)
{
dictionary = new RouteValueDictionary(values);
dictionary.Remove("area");
}
return routes2.GetVirtualPath(requestContext, dictionary);
}

public static void IgnoreRoute(this RouteCollection routes, string url)
{
routes.IgnoreRoute(url, null);
}

public static void IgnoreRoute(this RouteCollection routes, string url, object constraints)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (url == null)
{
throw new ArgumentNullException("url");
}
IgnoreRouteInternal internal3 = new IgnoreRouteInternal(url) {
Constraints = new RouteValueDictionary(constraints)
};
IgnoreRouteInternal item = internal3;
routes.Add(item);
}

public static Route MapRoute(this RouteCollection routes, string name, string url)
{
return routes.MapRoute(name, url, null, null);
}

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults)
{
return routes.MapRoute(name, url, defaults, null);
}

public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces)
{
return routes.MapRoute(name, url, null, null, namespaces);
}

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints)
{
return routes.MapRoute(name, url, defaults, constraints, null);
}

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces)
{
return routes.MapRoute(name, url, defaults, null, namespaces);
}

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 route2 = new Route(url, new MvcRouteHandler()) {
Defaults = new RouteValueDictionary(defaults),
Constraints = new RouteValueDictionary(constraints),
DataTokens = new RouteValueDictionary()
};
Route item = route2;
if ((namespaces != null) && (namespaces.Length > 0))
{
item.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, item);
return item;
}

// Nested Types
private sealed class IgnoreRouteInternal : Route
{
// Methods
public IgnoreRouteInternal(string url) : base(url, new StopRoutingHandler())
{
}

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary routeValues)
{
return null;
}
}
}

 

public class RouteCollection : Collection<RouteBase>
{
// Fields
private Dictionary<string, RouteBase> _namedMap;
private ReaderWriterLockSlim _rwLock;
private VirtualPathProvider _vpp;

// Methods
public RouteCollection() : this(HostingEnvironment.VirtualPathProvider)
{
}

public RouteCollection(VirtualPathProvider virtualPathProvider)
{
this._namedMap = new Dictionary<string, RouteBase>(StringComparer.OrdinalIgnoreCase);
this._rwLock = new ReaderWriterLockSlim();
this._vpp = virtualPathProvider;
}

public void Add(string name, RouteBase item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
if (!string.IsNullOrEmpty(name) && this._namedMap.ContainsKey(name))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("RouteCollection_DuplicateName"), new object[] { name }), "name");
}
base.Add(item);
if (!string.IsNullOrEmpty(name))
{
this._namedMap[name] = item;
}
}

protected override void ClearItems()
{
this._namedMap.Clear();
base.ClearItems();
}

public IDisposable GetReadLock()
{
this._rwLock.EnterReadLock();
return new ReadLockDisposable(this._rwLock);
}

private RequestContext GetRequestContext(RequestContext requestContext)
{
if (requestContext != null)
{
return requestContext;
}
HttpContext current = HttpContext.Current;
if (current == null)
{
throw new InvalidOperationException(SR.GetString("RouteCollection_RequiresContext"));
}
return new RequestContext(new HttpContextWrapper(current), new RouteData());
}

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 != 0)
{
if (!this.RouteExistingFiles)
{
string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (((appRelativeCurrentExecutionFilePath != "~/") && (this._vpp != null)) && (this._vpp.FileExists(appRelativeCurrentExecutionFilePath) || this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
{
return null;
}
}
using (this.GetReadLock())
{
foreach (RouteBase base2 in this)
{
RouteData routeData = base2.GetRouteData(httpContext);
if (routeData != null)
{
return routeData;
}
}
}
}
return null;
}

private static string GetUrlWithApplicationPath(RequestContext requestContext, string url)
{
string str = requestContext.HttpContext.Request.ApplicationPath ?? string.Empty;
if (!str.EndsWith("/", StringComparison.OrdinalIgnoreCase))
{
str = str + "/";
}
return requestContext.HttpContext.Response.ApplyAppPathModifier(str + url);
}

public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
requestContext = this.GetRequestContext(requestContext);
using (this.GetReadLock())
{
foreach (RouteBase base2 in this)
{
VirtualPathData virtualPath = base2.GetVirtualPath(requestContext, values);
if (virtualPath != null)
{
virtualPath.VirtualPath = GetUrlWithApplicationPath(requestContext, virtualPath.VirtualPath);
return virtualPath;
}
}
}
return null;
}

public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values)
{
RouteBase base2;
bool flag;
requestContext = this.GetRequestContext(requestContext);
if (string.IsNullOrEmpty(name))
{
return this.GetVirtualPath(requestContext, values);
}
using (this.GetReadLock())
{
flag = this._namedMap.TryGetValue(name, out base2);
}
if (!flag)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("RouteCollection_NameNotFound"), new object[] { name }), "name");
}
VirtualPathData virtualPath = base2.GetVirtualPath(requestContext, values);
if (virtualPath == null)
{
return null;
}
virtualPath.VirtualPath = GetUrlWithApplicationPath(requestContext, virtualPath.VirtualPath);
return virtualPath;
}

public IDisposable GetWriteLock()
{
this._rwLock.EnterWriteLock();
return new WriteLockDisposable(this._rwLock);
}

public void Ignore(string url)
{
this.Ignore(url, null);
}

public void Ignore(string url, object constraints)
{
if (url == null)
{
throw new ArgumentNullException("url");
}
IgnoreRouteInternal internal3 = new IgnoreRouteInternal(url) {
Constraints = new RouteValueDictionary(constraints)
};
IgnoreRouteInternal item = internal3;
base.Add(item);
}

protected override void InsertItem(int index, RouteBase item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
if (base.Contains(item))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("RouteCollection_DuplicateEntry"), new object[0]), "item");
}
base.InsertItem(index, item);
}

public Route MapPageRoute(string routeName, string routeUrl, string physicalFile)
{
return this.MapPageRoute(routeName, routeUrl, physicalFile, true, null, null, null);
}

public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess)
{
return this.MapPageRoute(routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, null, null, null);
}

public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults)
{
return this.MapPageRoute(routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, defaults, null, null);
}

public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints)
{
return this.MapPageRoute(routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, defaults, constraints, null);
}

public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens)
{
if (routeUrl == null)
{
throw new ArgumentNullException("routeUrl");
}
Route item = new Route(routeUrl, defaults, constraints, dataTokens, new PageRouteHandler(physicalFile, checkPhysicalUrlAccess));
this.Add(routeName, item);
return item;
}

protected override void RemoveItem(int index)
{
this.RemoveRouteName(index);
base.RemoveItem(index);
}

private void RemoveRouteName(int index)
{
RouteBase base2 = base[index];
foreach (KeyValuePair<string, RouteBase> pair in this._namedMap)
{
if (pair.Value == base2)
{
this._namedMap.Remove(pair.Key);
break;
}
}
}

protected override void SetItem(int index, RouteBase item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
if (base.Contains(item))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("RouteCollection_DuplicateEntry"), new object[0]), "item");
}
this.RemoveRouteName(index);
base.SetItem(index, item);
}

// Properties
public RouteBase this[string name]
{
get
{
RouteBase base2;
if (!string.IsNullOrEmpty(name) && this._namedMap.TryGetValue(name, out base2))
{
return base2;
}
return null;
}
}

public bool RouteExistingFiles { get; set; }

// Nested Types
private sealed class IgnoreRouteInternal : Route
{
// Methods
public IgnoreRouteInternal(string url) : base(url, new StopRoutingHandler())
{
}

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary routeValues)
{
return null;
}
}

private class ReadLockDisposable : IDisposable
{
// Fields
private ReaderWriterLockSlim _rwLock;

// Methods
public ReadLockDisposable(ReaderWriterLockSlim rwLock)
{
this._rwLock = rwLock;
}

void IDisposable.Dispose()
{
this._rwLock.ExitReadLock();
}
}

private class WriteLockDisposable : IDisposable
{
// Fields
private ReaderWriterLockSlim _rwLock;

// Methods
public WriteLockDisposable(ReaderWriterLockSlim rwLock)
{
this._rwLock = rwLock;
}

void IDisposable.Dispose()
{
this._rwLock.ExitWriteLock();
}
}
}

 

public class Route : RouteBase
{
// Fields
private ParsedRoute _parsedRoute;
private string _url;
private const string HttpMethodParameterName = "httpMethod";

// Methods
public Route(string url, IRouteHandler routeHandler)
{
this.Url = url;
this.RouteHandler = routeHandler;
}

public Route(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
{
this.Url = url;
this.Defaults = defaults;
this.RouteHandler = routeHandler;
}

public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
{
this.Url = url;
this.Defaults = defaults;
this.Constraints = constraints;
this.RouteHandler = routeHandler;
}

public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
{
this.Url = url;
this.Defaults = defaults;
this.Constraints = constraints;
this.DataTokens = dataTokens;
this.RouteHandler = routeHandler;
}

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;
}

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;
}

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);
}

private bool ProcessConstraints(HttpContextBase httpContext, RouteValueDictionary values, RouteDirection routeDirection)
{
if (this.Constraints != null)
{
foreach (KeyValuePair<string, object> pair in this.Constraints)
{
if (!this.ProcessConstraint(httpContext, pair.Value, pair.Key, values, routeDirection))
{
return false;
}
}
}
return true;
}

// Properties
public RouteValueDictionary Constraints { get; set; }

public RouteValueDictionary DataTokens { get; set; }

public RouteValueDictionary Defaults { get; set; }

public IRouteHandler RouteHandler { get; set; }

public string Url
{
get
{
return (this._url ?? string.Empty);
}
set
{
this._parsedRoute = RouteParser.Parse(value);
this._url = value;
}
}
}

 

public class MvcRouteHandler : IRouteHandler
{
// Fields
private IControllerFactory _controllerFactory;

// Methods
public MvcRouteHandler()
{
}

public MvcRouteHandler(IControllerFactory controllerFactory)
{
this._controllerFactory = controllerFactory;
}

protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.HttpContext.SetSessionStateBehavior(this.GetSessionStateBehavior(requestContext));
return new MvcHandler(requestContext);
}

protected virtual SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext)
{
string controllerName = (string) requestContext.RouteData.Values["controller"];
IControllerFactory factory = this._controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();
return factory.GetControllerSessionBehavior(requestContext, controllerName);
}

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

 

posted on 2012-04-05 23:11  啊熊  阅读(469)  评论(0编辑  收藏  举报