使用ASP.NET Core 3.x 构建 RESTful API P7 P8 内容协商
内容协商 (Content Negotiation)
人们经常将 RESTful API
与 Json
联系在一起,是因为 Json
是 RESTful API
表述,结果的一种方式,但是 RESTful API
表述结果,不仅仅会使用 Json
,也有可能会使用 XML
,以及一些其它自定义的数据格式,那么到底需要 RESTful API
返回什么样的数据格式类型呢?那么这就叫做 内容协商
,即 API
消费者需要明确的告知, API
它需要什么样的返回结果的数据格式,以便返回的结果,能够得到顺利的解析.
- 内容协商:针对一个响应,当有多种表示格式可用的时候,选取最佳的一个表述.
Accept Header
在请求报文中 Accept Hander 是用来告诉Api,消费者需要API来返回什么样格式的数据.
- Media Type (媒体类型)
- application/json
- application/xml
- ...
- 如果消费者没有告诉
API
它需要的数据格式,那么API
会以API
自己默认的数据格式返回数据. - 如果
消费者
明确告知了API
自己需要的数据格式,但是API
不支持这种数据格式,那么API
就应该返回406
的HTTP Status Code
,即Not Acceptable
- 输出格式
- 在 ASP .NET Core 里面对应的就是 Output Formatters
Content-Type Hander
在请求报文中 Content-Type 是用来告诉 API
,消费者传递过来的数据的格式是什么样的,以便 API
可以方便的解析消费者的请求参数.
-
Media Type(媒体类型)
- application/json
- application/xml
- ...
-
输出格式
-
ASP .NET Core 里面对应的就是Input formatters.
Accept Hander 与 Content-Type Hander 的应用
在默认情况下 ASP .Net Core 使用 JSON 作为数据输入和输出的格式化器.
下面开始写代码对上理论进行验证
如当消费者要求的返回格式,API
不支持,那么 API
应该返回相应的 HTTP 状态码.
为此在 ASP .Net Core 中,我们需要在 Startup.cs 文件的 ConfigureServices 方法中编写以下代码:
services.AddControllers(setup =>
{
//例子:当消费者要求返回的数据格式是json时,如果服务器端默认的就是xml格式,而且仅仅只支持xml格式,
//那么默认的就会将xml格式返回回去,并且不会返回406状态码,所以ReturnHttpNotAcceptable的默认值就是false
//setup.ReturnHttpNotAcceptable = false;
//当为true时,表示当消费者要求的返回的数据类型,与数据库支持的返回的数据类型不一致时,
//就会返回 HTTP 状态码 406 ,也就是NotAcceptable
setup.ReturnHttpNotAcceptable = true;
});
当我们将 ReturnHttpNotAcceptable 的值设置为true时,表示当消费者要求返回的数据格式,不被服务器所支持,那么服务器就会返回406,如图:
那么我们让我们的 API
既支持json格式的返回,也支持xml格式的返回呢?
我们可以将代码这么写,如下:
services.AddControllers(setup =>
{
//例子:当消费者要求返回的数据格式是json时,如果服务器端默认的就是xml格式,而且仅仅只支持xml格式,
//那么默认的就会将xml格式返回回去,并且不会返回406状态码,所以ReturnHttpNotAcceptable的默认值就是false
//setup.ReturnHttpNotAcceptable = false;
//当为true时,表示当消费者要求的返回的数据类型,与数据库支持的返回的数据类型不一致时,
//就会返回 HTTP 状态码 406 ,也就是NotAcceptable
setup.ReturnHttpNotAcceptable = true;
//OutputFormatters是一个集合,这个集合里面可以放置多个格式化器,用来支持多种消费者要求的返回格式,
//这OutputFormatters中的第一个元素设置,就是这个集合默认的返回格式的格式化器,默认情况下OutputFormatters
//中只有一个json格式化器.
//下面我们添加对xml格式化器的支持
//setup.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
//如果我们想添加xml格式化器,并使其成为默认的数据格式化器,那么我们使用如下写法即可:
//那么当消费者没有要求返回格式时,API会默认返回xml格式的数据.
setup.OutputFormatters.Insert(0, new XmlDataContractSerializerOutputFormatter());
});
请求返回的数据如下:
请求返回的数据格式如下:
此时我们要求 API
返回Json格式的数据也是可以的,因为 API
也支持了返回Json的设置,如下:
此处我们需要注意:千万不能在Action中使用return new JsonResult(对象);
的形式来返回数据,否则就不能根据消费者要求的数据格式来返回数据了.
那么我们如何支持输入参数的数据格式的支持呢?
使用方式和 OutputFormatters
是一样的存在一个叫InputFormatters
,它的使用方式和OutputFormatters
, 是一样的,代码如下:
//添加对请求参数格式是xml的支持
setup.InputFormatters.Insert(0,new XmlDataContractSerializerInputFormatter(setup));
但是上述写法都只是 ASP .Net Core 3.x 之前的写法,在3.x 之后的写法是这样的,代码如下:
services.AddControllers(setup =>
{
setup.ReturnHttpNotAcceptable = true;
}).AddXmlDataContractSerializerFormatters();
我们可以接在 AddControllers() 方法之后,接着写 .AddXmlDataContractSerializerFormatters()
方法即可,它既表明支持消费者传入的参数是xml格式,也支持消费者要求的返回数据格式是xml.