how to post plain text to ASP.NET Web API endpoint?

[Originally Posted By]: http://stackoverflow.com/questions/25631970/how-to-post-plain-text-to-asp-net-web-api-endpoint/29914360#29914360

I have an ASP.NET Web API endpoint with controller action defined as follows :

[HttpPost]
public HttpResponseMessage Post([FromBody] object text)

If my post request body contains plain text ( i.e. should not be interpreted as json, xml, or any other special format ), then I thought I could just include following header to my request :

Content-Type: text/plain

However, I receive error :

No MediaTypeFormatter is available to read an object of type 'Object' from content with media type 'text/plain'.

If I change my controller action method signature to :

[HttpPost]
public HttpResponseMessage Post([FromBody] string text)

I get a slightly different error message :

No MediaTypeFormatter is available to read an object of type 'String' from content with media type 'text/plain'.
shareedit

Actually it’s a shame that web API doesn’t have a MediaTypeFormatter for plain text. Here is the one I implemented. It can also be used to Post content.

public class TextMediaTypeFormatter : MediaTypeFormatter
{
    public TextMediaTypeFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
    }

    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 Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, System.Net.TransportContext transportContext, System.Threading.CancellationToken cancellationToken)
    {
        var buff = System.Text.Encoding.UTF8.GetBytes(value.ToString());
        return writeStream.WriteAsync(buff, 0, buff.Length, cancellationToken);
    }

    public override bool CanReadType(Type type)
    {
        return type == typeof(string);
    }

    public override bool CanWriteType(Type type)
    {
        return type == typeof(string);
    }
}
 

You need to “register” this formatter in your HttpConfig by something like that:

config.Formatters.Insert(0, new TextMediaTypeFormatter());
shareedit

Since web API doesn’t have out of box formatter for handling text/plain, some options:

  1. Modify your action to have no parameters…reason is having parameters triggers request body deserialization. Now you can read the request content explicitly by doing “await Request.Content.ReadAsStringAsync()” to get the string
  2. Write a custom mediatypeformatter to handle ‘text/plain’…its actually simple to write in this case and you could keep the parameters on the action.
shareedit
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s