Case A
Please consider the following very simple OWIN hosted service (my VS project is a simple, empty web application with windows authentication enabled). Behavior is the same under IIS Express or IIS, with or without Visual Studio running.
SERVER CODE
public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional } ); app.UseWebApi(config); } } public class ValuesController : ApiController { [Authorize(Roles = "Managers")] public void Put(int id, [FromBody]string value) { } }
Now consider a client that uses System.Net.HttpClient to make a PUT request while the userdoes not belong to the 'Managers' group:
CLIENT CODE
var handler = new HttpClientHandler { UseDefaultCredentials = true }; HttpClient httpClient = new HttpClient(handler) { BaseAddress = new Uri(url) }; var response = httpClient.PutAsync("api/values/5", new StringContent("test"), CancellationToken.None).Result;
Expected result: response.StatusCode should be Unauthorized 401
Actual result: Exception is thrown: "The request was aborted: The request was canceled"
Case B
Same like Case A, but the controller is not hosted under OWIN but under a standard ASP.NET Web Application.
Actual result: As expected (response.StatusCode should be Unauthorized 401)
Case C
Same like Case A, but the client does not send a content (2nd parameter of PutAsync is null).
Actual result: As expected (response.StatusCode should be Unauthorized 401)
Case D
Same like Case A, but instead of using HttpClient, I use
RestSharp (an alternative client for rest services).
Actual result: As expected (response.StatusCode should be Unauthorized 401)
Case E
Same like Case A, but while running in debug mode, I put a breakpoint in the constructor of the controller.
Actual result: As expected (response.StatusCode should be Unauthorized 401)
Case F
Same like Case A, but the client runs on different machine than the server.
Actual result: As expected (response.StatusCode should be Unauthorized 401)
Case G
Same like Case A, but fiddler is on in an attempt to diagnose the problem.
Actual result: As expected (response.StatusCode should be Unauthorized 401)
My Conclusions
It seems that when under OWIN, the server does not wait for the client to upload the content. Only the headers of the request are enough to determine that the client does not have access anyway. So the server sends the Unauthorized response early and then drops the channel. It also seems that, even though RestSharp can detect the 401 response and can make the reasonable assumption that it does not make sense to upload the content, the standard System.Net.HttpClient cannot do that! It does not read the response until it finishes with the content upload, which fails because the server dropped the channel.
What do you think?