call web api by passing simple and complex parameter

27,341

Solution 1

field1, field2 and field4 parameters are expected in the Url, not in the request body. That's why the request Url should look like: http://xxx.xxx.xx.xx:1234/api/home/processfields?field1=value1&field2=value2&field4=value4

field3 is deserialized from the body. However as it is string parameter, request body should be built not as JSON object:

{
  "field3": "value3"
}

but as JSON string:

"value3"

Here is adjusted client code that should work:

using (var client = new HttpClient())
{
    //set up client
    client.BaseAddress = new Uri(Baseurl);
    client.DefaultRequestHeaders.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var requestUri = new Uri($"api/home/processfields?field1={HttpUtility.UrlEncode(field1)}&field2={HttpUtility.UrlEncode(field2)}&field4={HttpUtility.UrlEncode(field4)}", UriKind.Relative);
    var content = new StringContent($"\"{field3}\"", Encoding.UTF8, "application/json");
    var response = await client.PostAsync(requestUri, content);
    var result = await response.Content.ReadAsStringAsync();
}

Solution 2

First, looking at the Web API method signature, I don't think there's any JSON involved here at all. So I think you can skip setting the Accept header. (If the [FromBody] parameter were a complex object rather than a string, then JSON serialization would likely come into play.)

Second, never use .Result with HttpClient. It is an async-only API and you should be using async / await, otherwise you're just inviting deadlocks.

Finally, as others have pointed out, field1, field2, and field4 go in the query string, not the body. If you want a more structured way to do this, and with less ceremony overall, consider using Flurl (disclaimer: I'm the author), which uses HttpClient under the hood:

using Flurl.Http;

var result = await BaseUrl
    .AppendPathSegment("api/home/processfields")
    .SetQueryParams(new { field1, field2, field4 })
    .PostStringAsync(field3)
    .ReceiveString();

Solution 3

bodyClass obj = new bodyClass();
obj.empName= "your param value";
string DATA = Newtonsoft.Json.JsonConvert.SerializeObject(obj);

var client = new HttpClient();
HttpContent content = new StringContent(DATA, UTF8Encoding.UTF8, "application/json");
HttpResponseMessage messge = client.PostAsync("your api url", content).Result;

if (messge.IsSuccessStatusCode)
{
      string result = messge.Content.ReadAsStringAsync().Result;
}
Share:
27,341
santa029
Author by

santa029

Updated on September 12, 2020

Comments

  • santa029
    santa029 over 3 years

    Getting an error message of no http resource or action found in controller. In a web api I have a from body and from uri parameter.

    [HttpPost]        
    public IHttpActionResult processfields(
        [FromUri]string field1,
        [FromUri]string field2, 
        [FromBody] string field3, 
        [FromUri]string field4
    ){...}
    

    In the client I want to call the web api by doing--

    using (var client = new HttpClient())
    {
        //set up client
        client.BaseAddress = new Uri(Baseurl);
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
    
         var values = new Dictionary<string, string>();
         values.Add("field1", field1);
         values.Add("field2", field2);
         values.Add("field3", field3);
         values.Add("field4", filed4);
    
    
         var jsonString = JsonConvert.SerializeObject(values);
         try
         {
    
             HttpResponseMessage Res = client.PostAsync("api/home/processfields", new StringContent(jsonString, Encoding.UTF8, "application/json")).Result;
             var result = Res.Content.ReadAsStringAsync();
         }
    }
    

    While debugging, it executes the last line above but nothing happens and error message says--

    {"Message":"No HTTP resource was found that matches the request URI 'http://xxx.xxx.xx.xx:1234/api/home/processfields'.","MessageDetail":"No action was found on the controller 'home' that matches the request."}

    my webapi.config has

    // Web API routes
    config.MapHttpAttributeRoutes();
    
    
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );