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.
I experienced this while I was using postman to test the web api and the request type was set to plain text instead of application/json.
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 HttpResponseException
s 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.
You can put a breakpoint on the exception in OnException()
and view the context.Exception.Response, and see the "Reason Phrase" for an explanation.
You can also do this to access it via code:
((System.Web.Http.HttpResponseException)context.Exception).Response.ReasonPhrase
For me it was
Unsupported Media Type
Which other people have already mentioned can happen when you do a text request, because text requests are not handled by default. If you do want to allow text, maybe look at: how to post plain text to ASP.NET Web API endpoint?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With