Asp.Net MVC<三> : ASP.NET MVC 基本原理及项目创建
- MVC之前的那点事儿系列
- http://www.projky.com/asp.netmvc/5.0/
- http://www.cnblogs.com/greatandforever/archive/2010/04/20/1715914.html
MVC模拟(摘自ASP.NET MVC5框架揭秘)
Asp.net中,通过HttpModule的形式定义拦截器,也就是路由表的调用。路由表解析出相应的Controller类型和Action方法的名称及必要参数。然后依据路由数据和请求上下文,选择特定的HttpHandler,采用反射的机制激活目标Controller,执行相应的方法。
实现IHttpModule创建自定义的拦截器
public class UrlRoutingModule : IHttpModule
{
public void Dispose()
{ } public void Init(HttpApplication context)
{
context.PostResolveRequestCache += OnPostResolveRequestCache;
} //调用路由表,依据路由数据切换Handler
protected virtual void OnPostResolveRequestCache(object sender, EventArgs e)
{
HttpContextWrapper httpContext = new HttpContextWrapper(HttpContext.Current);
RouteData routeData = RouteTable.Routes.GetRouteData(httpContext);
if (null == routeData)
{
return;
}
RequestContext requestContext = new RequestContext
{
RouteData = routeData,
HttpContext = httpContext
};
IHttpHandler handler = routeData.RouteHandler.GetHttpHandler(requestContext);
httpContext.RemapHandler(handler);
}
}
实现IHttpHandler创建自定义的处理程序
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);
}
}
路由表解析URL
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)
{
foreach (var route in this.Values)
{
RouteData routeData = route.GetRouteData(httpContext);
if (null != routeData)
{
return routeData;
}
}
return null;
}
}
继承RouteBase创建自定义的Route类型
//路由
public class Route : RouteBase
{
//匹配相应的IHttpHandler
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();
} //获取路由数据,不匹配则返回null.
public override RouteData GetRouteData(HttpContextBase httpContext)
{
IDictionary<string, object> variables; if (this.Match(httpContext.Request
.AppRelativeCurrentExecutionFilePath.Substring(2), out variables))
{
//匹配成功
RouteData routeData = new RouteData();
//Controller和Action名称
foreach (var item in variables)
{
routeData.Values.Add(item.Key, item.Value);
}
//模版中限定的命名空间集合
foreach (var item in DataTokens)
{
routeData.DataTokens.Add(item.Key, item.Value);
}
//IHttpHandler路由
routeData.RouteHandler = this.RouteHandler;
return routeData;
}
return null;
} //判别当前路由对象(this)是否匹配,匹配则找到对应的Controller和Action名称
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 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 Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add("default", new Route { Url = "{controller}/{action}" });
}
}
实现IRouteHandler自定义HttpHandler提供机制
public class MvcRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MvcHandler(requestContext);
}
}
Controller实例的获取
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 DefaultControllerFactory : IControllerFactory
{
private static List<Type> controllerTypes = new List<Type>(); static DefaultControllerFactory()
{
//查找包内所有IController
foreach (Assembly assembly in BuildManager.GetReferencedAssemblies())
{
foreach (Type type in assembly.GetTypes().Where(type => typeof(IController).IsAssignableFrom(type)))
{
controllerTypes.Add(type);
}
}
} public IController CreateController(RequestContext requestContext, string controllerName)
{
string typeName = controllerName + "Controller";
Type controllerType = controllerTypes.FirstOrDefault(c => string.Compare(typeName, c.Name, true) == 0);
if (null == controllerType)
{
return null;
}
return (IController)Activator.CreateInstance(controllerType);
}
}
初始化(添加Controller工厂实例)
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory());
}
}
Action方法的执行
public abstract 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 class ControllerActionInvoker : IActionInvoker
{
public IModelBinder ModelBinder { get; private set; }
public ControllerActionInvoker()
{
this.ModelBinder = new DefaultModelBinder();
} public void InvokeAction(ControllerContext controllerContext, string actionName)
{
MethodInfo methodInfo = controllerContext.Controller.GetType().GetMethods().First(m => string.Compare(actionName, m.Name, true) == 0);
List<object> parameters = new List<object>();
foreach (ParameterInfo parameter in methodInfo.GetParameters())
{
parameters.Add(this.ModelBinder.BindModel(controllerContext, parameter.Name, parameter.ParameterType));
}
ActionExecutor executor = new ActionExecutor(methodInfo);
ActionResult actionResult = (ActionResult)executor.Execute(controllerContext.Controller, parameters.ToArray());
actionResult.ExecuteResult(controllerContext);
}
}
internal class ActionExecutor
{
private static Dictionary<MethodInfo, Func<object, object[], object>> executors = new Dictionary<MethodInfo, Func<object, object[], object>>();
private static object syncHelper = new object();
public MethodInfo MethodInfo { get; private set; } public ActionExecutor(MethodInfo methodInfo)
{
this.MethodInfo = methodInfo;
} public object Execute(object target, object[] arguments)
{
Func<object, object[], object> executor;
if (!executors.TryGetValue(this.MethodInfo, out executor))
{
lock (syncHelper)
{
if (!executors.TryGetValue(this.MethodInfo, out executor))
{
executor = CreateExecutor(this.MethodInfo);
executors[this.MethodInfo] = executor;
}
}
}
return executor(target, arguments);
} private static Func<object, object[], object> CreateExecutor(MethodInfo methodInfo)
{
ParameterExpression target = Expression.Parameter(typeof(object), "target");
ParameterExpression arguments = Expression.Parameter(typeof(object[]), "arguments"); List<Expression> parameters = new List<Expression>();
ParameterInfo[] paramInfos = methodInfo.GetParameters();
for (int i = 0; i < paramInfos.Length; i++)
{
ParameterInfo paramInfo = paramInfos[i];
BinaryExpression getElementByIndex = Expression.ArrayIndex(arguments, Expression.Constant(i));
UnaryExpression convertToParameterType = Expression.Convert(getElementByIndex, paramInfo.ParameterType);
parameters.Add(convertToParameterType);
} UnaryExpression instanceCast = Expression.Convert(target, methodInfo.ReflectedType);
MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameters);
UnaryExpression convertToObjectType = Expression.Convert(methodCall, typeof(object));
return Expression.Lambda<Func<object, object[], object>>(convertToObjectType, target, arguments).Compile();
}
}
public class RawContentResult : ActionResult
{
private Action<TextWriter> Callback { get; set; }
public RawContentResult(Action<TextWriter> action)
{
this.Callback = action;
}
public override void ExecuteResult(ControllerContext context)
{
this.Callback(context.RequestContext.HttpContext.Response.Output);
}
}
解析Action的参数
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)
{
Dictionary<string, object> dataSource = new Dictionary<string, object>(); //数据来源一:HttpContext.Current.Request.Form
foreach (string key in HttpContext.Current.Request.Form)
{
if (dataSource.ContainsKey(key.ToLower()))
{
continue;
}
dataSource.Add(key.ToLower(), HttpContext.Current.Request.Form[key]);
} //数据来源二:HttpContext.Current.Request.QueryString
foreach (string key in HttpContext.Current.Request.QueryString)
{
if (dataSource.ContainsKey(key.ToLower()))
{
continue;
}
dataSource.Add(key.ToLower(), HttpContext.Current.Request.QueryString[key]);
} //数据来源三:ControllerContext.RequestContext.RouteData.Values
foreach (var item in controllerContext.RequestContext.RouteData.Values)
{
if (dataSource.ContainsKey(item.Key.ToLower()))
{
continue;
}
dataSource.Add(item.Key.ToLower(), controllerContext.RequestContext.RouteData.Values[item.Key]);
} //数据来源四:ControllerContext.RequestContext.RouteData.DataTokens
foreach (var item in controllerContext.RequestContext.RouteData.DataTokens)
{
if (dataSource.ContainsKey(item.Key.ToLower()))
{
continue;
}
dataSource.Add(item.Key.ToLower(), controllerContext.RequestContext.RouteData.DataTokens[item.Key]);
} if (dataSource.TryGetValue(modelName.ToLower(), out value))
{
value = Convert.ChangeType(value, modelType);
return true;
}
return false;
}
}
ActionResult
public class HomeController : ControllerBase
{
public ActionResult Index(SimpleModel model)
{
Action<TextWriter> callback = writer =>
{
writer.Write(string.Format("Controller: {0}<br/>Action: {1}<br/><br/>", model.Controller, model.Action));
writer.Write(string.Format("Foo: {0}<br/>Bar: {1}<br/>Baz: {2}", model.Foo, model.Bar, model.Baz));
};
return new RawContentResult(callback);
}
}
MVC项目搭建
MVC5中只有一种ASP.NET Web Application项目类型。通过NuGet可以在开发过程中可以随时添加对其他框架的支持。
首先可以新建一个空站
可以向其中添加aspx文件做web Form开发。也可以随时引入MVC框架。
添加单元测试
使用模版
简洁版创建
Asp.Net MVC<三> : ASP.NET MVC 基本原理及项目创建的更多相关文章
- 七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理
第三天我们将学习Asp.Net中数据处理功能,了解数据访问层,EF,以及EF中常用的代码实现方式,创建数据访问层和数据入口,处理Post数据,以及数据验证等功能. 系列文章 七天学会ASP.NET M ...
- 七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理 【转】
http://www.cnblogs.com/powertoolsteam/p/MVC_three.html 第三天我们将学习Asp.Net中数据处理功能,了解数据访问层,EF,以及EF中常用的代码实 ...
- 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递
通过第一天的学习之后,我们相信您已经对MVC有一些基本了解. 本节所讲的内容是在上节的基础之上,因此需要确保您是否掌握了上一节的内容.本章的目标是在今天学习结束时利用最佳实践解决方案创建一个小型的MV ...
- 七天来学习ASP.NET MVC (两)——ASP.NET MVC 数据传输
通过第一天的学习之后,我们相信您已经对MVC有一些基本了解. 本节所讲的内容是在上节的基础之上.因此须要确保您是否掌握了上一节的内容. 本章的目标是在今天学习结束时利用最佳实践解决方式创建一个小型的M ...
- 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 【转】
http://www.cnblogs.com/powertoolsteam/p/MVC_two.html 通过第一天的学习之后,我们相信您已经对MVC有一些基本了解. 本节所讲的内容是在上节的基础之上 ...
- 【MVC】ASP.NET MVC Forms验证机制
http://www.cnblogs.com/bomo/p/3309766.html 随笔 - 121 文章 - 0 评论 - 92 [MVC]ASP.NET MVC Forms验证机制 ASP. ...
- Pro ASP.NET MVC –第六章 MVC的基本工具
在本章,我们将介绍每个MVC程序员"武器库"的三个重要工具:依赖注入容器.单元测试框架和mock工具.在本书,对于三个工具分别都只用了一种方式实现,但每个工具都还有其他的实现方式. ...
- Asp.Net MVC 路由 - Asp.Net 编程 - 张子阳
http://cache.baiducontent.com/c?m=9d78d513d98316fa03acd2294d01d6165909c7256b96c4523f8a9c12d522195646 ...
- Asp .Net MVC4笔记之走进MVC
一.MVC三层架构: mvc三层架构,大家都比较熟悉了,这里再介绍一下.Mvc将应用程序分离为三个部分: Model:是一组类,用来描述被处理的数据,同时也定义这些数据如何被变更和操作的业务规则.与数 ...
随机推荐
- Android开发学习——ListView+BaseAdapter的使用
ListView 就是用来显示一行一行的条目的MVC结构 * M:model模型层,要显示的数据 ----people集合 * V:view视图层,用户看到的界面 ...
- IOS开发之功能模块--输入框随着键盘的位置移动而移动
废话不多说,先直接上效果图: 先熟悉一下在Cocoa框架中会用到的key键: 然后直接上Demo的源码截图: 看代码之前,补充说一句,Demo中的文本框以及文本框的背后灰色的View是通过storyb ...
- 使用putty与SSHSecureShellClient登录远程服务器完成与本地Git项目的同步
使用软件远程登录管理服务器 今天给大家介绍两款远程登录管理服务器的软件(Putty和SSHSecureShellClient),这两款也是我在工作中经常的软件. 使用 PuTTY 远程登录管理服务器 ...
- MVC学习系列5--Layout布局页和RenderSection的使用
我们开发网站项目的时候,都会遇到这样的问题:就是页面怎么统一风格,有一致的外观,在之前ASP.NET的时代,我们有两种选择,一个是使用MasterPage页,一个是手动,自己在每个页面写CSS样式,但 ...
- 【转载】latch: cache buffers chains
本文转自惜分飞的博客,博客原文地址:www.xifenfei.com/1109.html,支持原创,分享知识! 当一个数据块读入sga区,相应的buffer header会被放置到hash列表上,我们 ...
- SOA架构设计经验分享—架构、职责、数据一致性
阅读目录: 1.背景介绍 2.SOA的架构层次 2.1.应用服务(原子服务) 2.2.组合服务 2.3.业务服务(编排服务) 3.SOA化的重构 3.1.保留服务空间,为了将来服务的组合 4.运用DD ...
- WSTMall网站系统最新官方版
WSTMall V1.0是在thinkphp 的经典版本3.2.2基础上进行优化开发的, TP 3.2.2不是thinkphp的一个最新的版本,却是thinkphp最金典的一个版本,正所谓站在巨人的肩 ...
- mysql innodb 性能优化
建议参数: max_connections=800 key_buffer_size=512M query_cache_size=128M sort_buffer_size=64M table_open ...
- linux vsftpd 配置
linux 使用vsftpd 实现ftp上传 安装 vsftpd yum install -y vsftpd 配置vsftpd 备份配置文件后 将/etc/vsftpd/vsftpd.conf内容替换 ...
- J2EE基础之Servlet
J2EE基础之Servlet 1. 什么是Servlet? Servlet即Java服务小程序,是使用应用程序设计接口以及相关类和方法的Java程序.它可以作为一种插件,像Applet程序一样嵌入到 ...