Umieścić zawartość w obiekcie HttpResponseMessage?

180

Kilka miesięcy temu Microsoft zdecydował się zmienić klasę HttpResponseMessage. Wcześniej można było po prostu przekazać typ danych do konstruktora, a następnie zwrócić komunikat z tymi danymi, ale już nie.

Teraz musisz użyć właściwości Content, aby ustawić treść wiadomości. Problem polega na tym, że jest to typ HttpContent i nie mogę znaleźć sposobu na przekonwertowanie ciągu, na przykład, na HttpContent.

Czy ktoś wie, jak sobie z tym poradzić? Wielkie dzięki.

pretor
źródło

Odpowiedzi:

216

W szczególności w przypadku ciągu znaków najszybszym sposobem jest użycie konstruktora StringContent

response.Content = new StringContent("Your response text");

Istnieje wiele dodatkowych potomków klasy HttpContent dla innych typowych scenariuszy.

Jim O'Neil
źródło
Zobacz mój post poniżej, aby utworzyć własne pochodne typy StringContent (np. JSON, XML itp.).
bytedev
135

Powinieneś utworzyć odpowiedź za pomocą Request.CreateResponse :

HttpResponseMessage response =  Request.CreateResponse(HttpStatusCode.BadRequest, "Error message");

Możesz przekazywać obiekty, a nie tylko ciągi znaków, do CreateResponse i serializuje je na podstawie nagłówka Accept żądania. Dzięki temu nie musisz ręcznie wybierać programu formatującego.

Florin Dumitrescu
źródło
Automatycznie działa z typami zawartości, więc możesz zrobić xml / json bez dodatkowego kodu
Myślę, że bardziej poprawne byłoby wywołanie, CreateErrorResponse()jeśli odpowiedź jest błędem, tak jak w przykładzie tej odpowiedzi. Wewnątrz mojego haczyka, którego używam: this.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "message", exception); I to jest poprawna odpowiedź, jeśli w ogóle martwisz się o uszanowanie nagłówka Accept dzwoniącego, bez dodatkowych szyderstw. (I używasz WebAPI)
JMD
2
@FlorinDumitrescu Chodziło mu o to, że działa to TYLKO w przypadku dziedziczenia ApiController. Jeśli Controllerzamiast tego dziedziczysz tylko dziedziczenie , to nie działa i musisz to stworzyć samodzielnie: HttpResponseMessage msg = new HttpResponseMessage(); msg.Content = new StringContent("hi"); msg.StatusCode = HttpStatusCode.OK;
vapcguy
64

Najwyraźniej nowy sposób, aby to zrobić, jest szczegółowo opisany tutaj:

http://aspnetwebstack.codeplex.com/discussions/350492

Cytując Henrika,

HttpResponseMessage response = new HttpResponseMessage();

response.Content = new ObjectContent<T>(T, myFormatter, "application/some-format");

Zasadniczo należy więc utworzyć typ ObjectContent, który najwyraźniej może zostać zwrócony jako obiekt HttpContent.

pretor
źródło
31
co to jest myFormatter
Greg Z.
1
@ user1760329 będzie to new JsonMediaTypeFormatter();lub podobne, w zależności od formatu
Jan
1
ObjectContentnie został znaleziony, używając WCF
Medet Tleukabiluly
2
Nie zakwalifikowałbym tego jako „nowego sposobu na zrobienie tego” - ten artykuł, do którego się odnosisz, wymienia go jako alternatywę w przypadku, gdy chcesz mieć „pełną kontrolę nad formatowaniem [typu nośnika], którego chcesz używać”
Bern
Dzięki @praetor. To było dla mnie bardzo pomocne
SO User
53

Najłatwiejszym w użyciu rozwiązaniem jednokreskowym

return new HttpResponseMessage( HttpStatusCode.OK ) {Content =  new StringContent( "Your message here" ) };

W przypadku serializowanej zawartości JSON:

return new HttpResponseMessage( HttpStatusCode.OK ) {Content =  new StringContent( SerializedString, System.Text.Encoding.UTF8, "application/json" ) };
Simon Mattes
źródło
to nie zadziałało, ponieważ IHttpActionResult wymaga zwracanego typu ResponseMessageResult. Zobacz moją odpowiedź poniżej, na co skończyłem. Zwróć także uwagę, że uwzględniłem JsonContent nashawn (jako wyprowadzony z klasy bazowej StringContent).
Adam Cox
1
Po prostu zawiń HttpResponseMessage, a następnie: return new ResponseMessageResult (return new HttpResponseMessage (HttpStatusCode.OK) {new StringContent ("Twoja wiadomość tutaj")}); :)
Simon Mattes
41

Dla dowolnego obiektu T możesz:

return Request.CreateResponse<T>(HttpStatusCode.OK, Tobject);
ScubaSteve
źródło
5
Z wyjątkiem Requestjest dostępna tylko w przypadku CreateResponsemetody, jeśli dziedziczenie ApiController. Nie będzie działać, jeśli używasz Controller.
vapcguy
15

Możesz tworzyć własne wyspecjalizowane typy treści. Na przykład jeden dla zawartości Json i jeden dla zawartości XML (a następnie przypisz je do HttpResponseMessage.Content):

public class JsonContent : StringContent
{
    public JsonContent(string content)
        : this(content, Encoding.UTF8)
    {
    }

    public JsonContent(string content, Encoding encoding)
        : base(content, encoding, "application/json")
    {
    }
}

public class XmlContent : StringContent
{
    public XmlContent(string content) 
        : this(content, Encoding.UTF8)
    {
    }

    public XmlContent(string content, Encoding encoding)
        : base(content, encoding, "application/xml")
    {
    }
}
bytedev
źródło
bardzo zadbane i czyste wykonanie.
Sam
3

Zainspirowany odpowiedzią Simona Mattesa, musiałem spełnić wymagany przez IHttpActionResult typ zwrotu ResponseMessageResult. Używając również JsonContent nashawn, skończyło się na ...

        return new System.Web.Http.Results.ResponseMessageResult(
            new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK)
            {
                Content = new JsonContent(JsonConvert.SerializeObject(contact, Formatting.Indented))
            });

Zobacz odpowiedź nashawn na JsonContent.

Adam Cox
źródło
interpolacja strun wydaje się niepotrzebna
Igor Pashchuk
0

Nie ma wątpliwości, że masz rację Florin. Pracowałem nad tym projektem i stwierdziłem, że ten fragment kodu:

product = await response.Content.ReadAsAsync<Product>();

Można zastąpić:

response.Content = new StringContent(string product);
Steven WH
źródło
1
Ta odpowiedź nie wydaje się być odpowiednia dla pytania i nie pokazuje, jak przejść od przedmiotu (produktu) do sznurka
mageos