我想为不同的路由或控制器使用不同的JSON输出格式化程序。默认和自定义json输出格式化程序
启动.cs
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
options.OutputFormatters.Add(new CustomJsonMediaFormatter());
});
CustomJsonMediaFormatter
public class CustomJsonMediaFormatter : TextOutputFormatter
{
public JsonMediaFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/vnd.XYZ+json"));
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
protected override bool CanWriteType(Type type)
{
return true;
}
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
// my code
}
}
控制器A
[ApiController]
[Produces("application/vnd.XYZ+json")]
public class AController : BaseController
{
[HttpGet]
public async Task<IActionResult> Get()
{
// return an object
}
}
控制器B
[ApiController]
[Produces("application/json")]
public class BController : BaseController
{
[HttpGet]
public async Task<IActionResult> Get()
{
// return an object
}
}
当我用Postman向a Cotroller发出请求时,它没有使用我的自定义输出格式化程序。它仍然使用默认的JSON输出格式化程序。
它似乎采用了列表中的第一个JSON输出格式化程序。我试图清除输出格式化程序列表并添加我的自定义json格式化程序。然后它总是使用自定义格式化程序。
我想对自定义输出格式化程序做的是:我想从对象中删除一些不允许用户查看的字段,具体取决于配置。但仅适用于某些API控制器,而不是所有控制器。
如果你查看他们的文档,你会发现他们在列表的开头插入了客户格式化程序。https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/custom-formatters?view=aspnetcore-5.0#如何配置emvc-to-use-a自定义格式化程序
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.InputFormatters.Insert(0, new VcardInputFormatter());
options.OutputFormatters.Insert(0, new VcardOutputFormatter());
});
}
这让我相信格式化程序的执行顺序确实很重要,并且很可能在检查您的自定义内容接受类型之前执行默认的json。
尝试将DI更新为:
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
options.OutputFormatters.Insert(0, new CustomJsonMediaFormatter());
});
我得到了解决方案。重写函数CanWriteResult。从上下文中我们得到内容类型
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
{
return context.ContentType == "application/vnd.XYZ+json";
}
再加上@JohnD关于格式化程序顺序的回答,它的工作非常完美!
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
options.OutputFormatters.Insert(0, new CustomJsonMediaFormatter());
});