locked
WebAPI: PostAsync with single or multiple query string does not work RRS feed

  • Question

  • User264732274 posted

    see my sample web api action which take one string type parameter.

    [HttpPost, Route("DeleteCustomer")]
    public HttpResponseMessage DeleteProduct(string customerID)
    {
        HttpResponseMessage response = null;
        Customer customer = repository.Get(customerID);
        if (customer == null)
        {
            var message = string.Format("No customer found by the ID {0}", customerID);
            HttpError err = new HttpError(message);
            response = Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, err);
            response.ReasonPhrase = message;
        }
        else
        {
            if(repository.Remove(customerID))
            {
                response = Request.CreateResponse<Customer>(HttpStatusCode.Created, customer);
                response.ReasonPhrase = "Customer successfully deleted";
            }
            else
            {
                var message = string.Format("Due to some error customer not removed");
                HttpError err = new HttpError(message);
                response = Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, err);
                response.ReasonPhrase = message;
            }
        }
    
    
        return response;
    }

    and calling like this below way with http client but not working and giving error Not found

    private void btnDelete_Click(object sender, EventArgs e)
    {
        var uri = new Uri(ConfigurationManager.AppSettings["baseAddress"] + "/api/customer/DeleteCustomer");
    
        var content = new FormUrlEncodedContent(new[] 
        {
            new KeyValuePair<string, string>("customerID", "CUS01")
        });
    
        try
        {
            using (var client = new HttpClient())
            {
                using (var response = client.PostAsync(uri, content).Result)
                {
                    if (response.IsSuccessStatusCode)
                    {
                        MessageBox.Show(response.ReasonPhrase);
                    }
                    else
                    {
                        Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
                        var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content.ReadAsStringAsync().Result);
                        MessageBox.Show(dict["Message"]);
                    }
                }
            }
        }
        catch (HttpRequestException ex)
        {
            // catch any exception here
        }            
    
    }
    

    some one please see my code and tell me where i made the mistake in calling code ? thanks

    Thursday, September 1, 2016 1:17 PM

Answers

  • User36583972 posted

    Hi   sudip_inn,

    If you want to use FormUrlEncodedContent, you should change your Web API code like the below.

    FormUrlEncodedController:

      public class FormUrlEncodedController : ApiController
        {
            [AllowAnonymous]
            [HttpPost()]
            public HttpResponseMessage TestFormUrlEncoded()
            {
                if (!IsFormUrlEncodedContent(this.Request.Content))
                {
                    return this.Request.CreateResponse(HttpStatusCode.BadRequest);
                }
                // Read content as a collection of key value pairs
                foreach (var parameter in ReadAsFormUrlEncodedContentAsync(this.Request.Content).Result)
                {
                    var key = parameter.Key;
                    var value = parameter.Value;
    
                    if (!String.IsNullOrEmpty(key))
                    {
                       
                    }
                }
                return this.Request.CreateResponse(HttpStatusCode.OK);
            }
    
          
            public static bool IsFormUrlEncodedContent(HttpContent content)
            {
                if (content == null || content.Headers == null)
                {
                    return false;
                }
    
                return String.Equals(
                    content.Headers.ContentType.MediaType,
                    FormUrlEncodedMediaTypeFormatter.DefaultMediaType.MediaType,
                    StringComparison.OrdinalIgnoreCase
                );
            }
    
          
            public static Task<IEnumerable<KeyValuePair<string, string>>> ReadAsFormUrlEncodedContentAsync(HttpContent content)
            {
                return ReadAsFormUrlEncodedContentAsync(content, CancellationToken.None);
            }
    
            public static Task<IEnumerable<KeyValuePair<string, string>>> ReadAsFormUrlEncodedContentAsync(HttpContent content, CancellationToken cancellationToken)
            {
                return Task.Factory.StartNew<IEnumerable<KeyValuePair<string, string>>>(
                    (object state) =>
                    {
                        var result = new List<KeyValuePair<string, string>>();
    
                        var httpContent = state as HttpContent;
    
                        if (httpContent != null)
                        {
                            var encoding = Encoding.UTF8;
                            var charSet = httpContent.Headers.ContentType.CharSet;
    
                            if (!String.IsNullOrEmpty(charSet))
                            {
                                try
                                {
                                    encoding = Encoding.GetEncoding(charSet);
                                }
                                catch (ArgumentException)
                                {
                                    encoding = Encoding.UTF8;
                                }
                            }
    
                            NameValueCollection parameters = null;
    
                            using (var reader = new StreamReader(httpContent.ReadAsStreamAsync().Result, encoding))
                            {
                                parameters = HttpUtility.ParseQueryString(reader.ReadToEnd(), encoding);
                            }
    
                            if (parameters != null)
                            {
                                foreach (var key in parameters.AllKeys)
                                {
                                    result.Add(
                                        new KeyValuePair<string, string>(key, parameters[key])
                                    );
                                }
                            }
                        }
    
                        return result;
                    },
                    content,
                    cancellationToken
                );
            }
    
    
        }
    

    Client:

             using (var client = new HttpClient())
                {
                    var baseUrl = Request.Url.GetLeftPart(UriPartial.Authority);
                    var uri = new Uri(baseUrl);            
                    client.BaseAddress = uri;             
                    var values = new List<KeyValuePair<string, string>>();
                    values.Add(new KeyValuePair<string, string>("customerID", "CUS01"));
                    // Send session data via POST using form-url-encoded content
                    using (var content = new FormUrlEncodedContent(values))
                    {
                        using (var response = client.PostAsync("/api/FormUrlEncoded", content).Result)
                        {
                            Console.WriteLine(response.StatusCode);
                        }
                    }
                }

    Note: I remember that I have provided many ways for you, please choose a suitable method.

    Best Regards,

    Yohann Lu

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, September 2, 2016 4:45 AM

All replies

  • User1881638666 posted

    Hi stupid_inn,

    Based on your request uri,

    var uri = new Uri(ConfigurationManager.AppSettings["baseAddress"] + "/api/customer/DeleteCustomer");

    Not Found - 404 mean the requested resource is not found.

    What is the name of the controller class. 

    If you have not used the RoutePrefix attribute on the controller class, class should be 'CustomerController'.

    If you have specified RoutePrefix attribute, that should be considered.

    And what is the default route added in the WebApiConfig.cs file?

    Thanks & Regards,

    Wenushka

    Thursday, September 1, 2016 2:51 PM
  • User36583972 posted

    Hi   sudip_inn,

    If you want to use FormUrlEncodedContent, you should change your Web API code like the below.

    FormUrlEncodedController:

      public class FormUrlEncodedController : ApiController
        {
            [AllowAnonymous]
            [HttpPost()]
            public HttpResponseMessage TestFormUrlEncoded()
            {
                if (!IsFormUrlEncodedContent(this.Request.Content))
                {
                    return this.Request.CreateResponse(HttpStatusCode.BadRequest);
                }
                // Read content as a collection of key value pairs
                foreach (var parameter in ReadAsFormUrlEncodedContentAsync(this.Request.Content).Result)
                {
                    var key = parameter.Key;
                    var value = parameter.Value;
    
                    if (!String.IsNullOrEmpty(key))
                    {
                       
                    }
                }
                return this.Request.CreateResponse(HttpStatusCode.OK);
            }
    
          
            public static bool IsFormUrlEncodedContent(HttpContent content)
            {
                if (content == null || content.Headers == null)
                {
                    return false;
                }
    
                return String.Equals(
                    content.Headers.ContentType.MediaType,
                    FormUrlEncodedMediaTypeFormatter.DefaultMediaType.MediaType,
                    StringComparison.OrdinalIgnoreCase
                );
            }
    
          
            public static Task<IEnumerable<KeyValuePair<string, string>>> ReadAsFormUrlEncodedContentAsync(HttpContent content)
            {
                return ReadAsFormUrlEncodedContentAsync(content, CancellationToken.None);
            }
    
            public static Task<IEnumerable<KeyValuePair<string, string>>> ReadAsFormUrlEncodedContentAsync(HttpContent content, CancellationToken cancellationToken)
            {
                return Task.Factory.StartNew<IEnumerable<KeyValuePair<string, string>>>(
                    (object state) =>
                    {
                        var result = new List<KeyValuePair<string, string>>();
    
                        var httpContent = state as HttpContent;
    
                        if (httpContent != null)
                        {
                            var encoding = Encoding.UTF8;
                            var charSet = httpContent.Headers.ContentType.CharSet;
    
                            if (!String.IsNullOrEmpty(charSet))
                            {
                                try
                                {
                                    encoding = Encoding.GetEncoding(charSet);
                                }
                                catch (ArgumentException)
                                {
                                    encoding = Encoding.UTF8;
                                }
                            }
    
                            NameValueCollection parameters = null;
    
                            using (var reader = new StreamReader(httpContent.ReadAsStreamAsync().Result, encoding))
                            {
                                parameters = HttpUtility.ParseQueryString(reader.ReadToEnd(), encoding);
                            }
    
                            if (parameters != null)
                            {
                                foreach (var key in parameters.AllKeys)
                                {
                                    result.Add(
                                        new KeyValuePair<string, string>(key, parameters[key])
                                    );
                                }
                            }
                        }
    
                        return result;
                    },
                    content,
                    cancellationToken
                );
            }
    
    
        }
    

    Client:

             using (var client = new HttpClient())
                {
                    var baseUrl = Request.Url.GetLeftPart(UriPartial.Authority);
                    var uri = new Uri(baseUrl);            
                    client.BaseAddress = uri;             
                    var values = new List<KeyValuePair<string, string>>();
                    values.Add(new KeyValuePair<string, string>("customerID", "CUS01"));
                    // Send session data via POST using form-url-encoded content
                    using (var content = new FormUrlEncodedContent(values))
                    {
                        using (var response = client.PostAsync("/api/FormUrlEncoded", content).Result)
                        {
                            Console.WriteLine(response.StatusCode);
                        }
                    }
                }

    Note: I remember that I have provided many ways for you, please choose a suitable method.

    Best Regards,

    Yohann Lu

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, September 2, 2016 4:45 AM
  • User264732274 posted

    @Yohann you wrote so many code for web api action side just to use FormUrlEncodedContent at client side...why?

    please share the knowledge.

    Friday, September 2, 2016 9:37 AM