mvc基础系列说谈(3)——controller与action

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

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

 

重定向到新地址。示例:

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

 

博客园大道至简

http://www.cnblogs.com/jams742003/

转载请注明:博客园

目录
相关文章
|
前端开发 Java 数据安全/隐私保护
深入理解 Spring MVC Controller —— 请求参数获取
前言 接上篇《深入理解 Spring MVC Controller —— 请求映射》,上篇主要介绍了处理器方法及请求映射的定义。有了处理器方法 Spring MVC 就可以对请求进行处理,有了请求映射 Spring MVC 就能知道哪些请求应该由哪些处理器方法来处理。
643 0
深入理解 Spring MVC Controller —— 请求参数获取
|
4月前
|
XML 前端开发 JavaScript
SpringMVC中单独配置<mvc:default-servlet-handler/> 导致 Controller失效
SpringMVC中单独配置<mvc:default-servlet-handler/> 导致 Controller失效
75 0
|
8月前
|
设计模式 JSON 前端开发
2021-08-11Spring MVC,入门项目搭建及流程,springMVC的适配器和映射器,基于注解的controller,映射请求,方法返回值,requestmapping注解
2021-08-11Spring MVC,入门项目搭建及流程,springMVC的适配器和映射器,基于注解的controller,映射请求,方法返回值,requestmapping注解
39 0
|
10月前
|
前端开发 Java Spring
《Spring MVC》 第三章 @Controller、@RequestMapping 注解和获取请求参数
《Spring MVC》 第三章 @Controller、@RequestMapping 注解和获取请求参数
136 0
|
10月前
|
前端开发 Java Spring
spring mvc 一次请求如何映射到对应的controller 如何规避冲突
spring mvc 一次请求如何映射到对应的controller 如何规避冲突
93 0
|
前端开发 Java 索引
Spring MVC Controller 方法参数 Map 的实现类是什么?
问题 题主问题描述如下: 在SpringBoot中,Controller的参数中有Map接口类型的,请问他的实现类是什么? 突发奇想,在SpringBoot中,Controller的参数中有Map接口类型的
346 0
Spring MVC Controller 方法参数 Map 的实现类是什么?
|
XML JSON 前端开发
深入理解 Spring MVC Controller —— 请求映射
前言 基于注解的 Spring MVC 的项目中,Controller 应该是我们接触最多的类了,这里提到的 Controller 并非是某一个具体的接口或类,而是一种概念,只要我们我们定义的类中包含了处理请求的方法,这个类就可以称为 Controller,而处理请求的方法被称为处理器方法。
612 0
深入理解 Spring MVC Controller —— 请求映射
|
设计模式 安全 前端开发
面试官:Spring MVC 如何保证 Controller 的并发安全性?面试必问。。
单例模式(Singleton)是程序设计中一种非常重要的设计模式,设计模式也是Java面试重点考察的一个方面。
278 0
面试官:Spring MVC 如何保证 Controller 的并发安全性?面试必问。。
|
前端开发 Java 数据处理
【Spring MVC】(二)Controller、View之间的映射与参数传递
【Spring MVC】(二)Controller、View之间的映射与参数传递
409 0
|
前端开发 数据库
MVC中Action之间传值
MVC中Action之间传值
133 0
MVC中Action之间传值