2013-05-08 8 views
6

Ich verwende das OData-Beispielprojekt unter http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/working-with-entity-relations. Im Get möchte ich in der Lage sein, die Filter in den QueryOptions des EntitySetController zu ändern:Die beste Methode zum Ändern einer 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(); 
    } 

ich in der Lage sein möchte Eigenschaften zu finden, die speziell bezeichnet werden. Ich kann das tun, indem ich this.QueryOptions.Filter.RawValue für die Eigenschaftsnamen analysiere, aber ich kann das RawValue nicht aktualisieren, da es nur gelesen wird. Ich kann jedoch eine andere Instanz von FilterQueryOption aus der modifizierten RawValue erstellen, aber ich kann sie nicht this.QueryOptions.Filter zuweisen, da dies auch nur gelesen wird.

Ich glaube, ich könnte das neue Filter nennen ApplyTo es vorbei _context.Products, aber dann werde ich separat die ApplyTo der anderen Eigenschaften von QueryOptions wie Skip und OrderBy nennen müssen. Gibt es eine bessere Lösung als diese?

aktualisieren

Ich habe versucht, die folgenden:

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(); 
    } 

und es scheint, bis zu einem Punkt Aufarbeitung werden. Wenn ich einen Haltepunkt setze, kann ich meine Produkte in der unencryptedProducts Liste sehen, aber wenn die Methode zurückkommt, erhalte ich keine Einzelteile. Ich habe versucht, die [Queryable(AllowedQueryOptions=AllowedQueryOptions.All)] wieder aufzusetzen, aber es hatte keine Wirkung. Irgendwelche Ideen, warum ich keine Gegenstände bekomme?

aktualisieren 2

entdeckte ich, dass meine Abfrage zweimal selbst angewendet wurde, obwohl ich nicht das Queryable Attribut verwende. Das bedeutete, dass die Liste trotz fehlender Rückgabewerte mit dem unverschlüsselten Wert abgefragt wurde und daher keine Werte zurückgegeben wurden.

Ich habe versucht, eine ODataController statt mit:

public class ODriversController : ODataController 
{ 

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

und das hat funktioniert! Zeigt dies an, dass ein Fehler in EntitySetController vorliegt?

+0

Sie versuchen zu beschränken, welche Eigenschaften der Client filtern kann? –

+1

Keine Antwort auf Ihre Frage, aber ich habe etwas in Ihrem Code falsch bemerkt. Sie verwenden entweder ODataQueryOptions oder das QueryableAttribute. ODataQueryOptions dient zur manuellen Steuerung der Abfrage. QueryableAttribute dient zum automatischen Anwenden der Abfrage. Ihr Code hat beides, was bedeutet, dass die Abfrage zweimal von ODataQueryOptions.ApplyTo und einmal vom QueryableAttribute angewendet wird. –

+0

Können Sie Ihr Szenario weiter erklären? Versuchen Sie, die eingehende $ filter-Abfrage zu transformieren und dann auszuführen? –

Antwort

4

Sie müssten ODataQueryOptions wahrscheinlich neu generieren, um Ihr Problem zu lösen. Lassen Sie uns sagen, wenn Sie ändern möchten, um hinzuzufügen $ orderby, können Sie dies tun wie:

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); 
Verwandte Themen