it-swarm.com.de

Lesen Sie HttpContent im Web-API-Controller

Wie kann ich den Inhalt der PUT-Anforderung in der MVC webApi-Controller-Aktion lesen?.

[HttpPut]
public HttpResponseMessage Put(int accountId, Contact contact)
{
    var httpContent = Request.Content;
    var asyncContent = httpContent.ReadAsStringAsync().Result;
...

Ich bekomme hier leere Zeichenfolge :(

Was ich tun muss, ist: herauszufinden, "welche Eigenschaften" in der anfänglichen Anfrage geändert/gesendet wurden (was bedeutet, dass wenn das Contact -Objekt 10 Eigenschaften hat und ich nur 2 von ihnen aktualisieren möchte, sende ich und Objekt mit nur zwei Eigenschaften, etwa so:

{

    "FirstName": null,
    "LastName": null,
    "id": 21
}

Das erwartete Endergebnis ist

List<string> modified_properties = {"FirstName", "LastName"}
65
Marty

Der Textinhalt in der ASP.NET-Web-API wird standardmäßig als schreibgeschützter Stream behandelt, der nur einmal gelesen werden kann.

Der erste Lesevorgang in Ihrem Fall wird durchgeführt, wenn die Web-API Ihr Modell bindet. Danach wird Request.Content gibt nichts zurück.

Sie können contact aus Ihren Aktionsparametern entfernen, den Inhalt abrufen und ihn manuell in Objekt deserialisieren (zum Beispiel mit Json.NET):

[HttpPut]
public HttpResponseMessage Put(int accountId)
{
    HttpContent requestContent = Request.Content;
    string jsonContent = requestContent.ReadAsStringAsync().Result;
    CONTACT contact = JsonConvert.DeserializeObject<CONTACT>(jsonContent);
    ...
}

Das sollte der Trick sein (vorausgesetzt, dass accountId ein URL-Parameter ist und nicht als Inhalt gelesen wird).

124
tpeczek

Sie können Ihren CONTACT-Parameter auf folgende Weise beibehalten:

using (var stream = new MemoryStream())
{
    var context = (HttpContextBase)Request.Properties["MS_HttpContext"];
    context.Request.InputStream.Seek(0, SeekOrigin.Begin);
    context.Request.InputStream.CopyTo(stream);
    string requestBody = Encoding.UTF8.GetString(stream.ToArray());
}

Hat mir die json-Darstellung meines Parameterobjekts zurückgegeben, damit ich sie für die Ausnahmebehandlung und -protokollierung verwenden kann.

Als akzeptierte Antwort gefunden hier

18
Anytoe

Auch wenn diese Lösung naheliegend erscheint, wollte ich sie nur hier posten, damit der nächste Kerl sie schneller googelt.

Wenn Sie das Modell dennoch als Parameter in der Methode haben möchten, können Sie ein DelegatingHandler erstellen, um den Inhalt zu puffern.

internal sealed class BufferizingHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        await request.Content.LoadIntoBufferAsync();
        var result = await base.SendAsync(request, cancellationToken);
        return result;
    }
}

Und füge es zu den globalen Message-Handlern hinzu:

configuration.MessageHandlers.Add(new BufferizingHandler());

Diese Lösung basiert auf Antwort von Darrel Miller .

Auf diese Weise werden alle Anforderungen gepuffert.

4
derwasp