什么是内容谈判?
内容协商是当服务器允许多种资源表示时,客户端可以从服务器中选择所需的资源表示的过程。换句话说,内容协商是当服务器被允许以多种表示格式交换数据时,客户端和服务器同意以一种表示格式交换数据的过程。就像 JSON、XML、HTML 和纯文本一样。
内容协商如何进行?
客户端向服务器发送 HTTP 请求,服务器返回“accept”标头。该标头指示客户端正在寻找的媒体类型或内容类型。服务器读取信息;如果服务器支持首选格式,则它会生成首选格式并将响应发送回客户端。
如果服务器不支持该格式,则它将以服务器支持的默认格式返回响应,错误代码为406:不可接受。
如果客户端没有在“ accept ”标头中指定任何格式,则服务器将以默认格式(即 JSON 格式)发回响应。
让我们去实现内容协商。
先决条件:
1、Visual Studio 2022(社区)。
2、.NET 6 SDK
让我们进入 Visual Studio,通过选择模板创建一个 ASP.NET Core Web API 项目。
一旦创建了项目文件,就创建一个具有操作方法和模拟数据的控制器。
[HttpGet("GetNegotiationFile")]
public IActionResult GetNegotiationFile()
{
List<string> add = new List<string>();
add.Add("susanta0");
add.Add("susanta1");
add.Add("susanta2");
add.Add("susanta3");
return Ok(add);
}
让我们继续使用 Postman 来使用它。
使用 Postman 消费
这是在“ Accept ”标头中指定“ application/json ”时的响应。
让我们将同一个 URL 的“Accept”标头更改为“ application/xml ”。
更改接受标头应用程序/xml 响应中没有变化
然而,我们可以看到,响应没有变化。
为什么?因为如前所述,默认情况下 .NET 返回 JSON 格式的数据。如果我们想获取其他格式的数据,则必须对其进行配置。让我们继续进行program.cs并对其进行配置。
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
}).AddXmlSerializerFormatters();
在这个配置中,首先我们需要告诉服务器尊重“accept”标头,并且我们添加了AddXmlSerializerFormatters()来支持响应中的XML格式。
在发出相同请求之前,我们先去 Postman 再测试一下
接受标头 application/xml 的响应
现在我们可以看到我们以 XML 形式收到了响应,并且经过配置后,它遵循了客户端请求的格式。
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
options.ReturnHttpNotAcceptable = true;
}).AddXmlSerializerFormatters();
现在我们必须设置另一个配置选项。ReturnHttpNotAcceptable = true;使用此配置,如果服务器不支持请求的格式类型,我们将不会获得默认配置。
让我们去 Postman 并请求类型“ text/plain ”,如果我们的应用程序不支持它,那么它将给出错误代码406:不可接受。
我们可以在 Postman 中看到响应。
响应代码 406
默认情况下,“ text/plain ”不起作用;现在我们将研究“ text/plain ”类型,使应用程序以纯文本形式返回响应。
在配置之上,我们需要在builder.Services.AddControllers中再添加一行配置。
选项.FormatterMappings.SetMediaTypeMappingForFormat(“txt”,“text/plain”);
builder.Services.AddControllers(options =>
{
options.Filters.Add(new HttpExceptionFilter());
options.RespectBrowserAcceptHeader = true;
options.ReturnHttpNotAcceptable = true;
options.FormatterMappings.SetMediaTypeMappingForFormat("txt", "text/plain");
}).AddXmlSerializerFormatters();
使用新的端点来消费它
[HttpGet("GetNegotiationFile")]
public IActionResult GetNegotiationFile()
{
return Ok("OK");
}
让我们使用邮递员来使用端点。
我们可以看到 Accept 标头的响应:text/plain
现在您可以看到配置完成后,它返回 200 OK。但我们需要记住,我们必须仅返回字符串数据作为响应。
我们讨论的所有这些格式都是 asp.net core 框架内置支持的。只需启用配置即可。
如果客户端需要以服务器默认不支持的自定义格式进行响应,该怎么办?为了使自定义格式正常工作,我们需要设置自定义输出格式。
在 asp.net core API 中实现自定义格式。
让我们继续创建一个名为“ format ”的文件夹,并添加一个名为CsvOutputFormatter的空类。
我们将在这里实现以 csv 形式返回响应的功能。
public class CsvOutputFormatter : TextOutputFormatter
{
public CsvOutputFormatter()
{
SupportedMediaTypes.Add("text/csv");
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
var response = context.HttpContext.Response;
var buffer = new StringBuilder();
var data = context.Object as IEnumerable;
if (data != null)
{
// Write CSV rows
foreach (var record in data)
{
buffer.Append(string.Join(",", record));
}
}
await response.WriteAsync(buffer.ToString());
}
}
这里我们有一个TextOutputFormatter是一个抽象类,它有一个方法WriteResponseBodyAsync,负责以 csv 格式写入响应。
现在我们需要在program.cs类中的 Inbuild 输出格式化程序列表中配置此输出格式化程序类以使其工作。然后让我们继续添加它。
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
options.ReturnHttpNotAcceptable = true;
options.FormatterMappings.SetMediaTypeMappingForFormat("txt", "text/plain");
options.OutputFormatters.Add(new CsvOutputFormatter());
}).AddXmlSerializerFormatters();
让我们在控制器中添加并编写代码。
[HttpGet("GetNegotiationFile")]
public IActionResult GetNegotiationFile()
{
List<string> add = new List<string>();
add.Add("susanta0");
add.Add("susanta1");
add.Add("susanta2");
add.Add("susanta3");
return Ok(add);
}
我们去找邮递员核实一下吧。
对文本/csv 文件的响应
现在我们的应用程序发送 200 OK 作为响应。
现在我们进行示范。
结论:在本教程中,我们了解到可以根据客户需求限制或添加选项。如果客户端不支持该格式,我们可以实现自定义格式化程序。
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。