浅谈 asp.net core web api

本篇已收录至 asp.net core 随笔系列

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc?view=aspnetcore-3.1

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

  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的返回值类型

包括三种:

  • Specific type
  • IActionResult
  • ActionResult<T>
posted @ 2020-04-03 14:00  YanyuWu  阅读(514)  评论(0编辑  收藏  举报