public HttpResponseMessage Put(string id, [FromBody]string value)
{
}
The trouble is, while they'll happily build and deploy they don't actually work in practice!
Why?
Because the [FromBody] attribute tells Web API to stream the HTTP body into the variable it's about to create. The default variable is "value" and is of type System.String. And Web API has no way to stream any HTTP content types into a string. To help further, some content types will throw an error saying no MediaTypeFormatter is present while other content types will simply process the body and send NULL into the variable.
The trick is to create a new MediaTypeFormatter which recognises the content type text/plain and streams it into a string. Create a new class in your project and add the following text...
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace RESTfulServices.Helpers
{
public class TextMediaTypeFormatter : MediaTypeFormatter
{
public TextMediaTypeFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var taskCompletionSource = new TaskCompletionSource<object>();
try
{
var memoryStream = new MemoryStream();
readStream.CopyTo(memoryStream);
var s = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
taskCompletionSource.SetResult(s);
}
catch (Exception e)
{
taskCompletionSource.SetException(e);
}
return taskCompletionSource.Task;
}
public override bool CanReadType(Type type)
{
return type == typeof(string);
}
public override bool CanWriteType(Type type)
{
return false;
}
}
}
Now you make this new formatter available to your API by adding the following line to the bottom of your Global.asax file...
GlobalConfiguration.Configuration.Formatters.Insert(0, new RESTfulServices.Helpers.TextMediaTypeFormatter());
All that's left to do is to send your HTTP message with the following header information...
Content-Type: text/plain
This will load the entire body into your "value" string variable, ready for you to parse as appropriate.
(Thanks to https://myadventuresincoding.wordpress.com/2012/06/19/c-supporting-textplain-in-an-mvc-4-rc-web-api-application/ for saving my vacation!)