访问Web API中的消息处理程序和操作筛选器中的实际请求

时间:2017-12-17 05:00:12

标签: asp.net asp.net-web-api asp.net-web-api2

这更像是一个与设计相关的问题,我们非常感谢任何正确方向的帮助/指示。

我正在开发一个ASP.NET Web API2应用程序,并有一个授权过滤器和其他Action过滤器。在这些过滤器中,我需要访问作为HttpPost请求体的一部分的Request对象。 我使用以下代码来读取请求正文内容并反序列化为所需的对象。它工作正常。

//actionContext is HttpActionContext
var requestContent = actionContext.Request.Content.ReadAsStringAsync();
var request = JsonSerializer.GetObject<BaseOTARequestModel>(requestContent.Result);

为了提供特定请求,我将请求内容反序列化两次(我有2个过滤器)。一旦请求到达控制器操作,Web API框架就会再次对其进行反序列化。我感到内疚,每次请求被反序列化3次,并且感觉有更好的方法可以解决这个问题。

如何避免在请求中多次反序列化请求?

1 个答案:

答案 0 :(得分:1)

我接受了这个挑战并想出了这个解决方案。这是一个基本过滤器属性类:

public abstract class BaseOTARequestFilterAttribute : ActionFilterAttribute
{
    private HttpActionContext _actionContext;

    protected BaseOTARequestModel RequestModel
    {
        get
        {
            if (_actionContext.Request.Properties.ContainsKey("RequestModel"))
            {
                return _actionContext.Request.Properties["RequestModel"] as BaseOTARequestModel;
            }

            return null;
        }
        set
        {
            _actionContext.Request.Properties["RequestModel"] = value;
        }
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        _actionContext = actionContext;

        if (RequestModel == null)
        {
            //actionContext is HttpActionContext
            var requestContent = actionContext.Request.Content.ReadAsStringAsync();
            RequestModel = JsonSerializer.GetObject<BaseOTARequestModel>(requestContent.Result);
        }
    }
}

此基类处理反序列化并使用Request.Properties集合来存储它。 (好吧,我知道Web API是无状态的,但这种状态只存在于执行请求期间,因此非常好。)

您的各种属性都应该继承此基类,并且可以使用派生对象,如下所示:

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        base.OnActionExecuting(actionContext);

        var data = RequestModel;
        // etc.
    }

这可能不是最优雅的解决方案,但我相信它有效。有兴趣听取他人的意见。