从.NET Framework WebApi迁移到.NET Core:如何按查询参数选择OutputFormatter?
.NET Core WebApi 根据查询参数选择 OutputFormatter 实现方案
在.NET Core WebApi中,原.NET Framework依赖的IContentNegotiator已被全新的内容协商机制替代,以下是适配迁移需求的具体实现方案:
1. 适配自定义 OutputFormatter
先将原ConvertResultRawFormatter改造为.NET Core标准的OutputFormatter(对应Framework中的MediaTypeFormatter):
public class ConvertResultRawFormatter : OutputFormatter { public ConvertResultRawFormatter() { // 声明格式化器支持的媒体类型 SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain")); } protected override bool CanWriteType(Type type) { // 定义该格式化器可处理的数据类型,按需调整逻辑 return true; } public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context) { var response = context.HttpContext.Response; // 替换为你的原始格式序列化逻辑 var rawContent = context.Object?.ToString() ?? string.Empty; await response.WriteAsync(rawContent); } }
2. 实现查询参数驱动的内容协商
方式一:自定义内容协商策略
创建自定义策略类,读取查询参数并匹配对应的格式化器:
public class QueryParamContentNegotiationPolicy : IContentNegotiationPolicy { public ContentNegotiationResult Negotiate(Type type, HttpRequest request, IList<IOutputFormatter> formatters) { // 获取查询参数(示例使用"format"作为参数名) var format = request.Query["format"].FirstOrDefault()?.ToLower(); IOutputFormatter targetFormatter = format switch { "raw" => formatters.FirstOrDefault(f => f is ConvertResultRawFormatter), "json" => formatters.FirstOrDefault(f => f is SystemTextJsonOutputFormatter), // 可扩展更多格式规则 _ => formatters.FirstOrDefault(f => f is SystemTextJsonOutputFormatter) // 默认返回JSON格式化器 }; if (targetFormatter != null) { // 返回选中的格式化器及对应媒体类型 var mediaType = targetFormatter is ConvertResultRawFormatter ? "text/plain" : "application/json"; return new ContentNegotiationResult(targetFormatter, MediaTypeHeaderValue.Parse(mediaType)); } // 无匹配时使用默认协商逻辑 return new DefaultContentNegotiationPolicy().Negotiate(type, request, formatters); } }
在Program.cs(.NET 6+)中注册配置:
builder.Services.AddControllers(options => { // 添加自定义格式化器 options.OutputFormatters.Add(new ConvertResultRawFormatter()); // 替换默认内容协商策略 options.ContentNegotiationPolicy = new QueryParamContentNegotiationPolicy(); // 配置JSON格式化器忽略Null值(对应原JsonMediaTypeFormatter的配置) var jsonFormatter = options.OutputFormatters.OfType<SystemTextJsonOutputFormatter>().First(); jsonFormatter.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; });
方式二:在格式化器内直接判断查询参数
如果逻辑简单,可直接在自定义格式化器中检查查询参数,决定是否启用:
public class ConvertResultRawFormatter : OutputFormatter { public ConvertResultRawFormatter() { SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain")); } protected override bool CanWriteType(Type type) { return true; } public override bool CanWriteResult(OutputFormatterCanWriteContext context) { // 仅当查询参数指定"format=raw"时启用该格式化器 var formatParam = context.HttpContext.Request.Query["format"].FirstOrDefault(); return formatParam?.ToLower() == "raw" && base.CanWriteResult(context); } public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context) { var response = context.HttpContext.Response; var rawContent = context.Object?.ToString() ?? string.Empty; await response.WriteAsync(rawContent); } }
注册配置简化为:
builder.Services.AddControllers(options => { options.OutputFormatters.Add(new ConvertResultRawFormatter()); var jsonFormatter = options.OutputFormatters.OfType<SystemTextJsonOutputFormatter>().First(); jsonFormatter.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; });
3. 测试验证
发送请求时通过查询参数指定格式:
- 调用原始格式:
GET /api/your-endpoint?format=raw - 调用JSON格式:
GET /api/your-endpoint?format=json
内容的提问来源于stack exchange,提问作者Tomas
相关产品推荐
相关产品推荐

