使用Owin自托管时,从Web Api控制器抛出HttpResponseException

时间:2014-07-03 08:09:31

标签: c# asp.net-web-api owin

我们正在构建一个我们使用Owin托管的WebApi。以前我们在控制器操作中使用HttpResponseException返回404状态代码等,并且运行良好。

但是,当我们开始使用Owin(自托管)时,我们遇到了这种方法的问题,导致HttpResponseException被序列化为json / xml,状态代码从404更改为500(内部服务器错误) )。这是我们的代码:

public class InvoicesController : ApiController
{
    private readonly IInvoiceRepository _invoiceRepository;

    public InvoicesController(IInvoiceRepository invoiceRepository)
    {
        _invoiceRepository = invoiceRepository;
    }

    [HttpGet]
    public IEnumerable<AccountCodeAssignment> AssignAccountCodesToInvoiceById(int id)
    {
        var invoice = _invoiceRepository.Get(id);

        if (invoice == null) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, "Invoice not found"));

        yield return new AccountCodeAssignment(1, ...);
        yield return new AccountCodeAssignment(2, ...);
        yield return new AccountCodeAssignment(3, ...);
        yield return new AccountCodeAssignment(4, ...);
    }
}

这是我们回复的响应以及500响应代码:

{
    "Message": "An error has occurred.",
    "ExceptionMessage": "Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details.",
    "ExceptionType": "System.Web.Http.HttpResponseException",
    "StackTrace": "   at AccountCodeAssignmentService.Controllers.InvoicesController.<AssignAccountCodesToInvoiceById>d__0.MoveNext() in c:\\Projects\\AccountCodeAssignmentService\\Source\\AccountCodeAssignmentService\\Controllers\\InvoicesController.cs:line 38\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n   at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__13.MoveNext()"
}

使用Owin自托管时,不支持任何关于我们做错了什么或是HttpResponseException的想法吗?

修改 使用WebApi的一大优势是能够使用并返回我们自己的类型,因此我们希望避免更改返回类型。我们目前正在产生AccountCodeAssignment,因此不能选择更改返回类型。

5 个答案:

答案 0 :(得分:6)

我在使用邮递员测试web api时遇到了这种情况,请求类型设置为纯文本而不是application / json。

答案 1 :(得分:4)

我不认为问题在于投掷HttpResponseException。如果查看发布的堆栈跟踪,问题似乎出现在MoveNext()的调用中。这是您拥有的yield语句的内部C#表示。

我可能是错的,但验证这个的最简单方法是在第一个yield语句上放置一个断点,看它是否会命中它。我的猜测是它会,即它不会抛出HttpResponseException。此外,只需暂时更改您的代码,始终抛出HttpResponseException并查看它如何处理它。

我目前正在开发一个使用OWIN自我托管的项目,我可以毫无问题地抛出HttpResponseException

在相关说明中,您可能需要调查global exception handling。我发现将所有异常处理集中在一个地方非常有用。请注意,HttpResponseException是一种特殊情况,并不由全局异常处理程序处理。

答案 2 :(得分:2)

对我来说,我的api标头中缺少content-type。在将内容类型添加为application / json后,为我解决了此问题。可能会帮助其他人。

答案 3 :(得分:1)

不是100%肯定,但可能会发生这种情况,因为您的操作返回IEnumerable&lt;&gt;

尝试将其更改为IHttpActionResult

试试这个

  [ResponseType(typeof(AccountCodeAssignment))]
         public IHttpActionResult AssignAccountCodesToInvoiceById (int id)
        {

         var invoice = _invoiceRepository.Get(id);

                if (invoice == null) {

                return NotFound();
         }



               return Ok(invoice);
            }

答案 4 :(得分:0)

您可以在<table> <thead> <tr class="d-flex"> <th class="col-3">3 columns wide header</th> <th class="col-sm-5">5 columns wide header</th> <th class="col-sm-4">4 columns wide header</th> </tr> </thead> <tbody> <tr class="d-flex"> <td class="col-3">3 columns wide content</th> <td class="col-sm-5">5 columns wide content</th> <td class="col-sm-4">4 columns wide content</th> </tr> </tbody> </table> 的异常上设置断点,并查看 context.Exception.Response ,并查看“原因短语”以获取说明。

您也可以通过代码访问它:

OnException()

对我来说是

  

不支持的媒体类型

在您进行文本请求时,可能还会发生其他人提到的问题,因为默认情况下不会处理文本请求。如果您确实想允许输入文字,则可以查看: like