Controller的職責是把模型資料交給視圖呈現。每個Controller中含有多個Action(動作), Url通過路由功能找到相應控制器下的相應的動作。動作傳回一個ActionResult 類型的結果。
看一下ActionResult 的結構:
public abstract class ActionResult
{
protected ActionResult();
public abstract void ExecuteResult(ControllerContext context);
}
最主要的是這個結果帶有一個ExecuteResult方法,這個方法用于把ControllerContext和TempData,ViewData 傳遞到視圖上下文中(ViewContext)。
動作傳回的結果View()方法傳回類型是:ViewResult。它的父類是:ViewResultBase。
它重寫了:protected override ViewEngineResult FindView(ControllerContext context);用于尋找aspx檔案
ViewResult父類的基類是ActionResult,它有很多個重載。
System.Web.Mvc.ContentResult;
System.Web.Mvc.EmptyResult
System.Web.Mvc.FileResult
System.Web.Mvc.HttpUnauthorizedResult
System.Web.Mvc.JavaScriptResult
System.Web.Mvc.JsonResult
System.Web.Mvc.RedirectResult
System.Web.Mvc.RedirectToRouteResult
System.Web.Mvc.ViewResultBase
下邊列出controller中用于得到ActionResult派生類執行個體的一些方法:
protected internal ContentResult Content(string content);
protected internal FileStreamResult File(Stream fileStream, string contentType);
protected internal FileContentResult File(byte[] fileContents, string contentType);
protected internal FilePathResult File(string fileName, string contentType);
protected internal JsonResult Json(object data);
protected internal RedirectToRouteResult RedirectToAction(string actionName);
protected internal RedirectToRouteResult RedirectToRoute(string routeName);
(一)ContentResult
以ContentResult為例來測試一下:
public ActionResult TextTest()
return Content("文本");
}
在源碼中檢視,它就是一行文本。現在分析一下這個過程,它是怎樣顯示在頁面上的。
調用Controller的Content(string s)方法,就是調用Content(string,null,null)
protected internal virtual ContentResult Content(
string content, string contentType, Encoding contentEncoding)
ContentResult result = new ContentResult();
result.Content = content;
result.ContentType = contentType;
result.ContentEncoding = contentEncoding;
return result;
這裡它傳回一個ContentResult類型對象,這個對象的Content屬性設定為Content("文本")中的“文本”。在動作中的
return
之後,執行ExecuteResult方法:
public override void ExecuteResult(ControllerContext context)
if (context == null)
{
throw new ArgumentNullException("context");
}
HttpResponseBase response = context.HttpContext.Response;
if (!string.IsNullOrEmpty(this.ContentType))
response.ContentType = this.ContentType;
if (this.ContentEncoding != null)
response.ContentEncoding = this.ContentEncoding;
if (this.Content != null)
response.Write(this.Content);
這個方法與View()方法中的ExecuteResult有差別:
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;
ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData);
this.View.Render(viewContext, context.HttpContext.Response.Output);
if (result != null)
Result.ViewEngine.ReleaseView(context, this.View);
從這裡來看,ContentResult是直接響應文本,而不生成ViewContext。
(二)JsonResult
再來看一下JsonResult,因為這個會經常用到,是以也說明一下這個。
Controller的protected internal JsonResult Json(object data)方法,最終調用的是:
protected internal virtual JsonResult Json(object data, string contentType,
Encoding contentEncoding)
JsonResult result = new JsonResult();
result.Data = data;
result.ContentType = contentType;
result.ContentEncoding = contentEncoding;
return result;
其中的要json序列化的對象data,被寫給了JsonResult的Data屬性。
然後,在JsonResult 中的Data屬性是這樣的:
public object Data
[CompilerGenerated]
get
return this.<Data>k__BackingField;
set
this.<Data>k__BackingField = value;
然後執行ExecuteResult方法:
else
response.ContentType = "application/json";
if (this.Data != null)
JavaScriptSerializer serializer = new JavaScriptSerializer();
response.Write(serializer.Serialize(this.Data));
可以看到當JsonResult的Data屬性不為無的時候,被序列化了。用的方法是JavaScriptSerializer 對象的Serialize()方法。這個對象位于:System.Web.Script.Serialization
到這裡,也沒有生成視圖上下文,直接響應為一個Json對象(在浏覽器上可以看到是一個Json串,有關Json串與Json對象可以參見我的部落格:
http://www.cnblogs.com/jams742003/archive/2009/12/29/1634764.html)。
現在測試一下JsonResult。
{"UserName":"宋江","Age":30,"Company":"好漢公司"}
(三)RedirectResult
RedirectResult用于重定向頁面。這裡也說明一下。
在controller中,用于傳回RedirectResult類型的方法是Redirect(string url):
protected internal virtual RedirectResult Redirect(string url)
if (string.IsNullOrEmpty(url))
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "url");
return new RedirectResult(url);
然後看RedirectResult 類:
通過傳遞重定向位址的參數的構造器來給Url屬性寫值,然後執行ExecuteResult方法:
string url = UrlHelper.Content(this.Url, context.HttpContext);
context.HttpContext.Response.Redirect(url, false);
來重定向到目标Url
以示例說明。
return Redirect("http://www.126.com");
(四)RedirectToRouteResult
RedirectToRouteResult是一個很有用的,它用于路由重定向
(1)RedirectToAction方法
protected internal RedirectToRouteResult RedirectToAction(string actionName,
string controllerName)
return this.RedirectToAction(actionName, controllerName, (RouteValueDictionary)null);
它用于重訂向到特定控制器中的動作(動作,應該說是控制器通過動作傳回模型到視圖)。
它最終要執行的方法是:
protected internal virtual RedirectToRouteResult
RedirectToAction(string actionName, string controllerName, RouteValueDictionary routeValues)
RouteValueDictionary dictionary;
if (this.RouteData == null)
dictionary = RouteValuesHelpers.MergeRouteValues(actionName,
controllerName, null, routeValues, true);
controllerName, this.RouteData.Values, routeValues, true);
return new RedirectToRouteResult(dictionary);
如果routeValues為無的話,
if (this.RouteData == null)
dictionary = RouteValuesHelpers.MergeRouteValues(actionName,
controllerName, null, routeValues, true);
mergeRouteValues方法會根據提供的控制器名和動作名,建立RouteValueDictionary dictionary
然後通過RedirectToRouteResult的構造器來建立一個RedirectToRouteResult對象。然後執行ExecuteResult方法:
string str = UrlHelper.GenerateUrl(this.RouteName, null, null,
this.RouteValues, this.Routes, context.RequestContext, false);
if (string.IsNullOrEmpty(str))
throw new InvalidOperationException(MvcResources.ActionRedirectResult_NoRouteMatched);
context.HttpContext.Response.Redirect(str, false);
重定向到新位址。示例:
return RedirectToAction("ModelTest", "News");
(2)RedirectToRoute
這個方法也是要建立RedirectToRouteResult對象,這裡不再贅述。
protected internal virtual RedirectToRouteResult RedirectToRoute(string routeName,
RouteValueDictionary routeValues)
return new RedirectToRouteResult(routeName,
RouteValuesHelpers.GetRouteValues(routeValues));
部落格園大道至簡
http://www.cnblogs.com/jams742003/轉載請注明:部落格園