【问题标题】:Asp.Net Core Keep default output formatter after adding customAsp.Net Core 添加自定义后保留默认输出格式化程序
【发布时间】:2021-08-08 20:29:29
【问题描述】:

我正在使用 Net 5.0。 我为 ObjectResult 添加了自定义输出格式化程序。

var result = new ObjectResult(list)
{
    StatusCode = (int)HttpStatusCode.OK
};
result.Formatters.Add(new ExcelOutputFormatter());
return result;

但现在它会为每个请求返回我的自定义输出,无论我向 Accept Header 写什么。

如果我不添加自定义输出格式化程序,我希望保留 */* 以返回它的结果。
就我而言,我希望 application/json 类似于默认值,并且仅将我的格式化程序用于 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

我找到了 XmlSerializerOutputFormatter,我可以在我的格式化程序之前添加它,这样它就返回 XML 作为默认值,而我的 excel 只返回指定的标题。但我没有找到可行的 JSON 格式化程序。我正在使用一些默认的 .net 核心格式化程序,我没有在 Startup.cs 中添加任何格式化程序。

这是我的输出格式化程序

public class ExcelOutputFormatter : OutputFormatter
{
    public ExcelOutputFormatter()
    {
        SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
    }

    protected override bool CanWriteType(Type type)
    {
        return typeof(IEnumerable<Person>).IsAssignableFrom(type);
    }

    public override Task WriteResponseBodyAsync(
        OutputFormatterWriteContext context)
    {
        var httpContext = context.HttpContext;
        var serviceProvider = httpContext.RequestServices;

        var logger = serviceProvider.GetRequiredService<ILogger<ExcelOutputFormatter>>();

        var persons = context.Object as IEnumerable<Person>;

        var workbook = new ClosedXML.Excel.XLWorkbook();
        workbook.Worksheets.Add("Test");

        workbook.SaveAs(httpContext.Response.Body);

        return Task.CompletedTask;
    }
}

【问题讨论】:

  • WriteResponseBodyAsync 中添加一些解析怎么样?检查context.HttpContext.Request.Headers 中的 Accept Header 并根据它执行不同的操作?
  • 我想使用格式化程序,所以我不需要自己检查标题。如果我添加多个格式化程序,则每个仅针对它的类型调用,如果无法确定任何匹配项,则使用第一个添加的。但我希望它会使用某种全局设置,因为其他控制器在没有指定任何内容的情况下返回 json。
  • 如果您添加一个格式化程序,它们会按顺序进行评估。如果 CanWriteType 匹配,它将始终被使用。因此,您必须始终自己添加支票。
  • 我无法检查 CanWriteType 中的 Accept 标头以返回 false。如果我将文本/纯文本写入接受,我的格式化程序也会被调用。也许有一种方法可以获取默认用于控制器的格式化程序列表并将其添加到我的 ObjectResult 格式化程序列表中?
  • 我的问题类似,但略有不同。我在 services.AddControllers 注册中添加了我的自定义格式化程序。 lang-c# services.AddControllers(options =&gt; { options.RespectBrowserAcceptHeader = true; options.OutputFormatters.Add(new CsvOutputFormatter()); }) 我发现 Accept 标头受到尊重,一切都按预期工作。但是 - 如果未提供 Accept 标头,则默认为自定义格式化程序。希望默认为 application/json 格式化程序

标签: c# json asp.net-core asp.net-core-webapi .net-5


【解决方案1】:

您应该将格式化程序添加到您的 mvc 选项中

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.OutputFormatters.Insert(0, new ExcelOutputFormatter ());
    });
}

你可以在这里查看

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.mvcoptions?view=aspnetcore-5.0

https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/custom-formatters?view=aspnetcore-5.0

https://medium.com/c-sharp-progarmming/net-5-custom-output-formatter-6651eadef8e1

【讨论】:

  • 我想我尝试过类似的方法,但它只使用了 ExcelFormatter 而从不使用 json。将再试一次,并告知。我希望我能找到时间回到项目中的这个问题。
  • 我实现了同样的你在这里查看它medium.com/c-sharp-progarmming/…
【解决方案2】:

尝试覆盖 CanWriteResult;

public override bool CanWriteResult(OutputFormatterCanWriteContext context)
    {
        if (!context.HttpContext.Request.Headers.TryGetValue(HeaderNames.Accept, out StringValues accepts) || !SupportedMediaTypes.Contains(accepts[0]))
            return false;

        return base.CanWriteResult(context);
    }

【讨论】:

  • 看起来不错。我希望我有时间尽快尝试并删除解决方法。
【解决方案3】:

您需要在适当的位置链接您的输出格式化程序。

services.AddControllers(options => {})
    .AddNewtonsoftJson().AddXmlSerializerFormatters().AddExcelOutputFormatter();
// ...
public static IMvcBuilder AddExcelOutputFormatter(this IMvcBuilder builder)
{
    builder.Services.TryAddEnumerable(
        ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, ExcelOutputFormatterSetup>());            
    return builder;
}
class ExcelOutputFormatterSetup : IConfigureOptions<MvcOptions>
{
    void IConfigureOptions<MvcOptions>.Configure(MvcOptions options)
    {
        options.OutputFormatters.Add(new ExcelOutputFormatter());
    }
}

我遇到了同样的问题,上面的答案让我保持 json 作为默认格式化程序和基于 Accept 标头的自定义格式化程序...原始链接发布在下面 学分:Found here

【讨论】:

  • 好吧,但这会迫使我使用 NewtonsoftJson。我不想添加新的包/格式化程序,因为我对内置没有任何问题(.Net 库的一部分?我不知道)。而且我没有找到任何可以显式添加默认 json 格式化程序的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-15
  • 2022-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
相关资源
最近更新 更多