parameter net frombody example body asp text asp.net-web-api http-post content-type http-request

text - net - web api frombody parameters



cómo enviar texto sin formato al punto final de la API web ASP.NET? (5)

Tengo un punto final de la API web ASP.NET con la acción del controlador definida de la siguiente manera:

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

Si mi cuerpo de solicitud postal contiene texto sin formato (es decir, no debe interpretarse como json, xml o cualquier otro formato especial), entonces pensé que podría incluir el siguiente encabezado en mi solicitud:

Content-Type: text/plain

Sin embargo, recibo un error:

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

Si cambio la firma de mi método de acción del controlador a:

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

Aparece un mensaje de error ligeramente diferente:

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


Como la API web no tiene un formateador fuera de la caja para manejar texto / texto simple, algunas opciones:

  1. Modifique su acción para no tener parámetros ... razón por la que los parámetros desencadenan la deserialización del cuerpo de la solicitud. Ahora puede leer el contenido de la solicitud de forma explícita haciendo "aguardar Request.Content.ReadAsStringAsync ()" para obtener la cadena

  2. Escribir un formato de texto personalizado para manejar ''text / plain'' ... es realmente simple de escribir en este caso y puede mantener los parámetros en la acción.


De hecho, es una pena que la API web no tenga un MediaTypeFormatter para texto sin formato. Aquí está el que implementé. También se puede usar para publicar contenido.

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

Necesita "registrar" este formateador en su HttpConfig de la siguiente manera:

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


En ASP.NET Core 2.0 simplemente haz lo siguiente:

using (var reader = new StreamReader(Request.Body)) { string plainText= reader.ReadToEnd(); // Do something else return Ok(plainText); }


En algunas situaciones, puede ser más sencillo dejar que JsonMediaTypeFormatter haga el trabajo:

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


Versión purificada utilizando el formateador de gwenzek que emplea 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); } }

Tenga en cuenta que intencionalmente no desecho StreamReader / StreamWriter, ya que esto eliminará los flujos subyacentes y romperá el flujo de Api web.

Para hacer uso de él, regístrese mientras construye HttpConfiguration:

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