When an exception(example: OperationCanceledException) occurs in a message handler, we do not convert it to a safe http response message at the HttpServer level. By 'safe', I mean to HttpResponseMessage with 500 Internal Server Error. However, we are doing this in Self host case.
Code of interest in HttpControllerHandler ([source](https://aspnetwebstack.codeplex.com/SourceControl/changeset/view/ad9271c39ed43e87ac7e89f958fd8f2b90953e90#src/System.Web.Http.WebHost/HttpControllerHandler.cs)):
```
public override Task ProcessRequestAsync(HttpContext context)
{
return ProcessRequestAsyncCore(new HttpContextWrapper(context));
}
internal async Task ProcessRequestAsyncCore(HttpContextBase contextBase)
{
HttpRequestMessage request = contextBase.GetHttpRequestMessage() ?? ConvertRequest(contextBase);
// Add route data
request.Properties[HttpPropertyKeys.HttpRouteDataKey] = _routeData;
HttpResponseMessage response = await _server.SendAsync(request, contextBase.Request.TimedOutToken);
await ConvertResponse(contextBase, response, request);
}
internal static async Task ConvertResponse(HttpContextBase httpContextBase, HttpResponseMessage response, HttpRequestMessage request)
{
Contract.Assert(httpContextBase != null);
Contract.Assert(request != null);
// A null response creates a 500 with no content
if (response == null)
{
CreateEmptyErrorResponse(httpContextBase.Response);
return;
}
CopyResponseStatusAndHeaders(httpContextBase, response);
// TODO 335085: Consider this when coming up with our caching story
if (response.Headers.CacheControl == null)
{
// DevDiv2 #332323. ASP.NET by default always emits a cache-control: private header.
// However, we don't want requests to be cached by default.
// If nobody set an explicit CacheControl then explicitly set to no-cache to override the
// default behavior. This will cause the following response headers to be emitted:
// Cache-Control: no-cache
// Pragma: no-cache
// Expires: -1
httpContextBase.Response.Cache.SetCacheability(HttpCacheability.NoCache);
}
// Asynchronously write the response body. If there is no body, we use
// a completed task to share the Finally() below.
// The response-writing task will not fault -- it handles errors internally.
try
{
if (response.Content != null)
{
await WriteResponseContentAsync(httpContextBase, response, request);
}
}
finally
{
request.DisposeRequestResources();
request.Dispose();
response.Dispose();
}
}
```
Code of interest in HttpControllerHandler ([source](https://aspnetwebstack.codeplex.com/SourceControl/changeset/view/ad9271c39ed43e87ac7e89f958fd8f2b90953e90#src/System.Web.Http.WebHost/HttpControllerHandler.cs)):
```
public override Task ProcessRequestAsync(HttpContext context)
{
return ProcessRequestAsyncCore(new HttpContextWrapper(context));
}
internal async Task ProcessRequestAsyncCore(HttpContextBase contextBase)
{
HttpRequestMessage request = contextBase.GetHttpRequestMessage() ?? ConvertRequest(contextBase);
// Add route data
request.Properties[HttpPropertyKeys.HttpRouteDataKey] = _routeData;
HttpResponseMessage response = await _server.SendAsync(request, contextBase.Request.TimedOutToken);
await ConvertResponse(contextBase, response, request);
}
internal static async Task ConvertResponse(HttpContextBase httpContextBase, HttpResponseMessage response, HttpRequestMessage request)
{
Contract.Assert(httpContextBase != null);
Contract.Assert(request != null);
// A null response creates a 500 with no content
if (response == null)
{
CreateEmptyErrorResponse(httpContextBase.Response);
return;
}
CopyResponseStatusAndHeaders(httpContextBase, response);
// TODO 335085: Consider this when coming up with our caching story
if (response.Headers.CacheControl == null)
{
// DevDiv2 #332323. ASP.NET by default always emits a cache-control: private header.
// However, we don't want requests to be cached by default.
// If nobody set an explicit CacheControl then explicitly set to no-cache to override the
// default behavior. This will cause the following response headers to be emitted:
// Cache-Control: no-cache
// Pragma: no-cache
// Expires: -1
httpContextBase.Response.Cache.SetCacheability(HttpCacheability.NoCache);
}
// Asynchronously write the response body. If there is no body, we use
// a completed task to share the Finally() below.
// The response-writing task will not fault -- it handles errors internally.
try
{
if (response.Content != null)
{
await WriteResponseContentAsync(httpContextBase, response, request);
}
}
finally
{
request.DisposeRequestResources();
request.Dispose();
response.Dispose();
}
}
```