2012-09-19 15 views
46

¿Cómo puedo leer los contenidos de la solicitud PUT en la acción del controlador webApi de MVC?Lea HttpContent en el controlador WebApi

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

me sale cadena vacía aquí :(

Lo que tengo que hacer es: averiguar "qué propiedades" fueron modificados/enviado en la solicitud inicial (lo que significa que si el objeto Contact tiene 10 propiedades, y quiero actualizar sólo 2 de ellos, les mando y el objeto con sólo dos propiedades, algo como esto:

{ 

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

El resultado final esperado es

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

Respuesta

88

Por diseño, el contenido del cuerpo en ASP.NET Web API se trata como una secuencia de solo reenvío que solo se puede leer una vez.

La primera lectura en su caso se está realizando cuando la API web vincula su modelo, después de eso, el Request.Content no devolverá nada.

Se puede quitar el contact de sus parámetros de acción, obtener el contenido y deserializar manualmente en objeto (por ejemplo, con Json.NET):

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

Que debe hacer el truco (suponiendo que es accountId URL parámetro por lo que no se tratará como contenido leído).

+0

Gracias. Y sí, la identificación de la cuenta es un parámetro de URL. – Marty

+1

Me pregunto si podría crear un MessageHandler que llamó a LoadIntoBuffer() en el contenido de la solicitud antes de que se activara el archivador del modelo. –

+0

@DarrelMiller No estoy seguro si ASP.NET Web API aún enlazaría el modelo; necesita ser probado. – tpeczek

-5

La forma más fácil de leer el contenido de cualquier solicitud por lo general es usar un proxy HTTP como fiddler

que tiene la enorme ventaja de que le muestra todo tráfico local (además de las solicitudes completas - cabeceras, etc) y muchas otras solicitudes que leen el contenido de la solicitud dentro de una acción particular en un controlador en particular; por ejemplo, 401/404 etc.

También puede usar el compositor de fiddler para crear solicitudes de prueba desde cero o modificando solicitudes anteriores.

Si por alguna razón no se puede usar un proxy o debe ver la solicitud desde el interior de la aplicación web, entonces this answer ve sensata

11

Usted puede mantener su parámetro contacto con el siguiente enfoque:

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

devueltos para mí, la representación json de mi objeto de parámetro, por lo que podría usarlo para el manejo y el registro de excepciones.

encuentran como respuesta aceptada here

3

A pesar de que esta solución puede parecer obvio, sólo quería publicar aquí lo que el siguiente chico va a google que sea más rápido.

Si aún desea tener el modelo como parámetro en el método, puede crear un DelegatingHandler para almacenar el contenido.

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

y añadirlo a los controladores de mensajes globales:

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

Esta solución se basa en la answer por Darrel Miller.

De esta forma todas las solicitudes se almacenarán en el búfer.

+0

Creo que podría dañar el desempeño de mi servidor ... pero podría ser útil. –

Cuestiones relacionadas