[译]Action Results in Web API 2

单击此处查看原文

本文阐述了ASP.NET Web API是如何将controller action的返回值转换为HTTP response message的。

一个Web API controller action可以有以下几种返回值:

  1. void
  2. HttpResponseMessage
  3. IHttpActionResult
  4. Some other type(其他)

根据以上四种返回类型的不同,Web API会使用不同的机制创建HTTP response。

返回类型 创建方式
void 无内容
HttpResponseMessage 直接转换为Http response message
IHttpActionResult 调用ExecuteAsync来创建一个HttpResponseMessage,然后转换为Http response message
Other Type 将序列化的返回值写入response body;返回 状态码200(OK)

本文的其余部分将阐述以上四种情况的详细内容。

void

如果返回类型是void,Web API会直接返回一个空的HTTP response,状态码:200,表示无内容。

示例controller:

public class ValuesController : ApiController
{
public void Post()
{
}
}

HTTP response:

HTTP/1.1 204 No Content
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 02:13:26 GMT

HttpResponseMessage

如果action返回了一个HttpResponseMessage,Web API会将该返回值转换为一个HTTP response message,使用HttpResponseMessage对象的属性来填充这个HTTP response message。

下面的示例代码中对一个response message 进行了大量的控制。比如:它设置了Cache-Control header。

public class ValuesController : ApiController
{
public HttpResponseMessage Get()
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
response.Content = new StringContent("hello", Encoding.Unicode);
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromMinutes(20)
};
return response;
}
}

响应:

 HTTP/1.1 200 OK
Cache-Control: max-age=1200
Content-Length: 10
Content-Type: text/plain; charset=utf-16
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 08:53:35 GMT hello

如果你通过使用一个domain model(领域模型)来使用CreateResponse方法,Web API使用media formatter来将序列化的模型写入response body。

public HttpResponseMessage Get()
{
// Get a list of products from a database.
IEnumerable<Product> products = GetProductsFromDB(); // Write the list to the response body.
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, products);
return response;
}

Web API在请求中使用Accept header来选择formatter。更多详情,参见Content Negotiation

IHttpActionResult

IHttpActionResult接口在Web API 2中有过相关介绍。它主要定义了一个**HttpResponseMessage **factory。使用此接口有以下的几点优势:

  • 简化了你对controllers进行的unit test
  • 将创建Http responses的通用逻辑分离到独立的类中
  • 通过隐藏构建response的底层实现细节,使得controller action的功能简介明了

IHttpActionResult声明了一个方法:ExecuteAsync,用于异步创建HttpResponseMessage实例。

public interface IHttpActionResult
{
Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken);
}

如果一个controller action返回一个IHttpActionResult,Web API 将调用ExecuteAsync方法来创建一个HttpResponseMessage。然后它再将HttpResponseMessage转换为一个HTTP response message。

以下是一个IHttpActionResult接口的简单实现,它会创建一个纯文本的响应。

public class TextResult : IHttpActionResult
{
string _value;
HttpRequestMessage _request; public TextResult(string value, HttpRequestMessage request)
{
_value = value;
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage()
{
Content = new StringContent(_value),
RequestMessage = _request
};
return Task.FromResult(response);
}
}

controller action:

public class ValuesController : ApiController
{
public IHttpActionResult Get()
{
return new TextResult("hello", Request);
}
}

response:

HTTP/1.1 200 OK
Content-Length: 5
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 08:53:35 GMT hello

通常你需要将IHttpActionResult的实现写在System.Web.Http.Results命名空间下。因为ApiController定义的helper method会返回这些内置的action results。

下面的示例中,如果一个请求没有匹配到现有的product ID,这个controller将调用ApiController.NotFound来创建一个404(Not Found) response。否则,controller将调用ApiController.OK,来创建一个200(OK) response,它包含了product信息。

public IHttpActionResult Get (int id)
{
Product product = _repository.Get (id);
if (product == null)
{
return NotFound(); // Returns a NotFoundResult
}
return Ok(product); // Returns an OkNegotiatedContentResult
}

Other Return Type

如果返回类型是其他任何的一种形式,Web API使用了一个media formatter来序列化这些返回值,然后将这些序列化的值写入response body。这个response status code是200(ok)。

public class ProductsController : ApiController
{
public IEnumerable<Product> Get()
{
return GetAllProductsFromDB();
}
}

使用这种方法的缺点是,你无法直接返回一个error code,比如404。不过你可以抛出一个HttpResponseException异常来替代error code。更多详情,参见Exception Handling in ASP.NET Web API

Web API在请求中使用Accept header来选择formatter。更多详情,参见Content Negotiation

示例请求:

GET http://localhost/api/products HTTP/1.1
User-Agent: Fiddler
Host: localhost:24127
Accept: application/json

示例响应:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 08:53:35 GMT
Content-Length: 56 [{"Id":1,"Name":"Yo-yo","Category":"Toys","Price":6.95}]

Web API 2中的Action Results的更多相关文章

  1. 【Web API系列教程】1.2 — Web API 2中的Action Results

    前言 本节的主题是ASP.NET Web API怎样将控制器动作的返回值转换成HTTP的响应消息. Web API控制器动作能够返回下列的不论什么值: 1. void 2. HttpResponseM ...

  2. Web API项目中使用Area对业务进行分类管理

    在之前开发的很多Web API项目中,为了方便以及快速开发,往往把整个Web API的控制器放在基目录的Controllers目录中,但随着业务越来越复杂,这样Controllers目录中的文件就增加 ...

  3. Web API 2中的属性路由

    Web API 2中的属性路由 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.ht ...

  4. 从ASP.Net Core Web Api模板中移除MVC Razor依赖项

    前言 :本篇文章,我将会介绍如何在不包括MVC / Razor功能和包的情况下,添加最少的依赖项到ASP.NET Core Web API项目中. 一.MVC   VS WebApi (1)在ASP. ...

  5. [译] 在Web API 2 中实现带JSON的Patch请求

    原文链接:The Patch Verb in Web API 2 with JSON 我想在.NET4.6 Web API 2 项目中使用Patch更新一个大对象中的某个字断,这才意识到我以前都没有用 ...

  6. ASP.NET Web API 2 中的属性路由使用(转载)

    转载地址:ASP.NET Web API 2 中的属性路由使用

  7. ASP.NET Web API 2中的错误处理

    前几天在webapi项目中遇到一个问题:Controller构造函数中抛出异常时全局过滤器捕获不到,于是网搜一把写下这篇博客作为总结. HttpResponseException 通常在WebAPI的 ...

  8. Web API 2中的操作结果

    how ASP.NET Web API converts the return value from a controller action into an HTTP response message ...

  9. Web APi之控制器选择Action方法过程(九)

    前言 前面我们叙述了关于控制器创建的详细过程,在前面完成了对控制器的激活之后,就是根据控制器信息来查找匹配的Action方法,这就是本节要讲的内容.当请求过来时首先经过宿主处理管道然后进入Web AP ...

随机推荐

  1. Linux - 命令行 管道(Pipelines) 详细解释

    命令行 管道(Pipelines) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24249529 管道操作符" ...

  2. 开源文档管理系统LogicalDOC测试报告---安装篇

    开源文档管理系统LogicalDOC测试报告---安装篇 分类: Linux2011-06-22 15:40 7436人阅读 评论(3) 收藏 举报 文档管理测试mysql数据库installerja ...

  3. android 布局属性大全---初学者必备

    Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料,花费本人一个下午搞出来的,希望对其他人有用. 第一类:属性值为true或false android: ...

  4. Libcurl最初的实现tfp上传和下载功能

    研究报告指出的目标是使用libcurl实现ftp文件上传和下载功能 一.Libcurlde简要 Libcurl的而且易于使用的利用url进行文件传输的库. , libcurl当前支持DICT, FIL ...

  5. Hypeiron Planning/Essbase修改规划类型名称

    1.修改planning关系库 1.1--修改Plan_type,例如将type_name “Plan1”修改为”Plan1ts”,提交 SELECT * FROM hsp_plan_type FOR ...

  6. TodoList开发笔记 – Part Ⅳ

    跌跌撞撞总算是把客户端开发好了,后台的代码因为不复杂,就写了些单元测试跑一跑就算通过了,大部分时间都是在调整脚本. 这一节开始部署TodoList项目. 一.了解IIS(Internet Infoma ...

  7. 深入分析ENode的内部实现流程和关键地方的幂等设计

    ENode 2.0 - 深入分析ENode的内部实现流程和关键地方的幂等设计 前言 ENode架构图 ENode框架内部实现流程分析 Command的幂等处理 Domain Event持久化时的并发冲 ...

  8. 简话ASP.NET Web API

    简话ASP.NET Web API 在vs2012中,我们很容易在根据选择的ASP.NET MVC Web应用程序来新建一个Web API应用,聪明的你一定想见得到,Web API和MVC有着某种联系 ...

  9. 大数据工具篇之Hive与MySQL整合完整教程

    大数据工具篇之Hive与MySQL整合完整教程 一.引言 Hive元数据存储可以放到RDBMS数据库中,本文以Hive与MySQL数据库的整合为目标,详细说明Hive与MySQL的整合方法. 二.安装 ...

  10. Linux环境进程间通信(五): 共享内存(上)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...