您的位置:首页 > 其它

【MVC】关于Action返回结果类型的事儿(上)

2015-01-08 23:49 423 查看

一、ASP.NETMVC1.0Result几何?

Action的返回值类型到底有几个?咱们来数数看。

ASP.NETMVC1.0目前一共提供了以下十几种Action返回结果类型:

1.ActionResult(base)

2.ContentResult

3.EmptyResult

4.HttpUnauthorizedResult

5.JavaScriptResult

6.JsonResult

7.FileResult(base)

8.FileContentResult

9.FilePathResult

10.FileStreamResult

11.RedirectResult

12.RedirectToRouteResult

13.ViewResultBase(base)

14.ViewResult

15.PartialViewResult

一个列表下来看得人眼花缭乱,因为可用的Result很多,接着再瞧瞧类关系图以佐辨析:





如图中可见,ActionResult可谓人丁兴旺,目前膝下有儿9子(如图中红色所圈的类),ViewResultBase与FileResult又各有子两三口,这些儿孙们各司所长。那么各个Result都会干点啥事儿呢?这个问题说来话长,不过根据诸如“虎父无犬子”、“种瓜得瓜,种豆得豆”、“龙生龙,凤生凤,老鼠的孩子打地洞”的俗语,孩子们多少从他爹那儿遗传了点什么,所以要说明它们的才干之前,得先唠叨唠叨一下ActionResult这个爹,这个爷,因此这事情还是得先从ActionResult说起。

二、朴实的ActionResult

所有的Result都派生自ActionResult抽象类,因此ActionResult作为基类提供了最基础的功能,ActionResult是一个抽象类,其声明如下:

publicabstractclassActionResult{

publicabstractvoidExecuteResult(ControllerContextcontext);

}

看看普通人民、相貌平平的ActionResult,ActionResult是个朴素老百姓,没啥特长,就一个ExecuteResult()抽象方法,这个ExecuteResult()抽象方法还啥都不干,遗传给儿女孙子们让它们去发挥,那么它的责任其实就很明确了,它就是为遗传作准备的,繁殖下一代用的,是只公猪种。因为ActionResult是所有Result的基类,因此你可以在所有的Action上使用它作为返回值类型,而无需动脑筋来明确与返回值相同的类型。

二、EmptyResult

EmptyResult是ActionResult最没用的儿子,虽然生儿都想生孙仲谋,希望儿子们都是八斗之才,国家栋梁,可惜第一胎EmptyResult就严重破坏了它的梦想,看来也只能痛恨自己种子不够好。咱来瞧瞧这个没用的阿斗:

//表示一个啥都不干的结果,就像controlleraction返回null

publicclassEmptyResult:ActionResult{

privatestaticreadonlyEmptyResult_singleton=newEmptyResult();

internalstaticEmptyResultInstance{

get{

return_singleton;

}

}

publicoverridevoidExecuteResult(ControllerContextcontext){

}

}

EmptyResult遗传并实现了ActionResult的ExecuteResult()方法,同时也遗传了ActionResult的天真朴实的想法,也想“还是等下一代吧”,它有点老子的“无为”味道,所以它的ExecuteResult()方法像足了它的老爹,啥也不干。

EmptyResult类使用了简单的单例模式,看来这样不思进取的儿子,整个家族里头生一个就够糟糕了,用广东人的话说,生它还不如生块叉烧肉。

在Action中,若要返回一个空的页面(不常用),则可如下:

publicActionResultIndex()

{

returnnewEmptyResult();

}

执行后页面将缺省返回一个body为空的HMTL架构:

<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">
<html><head>
<metacontent="text/html;charset=gb2312"http-equiv=content-type></head>
<body></body></html>

三、RedirectResult

EmptyResult的“无为”给ActionResult的打击着实不小,只好将期待落在其他孩子身上,RedirectResult虽然不是什么大才,起码有一技之长,我们看看它的ExecuteResult()方法:

publicoverridevoidExecuteResult(ControllerContextcontext){

if(context==null){

thrownewArgumentNullException("context");

}

stringdestinationUrl=UrlHelper.Content(Url,context.HttpContext);

context.HttpContext.Response.Redirect(destinationUrl,false/*endResponse*/);

}

RedirectResult用于执行转移。事实上RedirectResult最终调用了Response.Redirect()进行转移,所以您可以使用RedirectResult跳转到任意的包括当前项目或网络上的Url,例如:http://www.cnblogs.com,对于当前项目的路径,因为使用了UrlHelper.Content()方法获取目标路径,所以RedirectResult传递的Url同时支持当前项目目录标识符~(即应用程序目录)。

四、RedirectToRouteResult

RedirectToRouteResult对于RedirectResult而言,其作用有所局限,仅能转移到路由(路由匹配的结果最终是一条相对当前项目的Url,例如:/Home/Index),总的来说与RedirectResult的最终作用是一样的,都是执行转移。RedirectResult较为直接地转移到任意指定的Url,而RedirectToRouteResult则转移到指定的路由(路由匹配所得结果最终也是一个的Url):

publicoverridevoidExecuteResult(ControllerContextcontext){

if(context==null){

thrownewArgumentNullException("context");

}

stringdestinationUrl=UrlHelper.GenerateUrl(RouteName,null/*actionName*/,null/*controllerName*/,RouteValues,Routes,context.RequestContext,false/*includeImplicitMvcValues*/);

if(String.IsNullOrEmpty(destinationUrl)){

thrownewInvalidOperationException(MvcResources.ActionRedirectResult_NoRouteMatched);

}

context.HttpContext.Response.Redirect(destinationUrl,false/*endResponse*/);

}

RedirectToRouteResult先通过调用UrlHelper.GenerateUrl()来获得路由匹配所得的最终Url,接着的执行转移过程与RedirectResult相同。

路由配置的过程在Global.asax文件中进行,在以MVC模板方式创建的MVC项目中都带有此文件,可在文件中的MvcApplication类的RegisterRoutes()方法中进行配置路由,该方法缺省的内容如下:

publicstaticvoidRegisterRoutes(RouteCollectionroutes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(

"Default",//Routename

"{controller}/{action}/{id}",//URLwithparameters

new{controller="Home",action="Index",id=""}//Parameterdefaults

);

}

RedirectToRouteResult可跳转至任何一条匹配的路由规则。是以利用路由转移可以跳转到其他控制器的Action。

五、ContentResult

ContentResult用于将字符串直接向客户端输出。ContentResult的ExecuteResult方法实际上是调用了Response.Write(string…),输入并无特别之处,但是在ASP时代,这个Response.Write()却是可以纵横页面。从输出一个简单的字符串到整个页面,Response.Write()都能胜任,所以ContentResult显得特别强大:

publicoverridevoidExecuteResult(ControllerContextcontext){

if(context==null){

thrownewArgumentNullException("context");

}

HttpResponseBaseresponse=context.HttpContext.Response;

if(!String.IsNullOrEmpty(ContentType)){

response.ContentType=ContentType;

}

if(ContentEncoding!=null){

response.ContentEncoding=ContentEncoding;

}

if(Content!=null){

response.Write(Content);

}

}

若没有提供任何输出的内容,ContentResult呈现的结果与EmptyResult是一样的,都是输出最基本的<body>标记内容为空的HTML,若内容不为空,则直接输出这些内容(不再输出其他任何HTML代码),例如:

publicActionResultIndex()

{

returnContent("a");

}

其页面的HTML代码也将只有一个字符a,要补全所有基本标记需要在字符串中编写,例如:

publicActionResultIndex()

{

returnContent("<!DOCTYPEHTMLPUBLIC""-//W3C//DTDHTML4.0Transitional//EN"">"+

"<html>"+

"<head><metacontent=""text/html;charset=gb2312""http-equiv=content-type></head>"+

"<body>"+

"abc"+

"</body>"+

"</html>"

);

}

当然不建议使用此方法来输出页面标记,ContentResult用在Ajax中颇为合适,因为只要内容不为空,输出的字符串与传送到客户端的内容一致,没有额外的附加内容。

事实上从ContentResult我们可以看到一个ActionResult其实并无特别,从前面几个Result来看,其实不过是Response.Redirect或Response.Write,此外还可以利用二进制流Response.OutputStream.Write向客户端上载文件……据此我们所以拓展编写更多针对实际意义的Result。例如XmlResult(文件)、RssResult(跟XmlResult其实是一样的)等等。

六、JsonResult

JsonResult首先将指定的对象序列化为Json字符串,然后将字符串写入到HTTP输出流。撇开对象序列化为Json字符串这一过程,实际上与ContentResult其实是一样的,因为JsonResult与ContentResult都是调用Response.Write()向HTTP输出流写入一些内容。所以对此不再赘述:

publicoverridevoidExecuteResult(ControllerContextcontext){

if(context==null){

thrownewArgumentNullException("context");

}

HttpResponseBaseresponse=context.HttpContext.Response;

if(!String.IsNullOrEmpty(ContentType)){

response.ContentType=ContentType;

}

else{

response.ContentType="application/json";

}

if(ContentEncoding!=null){

response.ContentEncoding=ContentEncoding;

}

if(Data!=null){

//TheJavaScriptSerializertypewasmarkedasobsoletepriorto.NETFramework3.5SP1

#pragmawarningdisable0618

JavaScriptSerializerserializer=newJavaScriptSerializer();

response.Write(serializer.Serialize(Data));

#pragmawarningrestore0618

}

}

有个地方想唠叨两句,在代码中的:

response.ContentType="application/json";

若要直接向页面输出的话需要更改为文本类型,例如text/html,否则你要以文件形式下载JsonResult的结果内容。不过这对于将Json用于Ajax而言不会有什么影响。

七、JavaScriptResult

道与JsonResult、ContentResult相同。所以也不赘述,徒费唇舌:

publicoverridevoidExecuteResult(ControllerContextcontext){

if(context==null){

thrownewArgumentNullException("context");

}

HttpResponseBaseresponse=context.HttpContext.Response;

response.ContentType="application/x-javascript";

if(Script!=null){

response.Write(Script);

}

}

八、HttpUnauthorizedResult

HttpUnauthorizeResult设置客户端错误代号为401,即未经授权浏览状态,若设置了Form验证并且客户端没有任何身份票据,那么将转跳到指定的页面(例如登陆页):

publicoverridevoidExecuteResult(ControllerContextcontext){

if(context==null){

thrownewArgumentNullException("context");

}

//401istheHTTPstatuscodeforunauthorizedaccess-settingthis

//willcausetheactiveauthenticationmoduletoexecuteitsdefault

//unauthorizedhandler

context.HttpContext.Response.StatusCode=401;

}

可以学习HttpUnauthorizeResult来编写更多同类的返回结果,例如设置Response.StatusCode=404,这个是常见的“页面未找到”错误,403禁止访问等等。

九、FileResult

FileResult是一个抽象类,主要属性包括声明内容类型信息ContentType及文件名称FileDownloadName,客户端下载工具中将显示此名称(如果有指定,ContentType可指定任意非空字符串),如果不指定文件名,ContentType需要正确指定,否则无法识别待下载的文件类型。

FileResult用作其他向客户端上载文件的类的基类。

十、FilePathResult

FilePathResult继承自FileResult,使用FilePathResult类向客户端上载文件只需要给出文件的路径即可。FilePathResult将调用Response.TransmitFile()传输该文件:

protectedoverridevoidWriteFile(HttpResponseBaseresponse){

response.TransmitFile(FileName);

}

十一、FileContentResult

FileContentResult继承自FileResult。

FileContentResult将指定的字节内容写入二进制流(客户端将以文件形式下载),对比FilePathResult所不同的是FilePathResult是给出文件路径,然后将整份文件上载给客户,而FileContentResult则可以传输某一个字节数组,例如:

publicActionResultIndex()

{

returnFile(System.Text.Encoding.UTF8.GetBytes("你好吗"),"unknown","t.txt");

}

FileContentResult使用Response.OutputStream.Write输出内容:

protectedoverridevoidWriteFile(HttpResponseBaseresponse){

response.OutputStream.Write(FileContents,0,FileContents.Length);

}

十二、FileStreamResult

FileStreamResult继承自FileResult。

FileStreamResult向指定文件流读取数据,其他的内容与FileContentResult道同。请参考FileContentResult。

转自:http://www.cnblogs.com/ilovesilence/archive/2009/03/25/aspnetmvc-actionresult.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: