【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

posted @ 2022-02-27 15:16  .Neterr  阅读(135)  评论(0编辑  收藏  举报