Web API中间件意外短路

时间:2019-07-19 23:11:54

标签: c# asp.net-core

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

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();
    }

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

1 个答案:

答案 0 :(得分:1)

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

为了测试500个错误,我有意向模型添加了一个属性,该模型在数据库中没有相应的列。这会在无效的列名上抛出SqlException。但是,我错过了第二个例外,确切地告诉了我问题出在什么地方:

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

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