【ASP.NET Core】内容协商、自定义格式化响应
内容协商
客户端再请求头Accept
字段中指定什么样的MIME类型
,WebApi服务端就返回对应的MIME类型
(响应头的中Content-Type
就是Accept
中指定的MIME类型
)。
而现实状况是,Web API服务端能返回什么MIME类型的响应类型取决于有没有对应这个MIME类型的MediaTypeFormatter
。
ASP.NET Core Web API的默认提供JsonMediaTypeFormatter
,若是要支持 XmlMediaTypeFormatter
须要进行配置。
代码如下:
services.AddControllers(setupAction =>
{
setupAction.ReturnHttpNotAcceptable = true;
}).AddXmlDataContractSerializerFormatters();
发送http请求时添加请求头Accept : text/xml
,可以看到返回xml格式内容
自定义格式化程序
因为MVC的内置所以默认支持了json,xml和文本格式。如果我们想使用其他格式可以自定义。
创建自定义格式化程序步骤
- 从相应的基类中派生类。
- 在构造函数中指定有效的媒体类型和编码。
- 重写 CanReadType/CanWriteType、ReadRequestBodyAsync/WriteResponseBodyAsync 方法
- 注册格式化程序
从相应的基类中派生
从那些类中派生官方给的解释是;
对于文本媒体类型(例如,vCard),从 TextInputFormatter
或 TextOutputFormatter
基类派生。
对于二进制类型,从 InputFormatter
或 OutputFormatter
基类派生。
public class VcardOutputFormatter : TextOutputFormatter
{
public VcardOutputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/vcard"));
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
protected override bool CanWriteType(Type type)
{
if (typeof(Person).IsAssignableFrom(type)
|| typeof(IEnumerable<Person>).IsAssignableFrom(type))
{
return base.CanWriteType(type);
}
return false;
}
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
IServiceProvider serviceProvider = context.HttpContext.RequestServices;
var logger = serviceProvider.GetService(typeof(ILogger<VcardOutputFormatter>)) as ILogger;
var response = context.HttpContext.Response;
var buffer = new StringBuilder();
if (context.Object is IEnumerable<Person>)
{
foreach (Person person in context.Object as IEnumerable<Person>)
{
FormatVcard(buffer, person, logger);
}
}
else
{
var person = context.Object as Person;
FormatVcard(buffer, person, logger);
}
return response.WriteAsync(buffer.ToString());
}
private static void FormatVcard(StringBuilder buffer, Person person, ILogger logger)
{
buffer.AppendLine("BEGIN:VCARD");
buffer.AppendLine("VERSION:2.1");
buffer.AppendFormat($"N:{person.ID}");
buffer.AppendLine("END:VCARD");
logger.LogInformation($"Writing {person.ID}");
}
}
注册格式化程序
builder.Services.AddControllersWithViews(options =>
{
options.ReturnHttpNotAcceptable = true;
//options.InputFormatters.Insert(0, new VcardInputFormatter());
options.OutputFormatters.Insert(0, new VcardOutputFormatter());
});
参考:
https://learn.microsoft.com/zh-cn/aspnet/core/web-api/advanced/custom-formatters?view=aspnetcore-6.0