Subscribe to Martyr2's Programming Underground        RSS Feed
-----

Solving A Null Value When Posting A Simple String To A .NET Web API

Icon Leave Comment
The Problem: Many programmers, when creating a .NET Web API project, typically run into a situation where they want to post a simple x-www-form-urlencoded string datatype to an endpoint. They create the POST endpoint and attempt to post a string body to it only to find out that the value passed from the body is null. It can certainly be a frustrating endeavor to find a solution to this. After perhaps a few minutes of Google diving you run across an answer that mentions the use of an equal sign before the body string to get it to work. But then of course you have to account for this equal sign and it can just get messy. In this post we will talk about a few alternative solutions that we found to work out nicely which takes a different slant on the problem.

Let's See What We Are Talking About

Below is the typical POST endpoint you find in a default .NET C# Web API project. Here the parameter "value" is marked as being from the body of the post using an attribute. So if you send a POST request to the API, this endpoint will pick it up and its body content will be made available. But you will often find out that if the request is from a URL encoded simple string type, you will have a value of null show up here. That is the problem.

public void Post([FromBody]string value)
{
   // Do stuff with value unless it is form URL encoded which "value" may be null.
}



The Equal Sign Trick

If you look around the web you will see many developers telling others that in their POST endpoint to prefix the parameter with the [FromBody] attribute (like we show above) and then when they go to post the data add an equal sign before it. I am still not sure why Microsoft decided that in order for the endpoint to correctly recognize the form URL encoded data it must have this equal sign to start. This solution will work, but one problem... what if you can't control the data being posted? I ran into a situation like this with a webhook situation from a service called Chargify.

So for instance if we attempt to post "id=3&myvar=1&myothervar=2" then the parameter "value" should contain this string. But it won't unless you attach an equal sign onto the front when posted. That makes it "=id=3&myvar=1&myothervar=2". Again, this if fine if you control what is posted to the endpoint (like you are posting to it from an AJAX call on your page).

Another Solution... a Complex Type

Another idea bantered around is that if you use a more complex parameter type (not a string) then you can also get at the individual values. Which in fact is a really good solution most of the time because you know what is passed and will want to access each value. You can implement this solution using something like this...

public void Post(MyCustomType value)
{
   // Do stuff with value which is a MyCustomType object
   string id = value.id;
}

// Define your type. Take notice that its properties match parameters being passed in.
public class MyCustomType {
   public string id { get; set; }
   public string myvar { get; set; }
   public string myothervar { get; set; }
}




But the limitations here is that you also have to know what is going to be in the request. If there are a lot of values passed, creating a custom type to handle it all will be quite tedious. In the situation of Chargify, a typical webhook payload can have nearly 50-60 values easy. I am not sure I want to create a 50 property object type.


A Better More Flexible Solution... the Request

Another option which I think works out nicely and provides the developer the ultimate flexibility is through the use of the actual request object. Instead of just using what has been given to you, if you just tweak the signature a bit and change the parameter to a HttpRequestMessage you can not only get access to the raw string object from the body, but also access to things like the headers. This extra advantage of accessing the headers may come in handy to read in special header keys that may help you process the body. In our case of Chargify, they send along a header which has a HMAC SHA-256 encrypted value for us to verify the authenticity of the POST data. Worked out beautifully! Below is an example of how this works...


[HttpPost]
public void Post(HttpRequestMessage request)
{
   // Now pull out the body from the request (in our case "body" will be set to "id=3&myvar=1&myothervar=2")
   string body = request.Content.ReadAsStringAsync().Result;

   // Heck let's get the headers as well...
   var headers = request.Headers;
}



Now of course for this to work make sure you include a System.Net.Http using statement at the top of your document. But once you have access to the body you can split it or process it however you want. We found that if we split this value and load it up into a dictionary of keys and their values, it worked out tremendously well in that we could then use such a dictionary to quickly find a value (if it was included) and do great things like counting parameters, handling empty values and iterating through parameters.

Conclusion

We hope that you find this post really useful in handling the crazy issue of posting simple strings to a .NET Web API post endpoint. I know that when I ran into this it was a bit confusing since the way the project it setup from the beginning it simply won't be adequate for a standard form URL encoded posting scenario without a little trickery. To combat the problem we presented three solutions including prefixing the string with an equal sign and using the [FromBody] attribute (which works if you control what is posted), wrapping the parameter in a complex type to help with mapping known parameters to properties (if you are interested in certain parameters and know what they are) and lastly accessing the request directly and pulling out the data you need. All of these solutions work for the given scenario but we recommend the last solution which offers the most flexibility and advantages to other information about the post including headers. Thank you for reading! :)

Hey, thanks for reading! If you want to read more about topics like this or would like to get started with your own project, check out my blog at http://www.coderslexicon.com! There you can get my ebooks (like The Programmer Idea Book) and soup up your programming skills, find out great resource books and get free code in a variety of languages. Check it out!

0 Comments On This Entry