Search code examples
c#restasp.net-web-api2webapp2

WebApi POST method not found but GET works


I tried many time today to call a web api function with POST (HttpClient.PostAsync) method . But unfortunately I can't. Only the call with GET (HttpClient.GetAsync) method working with success. I try to follow many sample on the net, but always the same error. ("Not Found")

Thank you so much if somebody can help me

Here is the C# Web API:

[RoutePrefix("NewAreaMap")]
public class NewAreaMapController: ApiController
{
    [HttpPost]
    [ActionName("PostCreateAreaTemp")]
    public AreaTemp PostCreateAreaTemp(double southLatitude, double westLongitude, double northLatitude, double eastLongitude, int countryId, int worldId)
    {
        AreaTemp newTempMap = new AreaTemp();
        //.....
        * * Here is the C# code from client side: * *
            using(var client = new HttpClient())
            {
                client.BaseAddress = new Uri(ConfigurationManager.AppSettings["SrvWebApiPath"].ToString());
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                var values = new Dictionary < string,
                    string > ()
                    {
                        {
                            "southLatitude", southLatitude.ToString()
                        },
                        {
                            "westLongitude", westLongitude.ToString()
                        },
                        {
                            "northLatitude", northLatitude.ToString()
                        },
                        {
                            "eastLongitude", eastLongitude.ToString()
                        },
                        {
                            "countryId", countryId.ToString()
                        },
                        {
                            "worldId", worldId.ToString()
                        }
                    };
                var content = new FormUrlEncodedContent(values);
                HttpResponseMessage response = await client.PostAsync("api/NewAreaMap/PostCreateAreaTemp", content)
                if (response.IsSuccessStatusCode)
                {
                    string jsonData = response.Content.ReadAsStringAsync().Result;
                    newAreTemp = JsonConvert.DeserializeObject < AreaTemp > (jsonData);
                }
        }

The GET call work well with the following Url :

HttpResponseMessage response = await client.GetAsync("api/NewAreaMap/GetAreaTemp/?latitudeAreaCenter=7.02&longitudeAreaCenter=9.05");

Solution

  • Since you're posting a JSON, you might as well send it as an object. Or if you still want to keep the dictionary and the signature for the method you could try:

    var content = new StringContent(JsonConvert.SerializeObject(values),
                Encoding.UTF8, "application/json");
    

    Instead of

    var content = new FormUrlEncodedContent(values);
    

    Here's an example with an object.

    public class SampleObject
    {
        public double SouthLatitude { get;  set; }
        public double WestLongitude { get; set; }
        public double NorthLatitude { get; set; }
        public double EastLongitude { get; set; }
        public int CountryId { get; set; }
        public int WorldId { get; set; }
    }
    

    And change your request.

    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(ConfigurationManager.AppSettings["SrvWebApiPath"].ToString());
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
        var obj = new SampleObject
        {
            SouthLatitude = southLatitude,
            WestLongitude = westLongitude,
            NorthLatitude = northLatitude,
            EastLongitude = eastLongitude,
            CountryId = countryId,
            WorldId = worldId
        };
    
        // Send it as StringContent.
        var request = new StringContent(JsonConvert.SerializeObject(obj),
            Encoding.UTF8, "application/json");
    
        HttpResponseMessage response = await client.PostAsync("api/NewAreaMap/PostCreateAreaTemp", request)
        if (response.IsSuccessStatusCode)
        {
            string jsonData = response.Content.ReadAsStringAsync().Result;
            newAreTemp = JsonConvert.DeserializeObject<AreaTemp>(jsonData);
        }
    }
    

    And the signature on the server.

    public AreaTemp PostCreateAreaTemp(SampleObject sampleObject)
    

    Or if needed:

    public AreaTemp PostCreateAreaTemp([FromBody]SampleObject sampleObject)