Esiste un modo per forzare l'API Web ASP.NET a restituire il testo normale?


125

Devo ottenere una risposta in chiaro da un controller API Web ASP.NET.

Ho provato a fare una richiesta con Accept: text/plainma non sembra fare il trucco. Inoltre, la richiesta è esterna e fuori dal mio controllo. Quello che vorrei realizzare è imitare il vecchio modo ASP.NET:

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

Qualche idea?

EDIT, soluzione : in base alla risposta di Aliostad, ho aggiunto il formattatore di testo WebAPIContrib , inizializzato in Application_Start:

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

e il mio controller ha finito per qualcosa del tipo:

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

Risposte:


231

Hmmm ... Non penso che tu abbia bisogno di creare un formatter personalizzato per farlo funzionare. Restituisci invece il contenuto in questo modo:

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

Questo funziona per me senza usare un formatter personalizzato.

Se desideri esplicitamente creare output e sovrascrivere la negoziazione del contenuto predefinita in base alle intestazioni Accept, non vorrai utilizzare Request.CreateResponse()perché forza il tipo mime.

Crea invece esplicitamente un nuovo HttpResponseMessagee assegna il contenuto manualmente. L'esempio precedente usa StringContentma ci sono alcune altre classi di contenuti disponibili per restituire dati da vari tipi / strutture di dati .NET.


1
Questa è in effetti la soluzione che ho scelto perché la mia API avrebbe restituito gli oggetti JSON al 99% di tutti i metodi, solo pochi (pochissimi) metodi avrebbero avuto bisogno di risposte in stringa (e per molti di quelli che uso un MemoryStream per restituire i dati direttamente nella risposta, quindi non è stato un problema.) Solo in 2 o 3 metodi ho restituito una stringa .NET, che veniva restituita come stringa JSON. La tua risposta, IMHO, è la risposta KISS per questo problema (anche se non è DRY al 100%, ma ho appena scritto un metodo di estensione per stringa per farlo ... :-) Bello!) StringContent è molto bello. Grazie.
Loudenvier,

Esistono diverse classi XXXContent personalizzate per creare tipi specifici di contenuti che rendono questo tipo di cose piuttosto semplice.
Rick Strahl,

Vedo la risposta corretta con questo approccio. Tuttavia, HttpContext.Current è null ora. Qualche idea su questo?
Nachiket Mehta,

@JavascriptEnthusiast - HttpContext.Current è nullo molto probabilmente perché sei un self-hosting o stai eseguendo lo stack OWin senza la pipeline System.Web. Non correlato a questa soluzione però.
Rick Strahl,

15

Se stai solo cercando un semplice formattatore di testo / testo senza aggiungere dipendenze aggiuntive, questo dovrebbe fare il trucco.

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

Non dimenticare di aggiungerlo alla tua configurazione API Web globale.

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

Ora puoi passare oggetti stringa a

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

12
  • Fare attenzione a non utilizzare il contesto nell'API Web ASP.NET o prima o poi ti dispiacerà. La natura asincrona dell'API Web ASP.NET rende l'utilizzo di HttpContext.Currentuna responsabilità.
  • Usa un formattatore di testo semplice e aggiungi ai tuoi formattatori. Ce ne sono dozzine in giro. Potresti anche scrivere il tuo facilmente. WebApiContrib ne ha uno.
  • È possibile forzarlo impostando l'intestazione del tipo di contenuto su httpResponseMessage.Headersa text/plainnel vostro controller a condizione di aver registrato semplice formattatore di testo.

Non preoccuparti, non ho implicato né intendevo usare l'oggetto HttpContext, l'ho appena aggiunto per illustrare come si farebbe nel classico ASP.NET
Magnus Johansson,

Bene, waddayknow, ho già fatto riferimento a WebAPIContrib, a volte è semplice.
Magnus Johansson,

@Magnus Certo. In effetti ho cambiato il testo dopo aver letto quello che avevo scritto. Ma leggere un'altra risposta mi ha fatto sottolineare questo primo punto.
Aliostad,

Stai dicendo di non usare HttpContext.Current, quali sono le alternative?
surya,

@spiderdevil sì, è assolutamente quello che sto dicendo. Non dovresti averne bisogno, passa direttamente richiesta / risposta / configurazione.
Aliostad,


6

Quando accetta: text / plain non funziona, quindi non esiste un formattatore registrato per i tipi di testo mime.

Puoi assicurarti che non ci siano formattatori per il tipo mime specificato ottenendo un elenco di tutti i formattatori supportati dalla configurazione del servizio.

Crea un formatter di tipo di supporto molto semplice che supporti i tipi mime di testo.

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


Vorrei poter accettare anche la tua risposta, la risposta accettata mi ha salvato il problema di scrivere il mio formatter. +1 almeno.
Magnus Johansson,

0

Un'estensione come la seguente può ridurre il numero di righe e abbellire il tuo codice:

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


Ora puoi utilizzare l'estensione definita nel tuo Web API:

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


Con il routing {DOMAIN}/api/Home/Indexpuoi vedere il seguente testo normale:

MyPlainTextResponse


Non sprecare lo spazio dei nomi di stringa con elementi non correlati alla stringa.
Rambalac,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.