Does anyone know why the behaviour of throwing exceptions within a PUT action method in a controller in ASP.NET WebAPI would be different from any other actions and verb types?
Essentially I have the code below (I normally have an exception filter globally registered but I’ve disabled that to ensure it isn’t the cause).
public class JourneysController : ApiController
{
private IJourneyRepository repository = null;
public JourneysController(IJourneyRepository repository)
{
this.repository = repository;
}
public async Task<Journey> GetById(string id)
{
throw new BusinessException("test1");
var item = await repository.Get(id);
if (item == null) throw new HttpResponseException(HttpStatusCode.NotFound);
return item;
}
public async Task<HttpResponseMessage> Post(HttpRequestMessage request, [FromBody]Journey value)
{
throw new BusinessException("test2");
value = await repository.Add(value);
var response = request.CreateResponse<Journey>(HttpStatusCode.Created, value);
string uri = Url.Link("DefaultApi", new { id = value.Id });
response.Headers.Location = new Uri(uri);
return response;
}
public async void Put(string id, [FromBody]Journey value)
{
throw new BusinessException("test3");
value.Id = id;
if (!await repository.Update(value)) throw new HttpResponseException(HttpStatusCode.NotFound);
}
public HttpResponseMessage Delete(string id)
{
throw new BusinessException("test4");
repository.Remove(id);
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
}
When I execute (using Chrome Advanced REST client) the GET, POST and DELETE verbs I get a payload like the following (no easy way to copy/paste out of the client):
500 Internal Server Error
Date: Tue, 25 Sep 2012 15:37:56 GMT
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 813
Pragma: no-cache
{
"Message": "An error has occurred.",
"ExceptionMessage": "test4",
"ExceptionType": "KieranBenton.LeaveNow.Services.Model.BusinessException",
"StackTrace": " <snip>"
}
However the PUT action returns me a yellow screen of death payload like:
<span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>
<h2> <i>test3</i> </h2></span>
<font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">
<b> Description: </b>An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
<b> Exception Details: </b>KieranBenton.LeaveNow.Services.Model.BusinessException: test3
Has anyone got any idea why this might be happening or if I’ve actually stumbled across a bug?
Thanks.
One guideline for
asyncis to avoidasync void.The
asyncequivalent of a synchronous method returningvoidis anasyncmethod returningTask.async voidonly exists so that event handlers may beasync.As you noticed, the exception handling is different. Any exceptions raised from an
async voidare sent directly to theSynchronizationContextthat was current when the method started. This is natural for event handlers, but is confusing in other scenarios.ASP.NET establishes a
SynchronizationContextthat represents the current HTTP request, so any exceptions from anasync voidmethod are not passed up to the WebAPI code that’s running the controller; they get passed around the WebAPI framework straight to the ASP.NET request context.