0

I am currently building a web.api for a pizzaria, C#, and .NET 4.6
I have a C# client that wants to select a pizza from code.. the pizza is in json.

{"id":1,"Name":"Magariatha"}  

I am calling from an asp.net site hosted in iis express, I dont get through. If I call from Fiddler, the call passes through, and the pizza is selected and can get ordered ;-)

My PizzaController looks like:

public HttpResponseMessage Put(Pizza pizza)
{
   string pizzaApi = "Api/Pizza/";   
   var handler = new WebRequestHandler() {  
       AllowAutoRedirect = false,  
       UseProxy = false };

   using( var client = new HttpClient(handler)) {  
      client.BaseAdresse = new Uri("http://localhost:12345");   
      var media = new MediaTypeWithQualityHeaderValue("application/json");  
      client.DefaultRequestHeaders.Accept.Add(media);  

     // so far so good, but the trouble starts in the next line...
     return client.PutAsJsonAsync(pizzaApi, pizza).
              ContinueWith(x => x.Result.EnsureSuccessStatusCode)).Result;  
  } // end using
} // end put

It appears that something get disposed in the call to putasjson, before the server gets accessed. But I cannot figure out why.. I get the message:

Exception thrown: 'System.ObjectDisposedException' in System.Net.Http.dll
kfn
  • 620
  • 1
  • 7
  • 26
  • I tried with fiddler and the call passed through to the server, but with postman I got this error: "Message": "The request entity's media type 'multipart/form-data' is not supported for this resource.", "ExceptionMessage": "No MediaTypeFormatter is available to read an object of type 'Scanner' from content with media type 'multipart/form-data'.", – kfn Jun 29 '17 at 13:25

2 Answers2

0

tl;dr: By splitting the offending call into multiple different calls it became apparent that there's a completely different issue at hand with acces rights. The rest of this answer was just a journey to the answer for OPs problem.

The problem is that because you are returning before closing the using statement block it actually gets closed before the return and then the client object is already disposed and any further call on it results in an exception.

we have also figured out in the comments that client.BaseAddress and then the apicall adress have strange requirements as this guy (Why is HttpClient BaseAddress not working?) has found out the hard way.

string pizzaApi = "Api/Pizza"; // no slash at the end
client.BaseAddress = new Uri("http://localhost:12345/") // slash at the end

You should instead pull out the result variable from outside the using block, close it when required and return the result afterwards.

public HttpResponseMessage Put(Pizza pizza)
{
    string pizzaApi = "Api/Pizza";   
    var handler = new WebRequestHandler() {  
        AllowAutoRedirect = false,  
        UseProxy = false };

     // no clue what type this should be so change var to the type accordingly
    var result;

    using( var client = new HttpClient(handler)) 
    {  
      client.BaseAdresse = new Uri("http://localhost:12345/");   
      var media = new MediaTypeWithQualityHeaderValue("application/json");  
      client.DefaultRequestHeaders.Accept.Add(media);  
      result = client.PutAsJsonAsync(pizzaApi, pizza).
          ContinueWith(x => x.Result.EnsureSuccessStatusCode)).Result;
     } // end using here instead
     return result;  

} // end put
pijemcolu
  • 2,257
  • 22
  • 36
  • That doesn't appear to solve the problem, I've seen the suggestion in other posts before and tried it. – kfn Jun 29 '17 at 12:03
  • Try to cut that PutAsJsonAsync method call and other follow up methods to multiple lines to see which method call is the offender. – pijemcolu Jun 29 '17 at 12:08
  • I even tried it without the using, and disposed of the client in a finally block, no change... – kfn Jun 29 '17 at 12:09
  • If I change to : var xx = client.PutAsJsonAsync(pizzaApi, pizza); var yy = ContinueWith(x => x.Result.EnsureSuccessStatusCode)); var zz = yy.Result; and return zzz; // I dont fall asleep, but the get a crash in the PutAsJson.. – kfn Jun 29 '17 at 12:18
  • Ok so the problem is ... You must place a slash at the end of the BaseAddress, and you must not place a slash at the beginning of your relative URI. that means that your client.BaseAddress (no e at the end) should be `http://localhost:12345/` – pijemcolu Jun 29 '17 at 12:25
  • https://stackoverflow.com/questions/23438416/why-is-httpclient-baseaddress-not-working `client.BaseAddress = new Uri("http://localhost:12345/");` `string pizzaApi = "Api/Pizza";` Notice the slashes are different. – pijemcolu Jun 29 '17 at 12:30
  • That wasn't the issues either.. There is apperntly some other issue at hand, the Get operations works nicely... (and thanks for you help) – kfn Jun 29 '17 at 12:41
0

I finally got it ;-)
After reading this I understood why and how to fix it: http://chimera.labs.oreilly.com/books/1234000001708/ch14.html#_peeling_off_the_layers

The problem was that, yes I use the HttpClient inside a using statement, that automatically cleans up, and disposes of the WebRequestHandler before it is time. But there is a workaround !!!

There is an optional second parameter to the constructor that takes a bool, that controls if the dispose is automated. Appearently all I need to do is use the constructor, and handle the disposing of the handler manually ;-) ... var handler = new WebRequestHandler(); ... using ( var client = new HttpClient(handler,false)) { //< FALSE ADDED !!! ... } handler.Dispose();

and it all works nicely, - I hope someone finds this usefull.

kfn
  • 620
  • 1
  • 7
  • 26