2014-07-01 36 views
0

TL; DR:我的OData請求似乎是按照每個OData GET方法(每個控制器)執行一次且僅一次自定義JsonFormatter,這會導致「卡住」(緩存?)自定義格式。
Web API似乎正在緩存帶有OData請求的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和發現,如果我回收應用程序池,格式似乎被刷新。所以它肯定似乎有東西被緩存,問題是'什麼'和'爲什麼' - 頁面結果自動緩存?如何停止正在緩存的內容?

回答

0

我不知道我的問題被問得很好,因爲當時我並不完全知道我在找什麼或出了什麼問題......但是,從那以後,我找到了答案並認爲我會發布,以防萬一有人遇到我的問題。

我遇到的問題是我需要不根據調用者的權限序列化我的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 
    } 
    ..... 
} 

似乎目前工作很好。希望這可以幫助別人!