Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call PUT method from Web Api using HttpClient?

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()
            );
like image 235
Shubhajyoti Ghosh Avatar asked Apr 09 '13 19:04

Shubhajyoti Ghosh


People also ask

What is put method in Web API?

The HTTP PUT method is used to update an existing record in the data source in the RESTful architecture. So let's create an action method in our StudentController to update an existing student record in the database using Entity Framework. The action method that will handle HTTP PUT request must start with a word Put.

What is HttpClient in Web API?

HttpClient is a modern HTTP client for . NET applications. It can be used to consume functionality exposed over HTTP. For example, a functionality exposed by an ASP.NET Web API can be consumed in a desktop application using HttpClient.


1 Answers

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());
}
like image 101
carlosfigueira Avatar answered Nov 15 '22 07:11

carlosfigueira