文章出處

感覺好久沒有學習了, 汗. 年就這么過完了, 感覺沒有嘗到過年的味道. 現在的年過的有些冷清了.

除了體重證明著我過了一個年, 還有一件值得開心的事情, 終于把女朋友變成未婚妻了. 這是一大進步吧. 

閑話不扯了, 繼續之前沒有完成的學習.

前面 結尾處, 提到了這個方法:

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

 

目錄已同步


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()