我的问题与这个问题非常相似:如何将针对 DTO 的 OData 查询映射到 EF 实体? 我有一个简单的设置来测试 ASP.NET Web API OData V4 $filter 功能。我想要做的是将“ProductDTO”的某些属性“别名”与“Product”实体的属性匹配。例如,用户将使用以下请求调用“ProductsController”:
GET products?$filter=DisplayName eq ‘test’
产品类:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Level { get; set; }
public Product()
{ }
}
ProductDTO类:
public class ProductDTO
{
public int Id { get; set; }
public string DisplayName { get; set; }
public int DisplayLevel { get; set; }
public ProductDTO(Product product)
{
this.DisplayName = product.Name;
this.DisplayLevel = product.Level;
}
}
产品控制器:
public class ProductsController : ApiController
{
public IEnumerable<ProductDTO> Get(ODataQueryOptions<Product> q)
{
IQueryable<Product> products = this._products.AsQueryable();
if (q.Filter != null) products = q.Filter.ApplyTo(this._products.AsQueryable(), new ODataQuerySettings()) as IQueryable<Product>;
return products.Select(p => new ProductDTO(p));
}
}
当然,我遇到了下面的异常:
在类型 'TestAPI.Models.Product' 上找不到名为“DisplayName”的属性。
我试图使用新引入的别名特性,通过将以下行添加到WebApiConfig.cs文件中实现。
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
…
IEdmModel model = GetModel();
config.MapODataServiceRoute("*", "*", model);
}
private static IEdmModel GetModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
EntitySetConfiguration<Product> products = builder.EntitySet<Product>("Product");
products.EntityType.Property(p => p.Name).Name = "DisplayName";
products.EntityType.Property(p => p.Level).Name = "DisplayLevel";
return builder.GetEdmModel();
}
}
我想我可能错误地使用了别名功能,因为会抛出与上述描述相同的异常。如果我调用以下请求,则可以正常工作,但这不是我想要实现的目标:
GET products?$filter=Name eq ‘test’
更新:
我同意gdoron的看法,Get
终结点应该是这样的:
public IEnumerable<ProductDTO> Get(ODataQueryOptions<ProductDTO> q)
但是这个问题不需要使用AutoMapper解决吧?
new ODataQueryContext(model, typeof(TypeName), q.Context.Path)
,也可以使用new ODataQueryContext(model, typeof(TypeName), null)
。 - Gilberto Alexandre