1.定义httpmodule <system.webServer> <modules> <add name="UrlRoutingModule" type="WebApp.UrlRoutingModule,WebApp"/> </modules> <validation validateIntegratedModeConfiguration="false" /> </system.webServer> 2.对应的mvc类 using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web; using System.Web.Compilation; using System.Web.UI; using System.Web.UI.WebControls; namespace WebApp { /// <summary> /// 二次封装的请求上下文:包括原始的HttpContextBase和经过提取的路由数据对象 /// </summary> public class RequestContext { public virtual HttpContextBase HttpContext { get; set; } public virtual RouteData RouteData { get; set; } } public interface IRouteHandler { IHttpHandler GetHttpHandler(RequestContext requestContext); } public abstract class RouteBase { public abstract RouteData GetRouteData(HttpContextBase httpContext); } public class RouteData { public IDictionary<string, object> Values { get; private set; } public IDictionary<string, object> DataTokens { get; private set; } public IRouteHandler RouteHandler { get; set; } public RouteBase Route { get; set; } public RouteData() { this.Values = new Dictionary<string, object>(); this.DataTokens = new Dictionary<string, object>(); this.DataTokens.Add("namespaces", new List<string>()); } public string Controller { get { object controllerName = string.Empty; this.Values.TryGetValue("Controller", out controllerName); return controllerName.ToString(); } } public string ActionName { get { object actionName = string.Empty; this.Values.TryGetValue("Action", out actionName); return actionName.ToString(); } } } public class Route : RouteBase { public IRouteHandler RouteHandler { get; set; } public string Url { get; set; } public IDictionary<string, object> DataTokens { get; set; } public Route() { this.DataTokens = new Dictionary<string, object>(); this.RouteHandler = new MvcRouteHandler(); } public override RouteData GetRouteData(HttpContextBase httpContext) { IDictionary<string, object> variables; //如 AppRelativeCurrentExecutionFilePath的值~/home/index,前两个是~/我们从第三位取值, //所以substring(2)的结果是home/index match返回返回符合路由规则的路由参数这里 字典里controller:"home",action:"index" if (this.Match(httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2), out variables)) { RouteData routeData = new RouteData(); foreach (var item in variables) { routeData.Values.Add(item.Key, item.Value); } foreach (var item in DataTokens) { routeData.DataTokens.Add(item.Key, item.Value); } routeData.RouteHandler = this.RouteHandler; return routeData; } return null; } protected bool Match(string requestUrl, out IDictionary<string, object> variables) { variables = new Dictionary<string, object>(); string[] strArray1 = requestUrl.Split('/'); string[] strArray2 = this.Url.Split('/');//其中的某条路由规则 if (strArray1.Length != strArray2.Length) { return false; } for (int i = 0; i < strArray2.Length; i++) { if (strArray2[i].StartsWith("{") && strArray2[i].EndsWith("}")) { variables.Add(strArray2[i].Trim("{}".ToCharArray()), strArray1[i]); } } return true; } } public class RouteTable { public static RouteDictionary Routes { get; private set; } static RouteTable() { Routes = new RouteDictionary(); } } public class RouteDictionary : Dictionary<string, RouteBase> { public RouteData GetRouteData(HttpContextBase httpContext) { //便利global.asax添加的路由规则 foreach (RouteBase route in this.Values) { //比如获取得到其中的某一条路由规则 "{Controller}/{Action}" 比如我们请求地址/home/index 对应的数据层次就像routeData.Value=["Controller":"home","Action":"index"] //routeData.RouteHandler=MvcHandler RouteData routeData = route.GetRouteData(httpContext); if (routeData != null) { return routeData; } } return null; } } public class UrlRoutingModule : IHttpModule { public void Dispose() { } public void Init(HttpApplication context) { context.PostResolveRequestCache += onPostResolveRequestCache; } public virtual void onPostResolveRequestCache(object sender, EventArgs e) { HttpContextWrapper httpContext = new HttpContextWrapper(HttpContext.Current); RouteData routeData = RouteTable.Routes.GetRouteData(httpContext); if (routeData == null) { return; } RequestContext requestContext = new RequestContext { RouteData = routeData, HttpContext = httpContext }; IHttpHandler handler = routeData.RouteHandler.GetHttpHandler(requestContext);//这里返回MvcHandler httpContext.RemapHandler(handler);//UrlRoutingModule使用MvcHandler处理器处理,调用响应的processrequest方法 } } public class MvcRouteHandler : IRouteHandler { public IHttpHandler GetHttpHandler(RequestContext requestContext) { return new MvcHandler(requestContext); } } public class MvcHandler : IHttpHandler { public bool IsReusable { get { return false; } } public RequestContext RequestContext { get; private set; } public MvcHandler(RequestContext requestContext) { this.RequestContext = requestContext; } public void ProcessRequest(HttpContext context) { string controllerName = this.RequestContext.RouteData.Controller; IControllerFactory controllerFactory = ControllerBuilder.Current.GetControllerFactory(); IController controller = controllerFactory.CreateController(this.RequestContext, controllerName); controller.Execute(this.RequestContext); } } public interface IController { void Execute(RequestContext requestContext); } public interface IControllerFactory { IController CreateController(RequestContext requestContext, string controllerName); } public class ControllerBuilder { private Func<IControllerFactory> factoryThunk; public static ControllerBuilder Current { get; private set; } static ControllerBuilder() { Current = new ControllerBuilder(); } public IControllerFactory GetControllerFactory() { return factoryThunk(); } public void SetControllerFactory(IControllerFactory controllerFactory) { factoryThunk = () => controllerFactory; } } public class DefaultControllerFactry : IControllerFactory { private static List<Type> controllerTypes = new List<Type>(); /// <summary> /// 构造函数加载所有的控制器类的类型放在controllerTypes /// </summary> static DefaultControllerFactry() { foreach (Assembly assembly in BuildManager.GetReferencedAssemblies()) { foreach (Type type in assembly.GetTypes().Where(type => typeof(IController).IsAssignableFrom(type))) { controllerTypes.Add(type); } } } /// <summary> /// 通过controllerTypes集合和具体的控制器名称controllerName,反射创建对应控制器 /// </summary> /// <param name="requestContext"></param> /// <param name="controllerName"></param> /// <returns></returns> public IController CreateController(RequestContext requestContext, string controllerName) { string typeName = controllerName + "Controller"; Type controllerType = controllerTypes.FirstOrDefault(c => string.Compare(typeName, c.Name, true) == 0); if (controllerType == null) { return null; } return (IController)Activator.CreateInstance(controllerType); } } public class ControllerBase : IController { protected IActionInvoker ActionInvoker { get; set; } public ControllerBase() { this.ActionInvoker = new ControllerActionInvoker(); } public void Execute(RequestContext requestContext) { ControllerContext context = new ControllerContext { RequestContext = requestContext, Controller = this }; string actionName = requestContext.RouteData.ActionName; this.ActionInvoker.InvokeAction(context, actionName); } } public interface IActionInvoker { void InvokeAction(ControllerContext context, string actionName); } /// <summary> /// 控制器上下文:包含控制器和二次封装过的RequestContext请求上下文 /// </summary> public class ControllerContext { /// <summary> /// 包含使用的控制器 /// </summary> public ControllerBase Controller { get; set; } public RequestContext RequestContext { get; set; } } public class ControllerActionInvoker : IActionInvoker { public IModelBinder ModelBinder { get; private set; } public ControllerActionInvoker() { this.ModelBinder = new DefaultModelBinder(); } public void InvokeAction(ControllerContext controllerContext, string actionName) { MethodInfo method = controllerContext.Controller.GetType().GetMethods() .First(m => string.Compare(actionName, m.Name, true) == 0); List<object> parameters = new List<object>(); foreach (ParameterInfo parameter in method.GetParameters()) { //把请求的参数绑定对应方法参数的模型上 parameters.Add(this.ModelBinder.BindModel(controllerContext, parameter.Name, parameter.ParameterType)); } ActionResult actionResult = method.Invoke(controllerContext.Controller, parameters.ToArray()) as ActionResult; actionResult.ExecuteResult(controllerContext); } } public interface IModelBinder { object BindModel(ControllerContext controllerContext, string modelName, Type modelType); } public class DefaultModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, string modelName, Type modelType) { if (modelType.IsValueType || typeof(string) == modelType) { object instance; if (GetValueTypeInstance(controllerContext, modelName, modelType, out instance)) { return instance; } return Activator.CreateInstance(modelType); } object modelInstance = Activator.CreateInstance(modelType); foreach (PropertyInfo property in modelType.GetProperties()) { if (!property.CanWrite || (!property.PropertyType.IsValueType && property.PropertyType != typeof(string))) { continue; } object propertyValue; if (GetValueTypeInstance(controllerContext, property.Name, property.PropertyType, out propertyValue)) { property.SetValue(modelInstance, propertyValue, null); } } return modelInstance; } private bool GetValueTypeInstance(ControllerContext controllerContext, string modelName, Type modelType, out object value) { System.Collections.Specialized.NameValueCollection form = HttpContext.Current.Request.Form; string key; if (null != form) { key = form.AllKeys.FirstOrDefault(k => string.Compare(k, modelName, true) == 0); if (key != null) { value = Convert.ChangeType(form[key], modelType); return true; } } key = controllerContext.RequestContext.RouteData.Values .Where(item => string.Compare(item.Key, modelName, true) == 0) .Select(item => item.Key).FirstOrDefault(); if (null != key) { value = Convert.ChangeType(controllerContext.RequestContext.RouteData.Values[key], modelType); return true; } key = controllerContext.RequestContext.RouteData.DataTokens .Where(item => string.Compare(item.Key, modelName, true) == 0) .Select(item => item.Key).FirstOrDefault(); if (null != key) { value = Convert.ChangeType(controllerContext.RequestContext.RouteData.DataTokens[key], modelType); return true; } value = null; return false; } } public abstract class ActionResult { public abstract void ExecuteResult(ControllerContext context); } public class RawContentResult : ActionResult { public string RawData { get; private set; } public RawContentResult(string rawData) { RawData = rawData; } public override void ExecuteResult(ControllerContext context) { context.RequestContext.HttpContext.Response.Write(this.RawData); } } public class SimpleModel { public string Controller { get; set; } public string Action { get; set; } } public class HomeController : ControllerBase { public ActionResult Index(SimpleModel model) { string content = string.Format("Controller:{0}<br/>Action:{1}", model.Controller, model.Action); return new RawContentResult(content); } } public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } } } 3.global.asax using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using System.Web; using System.Web.Compilation; using System.Web.Optimization; using System.Web.Routing; using System.Web.Security; using System.Web.SessionState; namespace WebApp { public class Global : HttpApplication { void Application_Start(object sender, EventArgs e) { // 在应用程序启动时运行的代码 //RouteConfig.RegisterRoutes(RouteTable.Routes); //BundleConfig.RegisterBundles(BundleTable.Bundles); RouteTable.Routes.Add("default", new Route { Url = "{Controller}/{Action}" }); ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactry()); } } }