Search code examples
c#.netasp.net-web-apidotnet-httpclientasp.net-web-api-routing

call web api by passing simple and complex parameter


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 }
);

Solution

  • 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();
    }