Web Api 请求内容在操作过滤器中为空 [英] Web Api Request Content is empty in action filter
问题描述
我有一个名为 Log
的属性,它尝试将请求和响应的内容记录到文本文件中.我已经把它放在我的控制器上以覆盖所有的动作.在 LogAttribute
中,我将内容作为字符串 (ReadAsStringAsync
) 读取,因此我不会丢失请求正文.
I have an attribute named Log
that tries to log the content of request and response into a text file. I've put that over my Controller to cover all the actions. In LogAttribute
I'm reading content as a string (ReadAsStringAsync
) so I don't lose request body.
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
}
// ..
}
另一方面,我已将 FromBody
属性放在我的操作参数类之前,以利用其优势.
On the other hand, I've put the FromBody
attribute before my action parameter class to take advantage of its benefits.
[Log]
public class SomethingController
{
public HttpResponseMessage Foo([FromBody] myModel)
{
// something
}
}
问题是 ActionExecuting
或 ActionExecuted
中的内容始终为空.
The problem is the content is always empty either in ActionExecuting
or ActionExecuted
.
我认为这是因为 FromBody
在我的 Log
属性之前运行,这与它们在代码中的顺序不同.我再次认为这是因为根据动作参数(路由处理)为请求找到最佳动作/控制器匹配.之后我的请求正文被清除,因为请求正文在 WebApi 中没有缓冲.
I think this is because FromBody
runs before my Log
attribute unlike their order in the code. And again I think its because of finding the best action/controller match for the request according to action parameters (Route Processing). After that my request body is cleared since request body is non-buffered in WebApi.
我想知道有没有什么办法可以改变FromBody
属性和我的Log
属性的运行时顺序?或其他解决问题的方法!我应该提到我不想删除 FromBody
并使用 HttpRequestMessage
而不是我的模型或类似的东西.
I want to know if there is any way to change the run time order of the FromBody
attribute and my Log
attribute? or something else that solves the problem! I should mention that I don't want to remove the FromBody
and using HttpRequestMessage
instead of my Model or something like that.
推荐答案
请求体是不可回绕的流;它只能读取一次.格式化程序已经读取了流并填充了模型.我们无法在操作过滤器中再次读取流.
The request body is a non-rewindable stream; it can be read only once. The formatter has already read the stream and populated the model. We're not able to read the stream again in the action filter.
你可以试试:
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"];
}
}
实际上,ActionArguments
只是一个字典,如果我们需要避免硬编码参数名称("myModel"
),我们可以循环遍历它.当我们创建一个通用动作过滤器,需要针对某些特定要求处理类似对象的类时,我们可以让我们的模型实现一个接口 => 知道哪个参数是我们需要处理的模型,但我们可以调用这些方法界面.
Actually, ActionArguments
is just a dictionary, we can loop though it if we need to avoid hardcoded parameter name ("myModel"
). When we create a generic action filter that needs to work on a class of similar objects for some specific requirements, we could have our models implement an interface => know which argument is the model we need to work on and we can call the methods though the interface.
示例代码:
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
}
}
}
这篇关于Web Api 请求内容在操作过滤器中为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!