Controller的职责是把模型数据交给视图呈现。每个Controller中含有多个Action(动作), Url通过路由功能找到相应控制器下的相应的动作。动作返回一个ActionResult 类型的结果。

看一下ActionResult 的结构:

public abstract class ActionResult
{
    
protected ActionResult();
    
public abstract void ExecuteResult(ControllerContext context);

 

最主要的是这个结果带有一个ExecuteResult方法,这个方法用于把ControllerContextTempDataViewData 传递到视图上下文中(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("文本");
}

 

在源码中查看,它就是一行文本。现在分析一下这个过程,它是怎样显示在页面上的。

 

调用ControllerContent(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有区别:

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

    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,因为这个会经常用到,所以也说明一下这个。

Controllerprotected 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,被写给了JsonResultData属性。

然后,在JsonResult 中的Data属性是这样的:

public object Data
{
    [CompilerGenerated]
    
get
    {
        
return this.<Data>k__BackingField;
    }

    [CompilerGenerated]
    
set
    {
        
this.<Data>k__BackingField = value;
    }
}

 

然后执行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;
    }
    
else
    {
        response.ContentType 
= "application/json";
    }

    
if (this.ContentEncoding != null)
    {
        response.ContentEncoding 
= this.ContentEncoding;
    }

    
if (this.Data != null)
    {
        JavaScriptSerializer serializer 
= new JavaScriptSerializer();
        response.Write(serializer.Serialize(
this.Data));
    }
}

 

可以看到当JsonResultData属性不为无的时候,被序列化了。用的方法是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方法:

public override void ExecuteResult(ControllerContext context)
{
    
if (context == null)
    {
        
throw new ArgumentNullException("context");
    }

    
string url = UrlHelper.Content(this.Url, context.HttpContext);
    context.HttpContext.Response.Redirect(url, 
false);
}

 

来重定向到目标Url

以示例说明。

public ActionResult TextTest()
{
   
return Redirect("http://www.126.com");
}

 

(四)RedirectToRouteResult

RedirectToRouteResult是一个很有用的,它用于路由重定向

1RedirectToAction方法

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);
    }
    
else
    {
        dictionary 
= RouteValuesHelpers.MergeRouteValues(actionName, 
                           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方法:

public override void ExecuteResult(ControllerContext context)
{
    
if (context == null)
    {
        
throw new ArgumentNullException("context");
    }
    
string str = UrlHelper.GenerateUrl(this.RouteName, nullnull
            
this.RouteValues, this.Routes, context.RequestContext, false); 

    
if (string.IsNullOrEmpty(str))
    {
       
throw new InvalidOperationException(MvcResources.ActionRedirectResult_NoRouteMatched);
    }

    context.HttpContext.Response.Redirect(str, 
false);
}

 

重定向到新地址。示例:

public ActionResult TextTest()
{
   
return RedirectToAction("ModelTest""News");
}

 

2RedirectToRoute

这个方法也是要创建RedirectToRouteResult对象,这里不再赘述。

protected internal virtual RedirectToRouteResult RedirectToRoute(string routeName, 
                                                 RouteValueDictionary routeValues)
{
    
return new RedirectToRouteResult(routeName,
            RouteValuesHelpers.GetRouteValues(routeValues));
}

 

posted on 2010-02-03 15:33  梅桦  阅读(10064)  评论(2编辑  收藏  举报