Web API似乎正在使用OData请求缓存JsonFormatter?

时间:2014-07-01 20:54:30

标签: json odata asp.net-web-api mediatypeformatter

TL; DR :我的OData请求似乎是每次OData GET方法(每个控制器)只打一次我的自定义JsonFormatter一次,这导致"卡住" (缓存?)自定义格式。


我正在开发一个Web API项目,并已实现并注册了我自己的JsonMediaTypeFormatter:

config.Formatters.Clear();
config.Formatters.Add(MyJsonFormatter);

' MyJsonFormatter'具有以下自定义实现:

 `-> SerializerSettings 
     `-> ContractResolver
         `-> CreateProperty

在我的protected override CreateProperty(MemberInfo member, MemberSerialization memberSerialization)方法中,我根据用户权限限制某些属性的序列化。

这适用于我的所有API端点 ,但 ,用于启用OData的GET请求。每个控制器都有一个使用对象主键的GET方法,以及一个OData GET方法,其格式类似于以下格式:

[HttpGet, Route]
public PageResult<Customer> GetOData(ODataQueryOptions<Customer> options) 
{
    IQueryable qCustomer = options.ApplyTo(_args.Context.Customers);
    return new PageResult<Customer>(qCustomer as IEnumerable<Customer>, Request.GetNextPageLink(), Request.GetInlineCount());
}

如果我在覆盖的CreateProperty方法上放置了一个断点,那么它会受到每个API请求的影响。但是,每个控制器只能按每个OData GET方法命中一次因此来自具有不同权限的其他用户的后续调用会跳过我的代码,并为我提供第一次调用时使用的格式。

如果我重新启动API,我可以再次点击断点(一次),并为调用的用户获取格式化权限,但后续调用(无论用户)是否未达到断点。显然,为每个OData请求重新启动API并不是我能解决的解决方案。

我花了将近一整天的时间来研究这个问题,并找到了几个帖子(hereherehereetc.)让我相信我需要实现我自己的ODataMediaTypeFormatter。

然而,如果是这种情况,为什么它会击中我的JsonFormatter断点?看起来它使用我的格式化程序,以某种方式缓存我对该控制器的格式权限,并从那时起使用它们。

(其次,创建我自己的ODataFormatter似乎不再是一个有效的选项,因为代码库显然已经发生了变化,因为this post - CreateEdmTypeSerializer不存在。(我使用的是Microsoft ASP.NET Web API 2.1 OData,版本5.1.2)。)


问题:有没有办法让OData能够很好地使用我的JsonFormatter,并为每个请求运行我的自定义CreateProperty代码?

如果有人能够至少解释这里发生的事情,那么可能有助于指出我需要走的方向,但现在我的大脑正在融化。 :P


更新:我发布到IIS,发现如果我回收应用程序池,格式化似乎会刷新。因此,似乎某些东西正在被缓存,问题是&#39;什么&#39;和&#39;为什么&#39; - PageResults会自动缓存吗?如何阻止缓存的任何缓存?

1 个答案:

答案 0 :(得分:1)

我不知道我的问题得到了很好的解答,因为当时我并不完全知道我在寻找什么或出了什么问题...但是,从那以后,我找到了答案,想想我会张贴以防其他人遇到我的问题。

我遇到的问题是我不需要根据调用者的权限序列化我的webapi Json响应中的特定属性。问题是,运行API的第一次调用工作正常,但后续调用没有达到我的断点,并且返回时具有第一个请求的权限。

我发现的决议是覆盖ContractResolver中的另一个方法来禁用我不想缓存的类型的缓存(在这种情况下,任何以Entity作为其基类的东西)。

public class SecurityContractResolver : DefaultContractResolver
{
    public override JsonContract ResolveContract(Type type)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        if (type.IsSubclassOf(typeof(Entity)))
            return CreateContract(type);  //don't use cache in base method - we need different contract resolution per user / permissions

        return base.ResolveContract(type);  // <-- the base class calls CreateContract and then caches the contract
    }
    .....
}

到目前为止似乎工作得很好。希望这有助于某人!