Accepting Different Types of Request Body Content In ASP..Net Web API

nn
n
n

n

n
nnASP.Net Web API is designed to accept request body in variety of ways and in different formats, however it become a real problem when you dont know how to intercept some of the requests sent to your Web API.
n
nRecently I had a requirement to consume a third party API, they asked that I should send my request as a single Json string and also write my two endpoints to accept a single Json string. This sound simple initially but then I realized along the line that it was a bit technical.
nnn
nnnIn this article I will show you based on my experience how to intercept request in Web API.
n
nCreating an endpoint to create customer in Web API is as simple as creating an action like so:
n

     [Route("customers")]n        [HttpPost]n        public HttpResponseMessage PostCustomer([FromBody] Customer customer)n        {n  n                 //Do stuff with customer object herenn   //Return message n   return Request.CreateResponse(HttpStatusCode.Created, newn                        {message = "Some respose message"n                            error = false,n                            status = "created"n                        });n           n        }n

nAnd the customer class is as simple as this:
n

public class Customern    {n        public string customerName { get; set; }n        public string email { get; set; }n        public string address { get; set; }n        public string phone { get; set; }n    }n

n

n

n

n

n

n

n

n

n

n

n

n
n
nIf you try making a request to this endpoint in two ways from postman like the image above, everything wil be fine, if you also send request using HttpClient like we have below, there wont be any issue at all.
n
n

async Task PostCustomer()n        {n            var customer = new Customer()n            {n                customerName = "John Doe",n                address = "Some Address somewhere",n                email = "john@doe.com",n                phone = "777-0980-22"n            };nn            var client = HttpClientHelper.CreateClient("http://localhost:28349/api/v1/");n            var bodyKeyValues = new List>();nn            foreach (var property in customer.GetType().GetProperties())n            {n                if (property.GetValue(customer) != null)n                {n                    bodyKeyValues.Add(new KeyValuePair(property.Name, property.GetValue(customer).ToString()));n                }n            }n            var formContent = new FormUrlEncodedContent(bodyKeyValues);nn            var response = await client.PostAsync("customers", formContent);nn            var json = await response.Content.ReadAsStringAsync();nn            var jsonResult = JsonConvert.SerializeObject(json);n            n        }nn

n

nSending Complex Object to API

nIt is totally different when it is required to send some complex object to API.
nnn
nnnLet’s say we are required to send some list of orders along with a single customer to our API then we will need to have two more classes, one for product and the other will be a composite class named order for both customer and products. Let’s create those.
n

public class Ordern    {n        public Customer customer { get; set; }n        public List products { get; set; }n    }nn    public class Productn    {n        public string productName { get; set; }n        public decimal price { get; set; }n    }n

nLet’s modify the PostCustomer method to take our Order class like so:nn
n

[Route("orders")]n        [HttpPost]n        public HttpResponseMessage PostCustomer([FromBody] Order order)n        {n            n            return new HttpResponseMessage()n            {n                Content = new StringContent(JsonConvert.SerializeObject(order), Encoding.UTF8, "application/json"),n                StatusCode = HttpStatusCode.OKn            };n        }n   n

nThere are many ways to send request to this actionresult using HttpClient. BUT WHAT HAPPENED IF YOU ARE ASKED TO SEND THE REQUEST AS A JSON STRING?nnWell, when I was asked to send it as a string, I did something likenn
n

[Route("orders")]n        [HttpPost]n        public HttpResponseMessage PostCustomer([FromBody] string order)n        {n            //order was always null heren            return new HttpResponseMessage()n            {n                Content = new StringContent(JsonConvert.SerializeObject(order), Encoding.UTF8, "application/json"),n                StatusCode = HttpStatusCode.OKn            };n        }n   n

nMay be my request was not composed correctly, here is how I sent my request:nnn
n

async Task PostOrder()n        {n            var _order = new Order()n            {n                customer = new Customer()n                {n                    customerName = "John Doe",n                    address = "Some Address somewhere",n                    email = "john@doe.com",n                    phone = "777-0980-22"n                },n                products = new Listn                {n                    new Product()n                    {n                        price = 2000,n                        productName = "Laptop"n                    },n                    new Product()n                    {n                        productName = "Mouse",n                        price = 150n                    }n                },n            };nnn            var client = HttpClientHelper.CreateClient("http://localhost:28349/api/v1/");nn            var jsonObj = JsonConvert.SerializeObject(_order);n            var response = await client.PostAsync("orders", new StringContent(jsonObj, Encoding.UTF32, "application/json"));n            var json = await response.Content.ReadAsStringAsync();nn            var jsonResult = JsonConvert.SerializeObject(json);n           ;n        }n   n

nLooks like everything is fine with my request. But why am I still getting null in my API? The reason is as far as I know Web API framework tried to populate that order parameter, it uses a JsonMediaTypeFormatter. Internally its trying to do thisn
nnnnn

JsonConvert.DeserializeObject(order)n

nThis can only work if you are sending a string literal like ‘This is my request body’ but since this request is a Json string it will always be null.
n

nWhat is the solution?

nI resolved this issue by taking advantage of HTTP. I change my method and came up with this and it worked for me.
n

[Route("orders")]n        [HttpPost]n        public HttpResponseMessage PostCustomer(HttpRequestMessage request)n        {n           //Read the string from request streamn            var jsonString = await request.Content.ReadAsStringAsync();n            //Deserialize it to Order objectn            var order = JsonConvert.DeserializeObject(jsonString);nn//Do stuff with ordernn            return new HttpResponseMessage()n            {n                Content = new StringContent(JsonConvert.SerializeObject(order), Encoding.UTF8, "application/json"),n                StatusCode = HttpStatusCode.OKn            };n        }n   n

nI hope this helps.nnIf you have faced this issue as a developer, please let me know how it was resolved.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top