希望通过本文能够了解如下内容:

  1. ControllerBase
  2. Attributes
  3. Action的返回值类型

ControllerBase

当我们开始实际上项目, 真正实操 anc 时, 肯定会用到 web api 框架和 mvc 框架. 这两个框架自动创建的 controller 继承了不同的父类, web api 创建的 controller 自动继承 controllerBase, mvc 创建的 controller 自动继承 controller, 两个区别是是否支持 views.

官网说了, 如果你的项目准备使用 web api的话, 不要创建一个继承自 controller 的 controller, 因为 controller 是带有一些 view 支持的. 并且 controller 本身也是继承自 controllerbase, 既然你是 web api 的controller, 去 handle web api request, 那么自然是不需要支持 views的, 所以直接使用 controllerbase. 但是有一种情况是例外的, 当你的controller同时想支持 web api 和 views 的时候, 那就继承 controller.

在抽象类 ControllerBase 中, 可以看到绝大多数定义的方法都是 xxxResult 方法. 我们细数一下ControllerBase为我们提供的Result都有哪些:

Result name

des

Accepted Result

创建一个status code 为202 accepted 的result作为response返回.

AcceptedAtAction Result

创建一个status code 为202 accepted 的result作为response返回.

AcceptedAtRoute Result

创建一个status code 为202 accepted 的result作为response返回.

BadRequestObject Result

Status400BadRequest

Challenge Result

返回身份认证失败的401 unauthorized 和 权限校验失败的 403 forbidden result

ConflictObject Result

Status409Conflict

Conflict Result

Status409Conflict

Content Result

返回指定的content string作为result

Created Result

Status201Created

CreatedAtAction Result

Status201Created

CreatedAtRoute Result

Status201Created

VirtualFile Result

Returns the file specified by virtualPath (Microsoft.AspNetCore.Http.StatusCodes.Status200OK)

FileStream Result

Returns a file in the specified fileStream (Microsoft.AspNetCore.Http.StatusCodes.Status200OK)

FileContent Result

Returns a file with the specified fileContents as content (Microsoft.AspNetCore.Http.StatusCodes.Status200OK)

ForbidResult

权限校验失败的 403 forbidden result

LocalRedirect Result

Creates a Microsoft.AspNetCore.Mvc.LocalRedirectResult object that redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to the specified local localUrl.

NoContent Result

Status204NoContent

NotFoundObject Result

Status404NotFound

Ok Result

Status200OK

PhysicalFile Result

Returns the file specified by physicalPath (Microsoft.AspNetCore.Http.StatusCodes.Status200OK)

Object Result

比较灵活, 需要后端api 开发人员手动指定 status code和问题展示细节等.

Redirect Result

Creates a Microsoft.AspNetCore.Mvc.RedirectResult object that redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to the specified url.

RedirectToAction Result

Redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to an action with the same name as current one. The 'controller' and 'action' names are retrieved from the ambient values of the current request.

RedirectToPage Result

Redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to the specified pageName.

RedirectToRouteResult

Redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to the specified route using the specified routeName, routeValues, and fragment.

SignIn Result

使用指定的身份认证信息创建的登录result

SignOut Result

使用指定的身份认证信息登出系统的result

Object Result

返回指定的code和value作为result

StatusCode Result

返回指定的code作为result

UnauthorizedObject Result

Status401Unauthorized

Unauthorized Result

Status401Unauthorized

UnprocessableEntityObject Result

Status422UnprocessableEntity

基本上很全了. 当我们实际使用时具体需要返回啥样的result, 可以随时去找一个对应合适的result放到response中返回去.

Attributes

除此外, 框架提供了很多 Attribute 用于定义 web api 中 controller 和 action 的行为.

[ApiController]

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

自动生成的 controller 文件头上面还有个标签叫做 [ApiControllerAttribute], 它是用于启动一些专门为了 api 设定的配置.

ApiController 可以定义的位置

  • 如果你的项目中有很多自定义的controller, 但是又不想一个一个都给打上标签, 可以声明一个父类controller, 在这个父类的controller上面打上[ApiController]标签, 并且在父类中定义一些common的method, 自定义的controller可以继承自该父类controller.
  • 除了在controller的上面定义, 还可以在 startup 中定义. 这样做有个问题就是所有的controller都相当于定义了该标签, 无法例外:
[assembly: ApiController]
namespace WebApiSample
{
    public class Startup
    {
        ...
    }
}

相当于路由的方式必须是标签路由方式

当 controller 上头被定义了该标签后, 表示路由的方式必须是通过标签定义

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

此时通过URL那种转义方式的路由就无法work了. 即我们在 startup.cs文件的configure方法里面通过 seEndpoints, UseMvc, or UseMvcWithDefaultRoute 这些方法定义的默认URL的转义会失效.

自动触发 http 400 code 的response

当 model validation 失败后, 会自动触发 http 400 code 的response, 所以下面的代码在一个 API 的 action 中是多余的:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

如何禁用这一默认行为? 可以在 startup.cs中按照如下进行配置:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
            options.SuppressConsumesConstraintForFormFileParameters = true;
            options.SuppressInferBindingSourcesForParameters = true;
            options.SuppressModelStateInvalidFilter = true;
            options.SuppressMapClientErrors = true;
            options.ClientErrorMapping[404].Link =
                "https://httpstatuses.com/404";
    });

使用[FromBody]参数标签对参数的数据源进行绑定 - model binding

可以在 action 的参数中使用一些参数标签来确定参数的来源.这种操作被称为 model binding, 可以作为 model binding 的参数标签如下:

Attribute

Binding source

[FromBody]

从http Request body中获取参数值. 不要在一个action中使用多余一个FromBody标签, 不支持这种操作.

[FromForm]

从httprequest body的form字段中获取参数值.

[FromHeader]

从 http headers 中获取参数值.

[FromQuery]

从query string中获取参数参数值. 但是支持持简单类型的数据获取

[FromRoute]

从当前request的RouteData中获取参数数据参数值. 只支持简单类型的参数(注意当你的values中有可能包含 %2f 时, 不要使用这个标签, 而是使用 [FromQuery], 因为在 [FromRoute] 中 %2f 不会按照理想的方式转义为 /. )

[FromServices]

这种情况是在你的action中使用了其他类的一个实例, 一般来说都是通过依赖注入的方式获取类的实例, 构造函数中注入的话, 可能没有必要. 因为只有这一个方法使用. 所以在参数中添加[FromServices]来获取.

Action的返回值类型