【问题标题】:Web API middleware short circuiting unexpectedlyWeb API 中间件意外短路
【发布时间】:2019-07-27 06:15:22
【问题描述】:

以下代码是错误处理中间件的一部分,其目标是即使抛出错误也为客户端提供一致的格式。

Accept 标头设置为application/xml 时,我尝试将响应序列化为 XML,否则返回 JSON。这篇文章帮助我开始了:https://www.devtrends.co.uk/blog/handling-errors-in-asp.net-core-web-api

if (context.Request.Headers["Accept"] == "application/xml")
{
    context.Response.ContentType = "application/xml";

    using (var stringwriter = new StringWriter())
    {
        var serializer = new XmlSerializer(response.GetType());
        serializer.Serialize(stringwriter, response);
        await context.Response.WriteAsync(stringwriter.ToString());
    }
}
else {
    context.Response.ContentType = "application/json";
    var json = JsonConvert.SerializeObject(response);
    await context.Response.WriteAsync(json);
}

else 块按预期工作。如果我在声明 XmlSerializer 的行上设置断点,则执行停止。如果我在下一行设置断点,则断点永远不会被命中;已向客户端发送响应。

我的中间件是这样配置的:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseStatusCodePagesWithReExecute("/error/{0}");
        app.UseExceptionHandler("/error/500");
        app.UseHsts();
        app.UseMiddleware<ErrorWrappingMiddleware>();
        app.UseMvc();
    }

为什么在if 块中调用context.Response.WriteAsync(stringwriter.ToString()); 之前向客户端返回响应?

【问题讨论】:

  • WebAPi 内置了 content-negotiation (docs.microsoft.com/en-us/aspnet/core/web-api/advanced/…),有什么理由写这个中间件吗?
  • 我已经看过这个页面并在我的配置中添加了AddXmlSerializerFormatters(),但是当返回错误时(例如状态代码 500),响应正文为空白。我想要一个格式一致的响应正文,因此需要额外的中间件。
  • 使用 XML 格式化程序时,仅返回类型不返回 IEnumerable 类型,这将引发异常。
  • 我们能得到一个更完整的例子吗?如果你在 var serializer = new XmlSerializer(response.GetType()); 周围设置一个 try catch 会发生什么? serializer.Serialize(字符串编写器,响应);等待 context.Response.WriteAsync(stringwriter.ToString());

标签: c# asp.net-core


【解决方案1】:

我发现了问题,这是一个愚蠢的错误。

为了测试 500 个错误,我有意将属性添加到数据库中没有对应列的模型中。这会在无效的列名上引发 SqlException。然而,我错过了第二个异常,它准确地告诉我问题出在哪里:

ApiResponse cannot be serialized because it does not have a parameterless constructor.

这发生在对serializer.Serialize(stringwriter, response) 的调用中。我引用的示例创建了一个ApiResponse 类(我试图序列化的response)。但是,在我学习的示例中,此类没有无参数构造函数,直到找到this 答案之前,我才意识到这是必要的。第二个异常停止了执行,但是由于我忘记打开开发模式并试图抛出异常,所以我没有注意到第二个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多