前言
什么是内容协商呢?是这样的,我们在请求的时候都有两个属性,一个是Content-Type,另一个是accept,这两个什么意思呢?
content-type 这个是表示自己传输的是什么内容,就像我们自动绑定参数的时候,我们既要知道从哪里获取,也要知道如何解析啊,不然该按哪种方式提取呢。
accept 这个是就像这个英文但是意思一样,接受,表示接受什么样的类型的返回类型。其实我们返回的全部是字节,到了我们前端转换为字符流,那么根据这个accept 再来解析。
看一下content-type 的参数:
Content-Type:type/subtype ;parameter
type:主类型,任意的字符串,如text,如果是号代表所有;
subtype:子类型,任意的字符串,如html,如果是号代表所有,用“/”与主类型隔开;
parameter:可选参数,如charset,boundary等。
这里举一个content-type 的例子哈:
Content-Type application/x-www-form-urlencoded; charset=UTF-8
这个是什么意思呢?比如说,有几个参数key=1 name=x,那么它将会这样传输key=1&name=x,然后放在body中,但是放之前会将一些特殊字符转码,比如说空格转换为%20。
再举一个例子吧:
Content-Type multipart/form-data;
这个相比大家非常的熟悉了,就是大名鼎鼎的form-data,这个和json还有xml不同,这个可以传递文件,所以主类型叫做多媒体类型multipart。
首先生成了一个 boundary 用于分割不同的字段,在请求实体里每个参数以------boundary开始,然后是附加信息和参数名,然后是空行,最后是参数内容。多个参数将会有多个boundary块。如果参数是文件会有特别的文件域。最后以------boundary–为结束标识。
为了更加形象的展示出,决定去网上弄一张图片。
大概是这样了。其他的就不介绍了,accept和这个差不多。下面就进入正文,我们写代码如何和后台协商呢?至于具体的解析,我们就不要去写了,毕竟够用,没必要自己去定义类型吧。
正文
首先我们要有一个步骤,或者说错误性验证。
就是如假设Content-Type 客户端填写的内容,不被我们服务器接受,那么我们作为服务器,我们要怎么做?
我们这个时候应该返回415错误,也就是Unsupported Media Type就是服务器不支持该媒体类型。
如果accept 无法满足客户端的请求,那么就应该返回406,服务器无法满足客户端,也急速no acceptable,不支持吧。
举个例子,我要请求某个公司的资料,然后返回application/json:
这时候其乐融融,满足了,那么我现在要返回xml。这时候出现问题了,明明我要的是xml,你给我json,我以为自己得到的是xml,结果解析失败。
这个时候就是服务器问题了,因为服务器没有提示406,不能满足对方。
在ConfigureServices 中配置一下,如下:
services.AddControllers(setup =>
{
setup.ReturnHttpNotAcceptable = true;
});
再请求一次406了,如下:
如果针对xml格式的话,我们如何返回json 又能返回xml,是写两个方法吗?不是的,我们可以做一些配置,让.net core框架自动来转换,果然框架才是第一生产力。
只要加刚才的基础上加上:setup.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());。
那么如果你想默认的返回格式是xml,那么你应该xml放在第一位:setup.OutputFormatters.Add(0,new XmlDataContractSerializerOutputFormatter())
这里简单介绍一下,.net core的OutputFormatters 表示的是输出格式化,那么还有输入格式化。InputFormatters 就是对media type的控制了。
那么看一下效果吧:
有些人可能这样没有效果,那么你返回可能是这样写的:return new JsonResult(company);,这个时候已经写死了格式,返回的还是json,并且服务器支持了xml所以也不会406,所以还是建议这样写ok(company)。
那么到这里就介绍这一小结,这里就有人问了,为啥不介绍Content-Type呢?因为系统默认支持全部,当然你可以通过InputFormatters 删除一些。。。比如setup.InputFormatters.Remove..
记得我前面提及过,apicontroller可以自动帮我们处理40x错误,比如415,默认解析是form-data,如果你没有传任何form-data,那么就是为空,空的是不可能是formdata类型,那么服务器解析不了那么就是415,这个新手还是遇到概率还是很高的。如果你写的int id,传过来的是一个string,那么会返回400,One or more validation errors occurred。