首页 > Python基础教程 >
-
ASP.net教程之使用 ASP.NET Core MVC 创建 Web API(四)
十三、返回值
在上一篇文章(使用 ASP.NET Core MVC 创建 Web API(二))中我们创建了GetBookItems和 GetBookItem两个方法,这两个方法的返回类型是 ActionResult<T> 类型。 ASP.NET Core 自动将对象序列化为 JSON,并将 JSON 写入响应消息的正文中。 GetBookItems和 GetBookItem方法正确执行,没有未经处理的异常的情况下,返回类型的响应代码为200。如果有未经处理的异常返回的响应代码为5xx。
一些操作方法的结果返回类型会是特殊格式,例如 JsonResult
和 ContentResult
。操作可以返回始终以特定方式进行格式设置的特定结果。 例如,返回 JsonResult
将返回 JSON 格式的数据,而不考虑客户端首选项。 同样,返回 ContentResult
将返回纯文本格式的字符串数据(仅返回字符串也是如此)。
ActionResult
返回类型可以表示大范围的 HTTP状态代码。例如, 在上一篇文章(使用 ASP.NET Core MVC 创建 Web API(二))我们创建的GetBookItem方法可以返回两个不同的状态值,如下:
1) 如果没有数据库中没有存在与请求 ID相匹配的书籍信息,则该方法将返回 404 NotFound 错误代码。如下图。
2)如果数据库中存在与请求ID相匹配的书籍信息,则此方法将返回 JSON格式数据的响应正文,并且产生 HTTP 200 响应。 如下图。
一)特定类型
在应用程序中我们对于操作方法的返回值最简单做法是返回.NET简单类型或复杂数据类型(如 string
或自定义对象类型)。请参考以下代码,该操作方法返回自定义 Book
对象的集合:
public Book GetBook(int id) { var bookItem = _context.Book.Find(id); return bookItem; }
1)在执行操作方法期间无需考虑已知条件时,返回特定类型即可满足要求。
2)当在操作方法执行期间需要考虑已知条件时,可能会有多个结果类型需要返回。在这种情况下,通常会将返回类型设为ActionResult或 ActionResult<T>,这样就可以返回基本简单类型或复杂返类型。
二)IActionResult 类型
当操作方法存在多个 ActionResult 需要返回时,适合使用 IActionResult 返回类型。 ActionResult
类型表示多种 HTTP 状态代码。 属于此类别的一些常见返回类型包括:BadRequestResult (400)、NotFoundResult (404) 和 OkObjectResult (200)。
由于操作中有多个返回类型和路径,因此可以使用 [ProducesResponseType] 特性。 此特性方便 Swagger 等工具生成的 API 帮助页生成更多描述性响应详细信息。 [ProducesResponseType]
指示操作将返回的已知类型和 HTTP 状态代码。如下面的示例:
[HttpGet("{id}")] [ProducesResponseType(typeof(Book), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async IActionResult GetBookById(int id) { var bookItem = await _context.Book.FindAsync(id); if (bookItem == null) { return NotFound(); } return Ok(bookItem); }
在上面的代码中,当与id相匹配
的书籍不存在数据库中时,则返回 404 状态代码。 调用 NotFound 帮助程序方法作为 return new NotFoundResult();
的快捷方式。 如果书籍信息存在数据库中,则返回代表有效负载的 bookItem对象和状态代码 200。 调用 Ok 帮助程序方法作为 return new OkObjectResult(bookItem);
的快捷方式。
三)ActionResult<T> 类型
ASP.NET Core 2.1 引入了面向 Web API 控制器操作的 ActionResult<T> 返回类型。 它支持返回从 ActionResult 派生的类型或返回特定类型。 ActionResult<T>
通过 IActionResult 类型可提供以下优势:
1) 可排除 [ProducesResponseType] 特性的 Type
属性。 例如,[ProducesResponseType(200, Type = typeof(
Book))]
可简化为[ProducesResponseType(200)]
。 此操作的预期返回类型改为根据 ActionResult<T>
中的 T
进行推断。
2) 隐式强制转换运算符支持将 T
和 ActionResult
均转换为 ActionResult<T>
。 将 T
转换为 ObjectResult,也就是将 return new ObjectResult(T);
简化为 return T;
。
C# 不支持对接口使用隐式强制转换运算符。 因此,必须使用 ActionResult<T>
,才能将接口转换为具体类型。 例如,在下面的示例中,使用IEnumerable
返回全部书籍信息:
[HttpGet] public async Task<ActionResult<IEnumerable<Book>>> GetBookItems() { return await _context.Book.ToListAsync(); }
大多数操作具有特定返回类型。 执行操作期间可能出现意外情况,不返回特定类型就是其中之一。 例如,操作的输入参数可能无法通过模型验证。 在此情况下,通常会返回相应的 ActionResult
类型,而不是特定类型。
十四、添加新增方法
接下来我们来实现一个新增方法,在WEB API中使用什么来实现新增方法呢?
特性[HttpPost]指示这个方法接收HTTP POST方法请求传过来的数据,并从 HTTP 请求正文中获取书籍信息的值。
在Visual Studio 2017中打开BookController.cs文件,在文件中添加以下 PostBookItem
方法:
// POST: api/Book [HttpPost] public async Task<ActionResult<Book>> PostBookItem(Book item) { _context.Book.Add(item); await _context.SaveChangesAsync(); return CreatedAtAction(nameof(GetBookItem), new { id = item.ID }, item); }
对于CreatedAtAction
方法的说明:
- 如果成功,则返回 HTTP 201 状态代码。 HTTP 201 是在服务器上创建新资源的 HTTP POST 方法的标准响应。
-
将
Location
标头添加到响应。Location
标头指定新建的书籍信息的 URI。 -
引用 GetBookItem操作以创建
Location
标头的 URI。 C#nameof
关键字用于避免在CreatedAtAction
调用中硬编码操作名称。
一)测试 PostBookItem 方法
1) 在Visual Studio 2017中按F5,启动BookApi应用程序。
2) 打开Firefox浏览器,并打开 Rester,在Reseter中,将 HTTP 方法设置为 POST
。
3) 选择“Headers”选项卡,选择“Content-Type”选项,并将值设置为 JSON (application/json),如下图。
4) 然后选择“BODY”选项卡,在请求正文中,输入我们想新增的书籍信息的 JSON,如下图:
JSON字符串:
{"name":"Python编程实践","releaseDate":"2018-02-12","price":55.49,"author":"马瑟斯","publishing":"机械工业出版社"}
5) 使用鼠标左键,单击“SEND”按钮。成功创建了一条新的书籍信息,返回响应为201。如下图。
如果收到 500内部服务器错误,则检查代码与数据是否符合数据库要求,405 不允许的方法错误,则可能是由于未在添加 PostBookItem
方法之后编译项目。
二) 测试位置标头 URI
6) 在前文我们对代码进行过解释,成功创建新的书籍信息之后,响应返回中的Location
标头指向新建的书籍信息的 URI。接下来我们来测试一下,在“Response”窗格中复制“位置”标头值,如下图。
7) 在Rester中把方法设置为“GET”。
8) 在URL输入框中,粘贴刚才复制的 URI(例如,https://localhost:5000/api/Book/24
),如下图。