2013-05-08 28 views
6

Tôi đang sử dụng dự án mẫu OData tại http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/working-with-entity-relations. Trong Nhận Tôi muốn có thể thay đổi Bộ lọc trong QueryOptions của EntitySetController:Cách tốt nhất để sửa đổi một 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(); 
    } 

Tôi muốn tìm thấy các thuộc tính được đề cập cụ thể. Tôi có thể làm điều này bằng cách phân tích cú pháp this.QueryOptions.Filter.RawValue cho tên thuộc tính nhưng tôi không thể cập nhật RawValue vì chỉ đọc được. Tuy nhiên, tôi có thể tạo một phiên bản khác của FilterQueryOption từ sửa đổi RawValue nhưng tôi không thể gán nó cho this.QueryOptions.Filter vì điều này cũng chỉ được đọc.

Tôi đoán tôi có thể gọi các bộ lọc mới của ApplyTo đi qua nó _context.Products, nhưng sau đó tôi sẽ cần phải riêng biệt gọi ApplyTo của các tài sản khác của QueryOptions như SkipOrderBy. Có một giải pháp tốt hơn này?

Cập nhật

tôi thử như sau:

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

và có vẻ như được làm việc lên đến một điểm. Nếu tôi đặt điểm ngắt, tôi có thể xem các sản phẩm của mình trong danh sách unencryptedProducts, nhưng khi phương thức trả về, tôi không nhận được bất kỳ mục nào. Tôi đã thử đặt lại [Queryable(AllowedQueryOptions=AllowedQueryOptions.All)] nhưng nó không có hiệu lực. Bất kỳ ý tưởng tại sao tôi không nhận được một mục?

Cập nhật 2

tôi phát hiện ra rằng truy vấn của tôi đã được áp dụng hai lần mặc dù tôi không sử dụng thuộc tính Queryable. Điều này có nghĩa rằng mặc dù tôi có các mục để trả về Danh sách đã được truy vấn với giá trị không được mã hóa và do đó không có giá trị nào được trả lại.

tôi đã cố gắng sử dụng một ODataController thay vì:

public class ODriversController : ODataController 
{ 

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

và điều này làm việc! Điều này có nghĩa là có lỗi trong số EntitySetController?

+0

Bạn đang cố gắng hạn chế những thuộc tính nào khách hàng có thể lọc không? –

+1

Không phải là câu trả lời cho câu hỏi của bạn, nhưng, tôi nhận thấy có điều gì đó sai trong mã của bạn. Bạn sử dụng ODataQueryOptions hoặc QueryableAttribute. ODataQueryOptions dành cho việc kiểm soát thủ công truy vấn. QueryableAttribute là để tự động áp dụng truy vấn. Mã của bạn có cả hai nghĩa là truy vấn sẽ được áp dụng hai lần một lần bởi ODataQueryOptions.ApplyTo và một lần bởi QueryableAttribute. –

+0

Bạn có thể giải thích thêm về tình huống của mình không? Bạn đang cố gắng chuyển đổi truy vấn bộ lọc $ đến rồi thực thi nó? –

Trả lời

4

Có thể bạn sẽ cần phải tạo lại ODataQueryOptions để giải quyết vấn đề của mình. Giả sử nếu bạn muốn sửa đổi để thêm $ orderby, bạn có thể thực hiện việc này như:

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); 
Các vấn đề liên quan