tutorial mvc example ejemplo c# asp.net asp.net-mvc asp.net-web-api

c# - mvc - El contenido de solicitud de Api web está vacío en filtro de acción



web api return json example (2)

El cuerpo de la solicitud es una secuencia no rebobinable; se puede leer solo una vez El formateador ya ha leído la secuencia y ha poblado el modelo. No podemos volver a leer la secuencia en el filtro de acción.

Tu podrías intentar:

public class LogAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { var myModel = actionContext.ActionArguments["myModel"]; } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { var myModel = actionContext.ActionArguments["myModel"]; } }

En realidad, ActionArguments es solo un diccionario, aunque podemos "myModel" si necesitamos evitar el nombre del parámetro codificado ( "myModel" ). Cuando creamos un filtro de acción genérico que necesita funcionar en una clase de objetos similares para algunos requisitos específicos, podemos hacer que nuestros modelos implementen una interfaz => saber qué argumento es el modelo en el que necesitamos trabajar y, aunque podemos llamar a los métodos, La interfaz.

Código de ejemplo:

public class LogAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { foreach(var argument in actionContext.ActionArguments.Values.Where(v => v is ILogable))) { ILogable model = argument as ILogable;//assume that only objects implementing this interface are logable //do something with it. Maybe call model.log } } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { foreach(var argument in actionContext.ActionArguments.Values.Where(v => v is ILogable))) { ILogable model = argument as ILogable;//assume that only objects implementing this interface are logable //do something with it. Maybe call model.log } } }

Tengo un atributo llamado Log que intenta registrar el contenido de la solicitud y la respuesta en un archivo de texto. Lo puse sobre mi Controlador para cubrir todas las acciones. En LogAttribute estoy leyendo el contenido como una cadena (ReadAsStringAsync) para no perder el cuerpo de la solicitud.

public class LogAttribute : ActionFilterAttribute { // .. public override void OnActionExecuting(HttpActionContext actionContext) { // stuff goes here var content = actionContext.Request.Content.ReadAsStringAsync().Result; // content is always empty because request body is cleared } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { // other stuff goes here var content = actionContext.Request.Content.ReadAsStringAsync().Result; // content is always empty because request body is cleared } // .. }

Por otro lado, he puesto el atributo FromBody antes de mi clase de parámetros de acción para aprovechar sus ventajas.

[Log] public class SomethingController { public HttpResponseMessage Foo([FromBody] myModel) { // something } }

El problema es que el contenido siempre está vacío en ActionExecuting o ActionExecuted.

Creo que esto se debe a que FromBody se ejecuta antes de mi atributo Log a diferencia de su orden en el código. Y de nuevo creo que es debido a encontrar la mejor coincidencia de acción / controlador para la solicitud según los parámetros de acción (Procesamiento de ruta). Después de eso, mi cuerpo de solicitud se borra ya que el cuerpo de la solicitud no está almacenado en WebApi.

Quiero saber si hay alguna forma de cambiar el orden de tiempo de ejecución del atributo FromBody y mi atributo de registro. o algo más que resuelve el problema! Debo mencionar que no quiero eliminar FromBody y usar HttpRequestMessage en lugar de mi Modelo o algo así.


Este enfoque funcionó para mí:

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í la representación json de mi objeto de parámetro de acción que desencadena el caso de registro o excepción.

Se encuentra como respuesta aceptada here