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'.
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());
Since Web API doesn't have out of box formatter for handling text/plain, some options:
Modify your action to have no parameters... reason is having parameters triggers request body de-serialization. Now you can read the request content explicitly by doing await Request.Content.ReadAsStringAsync()
to get the string
Write a custom MediaTypeFormatter to handle 'text/plain'... it's actually simple to write in this case and you could keep the parameters on the action.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With