感觉好久没有学习了, 汗. 年就这么过完了, 感觉没有尝到过年的味道. 现在的年过的有些冷清了.

除了体重证明着我过了一个年, 还有一件值得开心的事情, 终于把女朋友变成未婚妻了. 这是一大进步吧.

闲话不扯了, 继续之前没有完成的学习.

前面 结尾处, 提到了这个方法:

protected virtual void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
{
actionResult.ExecuteResult(controllerContext);
}

ExecuteResult方法是一个抽象方法. 那么来看一下, 都是有哪些类中来实现了这一方法.

这里的这些类, 应该还是让人蛮熟悉的吧. 在Action方法中, return View() / Json() / Content() / File() ...

这里的这些返回方式, 只有View()是还要去查找视图, 解析视图, 然后返回视图的, 所以先来看这个了.

一、View

//System.Web.Mvc.ViewResultBase
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (string.IsNullOrEmpty(this.ViewName))
{
this.ViewName = context.RouteData.GetRequiredString("action");
}
ViewEngineResult result = null;
if (this.View == null)
{
result = this.FindView(context);
this.View = result.View;
}
TextWriter output = context.HttpContext.Response.Output;
ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output);
this.View.Render(viewContext, output);
if (result != null)
{
result.ViewEngine.ReleaseView(context, this.View);
}
}

1. FindView(context)

这个方法也是一个抽象方法. 其实现类为: System.Web.Mvc.PartialViewResult 和 System.Web.Mvc.ViewResult.

这个方法就是去负责查找需要使用到的视图.

看一下ViewResult类中, 最终调用的方法

//System.Web.Mvc.VirtualPathProviderViewEngine
public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
string[] strArray;
string[] strArray2;
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (string.IsNullOrEmpty(viewName))
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "viewName");
}
string requiredString = controllerContext.RouteData.GetRequiredString("controller");
string str2 = this.GetPath(controllerContext, this.ViewLocationFormats, this.AreaViewLocationFormats, "ViewLocationFormats", viewName, requiredString, "View", useCache, out strArray);
string str3 = this.GetPath(controllerContext, this.MasterLocationFormats, this.AreaMasterLocationFormats, "MasterLocationFormats", masterName, requiredString, "Master", useCache, out strArray2);
if (!string.IsNullOrEmpty(str2) && (!string.IsNullOrEmpty(str3) || string.IsNullOrEmpty(masterName)))
{
return new ViewEngineResult(this.CreateView(controllerContext, str2, str3), this);
}
return new ViewEngineResult(strArray.Union<string>(strArray2));
}

查找到视图之后, 创建一个视图引擎, 然后返回这个视图引擎.

2. Render(viewContext, output)

这个方法就是去解析视图, 主要是为了解析其中的Razor, 生成最后的页面数据.

//System.Web.Mvc.BuildManagerCompiledView
public void Render(ViewContext viewContext, TextWriter writer)
{
if (viewContext == null)
{
throw new ArgumentNullException("viewContext");
}
object instance = null;
Type compiledType = this.BuildManager.GetCompiledType(this.ViewPath);
if (compiledType != null)
{
instance = this.ViewPageActivator.Create(this._controllerContext, compiledType);
}
if (instance == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_ViewCouldNotBeCreated, new object[] { this.ViewPath }));
}
this.RenderView(viewContext, writer, instance);
}

这里的RenderView也有两种实现类, 我们在vs中建mvc项目的时候, 可能有人注意到过, 视图有两种模式可以选, 一种是Razor, 另一种就是WebForm. 事实上, 确实是有两种语法以供使用的.

那这里只看一下Razor的语法了.

//System.Web.Mvc.RazorView
protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance)
{
if (writer == null)
{
throw new ArgumentNullException("writer");
}
WebViewPage page = instance as WebViewPage;
if (page == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, new object[] { base.ViewPath }));
}
page.OverridenLayoutPath = this.LayoutPath;
page.VirtualPath = base.ViewPath;
page.ViewContext = viewContext;
page.ViewData = viewContext.ViewData;
page.InitHelpers();
if (this.VirtualPathFactory != null)
{
page.VirtualPathFactory = this.VirtualPathFactory;
}
if (this.DisplayModeProvider != null)
{
page.DisplayModeProvider = this.DisplayModeProvider;
}
WebPageRenderingBase startPage = null;
if (this.RunViewStartPages)
{
startPage = this.StartPageLookup(page, RazorViewEngine.ViewStartFileName, this.ViewStartFileExtensions);
}
HttpContextBase httpContext = viewContext.HttpContext;
WebPageRenderingBase base4 = null;
object model = null;
page.ExecutePageHierarchy(new WebPageContext(httpContext, base4, model), writer, startPage);
}

3. ReleaseView(context, this.View)

//System.Web.Mvc.VirtualPathProviderViewEngine
public virtual void ReleaseView(ControllerContext controllerContext, IView view)
{
IDisposable disposable = view as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}

这里是释放资源了

二、Json

这个也是常用的, 返回时, 会在内部转换实体为Json格式字符串. 非常方便好用. 为前端直接提供数据.

public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if ((this.JsonRequestBehavior == JsonRequestBehavior.DenyGet) && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
}
HttpResponseBase response = context.HttpContext.Response;
if (!string.IsNullOrEmpty(this.ContentType))
{
response.ContentType = this.ContentType;
}
else
{
response.ContentType = "application/json";
}
if (this.ContentEncoding != null)
{
response.ContentEncoding = this.ContentEncoding;
}
if (this.Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
if (this.MaxJsonLength.HasValue)
{
serializer.MaxJsonLength = this.MaxJsonLength.Value;
}
if (this.RecursionLimit.HasValue)
{
serializer.RecursionLimit = this.RecursionLimit.Value;
}
response.Write(serializer.Serialize(this.Data));
}
}

目录已同步

MVC源码分析 - View的更多相关文章

  1. MVC源码分析 - View续之Razor

    过完年, 大家都忙碌起来了, 我也不例外. 不过并不是忙碌于去面试找工作, 而是忙碌于现在手上的工作. 闲话不多说了, 进入今天的主题. 一.Index页面在哪里 很奇怪, 在目录bin下面的dll文 ...

  2. ASP.NET MVC源码分析

    MVC4 源码分析(Visual studio 2012/2013) HttpModule中重要的UrlRoutingModule 9:this.OnApplicationPostResolveReq ...

  3. asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证

    原文:asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证 在前面的文章中我们曾经涉及到ControllerActionInvoker类GetPara ...

  4. 精尽Spring MVC源码分析 - 一个请求的旅行过程

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  5. 精尽Spring MVC源码分析 - HandlerAdapter 组件(四)之 HandlerMethodReturnValueHandler

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  6. 精尽Spring MVC源码分析 - HandlerExceptionResolver 组件

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  7. 精尽Spring MVC源码分析 - RequestToViewNameTranslator 组件

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  8. 精尽Spring MVC源码分析 - LocaleResolver 组件

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  9. 精尽Spring MVC源码分析 - ViewResolver 组件

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

随机推荐

  1. 【python】鼠标操作

    [python]鼠标操作 推荐地址:http://www.cnblogs.com/fnng/p/3288444.html --------------------------------------- ...

  2. js-数组方法push

    <script type="text/javascript">        var arr=[1,2,3,4,5]        arr.push(6,7)      ...

  3. java基础知识-逻辑运算符

    /*首先申明:逻辑运算符的操作数都是布尔型表达式*/ /* 演示逻辑运算符 & :两个操作数都为真的时候结果为真 | :两个操作数只要有一个为真,结果就为真 && :短路与,左 ...

  4. hdu 3910 Liang Guo Sha

    题目链接:hdu 3910 Liang Guo Sha 题目大意:Alice和Bob这两个小伙伴又发明了一种新游戏, 叫两国杀, 每个人手上有两张牌,“杀” 和“闪”, 然后有三个数值A,B和C, 当 ...

  5. Spring中注入bean学习的总结

    1.在类上直接加注解@Component,那么这个类就直接注入到Spring容器中了  ,像@Contrloller,@Service这些本质上都是@Component, 2.@Configurati ...

  6. SharePoint 列表中增加列编辑功能菜单

    需求描述 在企业的部署中,经常将SharePoint和TFS集成在一起,两个系统之间相互读取数据,展现开发进度.在TFS 2018之前版本中,由于TFS的门户定制功能有限,用户比较喜欢使用ShareP ...

  7. C#调用接口注意要点

    在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存cookie值,再进行其他接 ...

  8. 使用Code First建模自引用关系笔记

    原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasRequired:前者(A)包含后者(B)一个不为 ...

  9. PowerDesigner的Name和Code不同步设置

    1.“Tools”->"GeneralOptions"(最下方) 2.“Dialog”(左侧列表选第2个) 3.“Name to Code mirroring”的勾去掉

  10. 《jQuery基础教程(第四版)》学习笔记

    本书代码参考:Learning jQuery Code Listing Browser 原书: jQuery基础教程 目录: 第2章 选择元素 1. 使用$()函数 2. 选择符 3. DOM遍历方法 ...