Fran CD
Fran CD

Reputation: 327

Post (or put) request with uri parameter not working when calling with HttpClient

In trying to make a Web API in c# and consume it via c# HttpClient, I've already written some controllers and client calls and is working fine, but now I need to call a Post method with two parameters, one simple value (long) directly in the URL[FromURI], and the another one is a complex type passed in body.

I think I can simplify the answer, suppose I just want to call a post or put with one simple parameter passed in the URL.

First of all, lets see my web server mapping config:

HttpConfiguration config = new HttpConfiguration(); config.Routes.MapHttpRoute(
                    name: "DefaultWebApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional });

And thats my Put controller:

 [HttpPut]
 public IHttpActionResult PutComandas([FromUri] long ticket)
 {
 ...
 }

I can call this without problem using PostMan and URL like localhost:8200/api/Comandas?ticket=9, but I can't find a way to do that call with HttpClient, also, it's strange to me that I can not simply call (in PostMan) to localhost:8200/api/Comandas/9 as I can do with get requests... is like the routing configuration is working for gets, but not for puts/posts... Anyway, the real problem is: I can't find the way to do a correct put call with HttpClient. I'm trying:

HttpClient client = new HttpClient();
var response = client.PutAsync("localhost:8200/api/Comandas?ticket=9", null).Result;

but I receive a Not Found response.

Note: I can call Put/Post with complex body parameters without problems.

Upvotes: 0

Views: 3934

Answers (1)

andyb952
andyb952

Reputation: 2008

A cleaner way would be to use a Dictionary and pass as FormUrlEncodedContent

var url = "localhost:8200/api/Comandas";
var parameters = new Dictionary<string, string> { { "ticket", "9" } };
var encodedContent = new FormUrlEncodedContent(parameters);

var response = await client.PutAsync(url, encodedContent);

Also as a side note, HttpClient should only be instantiated once and then re-used: https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netframework-4.7.1#Remarks

EDIT: User has now clarified they are looking for both a Uri param and a Body param. Following on from code above:

AddQueryString is available through

Microsoft.Owin.Infrastructure.WebUtilities.AddQueryString()

or if using .NET Core

Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString()
var url = "localhost:8200/api/";
// Query string parameters
var parameters = new Dictionary<string, string>(){ { "ticket", "9" } };

// Create json for body
var content = new JObject(yourBodyObject);

// SetupHttpClient
client.BaseAddress = new Uri(url);

// This is the important bit
var requestUri = QueryHelpers.AddQueryString("Comandas", parameters);

var request = new HttpRequestMessage(HttpMethod.Put, requestUri);
// Setup headers for Content-Type
request.Headers.Add("Accept", "application/json");
// Add body content
request.Content = new StringContent(
    content.ToString(),
    Encoding.UTF8,
    "application/json"
);

// Send the request
client.SendAsync(request);

Upvotes: 3

Related Questions