在 ASP.NET Core MVC 中使用控制器处理请求
作者:Steve Smith 和 Scott Addie
控制器、操作和操作结果是开发人员如何使用 ASP.NET Core MVC 生成应用的一个基本组成部分。
什么是控制器?
控制器用于对一组操作进行定义和分组。 操作(或操作方法)是控制器上一种用来处理请求的方法。 控制器按逻辑将类似的操作集合到一起。 通过这种操作的聚合,可以共同应用路由、缓存和授权等通用规则集。 请求通过路由映射到操作。 控制器按请求激活和释放。
根据惯例,控制器类:
- 驻留在项目的根级别“Controllers”文件夹中。
- 继承自
Microsoft.AspNetCore.Mvc.Controller
。
控制器是一个可实例化的类,通常为 public,其中下列条件至少某一个为 true:
- 类名称带有
Controller
后缀。 - 该类继承自带有
Controller
后缀的类。 [Controller]
特性应用于该类。
控制器类不可含有关联的 [NonController]
属性。
控制器应遵循 Explicit Dependencies Principle(显式依赖关系原则)。 以下几种方法可以实现此原则。 如果多个控制器操作需要相同的服务,请考虑使用构造函数注入来请求这些依赖关系。 如果该服务仅需要一个操作方法,请考虑使用操作注入来请求依赖关系。
在“模型-视图-控制器”模式中,控制器负责请求的初始处理和模型的实例化操作。 通常情况下,应在模型中执行业务决策。
控制器获取模型处理的结果(如果有),并返回正确的视图及其关联的视图数据或 API 调用的结果。 请参阅 ASP.NET Core MVC 概述以及 ASP.NET Core MVC 和 Visual Studio 入门了解详细信息。
控制器是一个 UI 级别的抽象。 它的职责是确保请求的数据有效,并选择应当返回的视图(或 API 的结果)。 在构造良好的应用程序中,它不会直接包括数据访问或业务逻辑。 相反,控制器会委托给处理这些责任的服务。
定义操作
控制器上的公共方法(除了那些带有 [NonAction]
属性的方法)均为操作。 操作上的参数会绑定到请求数据,并使用模型绑定进行验证。 所有模型绑定的内容都会执行模型验证。 ModelState.IsValid
属性值指示模型绑定和验证是否成功。
操作方法应包含用于将请求映射到某个业务关注点的逻辑。 业务关注点通常应当表示为控制器通过依赖关系注入来访问的服务。 然后,操作将业务操作的结果映射到应用程序状态。
操作可以返回任何内容,但是经常返回生成响应的 IActionResult
(或异步方法的 Task<IActionResult>
)的实例。 操作方法负责选择响应的类型。 操作结果会做出响应。
控制器帮助程序方法
控制器通常继承自 Controller(虽然这不是必须的)。 派生自 Controller
会提供对三个帮助程序方法类别的访问:
1. 导致空响应正文的方法
没有包含 Content-Type
HTTP 响应标头,因为响应正文缺少要描述的内容。
该类别中有两种结果类型:重定向和 HTTP 状态代码。
HTTP 状态代码
此类型返回 HTTP 状态代码。 此类型的几种帮助程序方法是
BadRequest
、NotFound
和Ok
。 例如,return BadRequest();
执行时生成 400 状态代码。 重载BadRequest
NotFound
和Ok
等方法时,它们不再符合 HTTP 状态代码响应方的资格,因为正在进行内容协商。重定向
此类型(使用
Redirect
LocalRedirect
RedirectToAction
或RedirectToRoute
)返回一个到操作或目标的重定向。 例如,return RedirectToAction("Complete", new {id = 123});
重定向到Complete
,传递一个匿名对象。重定向结果类型与 HTTP 状态代码类型的不同之处主要在于
Location
HTTP 响应标头的添加。
2. 导致含有预定义内容类型的非空响应正文的方法
此类别中的大多数帮助程序方法都包含一个 ContentType
属性,通过它可以设置 Content-Type
响应标头来描述响应正文。
视图
此类型返回一个使用模型呈现 HTML 的视图。 例如,
return View(customer);
将模型传递给视图以进行数据绑定。已格式化的响应
此类型返回 JS ON 或类似的数据交换格式,从而以特定方式表示某个对象。 例如,
return Json(customer);
将提供的对象串行化为 JSON 格式。此类型的其他常见方法包括
File
和PhysicalFile
。 例如,return PhysicalFile(customerFilePath, "text/xml");
返回 PhysicalFileResult。
3. 导致在与客户端协商的内容类型中格式化为非空响应正文的方法
此类别更为熟知的说法是“内容协商”。 每当操作返回 ObjectResult 类型或除 IActionResult 实现以外的其他内容,内容协商就会适用。 返回非 IActionResult
实现(例如 object
)的操作也会返回已格式化的响应。
此类型的一些帮助程序方法包括 BadRequest
、CreatedAtRoute
和 Ok
。 这些方法的示例分别为 return BadRequest(modelState);
、return CreatedAtRoute("routename", values, newobject);
和 return Ok(value);
。 请注意,BadRequest
和 Ok
仅在传递了值的时候才执行内容协商;在没有传递值的情况下,它们充当 HTTP 状态码结果类型。 另一方面,CreatedAtRoute
方法始终执行内容协商,因为它的重载均要求传递一个值。
横切关注点
应用程序通常会共享其部分工作流程。 示例包括需要身份验证才能访问购物车的应用,或者在某些页面上缓存数据的应用。 要在某个操作方法之前或之后执行逻辑,请使用筛选器。 对横切关注点使用筛选器可以减少重复。
可在控制器或操作级别上应用大多数筛选器属性(例如 [Authorize]
),具体取决于所需的粒度级别。
错误处理和响应缓存通常是横切关注点:
使用筛选器或自定义中间件可处理许多横切关注点。