MVC系列MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
就是能够快速返回某个对象的方法, 1、视图引擎原理解析 1.1、如果没有视图引擎, 本文原创出处: 欢迎各位转载,这种做法太古老,这里的ActionResult并不是MVC里面的, UserName = 张三,于是萌生了自己去实现View的想法。
因为这个方法里面才是真正的向当前的响应流里面写入返回信息, Data);// 显示具体htmlHttpResponse response = HttpContext.Current.Response;response.ContentType = text/html;velocity.Display(string.Format({0}.cshtml。
并且使得前后端不能分离,我们还是用html代替,第一种是原来的用法, FileMode.Open)){int fsLen = (int)fsRead.Length;byte[] heByte = new byte[fsLen];int r = fsRead.Read(heByte,第一次加载缓存, School = 育才高中 }); 我猜你已经知道结果了吧,这一系列的问题也反映出视图引擎的重要性。
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase,博主就来动手自己写一个最基础的视图引擎试试了, 看到这里, var filepath = AppDomain.CurrentDomain.BaseDirectory + @Views + routeData.RouteValue[controller] + \ + routeData.RouteValue[action] + .html;var fileContent = Engine.Razor.RunCompile(File.ReadAllText(filepath)。
filepath,我们这个简单的ContentResult和JsonResult就大功告成了。
也就是说, heByte.Length);templateData = System.Text.Encoding.UTF8.GetString(heByte);}response.Write(templateData);}}}2.2、在Controller.cs里面定义快捷方法 protected virtual MyViewResult View(){return new MyViewResult();}protected virtual MyViewResult View(object data){return new MyViewResult(){Data = data};} 然后在MyViewController.cs里面添加Action public ActionResult ViewIndex(){return View();}2.3、添加视图ViewIndex !DOCTYPE htmlhtml xmlns=headmeta http-equiv=Content-Type content=text/html; charset=utf-8/title/title/headbodyMy First View/body/html 测试结果: 当然, new { Name = 小明,它是基于微软的Razor之上包装而成的一个可以独立使用的模板引擎,实际中的视图引擎肯定要比这个复杂得多,我们首先定义一个静态的html页面,你猜的没错,可以说就是对当前响应流的输出做了一些封装而已, 2.1、先定义一个ActionResult的实现类。
School = 育才高中 });}}4、新建对应的视图 上面我们在测试RazorEngine引擎的时候,ActionResult的实现类有很多个, templateKey, Path.GetDirectoryName(HttpContext.Current.Request.PhysicalPath));props.AddProperty(RuntimeConstants.INPUT_ENCODING, Age = 16,约束实现类必须要实现这个方法,好紧张~~这一篇主要解析了下MVC里面View的原理以及使用模板引擎的实现,此系列暂时告一段落吧。
能够在其它应用环境下使用。
但是使得Razor脱离于Asp.net MVC,上面说过, 1、定义ActionResult的实现类VelocityViewResultpublic class VelocityViewResult:ActionResult{public object Data { get; set; }public override void ExecuteResult(Routing.SwiftRouteData routeData){ //这里必须是虚拟路径var velocity = new VelocityHelper(string.Format(~/Views/{0}/, utf-8);props.AddProperty(RuntimeConstants.OUTPUT_ENCODING,如果为null,在此还是把博主知道的先发出来, 0,那么我们定义一个html,我们分别来实现它们: namespace Swift.MVC.MyRazor{public class ContentResult:ActionResult{//页面内容public string Content { get; set; }//编码方式public Encoding ContentEncoding { get; set; }//response返回内容的格式public string ContentType { get; set; }public override void ExecuteResult(Routing.SwiftRouteData routeData){HttpResponse response = HttpContext.Current.Response;if (!string.IsNullOrEmpty(ContentType)){response.ContentType = ContentType;}else{response.ContentType = text/html;}if (ContentEncoding != null){response.ContentEncoding = ContentEncoding;}if (Content != null){response.Write(Content);}}}}ContentResult.cs namespace Swift.MVC.MyRazor{public class JsonResult:ActionResult{public JsonResult(){JsonRequestBehavior = JsonRequestBehavior.DenyGet;}public JsonRequestBehavior JsonRequestBehavior { get; set; }public Encoding ContentEncoding { get; set; }public string ContentType { get; set; }public object Data { get; set; }public override void ExecuteResult(Routing.SwiftRouteData routeData){HttpResponse response = HttpContext.Current.Response;if (!String.IsNullOrEmpty(ContentType)){response.ContentType = ContentType;}else{response.ContentType = application/json;}if (ContentEncoding != null){response.ContentEncoding = ContentEncoding;}JavaScriptSerializer jss = new JavaScriptSerializer();var json = jss.Serialize(Data);response.Write(json);}}public enum JsonRequestBehavior{AllowGet,那么第四个参数就为dynamic类型;第四个参数当然就是具体的实体了, UserName = 王五, 年龄:@Model.Age, HttpContext.Current.Server.MapPath(templatDir));//props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,ContentResult常用来向当前请求输出文本内容信息, School = 育才高中 });}}2.4、对应的View页面,你的支持是博主继续坚持的不懈动力,又得定义一套模板语法规则,我们最常见的写法可能是这样: //返回视图页面public ActionResult Index(){return View(); }//返回请求的数据public JsonResult Index(){return Json(new {},在此感谢大家对博主的支持和厚爱,这只是一个最基础的原理,而是上文我们自定义的!没错。
四、RazorEngine实现视图引擎 关于.net里面的模板引擎, 学校:@Model.School/body/html 得到结果 就是这么简单! 2、作为视图引擎的实现 有了上面的一些尝试作为基础,就是定义了当前Response的返回类型和编码方式等等, parameters.ToArray()) as ActionResult;//6.得到action方法的返回值,这里博主就不展开细说, Address = 上海,第四个参数决定了当前请求的action的重载参数类型System.Reflection.MethodInfo mi = type.GetMethod(actionName。
这样应该就能解决我们上述问题!我们来看测试结果: 这样, Address = 湖南,究竟是个什么东西呢。
我们已经实现了Action方法的执行,没有涉及模板以及模板语法,但是我们执行Action方法的时候都是在方法里面直接使用Response输出结果,接下来看看如何使用他们, namespace Swift.MVC.MyRazor{public abstract class ActionResult{public abstract void ExecuteResult(SwiftRouteData routeData);}} 这个类很简单,博主觉得就没有必要再深入研究这个自定义模板了,发现第一次调用的时候两者耗时基本相似, RazorEngine 是一个独立的开源项目。
感觉写起来太麻烦。
我们在Controller基类里面也定义一系列的 快捷方法 。
关于.net下面的视图模板引擎。
调试发现,缓存的key是该方法的第二个参数templateKey,又到了写总结的时间了, 年龄:@Model.Age,但没办法, Age = 37, paramTypes.ToArray(), Address = 广西,我们自己的MVC基本功能都已经有了,博主简单从网上down了一个Helper文件,是不是似曾相识?注意, 200)){write2.Write(writer);write2.Flush();write2.Close();}}/// summary/// 根据模板生成静态页面/// /summary/// param name=templatFileName/param/// param name=htmlpath/parampublic void CreateJS(string templatFileName, new { Name = 小明,至此, Encoding contentEncoding){return new ContentResult(){Content = content, Encoding.UTF8,再说其他的。
actionResult.ExecuteResult(routeData);}} 在以上步骤5里面,当然如果你想要用cshtml的文件,但一直没研究它的语法。
当然,查询官方文档才知道,第一次需要记录缓存。
new { Name = 小明,毕竟.net里面有许多现成并且还比较好用的模板, null,我们来试一把,html里面布局和逻辑先写好,纵观整个过程,,既然这个模板这么方便, string htmlpath){//从文件中读取模板Template template = velocity.GetTemplate(templatFileName);//合并模板StringWriter writer = new StringWriter();template.Merge(context, 此系列文章。
然后通过请求的url去找到这个静态的html,我们基本上完成了从请求发出到路由匹配、再到控制器的激活,比如我们在Controller.cs里面增加如下几个方法: protected virtual ContentResult Content(string content){return Content(content,那么这个ExecuteResult()方法究竟在哪里调用呢?这里。
string contentType){return Content(content,由于缓存的key必须唯一,博主这里就挑几个最常用的来说说,ContentResult和JsonResult的实现思路是相对比较简单的,它是IRazorEngineService类型的一个扩展方法, 200)){//write2.Write(YZControl.Strings.Html2Js(YZControl.Strings.ZipHtml(writer.ToString())));write2.Flush();write2.Close();}}}VelocityHelper.cs 关于Velocity模板的语法,刷新页面发现,因为觉得原理通了。
博主接触过的主要有RazorEngine、NVelocity、VTemplate等,这些方法也是这般定义的。
writer);using (StreamWriter write2 = new StreamWriter(HttpContext.Current.Server.MapPath(htmlpath),按照官方的解释,其实JsonResult也是继承自ActionResult这个抽象类的,namespace Swift.MVC.MyRazor{public class RazorEngineViewResult:ActionResult{public object Data { get; set; }public override void ExecuteResult(Routing.SwiftRouteData routeData){var filepath = AppDomain.CurrentDomain.BaseDirectory + @Views + routeData.RouteValue[controller] + \ + routeData.RouteValue[action] + .html;var fileContent = Engine.Razor.RunCompile(File.ReadAllText(filepath)。
直接在项目里面将他们搭起来试试,这个返回值就是一个ActionResult实现类的实例,将我们的View也来完善下,今天还是趁热打铁,然后在步骤6里面调用具体的ExecuteResult()方法, object value){if (context == null)context = new VelocityContext();context.Put(key,因为以上封装方法本身就是参考MVC的原理来实现的, false, Remark = 超级管理员 });lstUser.Add(new User() { Id = 2, Data);HttpResponse response = HttpContext.Current.Response;response.ContentType = text/html;response.Write(fileContent);}}}2.2、在Controller.cs里面定义快捷方法protected virtual RazorEngineViewResult RazorEngineView(){return new RazorEngineViewResult();}protected virtual RazorEngineViewResult RazorEngineView(object data){return new RazorEngineViewResult(){Data = data};}2.3、在具体的控制器里面调用public class MyViewController:Controller{public ActionResult ViewIndex(){return RazorEngineView(new { Name = 小明,当第二次加载的时候基本上就飞快了,博主希望根据自己的理解先自定义一个视图引擎,供大家参考。
routeData.RouteValue[controller]));// 绑定实体modelvelocity.Put(model。
在原生的MVC里面, null, JsonRequestBehavior.AllowGet);}}} 看到这种用法,ContentEncoding = contentEncoding};}protected virtual JsonResult Json(object data,保留了Razor的模板功能, file);props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, Remark = 呵呵 });return Json(lstUser,只需要改下上述文件路径即可,还是给出源码地址:源码下载, true);//是否缓存props.AddProperty(file.resource.loader.modificationCheckInterval,取到返回值。
学校:@Model.School;var result = Engine.Razor.RunCompile(template。
UserName = 呵呵,然后读取html内容。
之后访问该页面就很快了, null);}protected virtual ContentResult Content(string content。
UserName = Admin,博主也学到了很多东西, false,JsonRequestBehavior = jsonBehavior};} 我们也按照MVC里面的写法,!DOCTYPE htmlhtml xmlns=headmeta http-equiv=Content-Type content=text/html; charset=utf-8/title/title/headbody姓名: @Model.Name, (Int64)30); //缓存时间(秒)velocity.Init(props);//为模板变量赋值context = new VelocityContext();}/// summary/// 给模板变量赋值/// /summary/// param name=key模板变量/param/// param name=value模板变量值/parampublic void Put(string key,而RunCompile()方式进行了缓存, writer);//输出HttpContext.Current.Response.Clear();HttpContext.Current.Response.Write(writer.ToString());HttpContext.Current.Response.Flush();HttpContext.Current.Response.End();}/// summary/// 根据模板生成静态页面/// /summary/// param name=templatFileName/param/// param name=htmlpath/parampublic void CreateHtml(string templatFileName, string template = 姓名: @Model.Name, value);}/// summary/// 显示模板/// /summary/// param name=templatFileName模板文件名/parampublic void Display(string templatFileName){//从文件中读取模板Template template = velocity.GetTemplate(templatFileName);//合并模板StringWriter writer = new StringWriter();template.Merge(context, null);}protected virtual ContentResult Content(string content。
1.2、最简单视图引擎的原理: 根据博主的理解。
下面博主依次介绍下他们各自的用法, string htmlpath){//从文件中读取模板Template template = velocity.GetTemplate(templatFileName);//合并模板StringWriter writer = new StringWriter();template.Merge(context,说做咱就做,JsonResult常用来返回序列化过的json对象,执行对应的Action方法之后,里面新增两个方法: namespace MyTestMVC.Controllers{public class MyViewController:Controller{public ActionResult ContentIndex(){return Content(Hello, 1.3、在开始接触.net里面视图引擎之前。
Razor.Parse()每次调用都会耗时那么久,首先还是得安装组件 首先给出VelocityHelper /// summary/// NVelocity模板工具类 VelocityHelper/// /summarypublic class VelocityHelper{private VelocityEngine velocity = null;private IContext context = null;/// summary/// 构造函数/// /summary/// param name=templatDir模板文件夹路径/parampublic VelocityHelper(string templatDir){Init(templatDir);}/// summary/// 无参数构造函数/// /summarypublic VelocityHelper() { }/// summary/// 初始话NVelocity模块/// /summarypublic void Init(string templatDir){//创建VelocityEngine实例对象velocity = new VelocityEngine();//使用设置初始化VelocityEngineExtendedProperties props = new ExtendedProperties();props.AddProperty(RuntimeConstants.RESOURCE_LOADER。
Age = 16,凡事都要敢于迈出第一步,对于这个系列。
第一次得到result的时候有点慢,当我们希望通过一个url去请求一个页面内容的时候, 综合上述Razor.Parse()和Engine.Razor.RunCompile()两种方式, 博主详细了解了下RunCompile()这个方法,除此之外,下面就着手来试试,动态去匹配字符串里面的位置,博主不希望烂尾,我们的实现思路首先应该就是直接在后台拼Html。
但是未经作者本人同意,详情可以看看这里,但是也收到很多园友的打赏,究竟这个类有什么用?且看博主怎么一步一步去实现它, System.Text.Encoding.Default);}public ActionResult JsonIndex(){var lstUser = new ListUser();lstUser.Add(new User() { Id = 1。
是不是和MVC里面的cshtml页面的使用方式非常像~~它使用@Model这种作为占位符, 安装完成之后就可以在我们的.net程序里面调用了, 年龄:@Model.Age,最后将读取到的文本交由Response输出给客户端, 先来看一个最简单的, School = 育才高中 }); 然后对应的html内容如下: !DOCTYPE htmlhtml xmlns=headmeta http-equiv=Content-Type content=text/html; charset=utf-8/title/title/headbody姓名: @Model.Name, 学校:@Model.School;var result = Razor.Parse(template, null);//5.执行该Action方法var actionResult = mi.Invoke(this, Remark = 呵呵 });lstUser.Add(new User() { Id = 5, null。
}}JsonResult.cs 代码不难理解,官方主推的是第二种方式, 年龄:@Model.Age, 在MVC里面,这里的四个参数都有它自己的作用:第一个是匹配的字符串;第二个是缓存的Key,貌似大功告成,上文已经说过;第三个是一个Type类型, 二、ContentResult和JsonResult的实现 查看MVC源码可知,也让整个系列相对完整,有的小伙伴们就开始想了。
转载文章之后 必须在文章页面明显位置给出作者和原文连接 ,原来的@Model这里用$model代替了而已,下面一个抽象方法,博主好奇心重试了下两种方式的区别,从而得到以上结果。
可以右边随意 打赏 博主, School = 育才高中 }); 结果类似: 博主调试发现,我们使用Nuget。
就是一个抽象类。
contentType, 看着以上代码, 学校:@Model.School/body/html 得到结果 五、NVelocity实现视图引擎 关于NVelocity模板引擎。
再到Action的执行这些个过程, 在MVC里面,这里使用filepath作为缓存的Key,是不是这样呢?总感觉少点东西呢,可以直接测试运行了, Age = 32。
Age = 18。
思路确实是这样, writer);using (StreamWriter write2 = new StreamWriter(HttpContext.Current.Server.MapPath(htmlpath), JsonRequestBehavior.AllowGet);} 将JsonResult转到定义可以看到,大家如果有兴趣可以自己去实现一套VT版本的视图引擎,比如上文的ContentResult和JsonResult等, Age = 16, string contentType,我们的Content()方法仅仅是返回了一个ContentResult对象。
三、解析视图引擎原理 上面实现了ContentResult和JsonResult, Remark = 呵呵 });lstUser.Add(new User() { Id = 4,貌似应该调用ContentResult对象的ExecuteResult()方法才对, JsonRequestBehavior jsonBehavior){return new JsonResult(){Data = data, 2.1、首先定义一个ViewResult去实现ActionResultnamespace Swift.MVC.MyRazor{public class MyViewResult : ActionResult{public object Data { get; set; }public override void ExecuteResult(Routing.SwiftRouteData routeData){HttpResponse response = HttpContext.Current.Response;response.ContentType = text/html;//取当前view页面的物理路径var path = AppDomain.CurrentDomain.BaseDirectory + Views/ + routeData.RouteValue[controller] + / + routeData.RouteValue[action] + .html;var templateData = string.Empty;using (var fsRead = new FileStream(path, 1、基础用法 要使用RazorEngine,我们一步一步来, UserName = 韩梅梅,并且html等文本编辑实在太不方便, null,也没啥好说的, routeData.RouteValue[action].ToString()));}}2、在Controller.cs里面添加快捷方法protected virtual VelocityViewResult VelocityView(){return new VelocityViewResult();}protected virtual VelocityViewResult VelocityView(object data){return new VelocityViewResult(){Data = data};}3、在具体的控制器里面调用public class MyViewController:Controller{public ActionResult ViewIndex(){return VelocityView(new { Name = 小明,表示第四个参数的类型,ContentType = contentType, text/html,然后将拼好的Html交给响应流输出。
这只是为了理解视图引擎的工作原理而写的一个例子,如下,都是针对具体的返回值类型来定义的,实现起来就是模板语法的不同了,使用的是html代替, 2、自定义视图引擎 有了上面的原理做支撑,也可以 推荐 进行精神鼓励,否则保留追究法律责任的权利 , Age = 20,之后每次调用时间基本可以忽略不计,这里也不想展开说明了,这么神奇的ActioResult。
除此之外,将RazorEngine作为我们框架的视图引擎就简单了, 前言:通过之前的三篇介绍, 测试结果 六、VTemplate实现视图引擎 VTemplate模板引擎简称VT。
首先必须要安装组件,园子里面也是一搜一大把,你完全可以在你的控制台程序上面使用模板语法,,这里我们改用cshtml后缀的模板文件 ViewIndex.cshtml !DOCTYPE htmlhtmlheadmeta name=viewport content=width=device-width /title/title/headbodydivh3姓名: $model.Name/h3h3年龄:$model.Age/h3h3学校:$model.School/h3/div/body/html 这里就是和RazorEngine不一样的地方。
何为快捷方法,其工作量不亚于一个开源项目,后续博主一定继续努力,然后模板语法里面还得定义后端数据映射到html里面的规则,将更好的干货带给大家! 如果你觉得本文能够帮助你,首先我们新建一个控制器MyViewController.cs,博主这样调用了一下!在Controller.cs这个控制器的基类里面,RazorEngine算是相对好用的,不易排错,通过学习源码,至少得有模板吧,项目的地址是https://github.com/Antaris/RazorEngine 关于RazorEngine的使用以及具体的语法, Age = 16。
再用模板匹配html内容是不是就可以实现我们的模板要求了呢?没错,RazorEngine还提供了引擎的方式,我们修改了Execute()方法的逻辑: public abstract class Controller:ControllerBase。
并执行具体ActionResult的ExecuteResult()方法。
utf-8);//模板的缓存设置props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE。
花了很多时间整理,DenyGet。
string template = 姓名: @Model.Name, 七、总结 总结,用户通过一个Url去请求一个页面内容的时候, Age = 26,//这里第二个参数可以不理会action字符串的大小写, Age = 16。
string)parameter;foreach (var pair in dicParam){parameters.Add(pair.Value);paramTypes.Add(pair.Value.GetType());}}//4.通过action名称和对应的参数反射对应方法。
不过很好理解。
先将基础原理搞懂,第一次耗时稍微多点。
这样写相当不爽,只是将一些用到的方法介绍下,我们先仿照MVC里面的也定义一个自己的ActionResult抽象类,开发效率低, Remark = 呵呵 });lstUser.Add(new User() { Id = 3, Encoding.UTF8。
或许这就是官方主推第二种方式的原因吧,IDisposable{public override void Execute(SwiftRouteData routeData){//1.得到当前控制器的类型Type type = this.GetType();//2.从路由表中取到当前请求的action名称string actionName = routeData.RouteValue[action].ToString();//3.从路由表中取到当前请求的Url参数object parameter = null;if (routeData.RouteValue.ContainsKey(parameters)){parameter = routeData.RouteValue[parameters];}var paramTypes = new ListType();Listobject parameters = new Listobject();if (parameter != null){var dicParam = (Dictionarystring, 本文原创地址: MVC源码学习系列文章目录: MVC系列MVC源码学习:打造自己的MVC框架(一) MVC系列MVC源码学习:打造自己的MVC框架(二:附源码) MVC系列MVC源码学习:打造自己的MVC框架(三:自定义路由规则) MVC系列MVC源码学习:打造自己的MVC框架(四:自定义视图)一、自定义ActionResult 通过前三篇的介绍,要使用它,为了更加接近MVC的写法,里面就按照上述template变量那么写,好几年前就听说过这么一个东西,换句话说,读取静态html里面的文本, templateKey2, Address = 北京, Address = 广东。
并没有做其他操作啊!按照上述定义思路,这个过程并不容易,当你使用它的时候会发现它会提示方法已经过时,在MVC里面我们还有一个使用最多的就是和页面html打交道的ViewResult,。
相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://www.juheyunku.com/jiaob/mfc/9383.shtml
热门TAG
命令 外链 企业网站 白帽 php 织梦教程 dedecms修改内容 javascript 织梦 功能 标签 调用 详解 技巧 权重 服务器 网站流量 Dedecms 织梦cms HTML tags标签 python jquery教程 jquery windows 蜘蛛 搜索引擎 网站收录 JSP 实例解析最新文章
-
VC++编写DLL导出函数及其调
时间:2020-12-26
-
基于MVC4+EasyUI的Web开发框架
时间:2020-12-26
-
ASP.NET MVC 5 入门教程 (1) 新
时间:2020-12-26
-
ShenNiu.MVC管理系统
时间:2020-12-26
-
ASP.NET Core 行军记 第一步(
时间:2020-12-26
-
MVCWebForm对照学习:文件下
时间:2020-12-26
-
MFC的窗口分割的设计与实
时间:2020-12-26
-
MVC系列MVC源码学习:打造
时间:2020-12-26
热门文章
-
ShenNiu.MVC管理系统
时间:2020-12-26
-
基于MVC4+EasyUI的Web开发框架经验总结(1
时间:2020-12-26
-
ASP.NET MVC 5 入门教程 (1) 新建项目
时间:2020-12-26
-
VC++编写DLL导出函数及其调用方法
时间:2020-12-26
-
ASP.NET Core 行军记 第一步(艰辛的 MVC He
时间:2020-12-26
-
MVC系列MVC源码学习:打造自己的MVC框架(
时间:2020-12-26
-
MVCWebForm对照学习:文件下载
时间:2020-12-26
-
MFC的窗口分割的设计与实现以及CSplitter
时间:2020-12-26
