Kristoffer Ahl Kristoffer Ahl - 1 year ago 51
C# Question

Throwing HttpResponseException from WebApi controller when using Owin self host

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

[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, ...);
}
}


and this is the response we get back along with a 500 response code:

{
"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()"
}


Any ideas on what we're doing wrong or is HttpResponseException not supported when using Owin self hosting?

Edit:
One of the big advantages of using WebApi for us is the ability to work with and return our own types, so we would like to avoid having to change the return type. We're currently yielding AccountCodeAssignment's so changing the return type is not an option.

Answer Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download