WebAPI学习笔记 -- 状态、协商

发布时间 2023-10-02 00:09:16作者: 老菜农

一、API消费者需要使用的概念

  • 资源的标识

  • HTTP方法

  • Payload有效载荷

1、资源标识

(1)使用名词而不是动词

  • 获取所有用户 GET api/user 而不是 /getUser

(2)要体现资源和结构/关系

  • 通过ID获取某个用户api/products/{usersId}

  • 可以让API具有很好的可预测性和一致性

例子
  • 系统有两种资源, 公司和员工, 想在想获取某公司下所有员工信息

"GET api/companies/{companyId}/employees"
  • 获取某个公司的某个员工信息

"GET api/companies/{companyId}/employees/{employeeId}"

(3)自定义查询

  • 获取所有的用户信息, 并要求结果是按年龄从小到大进行排序

"GET api/users?orderby=name"

二、[ApiController]

  • 这个属性是应用于Controller, 不是强制

  • 会启用如下行为

    • 要求使用属性路由(Attribute Routing)

    • 自动HTTP 400响应

    • 推断参数的绑定源

    • Multipart / form-data 请求推断

    • 错误状态代码问题的详细信息

三、状态码

会告知HTTPApi消费者

  • 请求是否执行成功了

  • 如果请求失败了, 那么谁为他负责

1、1xx信息性状态码

  • 属于信息性状态码, WebAPI并不使用

2、2xx成功状态码

  • 意味着状态执行的很成功

状态码 描述
200 - Ok 请求成功
201 - Created 请求成功并创建资源
204 - No Content 请求成功, 但是不应该返回任何东西, 比如删除

3、3xx跳转状态码

  • 用于跳转重定向, 绝大多数的WebAPI都不用

4、4xx状态码

  • 客户端错误

状态码 描述
400 - Bad Request 表示API消费者发送到服务器的请求是有错误的
401 - Unauthorized 表示没有提供授权信息或者提供的授权信息不正确
403 - Forbidden 表示身份认证已经成功, 但是已认证的用户却无法访问请求的资源
404 - Not Found 请求的资源不存在
405 - Method not allowed 当尝试发送请求到资源的时候, 使用了不被支持的HTTP方法
406 - Not Acceptable 表示API消费者请求的表述格式并不被WebAPI支持, 并且API不会提供默认的表述格式
409 - Conflict 表示请求与服务器当前状态冲突 通常指更新资源时发生的冲突
415 - Unsupported media type 406相反, 有一些请求必须带着数据发往服务器, 这些数据都属于特定的媒体类型, 如果API不支持该媒体格式, 就返回415
422 - Unprocessable entity 是HTTP扩展协议的一部分, 通常用来表示语义上有错误, 通常表示实体验证的错误

(1)409 - 并发冲突

  • 表示请求与服务器当前状态冲突

  • 通常指更新资源时发生的冲突

  • 通常用来处理并发问题的状态码

  • 比如, 编辑某个资源的时候, 该资源在服务器上又进行了更新, 所以编辑的资源版本和服务器的不一样, 或者表示你想创建的资源在服务器上已经存在了

(2)422 - 不合适的实体

  • 是HTTP扩展协议的一部分, 通常用来表示语义上有错误, 通常表示实体验证的错误

  • 说明服务器已经懂得了实体的Content Type - 415状态码肯定不合适

  • 而且实体的语法也没有问题 - 400也不合适

  • 但是服务器仍然无法处理这个实体

5、5xx服务器错误

  • 500, 表示服务器出现了错误, 客户端无能为力

四、错误和故障

1、错误

  • 错误通常是由API的消费者引起的, API消费者请求时传递的数据是不合理, 这时API就会正常的将其拒绝

  • HTTP 4xx错误

  • 并不会影响API的可用性

2、故障

  • 针对一个合理的请求, API无法返回它的响应, 是由API引起的错误

  • HTTP 5xx错误

  • 会对API整体可用性造成影响

五、内容协商

  • 内容协商是一个过程

    • 针对一个响应, 当有多种表述格式可用的时候, 选取最佳的一个表述

  • WebAPI如果面对多个消费者的时候, 不一定只用JSON字符串, 需要进行内容协商

1、HTTPHeader

(1)Accept Header发送请求时设置 - 表示响应时输出格式

  • 设置Accept Header为如下媒体类型

    • 媒体类型Media Type

      • application / json

      • application / xml

      • 可自定义其他

    • 如果没有设置, 则使用默认格式, 就是以上两种, 客户端默认的

    • 如果设置了, 但是不是WebAPI接受的, 就返回406错误

  • .NET Core对应的就是Output Formatters

Startup.cs
public class StartUp
{
    //...
    public void ConfigreServices(IServiceCollection services)
    {
        service.AddController(setup => 
        {
            //设置406 - API无法接受返回的格式 
            setup.ReturnHttpNotAcceptable = true;
            //设置输出格式接受集合, 原来JSON, 再加上XML
            setup.OutputFormatters.Add(new XmlDatContractSerializerOutputFormatter());
            //设置默认接受格式为XML
            setup.OutputFormatters.Insert(0, new XmlDatContractSerializerOutputFormatter());
        });
    }
}

(2)Content-Type Header发送请求时设置 - 表示请求时输入格式

  • 设置Content-Type Header为如下媒体类型, 可以更好的处理请求

    • 媒体类型Media Type

      • application / json

      • application / xml

      • 可自定义其他

  • .NET Core对应的就是Output Formatters

Startup.cs
public class StartUp
{
    //...
    public void ConfigreServices(IServiceCollection services)
    {
        service.AddController(setup => 
        {
            //设置输入格式接受集合, 原来JSON, 再加上XML
            setup.InputFormatters.Add(new XmlDatContractSerializerOutputFormatter());
            //设置默认格式为XML
            setup.InputFormatters.Insert(0, new XmlDatContractSerializerOutputFormatter());
        });
    }
}

新版支持输入输出一起加

public class StartUp
{
    //...
    public void ConfigreServices(IServiceCollection services)
    {
        service.AddController(setup => 
        {
            //...
            //设置406 - API无法接受返回的格式 
            setup.ReturnHttpNotAcceptable = true;
        }).AddXmlDataContractSerializerFormatters();
    }
}