c# - varios - Lea HttpContent en el controlador WebApi
se encontraron varias acciones que coincidían con la solicitud get (4)
¿Cómo puedo leer los contenidos en la solicitud PUT en la acción del controlador MVC 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" se modificaron / enviaron en la solicitud inicial (lo que significa que si el objeto de Contact
tiene 10 propiedades y quiero actualizar solo 2 de ellas, envío y objeto solo con dos propiedades) , algo como esto:
{
"FirstName": null,
"LastName": null,
"id": 21
}
El resultado final esperado es
List<string> modified_properties = {"FirstName", "LastName"}
Aunque esta solución puede parecer obvia, solo quería publicarla aquí para que el próximo chico la busque 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ñádalo a los manejadores de mensajes globales:
configuration.MessageHandlers.Add(new BufferizingHandler());
Esta solución se basa en la here de Darrel Miller .
De esta forma, todas las solicitudes se almacenarán en búfer.
La forma más fácil de leer el contenido de cualquier solicitud generalmente es usar un proxy HTTP como el fiddler
Tiene la enorme ventaja de mostrarle todo el tráfico local (más las solicitudes completas, encabezados, etc.) y muchas otras solicitudes que no le mostrarán leer 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 algún motivo no puede usar un proxy o debe ver la solicitud desde dentro de la aplicación web, esta respuesta parece sensata.
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, luego de eso Request.Content
no devolverá nada.
Puede eliminar el contact
de sus parámetros de acción, obtener el contenido y deserializarlo manualmente en un 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);
...
}
Eso debería ser el truco (suponiendo que accountId
sea un parámetro de URL, por lo que no se tratará como contenido leído).
Puede mantener su parámetro CONTACT 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());
}
Devolví 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.
Se encuentra como respuesta aceptada here