Web Api 请求内容在操作过滤器中为空 [英] Web Api Request Content is empty in action filter

查看:27
本文介绍了Web Api 请求内容在操作过滤器中为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 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
    }
}

问题是 ActionExecutingActionExecuted 中的内容始终为空.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆