zoukankan      html  css  js  c++  java
  • MVC源码分析

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

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

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

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

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

     

    目录已同步

  • 相关阅读:
    递归
    书评:《C程序设计语言》
    下一代互联网,今日揭开面纱:IPv6真的要来了
    庆祝Alan Mathison Turing(艾伦·图灵)诞辰100周年!
    svn常用命令行和批处理
    ORACLE 9i数据导入到ORACLE 10G中文出现的乱码问题
    Oracle 11G 的客户端,不再支持连接到ORACLE 8I
    DB2 一个汉字的Byte数,太操蛋了
    关于Windows 7 64位下Visual Studio 2010 开发的Asp.net程序连接Oracle 的出现的问题
    Web Frame 跨域调用Session 丢失问题
  • 原文地址:https://www.cnblogs.com/elvinle/p/6378300.html
Copyright © 2011-2022 走看看