We are building a WebApi that we're hosting using Owin. Previously we've used HttpResponseException for returning 404 status codes etc. in our controller actions and it's been working well.
However, when we started working with Owin (self hosted) we're experiencing an issue with this approach resulting in the HttpResponseException being serialized to json/xml and the status code to change from 404 to 500 (Internal Server Error). Here's the code we have:
public class InvoicesController : ApiController
private readonly IInvoiceRepository _invoiceRepository;
public InvoicesController(IInvoiceRepository invoiceRepository)
_invoiceRepository = invoiceRepository;
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, ...);
"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.",
"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()"
I don't think the problem is in throwing
HttpResponseException. If you look at the stack trace you posted, the problem appears to be in the call to
MoveNext(). This is an internal C# representation of the
yield statements you have.
I could be wrong, but the easiest way to verify this is to put a breakpoint on the first yield statement and see if it hits it. My guess is that it will, i.e. it won't throw a
HttpResponseException. Also, just change your code temporarily to always throw an
HttpResponseException and see how it handles it.
I'm currently working on a project that's self-hosted using OWIN and I can throw
HttpResponseExceptions without any issues.
On a related note, you may want to investigate global exception handling. I found it very useful to concentrate all my exception handling in one place. Note that
HttpResponseException is a special case and is not handled by the global exception handler.