ActionResult
ActionResult是Action的返回结果。ActionResult 有多个派生类,每个子类功能均不同,并不是所有的子类都需要返回视图View,有些直接返回流,有些返回字符串等。我们来看一下ActionResult派生类关系图
具体看一下每个类的功能,由于MSDN的示意图太简单不能完全表现所有的子类功能
类名 抽象类 父类 功能
 ActionResult  abstract  Object 顶层父类
ContentResult     根据内容的类型和编码,数据内容.通过Controller的Content方法返回
EmptyResult     返回空结果
FileResult abstract   写入文件内容,具体的写入方式在派生类中.
FileContentResult   FileResult 通过 文件byte[] 写入Response 返回客户端,Controller的File方法
FilePathResult   FileResult 通过 文件路径 写入Response 返回客户端,Controller的File方法
FileStreamResult   FileResult 通过 Stream 写入Response 返回客户端,Controller的File方法
HttpUnauthorizedResult     抛出401错误
JavaScriptResult     返回javascript文件
JsonResult     返回Json格式的数据
RedirectResult     使用Response.Redirect重定向页面
RedirectToRouteResult     根据Route规则重定向页面
ViewResultBase abstract   调用IView.Render() 返回视图,两个常用属性ViewData,TempData
PartialViewResult   ViewResultBase 调用父类ViewResultBase 的ExecuteResult方法. 
重写了父类的FindView方法. 
寻找用户控件.ascx文件
ViewResult   ViewResultBase

调用父类ViewResultBase 的ExecuteResult方法. 
重写了父类的FindView方法. 
寻找视图页面(aspx,cshtml或自定义视图)

Controller的View()方法默认封装ViewResult返回结果

简单的列几种写法,都是Controller已经封装好的
 public ActionResult ShowContent()
{
return Content("测试ContentResult方法"); //默认封装ContentResult文本返回
} public ActionResult Index(UserVO userVo)
{
return View(); //默认封装ViewResult返回
} public ActionResult DownLoadFile(string fileName)
{
return File(Server.MapPath(@"/Images/view.jpg"), @"image/gif");
} public ActionResult ToOther(string fileName)
{
return Redirect(@"http://localhost:1847/Menu/ShowContent");
}
当然你可以自己实现每种的类型返回,而不是通过Controller的方法返回。这个环节最重要的问题,当Action返回ActionResult后,这个ActionResult是如何工作的?ActionResult只有一个抽象方法 ExecuteResult ,当ActionResult实例被返回后,Controller执行器ControllerActionInvoker的InvokeAction方法在处理完IActionFilter之后调用了这段代码InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
看后两个参数,一个是IResultFilter过滤器,一个是Action返回的Result。该方法对返回ActionResult进行前置拦截后,接着调用ActionResult的ExecuteResult方法去处对应的响应业务(返回视图,或字符串,文件流等),最后又对ActionResult后置拦截了一次。调用棧比较深
 
//1---------------------------------
protected virtual ResultExecutedContext InvokeActionResultWithFilters(ControllerContext controllerContext, IList<IResultFilter> filters, ActionResult actionResult) {
ResultExecutingContext preContext = new ResultExecutingContext(controllerContext, actionResult);
//InvokeActionResult 做为委托被前置与后置包围了
Func<ResultExecutedContext> continuation = delegate {
InvokeActionResult(controllerContext, actionResult);
return new ResultExecutedContext(controllerContext, actionResult, false /* canceled */, null /* exception */);
}; // need to reverse the filter list because the continuations are built up backward
Func<ResultExecutedContext> thunk = filters.Reverse().Aggregate(continuation,
(next, filter) => () => InvokeActionResultFilter(filter, preContext, next));
return thunk();
}
//2--------------------------------------------
internal static ResultExecutedContext InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func<ResultExecutedContext> continuation) {
filter.OnResultExecuting(preContext); //前置拦截----------------------------------------
if (preContext.Cancel) {
return new ResultExecutedContext(preContext, preContext.Result, true /* canceled */, null /* exception */);
} bool wasError = false;
ResultExecutedContext postContext = null;
try {
postContext = continuation(); //ActionResult的ExecuteResult的调用环节------------------------------------------
}
catch (ThreadAbortException) {
// This type of exception occurs as a result of Response.Redirect(), but we special-case so that
// the filters don't see this as an error.
postContext = new ResultExecutedContext(preContext, preContext.Result, false /* canceled */, null /* exception */);
filter.OnResultExecuted(postContext); //出错了,后置拦截----------------------------------
throw;
}
catch (Exception ex) {
wasError = true;
postContext = new ResultExecutedContext(preContext, preContext.Result, false /* canceled */, ex);
filter.OnResultExecuted(postContext);
if (!postContext.ExceptionHandled) {
throw;
}
}
if (!wasError) {
filter.OnResultExecuted(postContext); //后置拦截----------------------------------------------
}
return postContext;
}
//3------------------------------------------------------------------
protected virtual void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) {
actionResult.ExecuteResult(controllerContext);
}
注释的地方注意看一下,InvokeActionResult 是调用ActionResult.ExecuteResult的方法,被做为委托放到IResultFilter前后拦截法中间执行。Controller的执行器ControllerActionInvoker 这几个环节的调度者。再看一下ActionResult.ExecuteResult方法的业务,挑选个有代表性的子类实现的业务贴上来,
FileResult基类 的ExecuteResult,但又调用了WriteFile方法,这个方法又下放到子类中实现了
ublic override void ExecuteResult(ControllerContext context) {
if (context == null) {
throw new ArgumentNullException("context");
} HttpResponseBase response = context.HttpContext.Response;
response.ContentType = ContentType; if (!String.IsNullOrEmpty(FileDownloadName)) {
// From RFC 2183, Sec. 2.3:
// The sender may want to suggest a filename to be used if the entity is
// detached and stored in a separate file. If the receiving MUA writes
// the entity to a file, the suggested filename should be used as a
// basis for the actual filename, where possible.
string headerValue = ContentDispositionUtil.GetHeaderValue(FileDownloadName);
context.HttpContext.Response.AddHeader("Content-Disposition", headerValue);
} WriteFile(response);
}
我们挑选FileStreamResult子类的WriteFile方法看看
protected override void WriteFile(HttpResponseBase response) {
// grab chunks of data and write to the output stream
Stream outputStream = response.OutputStream;
using (FileStream) {
byte[] buffer = new byte[_bufferSize]; while (true) {
int bytesRead = FileStream.Read(buffer, , _bufferSize);
if (bytesRead == ) {
// no more data
break;
} outputStream.Write(buffer, , bytesRead);
}
}
}
整个过程看下来FileStreamResult的ExecuteResult 将文件流写入HttpResponse中返回到客户端,而并不是返回视图。再看一下ViewResult的ExecuteResult的业务,这个业务是在父类的中实现的
ViewResultBase的ExecuteResult业务,ViewResultBase还有两个重要的性ViewData,TempData是在Acion返回的时候封装好的。
public override void ExecuteResult(ControllerContext context) {
if (context == null) {
throw new ArgumentNullException("context");
}
if (String.IsNullOrEmpty(ViewName)) {
ViewName = context.RouteData.GetRequiredString("action");
} ViewEngineResult result = null; if (View == null) {
result = FindView(context);
View = result.View;
} TextWriter writer = context.HttpContext.Response.Output;
ViewContext viewContext = new ViewContext(context, View, ViewData, TempData, writer);
View.Render(viewContext, writer); if (result != null) {
result.ViewEngine.ReleaseView(context, View);
}
}
 
先根据上下文中的路由+Action名找到对应的IView,然后调用IView的Render会出视图写入context.HttpContext.Response.Output返回到客户端。

《ASP.NET MVC4 WEB编程》学习笔记------.net mvc实现原理ActionResult/View的更多相关文章

  1. Asp.net MVC4高级编程学习笔记-视图学习第一课20171009

    首先解释下:本文只是对Asp.net MVC4高级编程这本书学习记录的学习笔记,书本内容感觉挺简单的,但学习容易忘记,因此在边看的同时边作下了笔记,可能其它朋友看的话没有情境和逻辑顺序还请谅解! 一. ...

  2. Asp.net MVC4高级编程学习笔记-视图学习第三课Razor页面布局20171010

    Razor页面布局 1)  在布局模板页中使用@RenderBody标记来渲染主要内容.比如很多web页面说头部和尾部相同,中间内容部分使用@RenderBody来显示不同的页面内容. 2)  在布局 ...

  3. Asp.net MVC4高级编程学习笔记-模型学习第四课基架与模型绑定20171027

    MVC模型 一.构建基架. MVC中的基架可以为应用程序提供CURD各种功能生成所需要的样板代码.在添加控制器的时候可以选择相应的模板以及实体对象来生成相应的模板代码. 首先定义一个模型类如下所示: ...

  4. Asp.net MVC4高级编程学习笔记-模型学习第五课MVC表单和HTML辅助方法20171101

    MVC表单和HTML辅助方法 一.表单的使用. 表单中的action与method特性.Action表示表单要提交往那里,因此这里就有一个URL.这个URL可以是相对或绝对地址.表单默认的method ...

  5. ASP.NET Core Web开发学习笔记-1介绍篇

    ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...

  6. Go web编程学习笔记——未完待续

    1. 1).GOPATH设置 先设置自己的GOPATH,可以在本机中运行$PATH进行查看: userdeMacBook-Pro:~ user$ $GOPATH -bash: /Users/user/ ...

  7. 《ASP.NET MVC4 WEB编程》学习笔记------Web API

    本文截取自情缘 1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集 ...

  8. 《ASP.NET MVC4 WEB编程》学习笔记------Web API 续

    目录 ASP.NET WEB API的出现缘由 ASP.NET WEB API的强大功能 ASP.NET WEB API的出现缘由 随着UI AJAX 请求适量的增加,ASP.NET MVC基于Jso ...

  9. 《ASP.NET MVC4 WEB编程》学习笔记------Model模型绑定

    本文转载自haiziguo Asp.net mvc中的模型绑定,或许大家经常用,但是具体说他是怎么一回事,可能还是会有些陌生,那么,本文就带你理解模型绑定.为了理解模型绑定,本文会先给出其定义,然后对 ...

随机推荐

  1. [参考]Oracle 11g的安装

    1.Linux中安装Oracle 11g http://www.cnblogs.com/gaojun/archive/2012/11/22/2783257.html 2.Windows中安装Oracl ...

  2. JavaEE EL的一些用法

    EL 可以在指示元素中设置EL是否使用 isELIgnored="true" true是不使用 也可以在web.xml中使用 <jsp-config> <jsp- ...

  3. iOS边练边学--NSURLSessionDataTask实现文件真正的断点续传

    实现重点: NSURLSessionDataTask要设置请求头,从路径中获取文件已经下载的长度(文件没有下载过的话,长度为0).通过这个长度设置请求的Range 如图: 接收到请求的时候key:文件 ...

  4. Spring-MVC流程图

    Spring MVC工作流程图 图一 图二  Spring工作流程描述       1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获:   ...

  5. [Asp.net mvc] Asp.net mvc Kendo UI Grid的使用(四)

    有段时间没写博客了,工作状态比较忙,抽空继续总结下Grid的使用,这次主要介绍模板以及其他官网介绍不详尽的使用方法.先Show出数据,然后讲解下.后台代码: public ActionResult O ...

  6. Shell good example

    (1) Source code #! /bin/bash reference ()     {     pa=\$"$1"     echo $pa     x=`eval &qu ...

  7. 42.Android之ListView中ArrayAdapter简单学习

    今天学习下Android中ListView关于ArrayAdapter数据绑定, 废话少说直接上代码. 改下布局文件: <?xml version="1.0" encodin ...

  8. NOI题库-小学奥赛QwQ

    今天Loli教育我们让我们来看看NOI题库的奥赛部分,不过,为何是小学的( ⊙ o ⊙ )啊!感觉智商被各种侮辱. 余数相同问题: 描述 已知三个正整数 a,b,c. 现有一个大于1的整数x,将其作为 ...

  9. php5.5安装及phpmyadmin&nginx配置php模块

    安装php5.5: 下载源地址:rpm -Uvh rpm包安装:yum install php55w.x86_64 php55w-cli.x86_64 php55w-common.x86_64 php ...

  10. POJ1703Find them, Catch them

    Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 37722   Accepted: ...