【发布时间】:2018-06-15 16:38:22
【问题描述】:
我正在为一组微服务创建概念验证,目前我正在处理内容协商。
我找到了Jeremy Likness 的一系列帖子,并开始查看他的demo 显示使用自定义格式化程序进行内容协商的帖子。
我从 GitHub 克隆了项目并运行了该项目。当我从 Postman 和 Insomnia 发送请求时,除了一个用例之外,我得到了预期的结果。问题是我无法为集合获得 CSV 格式的响应。
对于每个请求,我都会添加 accept 标头和适当的值(text/csv、text/xml、text/json)。
请求单个资源 (http://localhost:5000/api/todo/1) 时,使用自定义格式化程序将响应格式化为 CSV。这是预期的行为。但是,在请求集合 (http://localhost:5000/api/todo) 时,响应格式为 JSON。
我错过了什么?我在做什么来获取单个资源的 CSV 而不是集合的 JSON?包含accept: text/xml 和accept: text/json 的请求返回接受标头中指定的内容。这只是text/csv 的问题。
我在 Visual Studio 2017 和 VS Code 中运行代码,结果相同。
更新 #1 - 我在 CsvFormatter.WriteResponseBodyAsync() 上放置了一个断点。请求单个资源时会触发断点。请求集合时没有命中断点。
这里是startup.cs:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true;
options.FormatterMappings.SetMediaTypeMappingForFormat("xml", MediaTypeHeaderValue.Parse("text/xml"));
options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("text/json"));
options.FormatterMappings.SetMediaTypeMappingForFormat("csv", MediaTypeHeaderValue.Parse("text/csv"));
options.OutputFormatters.Add(new CsvFormatter());
})
.AddXmlSerializerFormatters();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
这是自定义格式化程序:
public class CsvFormatter : TextOutputFormatter
{
public CsvFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/csv"));
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
protected override bool CanWriteType(System.Type type)
{
return type == typeof(TodoItem);
}
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
var response = context.HttpContext.Response;
var buffer = new StringBuilder();
if (context.Object is IEnumerable<TodoItem>)
{
foreach(var todoItem in (IEnumerable<TodoItem>)context.Object)
{
FormatCsv(buffer, todoItem);
}
}
else
{
FormatCsv(buffer, (TodoItem)context.Object);
}
using (var writer = context.WriterFactory(response.Body, selectedEncoding))
{
return writer.WriteAsync(buffer.ToString());
}
}
private static void FormatCsv(StringBuilder buffer, TodoItem item)
{
buffer.AppendLine($"{item.Id},\"{item.Name}\",{item.IsComplete}");
}
}
【问题讨论】:
-
返回类型 == typeof(TodoItem) || typeof(IEnumerable
)??
标签: .net asp.net-core