zoukankan      html  css  js  c++  java
  • mvc基础系列说谈(3)——controller与action

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

  • 相关阅读:
    【gtest/gmock】警告与报错集合
    【gtest/gmock】gmock:Mock的常用方法
    【C++容器】vector 和 list 的区别
    【C++百科】C++标准库到底是什么?
    【C++】设置、改变、获取系统环境变量:setenv & putenv & getenv
    【C++调试】error: 编译报错合集
    【C++调试】 warning: 编译警告合集
    Linux常用命令
    tcpdump及wireshark组合使用
    Vim快捷键
  • 原文地址:https://www.cnblogs.com/jams742003/p/1662696.html
Copyright © 2011-2022 走看看