2012-07-20 16 views
107

Necesito obtener una respuesta en texto sin formato desde un controlador ASP.NET Web API.¿Hay alguna manera de forzar a ASP.NET Web API a que devuelva texto sin formato?

He intentado hacer una solicitud con Accept: text/plain pero no parece hacer el truco. Además, la solicitud es externa y está fuera de mi control. Lo que lograría es imitar la antigua forma de ASP.NET:

context.Response.ContentType = "text/plain"; 
context.Response.Write("some text); 

¿Alguna idea?

EDITAR, solución: Sobre la base de la respuesta de Aliostad, he añadido el formateador WebAPIContrib texto, inicializado en el Application_Start:

config.Formatters.Add(new PlainTextFormatter()); 

y mi controlador terminó algo como:

[HttpGet, HttpPost] 
public HttpResponseMessage GetPlainText() 
{ 
    return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, "Test data", "text/plain"); 
} 

Respuesta

192

Hmmm ... Creo que no es necesario crear un formateador personalizado para hacer este trabajo. En su lugar, devuelva el contenido como este:

[HttpGet] 
    public HttpResponseMessage HelloWorld() 
    { 
     string result = "Hello world! Time is: " + DateTime.Now; 
     var resp = new HttpResponseMessage(HttpStatusCode.OK); 
     resp.Content = new StringContent(result, System.Text.Encoding.UTF8, "text/plain"); 
     return resp; 
    } 

Esto funciona para mí sin utilizar un formateador personalizado.

Si explícitamente desea crear resultados y anular la negociación de contenido predeterminado basada en los encabezados Aceptar, no querrá usar Request.CreateResponse() porque fuerza el tipo mime.

En lugar de crear explícitamente un nuevo HttpResponseMessage y asignar el contenido manualmente. El ejemplo anterior usa StringContent pero hay bastantes otras clases de contenido disponibles para devolver datos de varios tipos/estructuras de datos .NET.

+1

Esta es, de hecho, la solución que busqué porque mi API devolvería objetos JSON al 99% de todos los métodos, solo unos pocos (muy pocos) métodos necesitarían respuestas de cadenas simples (y para muchos de esos uso un MemoryStream para devolver datos directamente en la respuesta, por lo que no fue un problema.) Solo en 2 o 3 métodos devolví una cadena .NET, y se devolvió como una cadena JSON. Su respuesta, en mi humilde opinión, es la respuesta KISS para este problema (aunque no es 100% DRY, pero acabo de escribir un método de extensión para hacer eso ... :-) ¡Bien!) StringContent es muy bueno. Gracias. – Loudenvier

+0

Hay una serie de clases XXXContent personalizadas para crear tipos específicos de contenido que hacen que este tipo de cosas sean bastante sencillas. –

+0

Veo la respuesta correcta con este enfoque. Sin embargo, HttpContext.Current es nulo ahora. Alguna idea sobre esto? –

6

Cuando Aceptar: texto/normal no funciona, entonces no hay un formateador registrado para los tipos de texto mimo.

Puede asegurarse de que no hay formateadores para el tipo de mime especificado al obtener una lista de todos los formateadores compatibles de la configuración del servicio.

Crea un formateador de tipo de medio muy sencillo que admita tipos de texto mime.

http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters

+0

gustaría poder aceptar su respuesta, así, la respuesta aceptada me ahorró la molestia de escribir mi propio formateador. +1 al menos. –

12
  • Por favor, tenga cuidado de no utilizar contexto en el API Web ASP.NET o que tarde o temprano se arrepentirá. La naturaleza asincrónica de ASP.NET Web API hace que usar HttpContext.Current sea una responsabilidad.
  • Utilice un formateador de texto sin formato y agréguelo a sus formateadores. Hay docenas de ellos alrededor. Incluso podrías escribir el tuyo fácilmente. WebApiContrib tiene uno.
  • Puede forzar estableciendo el encabezado de tipo de contenido en httpResponseMessage.Headers en text/plain en su controlador siempre que haya registrado el formateador de texto sin formato.
+0

No se preocupe, ni impliqué ni tenía la intención de utilizar el objeto HttpContext, simplemente lo agregué para ilustrar cómo se haría en el clásico ASP.NET –

+0

Bueno, hoy en día, ya he hecho referencia a WebAPIContrib, a veces es simple. –

+0

@Magnus Sure. De hecho, cambié la redacción después de leer lo que había escrito. Pero leer otra respuesta me hizo enfatizar ese primer punto. – Aliostad

11

Si solo está buscando un formateador de texto plano simple sin agregar dependencias adicionales, esto debería ser el truco.

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

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

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

    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext) 
    { 
     return Task.Factory.StartNew(() => { 
      StreamWriter writer = new StreamWriter(stream); 
      writer.Write(value); 
      writer.Flush(); 
     }); 
    } 

    public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger) 
    { 
     return Task.Factory.StartNew(() => { 
      StreamReader reader = new StreamReader(stream); 
      return (object)reader.ReadToEnd(); 
     }); 
    } 
} 

No olvide añadirlo a su configuración global Web API.

config.Formatters.Add(new TextPlainFormatter()); 

Ahora usted puede pasar objetos de cadena a

this.Request.CreateResponse(HttpStatusCode.OK, "some text", "text/plain"); 
0

Una extensión como la siguiente se puede reducir el número de líneas y embellecer su código:

public static class CommonExtensions 
{ 
    public static HttpResponseMessage ToHttpResponseMessage(this string str) 
    { 
     var resp = new HttpResponseMessage(HttpStatusCode.OK) 
     { 
      Content = new StringContent(str, System.Text.Encoding.UTF8, "text/plain") 
     }; 

     return resp; 
    } 
} 


Ahora puede consuma la extensión definida en su Web API:

public class HomeController : ApiController 
{ 
    [System.Web.Http.HttpGet] 
    public HttpResponseMessage Index() 
    { 
     return "Salam".ToHttpResponseMessage(); 
    } 
} 


Al encaminar {DOMAIN}/api/Home/Index se puede ver el siguiente texto:

MyPlainTextResponse

Cuestiones relacionadas