我正在使用EntitySetController创建一个oData web api控制器,除了获取总记录数之外,一切运行良好.
控制器定义如下:
public class MyODataController : EntitySetController<Entity1,int> where TEntity : class { public override IQueryable<Entity1> Get() { return EntityDatabase.Get(); } }
当我打电话给我时:
http://localhost:44789/oData/MyOData/$count
我收到错误:
检测到无效操作. ‘$count’不是可以绑定到’Collection([Entity1 Nullable = False])’的动作.
解决方法
不幸的是,虽然Web API在未来的版本中应该是开箱即用,但它并不支持$count开箱即用.在此期间,您仍然可以通过定义这些类来添加支持:
public class CountODataRoutingConvention : EntitySetRoutingConvention { public override string SelectAction(ODataPath odataPath,HttpControllerContext controllerContext,ILookup<string,HttpActionDescriptor> actionMap) { if (controllerContext.Request.Method == HttpMethod.Get && odataPath.PathTemplate == "~/entityset/$count") { if (actionMap.Contains("GetCount")) { return "GetCount"; } } return null; } } public class CountODataPathHandler : DefaultODataPathHandler { protected override ODataPathSegment ParseAtEntityCollection(IEdmModel model,ODataPathSegment prevIoUs,IEdmType prevIoUsEdmType,string segment) { if (segment == "$count") { return new CountPathSegment(); } return base.ParseAtEntityCollection(model,prevIoUs,prevIoUsEdmType,segment); } } public class CountPathSegment : ODataPathSegment { public override string SegmentKind { get { return "$count"; } } public override IEdmType GetEdmType(IEdmType prevIoUsEdmType) { return EdmCoreModel.Instance.FindDeclaredType("Edm.Int32"); } public override IEdmEntitySet GetEntitySet(IEdmEntitySet prevIoUsEntitySet) { return prevIoUsEntitySet; } public override string ToString() { return "$count"; } }
在MapODataRoute中注册它们:
IList<IODataRoutingConvention> routingConventions = ODataRoutingConventions.CreateDefault(); routingConventions.Insert(0,new CountODataRoutingConvention()); config.Routes.MapODataRoute("OData","odata",GetModel(),new CountODataPathHandler(),routingConventions);
public HttpResponseMessage GetCount(ODataQueryOptions<TEntity> queryOptions) { IQueryable<TEntity> queryResults = queryOptions.ApplyTo(Get()) as IQueryable<TEntity>; int count = queryResults.Count(); HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); response.Content = new StringContent(count.ToString(),Encoding.UTF8,"text/plain"); return response; }
为了避免将GetCount()复制到每个控制器,您可以定义一个从定义GetCount的EntitySetController派生的基类.