在ASP.NET Web Api中提供OData可查询的GET请求的正确方法是什么?这可能听起来像一个“什么是更好”的问题,但它应该是一个“什么工作”的问题。
一些假设:
Queryable
属性放入返回IQueryable<Model>
的操作方法。因此,您必须公开域模型吗?因此,如果我有一个Category
类型具有父项和子项的导航属性,序列化程序会抱怨我有循环引用,我无法摆脱这个错误。
我读过我应该使用DTO,但是如何?如何为将为数据库创建适当SQL的用户提供IQueryable<DTOModel>
?请记住,我想使用$filter
之类的内容。
我只想给用户一个没有序列化导航属性的模型对象的可过滤列表....但是如何?
答案 0 :(得分:3)
您不必公开IQueryable<>
- 您可以创建一个接受ODataQueryOptions
实例的方法并自行处理。这是一个代码示例,可以满足您的大部分需求。对您来说,制定最适合您的解决方案应该足够了。此方法还允许您保留EF代理类。
using System.Web.Http.OData;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Query;
[ActionName("Dto")]
public IList<DtoModel> GetDto(ODataQueryOptions<DtoModel> queryOptions)
{
var data2 = DatabaseData();
//Create a set of ODataQueryOptions for the internal class
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Model>("Model");
var queryContext = new ODataQueryContext(
modelBuilder.GetEdmModel(), typeof(Model));
var newQueryOptions = new ODataQueryOptions<Model>(queryContext, Request);
var t = new ODataValidationSettings() { MaxTop = 25 };
var s = new ODataQuerySettings() { PageSize = 25 };
newQueryOptions.Validate(t);
IEnumerable<Model> results =
(IEnumerable<Model>)newQueryOptions.ApplyTo(data2, s);
int skip = newQueryOptions.Skip == null ? 0 : newQueryOptions.Skip.Value;
int take = newQueryOptions.Top == null ? 25 : newQueryOptions.Top.Value;
IList<Model> internalResults = results.Skip(skip).Take(take).ToList();
// map from Model to Dto here using AutoMapper
AutoMapper.Mapper.CreateMap<Model, DtoModel>();
IList<DtoModel> webResults =
AutoMapper.Mapper.Map<IList<Model>, IList<DtoModel>>(internalResults);
return webResults;
}
示例中使用的数据是一组简单的Queryable
数据:
private IQueryable<Model> DatabaseData()
{
return (
new Model[] {
new Model() { id = 1, name = "one", type = "a" },
new Model() { id = 2, name = "two", type = "b" },
new Model() { id = 3, name = "three", type = "c" },
new Model() { id = 4, name = "four", type = "d" },
new Model() { id = 5, name = "five", type = "e" },
new Model() { id = 6, name = "six", type = "f" },
new Model() { id = 7, name = "seven", type = "g" },
new Model() { id = 8, name = "eight", type = "h" },
new Model() { id = 9, name = "nine", type = "i" }
})
.AsQueryable();
}
这些是测试类:
public class Poco
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
public class DtoModel
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
public class Model
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
public virtual ICollection<Poco> Pocos { get; set; }
}