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

Related searches

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());

Accepting Raw Request Body Content in ASP.NET Core API , So in this post I'll look at posting raw data – not JSON or XML, but just plain text or binary data – to an Web API controller and picking up that� Now I need to post a simple text, not wrapped in any xml or json. When we create a new API Controller, the post is defined like this. public void Post(string value) However, there is no way we can post plain text to it by deffining Content-Type: text/plain; charset=utf-8. The method receives the call, but the value is always empty.

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 de-serialization. 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'... it's actually simple to write in this case and you could keep the parameters on the action.

Accepting Raw Request Body Content with ASP.NET Web API, By default, Web API tries to get simple parameter types from the request URI, and complex types from the message body. Reply � Pierre Lebel. HTML forms use either GET or POST to send data to the server. The method attribute of the form element gives the HTTP method: <form action="api/values" method="post"> The default method is GET. If the form uses GET, the form data is encoded in the URI as a query string. If the form uses POST, the form data is placed in the request body.

Purified version using of gwenzek's formatter employing async/await:

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

    public override bool CanReadType(Type type) =>
        type == typeof(string);

    public override bool CanWriteType(Type type) =>
        type == typeof(string);

    public override async Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
    {
        var streamReader = new StreamReader(readStream);
        return await streamReader.ReadToEndAsync();
    }

    public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
    {
        var streamReader = new StreamWriter(writeStream);
        await streamReader.WriteAsync((string) value);
    }
}

Please note I intentionally do not dispose StreamReader/StreamWriter, as this will dispose underlying streams and break Web Api flow.

To make use of it, register while building HttpConfiguration:

protected HttpConfiguration CreateHttpConfiguration()
{
    HttpConfiguration httpConfiguration = new HttpConfiguration();
    ...
    httpConfiguration.Formatters.Add(new PlainTextFormatter());
    ...
    return httpConfiguration;
}

How to post text/plain, I have an ASP.NET Web API endpoint with controller action defined as follows : [ HttpPost] public HttpResponseMessage Post([FromBody]� - [Instructor] To create a new entry,…either an expense or an income,…we are going to create an API endpoint…which is going to handle these kind of requests.…So, for example, when the user posts or sends…some data to the back-end, our API endpoint…is going to check for data and then save it in our database.…So, let's get started.…In your visual studio, go to the controllers

In ASP.NET Core 2.0 you simply do the following :-

using (var reader = new StreamReader(Request.Body))
{
      string plainText= reader.ReadToEnd();

      // Do something else

      return Ok(plainText);
}

how to post plain text to ASP.NET Web API endpoint, The only missing piece is that your API doesn't know what to do when a will get you a basic implementation for dealing with plain text and how to add it to public async Task<IActionResult> Post([FromBody] string content). public class MyApiController : ApiController { public async void Post([FromBody]string value) { await Method(value) } } I have a Test Client, this program send 1000 post requests to my Web API to the same time. It is assumed that my controller should process 10,000 requests to the same time.

In some situations it might be simpler to let the JsonMediaTypeFormatter let do the work:

var formatter = GlobalConfiguration.Configuration.Formatters.Where(f=>f is System.Net.Http.Formatting.JsonMediaTypeFormatter).FirstOrDefault();
if (!formatter.SupportedMediaTypes.Any( mt => mt.MediaType == "text/plain" ))
    formatter.SupportedMediaTypes.Add( new MediaTypeHeaderValue( "text/plain" ) );

Processing text/plain in ASP.NET Web API – Hi, My Name is Ben, I would like to send the following XML document to my Web Api 2 controller; however, the [FromBody] parameter is always null. Here is the request XML body: &lt;razorInbound server="

I have read the following: Asp.net Core Post parameter is always null asp.net webapi 2 post parameter is always null web-api POST body object always null Web Api Parameter always null My endpoint

One ASP.NET Web API related question that frequently comes up frequently is how to capture the raw request content to a simple parameter on a controller method. Turns out that's not as easy as it should be. In this post I discuss how to natively capture the raw request content and then create a [NakedBody] attribute that makes it easy capture the raw content in a string or byte[] parameter.

Custom Date Deserialization in ASP.NET Core Web API This weekend I came across some oddly formatted datetimes while playing around with Twitter webhooks. When it came time to test my API endpoint to receive the Twitter event, I received a 400 response with a message indicating that one of the date fields the JSON payload could not be

Comments
  • don't you want your "text" parameter to be of the type string then?
  • yes i thought of that idea too but it doesn't help much ( please see my revised question )
  • @BaltoStar I know your question is 8 month old but I faced the same problem. See my answer below.
  • Hi BaltoStar, could you mark @gzou's answer as the answer? That would help the community seeing it as the answer. Thks
  • Exactly what I need! Great stuff!
  • Great! This is an awesome solution !
  • I wonder why not simplify ReadFromStreamAsync method to just: return await new StreamReader(readStream).ReadToEndAsync();
  • My MediaTypeFormatter does not have the Cancellation Token parameter on WriteToStreamAsync. Works when I removed that argument.
  • Thanks for the response Kiran. Actually, my action signature has additional [FromUri] parameters, which I left out to keep my question simple. So I guess this means I can't avoid implicit de-serialization of request body ? In which case I need to write a custom MediaTypeFormatter to handle 'text/plain' ....
  • request deserialization would only happen for the parameters which are normally considered to be read from body...examples: Explicitly [FromBody] decorated parameters, implicitly read from body(ex: complex types)...so my above answer only is for the ones meant to be read from the body...so you should be able to use FromUri parameters as usual...but in any case creating a custom formatter is the best approach as it fits well with Web API design..
  • Is it not dangerous to provide this formatter? text/plain is a valid enctype of a HTML form with post method. Be sure to add antiforgery token to prevent cross site request forgery.
  • What will disposing break specifically? I found that not disposing of them caused error when handling exceptions.
  • Simple and perfect!
  • Helped me out in 2020. It should not have been so difficult to find this answer. Thanks :)
  • If I do this and then set the body like this: resp.Content = new StringContent(outputString, Encoding.UTF8, "text\plain");, will it just output the string as-is (even if it is not JSON) with the text-plain content-type?