How to call PUT method from Web Api using HttpClient?

44,811

As you probably found out, no you can't. When you call PostAsJsonAsync, the code will convert the parameter to JSON and send it in the request body. Your parameter is a JSON array which will look something like the array below:

[1,"/","?aid",345,"&content=","aGVsbG8gd29ybGQ="]

Which isn't what the first function is expecting (at least that's what I imagine, since you haven't showed the route info). There are a couple of problems here:

  • By default, parameters of type byte[] (reference types) are passed in the body of the request, not in the URI (unless you explicitly tag the parameter with the [FromUri] attribute).
  • The other parameters (again, based on my guess about your route) need to be part of the URI, not the body.

The code would look something like this:

var uri = "api/Test/" + id + "/?aid=" + aid;
using (HttpResponseMessage response = client.PutAsJsonAsync(uri, filecontent).Result)
{
    return response.EnsureSuccessStatusCode();
}

Now, there's another potential issue with the code above. It's waiting on the network response (that's what happens when you access the .Result property in the Task<HttpResponseMessage> returned by PostAsJsonAsync. Depending on the environment, the worse that can happen is that it may deadlock (waiting on a thread in which the network response will arrive). In the best case this thread will be blocked for the duration of the network call, which is also bad. Consider using the asynchronous mode (awaiting the result, returning a Task<T> in your action) instead, like in the example below

public async Task<HttpResponseMessage> Put(int id, int aid, byte[] filecontent)
{
    // ...

    var uri = "api/Test/" + id + "/?aid=" + aid;
    HttpResponseMessage response = await client.PutAsJsonAsync(uri, filecontent);
    return response.EnsureSuccessStatusCode();
}

Or without the async / await keywords:

public Task<HttpResponseMessage> Put(int id, int aid, byte[] filecontent)
{
    // ...

    var uri = "api/Test/" + id + "/?aid=" + aid;
    return client.PutAsJsonAsync(uri, filecontent).ContinueWith<HttpResponseMessage>(
        task => task.Result.EnsureSuccessStatusCode());
}
Share:
44,811
Shubhajyoti Ghosh
Author by

Shubhajyoti Ghosh

Updated on July 09, 2022

Comments

  • Shubhajyoti Ghosh
    Shubhajyoti Ghosh almost 2 years

    I want to call Api function (1st) . from 2nd Api function using HttpClient. But I always get 404 Error.

    1st Api Function (EndPoint : http : // localhost : xxxxx /api/Test/)

    public HttpResponseMessage Put(int id, int accountId, byte[] content)
    [...]
    

    2nd Api function

    public HttpResponseMessage Put(int id, int aid, byte[] filecontent)
    {
        WebRequestHandler handler = new WebRequestHandler()
        {
            AllowAutoRedirect = false,
            UseProxy = false
        };
    
        using (HttpClient client = new HttpClient(handler))
        {
            client.BaseAddress = new Uri("http://localhost:xxxxx/");
    
            // Add an Accept header for JSON format.
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
            var param = new object[6];
            param[0] = id;
            param[1] = "/";
            param[2] = "?aid="; 
            param[3] = aid;                           
            param[4] = "&content=";
            param[5] = filecontent;
    
            using (HttpResponseMessage response = client.PutAsJsonAsync("api/Test/", param).Result)
            {
                return response.EnsureSuccessStatusCode();
            }
        }
    }
    

    So My question is that. Can I post Method Parameter as an object array from HttpClient as I did ? I don't want to Pass model as method parameter.

    What is the wrong in my code ?

    Unable to get any response , after change code to

    return client.PutAsJsonAsync(uri, filecontent)
               .ContinueWith<HttpResponseMessage>
                (
                   task => task.Result.EnsureSuccessStatusCode()
                );
    

    OR

    return client.PutAsJsonAsync(uri, filecontent)
               .ContinueWith
                (
                   task => task.Result.EnsureSuccessStatusCode()
                );