2012-07-20 15 views
107

Potrzebuję uzyskać odpowiedź z powrotem w postaci zwykłego tekstu z kontrolera ASP.NET Web API.Czy istnieje sposób na zmusić ASP.NET Web API do zwracania zwykłego tekstu?

Próbowałem zrobić prośbę wraz Accept: text/plain ale nie wydaje się, by rade. Ponadto żądanie jest zewnętrzne i nie podlega mojej kontroli. Co mogę osiągnąć, to naśladować stary sposób ASP.NET:

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

Wszelkie pomysły?

EDIT, rozwiązanie: podstawie odpowiedzi Aliostad za dodałem formater WebAPIContrib tekstową, zainicjowany go w Application_Start:

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

i mój kontroler skończyło się coś takiego:

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

Odpowiedz

192

Hmmm ... Nie sądzę, że trzeba utworzyć niestandardową formatowania do tej pracy. Zamiast tego należy zwrócić treść podobną do tej:

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

Działa to dla mnie bez użycia niestandardowego formatyzatora.

Jeśli jawnie chcesz utworzyć dane wyjściowe i zastąpić domyślną negocjację treści na podstawie nagłówków Accept, nie będziesz chciał używać Request.CreateResponse(), ponieważ wymusza to typ MIME.

Zamiast tego należy jawnie utworzyć nowy HttpResponseMessage i ręcznie przypisać zawartość. Powyższy przykład używa StringContent, ale istnieje sporo innych klas treści dostępnych do zwracania danych z różnych typów/struktur danych .NET.

+1

Jest to w rzeczywistości rozwiązanie, do którego dążyłem, ponieważ moje API zwróci obiekty JSON do 99% wszystkich metod, tylko kilka (bardzo mało) metod będzie potrzebować zwykłych odpowiedzi łańcuchowych (a dla wielu z nich używam obiektu MemoryStream do zwrócenia dane bezpośrednio w odpowiedzi, więc nie było problemu.) Tylko w 2 lub 3 metodach zwróciłem ciąg .NET, który był zwracany jako ciąg JSON. Twoja odpowiedź, IMHO, jest odpowiedzią KISS na ten problem (chociaż nie jest to 100% DRY, ale właśnie napisałem metodę rozszerzenia do napisu, żeby to zrobić ... :-) Nice!) StringContent jest bardzo miły. Dziękuję Ci. – Loudenvier

+0

Istnieje wiele niestandardowych klas XXXContent do tworzenia określonych typów treści, które sprawiają, że tego typu rzeczy są całkiem proste. –

+0

Widzę prawidłową odpowiedź z tym podejściem. Jednak HttpContext.Current ma teraz wartość null. Jakieś pomysły na ten temat? –

6

Gdy Accept: text/plain nie działa, to nie ma zarejestrowanego formatera dla typów MIME tekstowych.

można zapewnić, że nie ma formatujących dla określonego typu MIME przez uzyskanie listę wszystkich obsługiwanych formatujących od konfiguracji usług.

stworzyć bardzo prosty typ nośnika formatowania, które obsługują typy MIME text.

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

+0

Życzenie mogłem zaakceptowane odpowiedź, jak dobrze, zaakceptowane odpowiedź zaoszczędziło mi kłopotów z pisania mojego własny formater. Przynajmniej +1. –

12
  • Należy uważać, aby nie używać kontekst w ASP.NET Web API lub będzie prędzej czy później będzie przykro. Asynchroniczny charakter interfejsu ASP.NET Web API powoduje, że korzystanie z usługi HttpContext.Current jest odpowiedzialne.
  • Użyj formatera tekstowego i dodaj do swoich formaterów. Jest ich kilkanaście. Możesz nawet napisać swoje łatwo. WebApiContrib ma jeden.
  • można wymusić przez ustawienie typu nagłówek treści na httpResponseMessage.Headers do text/plain w kontrolerze pod warunkiem, że zostały zarejestrowane zwykły formatowania tekstu.
+0

Nie martw się, nie sugerowałem ani nie zamierzałem używać obiektu HttpContext, właśnie dodałem go, aby zilustrować, jak można to zrobić w klasycznym ASP.NET –

+0

No cóż, już wiem, już miałem odwołanie do WebAPIContrib, czasami jest to proste. –

+0

@Magnus Sure. Właściwie zmieniłem sformułowanie po przeczytaniu tego, co napisałem. Ale przeczytanie innej odpowiedzi sprawiło, że podkreśliłem tę pierwszą kwestię. – Aliostad

11

Jeśli szukasz tylko prostego formatyzatora tekstu/tekstu bez dodawania dodatkowych zależności, powinno to wystarczyć.

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

Nie zapomnij dodać go do globalnego Web API config.

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

Teraz można przekazać obiekty string do

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

Rozszerzenie jak poniżej można zmniejszyć liczbę linii i upiększyć swój kod:

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


Teraz możesz zużyj zdefiniowane rozszerzenie w swoim Web API:

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


Przesyłając {DOMAIN}/api/Home/Index można zobaczyć następujące zwykły tekst:

MyPlainTextResponse

Powiązane problemy