WebApi2官网学习记录---OData中的查询

EMD安全

  查询语法是基于entity data model(EDM),不是基于底层的model类型,可以从EDM排除一个属性,这样这个属性在client就不能被查询了。

有两种方式可以从EDM中排除一个属性

第一种使用 [IgnoreDataMember]特性

public class Employee
{
    public string Name { get; set; }
    public string Title { get; set; }
//当应用于类型的成员时,指定该成员不是数据协定的一部分且没有进行序列化 命名空间System.Runtime.Serialization [IgnoreDataMember]
public decimal Salary { get; set; } // Not visible in the EDM }

第二种方式以编程方式从EDM中排除属性 

var employees = modelBuilder.EntitySet<Employee>("Employees");
employees.EntityType.Ignore(emp => emp.Salary);

安全查询

     [Queryable]特性是一个action过滤器支持解析、验证以及应用查询,过滤器将查询选项转为一个LINQ表达式。

  Web API支持以下OData查询选项:  

为了使用OData的查询,必须显示指定查询可用。可以在全局进行配置或在指定的控制器或action上。

public static void Register(HttpConfiguration config)
{   
    config.EnableQuerySupport();
    // ...
}
public class ProductsController : ApiController
{
    [Queryable]
    IQueryable<Product> Get() {}
}

限制查询

  为了安全或性能方面的考虑,可能需要限制一些操作。Queryable]特性有一些内建的属性可以实现这一点。如下所示:

//仅允许$skip与$top操作
[Queryable(AllowedQueryOptions=AllowedQueryOptions.Skip | AllowedQueryOptions.Top)]
//在指定属性上进行排序,对于在数据库中没有索引的字段会禁止排序操作的
[Queryable(AllowedOrderByProperties="Id")] 
//仅允许“eq”这种逻辑操作
[Queryable(AllowedLogicalOperators=AllowedLogicalOperators.Equal)]
//禁止所有的算术操作
[Queryable(AllowedArithmeticOperators=AllowedArithmeticOperators.None)]

  可以通过构造一个QueryableAttribute的实例在定义全局查询过滤

var queryAttribute = new QueryableAttribute()
{
    AllowedQueryOptions = AllowedQueryOptions.Top | AllowedQueryOptions.Skip,
    MaxTop = 100
};
                
config.EnableQuerySupport(queryAttribute);

直接调用查询选项

  不使用[Queryable]特性,可以在controller中直接调用查询选项,这要做需要在方法中添加一个ODataQueryOptions参数

public IQueryable<Product> Get(ODataQueryOptions opts)
{
    var settings = new ODataValidationSettings()
    {
        // Initialize settings as needed.
        AllowedFunctions = AllowedFunctions.AllMathFunctions
    };

    opts.Validate(settings);

    IQueryable results = opts.ApplyTo(products.AsQueryable());
    return results as IQueryable<Product>;
}

查询验证

 [Querable]特性在执行之前就验证查询选项,验证步骤在QueryableAttribute.ValidateQuery 方法中执行,可以自定义验证过程。如下所示:

 1 public class MyOrderByValidator : OrderByQueryValidator
 2 {
 3     // Disallow the 'desc' parameter for $orderby option.
 4     public override void Validate(OrderByQueryOption orderByOption,
 5                                     ODataValidationSettings validationSettings)
 6     {
 7         if (orderByOption.OrderByNodes.Any(
 8                 node => node.Direction == OrderByDirection.Descending))
 9         {
10             throw new ODataException("The 'desc' option is not supported.");
11         }
12         base.Validate(orderByOption, validationSettings);
13     }
14 }
15 
16 public class MyQueryableAttribute : QueryableAttribute
17 {
18     public override void ValidateQuery(HttpRequestMessage request, 
19         ODataQueryOptions queryOptions)
20     {
21         if (queryOptions.OrderBy != null)
22         {
23             queryOptions.OrderBy.Validator = new MyOrderByValidator();
24         }
25         base.ValidateQuery(request, queryOptions);
26     }
27 }
28 
29 // Globally:
30 config.EnableQuerySupport(new MyQueryableAttribute());
31 
32 // Per controller:
33 public class ValuesController : ApiController
34 {
35     [MyQueryable]
36     public IQueryable<Product> Get()
37     {
38         return products.AsQueryable();
39     }
40 }
View Code

 如果直接使用ODataQueryOptions 可以设置验证器  

public IQueryable<Product> Get(ODataQueryOptions opts)
{
    if (opts.OrderBy != null)
    {
        opts.OrderBy.Validator = new MyOrderByValidator();
    }

    var settings = new ODataValidationSettings()
    {
        // Initialize settings as needed.
        AllowedFunctions = AllowedFunctions.AllMathFunctions
    };

    // Validate
    opts.Validate(settings);

    IQueryable results = opts.ApplyTo(products.AsQueryable());
    return results as IQueryable<Product>;
}

Note:在新版本的WebAPI中[Queryable]特性已经被否决,使用[EnableQuery]特性

posted @ 2015-04-22 14:50  senki  阅读(471)  评论(0)    收藏  举报