2013-05-08 17 views
6

私はhttp://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/working-with-entity-relationsでODataサンプルプロジェクトを使用しています。取得では、私はEntitySetControllerのQueryOptionsにフィルタを変更することができるようにしたい:WebAPI ODataを変更する最善の方法QueryOptions.Filter

public class ProductsController : EntitySetController<Product, int> 
{ 
    ProductsContext _context = new ProductsContext(); 

    [Queryable(AllowedQueryOptions=AllowedQueryOptions.All)] 
    public override IQueryable<Product> Get() 
    { 
     var products = QueryOptions.ApplyTo(_context.Products).Cast<Product>(); 
     return products.AsQueryable(); 
    } 

私は具体的に言及されているプロパティを見つけることができるようにしたいと思います。私はプロパティ名のためにthis.QueryOptions.Filter.RawValueを解析することでこれを行うことができますが、それは読み取り専用であるためRawValueを更新できません。ただし、RawValueからFilterQueryOptionの別のインスタンスを作成することはできますが、this.QueryOptions.Filterに割り当てることはできません。

私は新しいフィルタのApplyTo_context.Productsそれを渡して呼び出すことができますが、その後、私は別にSkipOrderByなどのQueryOptionsの他のプロパティのApplyToを呼び出す必要がありますね。これ以上の解決策はありますか?

更新

私は次のことを試してみました:

public override IQueryable<Product> Get() 
    { 
     IQueryable<Product> encryptedProducts = _context.Products; 

     var filter = QueryOptions.Filter; 
     if (filter != null && filter.RawValue.Contains("Name")) 
     { 
      var settings = new ODataQuerySettings(); 
      var originalFilter = filter.RawValue; 
      var newFilter = ParseAndEncyptValue(originalFilter); 
      filter = new FilterQueryOption(newFilter, QueryOptions.Context); 
      encryptedProducts = filter.ApplyTo(encryptedProducts, settings).Cast<Product>(); 

      if (QueryOptions.OrderBy != null) 
      { 
       QueryOptions.OrderBy.ApplyTo<Product>(encryptedProducts); 
      } 
     } 
     else 
     { 
      encryptedProducts = QueryOptions.ApplyTo(encryptedProducts).Cast<Product>(); 
     } 

     var unencryptedProducts = encryptedProducts.Decrypt().ToList(); 

     return unencryptedProducts.AsQueryable(); 
    } 

、それはポイントまで動作しているようです。ブレークポイントを設定した場合、私の製品はunencryptedProductsのリストに表示されますが、メソッドが返されたときにアイテムが取得されません。 [Queryable(AllowedQueryOptions=AllowedQueryOptions.All)]をもう一度入れてみましたが効果がありませんでした。なぜ私はアイテムを取得していないすべてのアイデア?

アップデート2

私は私のクエリは、私がQueryable属性を使用していないにもかかわらず、2回適用されていたことを発見しました。これは、リストを返す項目があっても、リストが暗号化されていない値で照会されていたため、値が返されていないことを意味していました。

public class ODriversController : ODataController 
{ 

    //[Authorize()] 
    //[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)] 
    public IQueryable<Products> Get(ODataQueryOptions options) 
    { 

と、これが働いた:

は、私が代わりにODataControllerを使用してみました!これはEntitySetControllerにバグがあることを示していますか?

+0

クライアントがフィルタできるプロパティを制限しようとしていますか? –

+1

あなたの質問には答えられませんが、あなたのコードに何か間違っていることが気づきました。 ODataQueryOptionsまたはQueryableAttributeを使用します。 ODataQueryOptionsは、問合せを手動で制御するためのものです。 QueryableAttributeは自動的にクエリを適用するためのものです。あなたのコードは両方とも、ODataQueryOptions.ApplyToによってクエリが2回、QueryableAttributeによって1回適用されることを意味します。 –

+0

シナリオをさらに説明できますか?受信した$フィルタクエリを変換して実行しようとしていますか? –

答えて

4

問題を解決するには、おそらくODataQueryOptionsを再生成する必要があります。たとえば、$ orderbyを追加するように変更する場合は、次のようにします。

string url = HttpContext.Current.Request.Url.AbsoluteUri; 
url += "&$orderby=name"; 
var request = new HttpRequestMessage(HttpMethod.Get, url); 
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
modelBuilder.EntitySet<Product>("Product"); 
var options = new ODataQueryOptions<Product>(new ODataQueryContext(modelBuilder.GetEdmModel(), typeof(Product)), request); 
関連する問題