Web Api OData v3 - Cast或IsOf函数的参数必须有一个类型

时间:2014-10-31 09:21:23

标签: asp.net-web-api odata

我有一个基本实体(Store),还有两个实现它的类型(CustomerEngineer)。

但是,当我尝试过滤某种类型时:

http://localhost:50050/odata/Store?$inlinecount=allpages&$top=20&$filter=isof(MyNamespace.Data.Core.Entities.Engineer)&$orderby=Name%20asc

我收到此错误:

{
  "odata.error":{
    "code":"","message":{
      "lang":"en-US","value":"The query specified in the URI is not valid. Cast or IsOf Function must have a type in its arguments."
    },"innererror":{
      "message":"Cast or IsOf Function must have a type in its arguments.","type":"Microsoft.Data.OData.ODataException","stacktrace":"   at Microsoft.Data.OData.Query.FunctionCallBinder.ValidateIsOfOrCast(BindingState state, Boolean isCast, List`1& args)\r\n   at Microsoft.Data.OData.Query.FunctionCallBinder.CreateUnboundFunctionNode(FunctionCallToken functionCallToken, List`1 args, BindingState state)\r\n   at Microsoft.Data.OData.Query.FunctionCallBinder.BindAsBuiltInFunction(FunctionCallToken functionCallToken, BindingState state, List`1 argumentNodes)\r\n   at Microsoft.Data.OData.Query.FunctionCallBinder.BindFunctionCall(FunctionCallToken functionCallToken, BindingState state)\r\n   at Microsoft.Data.OData.Query.MetadataBinder.BindFunctionCall(FunctionCallToken functionCallToken)\r\n   at Microsoft.Data.OData.Query.MetadataBinder.Bind(QueryToken token)\r\n   at Microsoft.Data.OData.Query.BinaryOperatorBinder.GetOperandFromToken(BinaryOperatorKind operatorKind, QueryToken queryToken)\r\n   at Microsoft.Data.OData.Query.BinaryOperatorBinder.BindBinaryOperator(BinaryOperatorToken binaryOperatorToken)\r\n   at Microsoft.Data.OData.Query.MetadataBinder.BindBinaryOperator(BinaryOperatorToken binaryOperatorToken)\r\n   at Microsoft.Data.OData.Query.MetadataBinder.Bind(QueryToken token)\r\n   at Microsoft.Data.OData.Query.FilterBinder.BindFilter(QueryToken filter)\r\n   at Microsoft.Data.OData.Query.ODataUriParser.ParseFilterImplementation(String filter, IEdmType elementType, IEdmEntitySet entitySet)\r\n   at System.Web.Http.OData.Query.FilterQueryOption.get_FilterClause()\r\n   at System.Web.Http.OData.Query.Validators.FilterQueryValidator.Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings)\r\n   at System.Web.Http.OData.Query.FilterQueryOption.Validate(ODataValidationSettings validationSettings)\r\n   at System.Web.Http.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n   at System.Web.Http.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n   at System.Web.Http.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n   at Vantage.Web.Api.Filters.AuthorizeQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions) in c:\\Users\\TimM\\Source\\Workspaces\\Workspace\\Vantage Web Prototype - API\\Vantage.Web.Api\\Filters\\AuthorizeQueryAttribute.cs:line 29\r\n   at System.Web.Http.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor)\r\n   at System.Web.Http.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"
    }
  }
}

为什么会这样?我使用了与实体一起返回的确切类型。

"odata.type":"MyNamespace.Data.Core.Entities.Engineer"

我正在使用Web Api 5.2.2,OData 5.3.1。谢谢你的帮助!

1 个答案:

答案 0 :(得分:1)

您需要使用单引号传递类型,如下所示:

http://localhost:50050/odata/Store?$inlinecount=allpages&$top=20&$filter=isof('MyNamespace.Data.Core.Entities.Engineer')&$orderby=Name%20asc

但是,当你这样做时,你将得到以下例外:

System.NotImplementedException: Unknown function 'isof'.
   at System.Web.Http.OData.Query.Expressions.FilterBinder.BindSingleValueFunctionCallNode(SingleValueFunctionCallNode node)
   at System.Web.Http.OData.Query.Expressions.FilterBinder.Bind(QueryNode node)
   at System.Web.Http.OData.Query.Expressions.FilterBinder.Bind(FilterClause filterClause, Type filterType, IEdmModel model, IAssembliesResolver assembliesResolver, ODataQuerySettings querySettings)
   at System.Web.Http.OData.Query.FilterQueryOption.ApplyTo(IQueryable query, ODataQuerySettings querySettings, IAssembliesResolver assembliesResolver)
   at System.Web.Http.OData.Query.ODataQueryOptions.ApplyTo(IQueryable query, ODataQuerySettings querySettings)
   at System.Web.Http.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor)
   at System.Web.Http.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
当前版本的OData WebApi集成中

'isof'是 不支持 。您可以查看源代码here。您会注意到堆栈跟踪会讨论名为BindSingleValueFunctionCallNode的方法。在那里有一个开关,有以下default案例:

default:
throw new NotImplementedException(Error.Format(SRResources.ODataFunctionNotSupported, node.Name));

请注意代码不会测试是否存在isofcast函数。在ClrCanonicalFunctionNames类中,只定义了这些OData函数:

// function names
internal const string StartswithFunctionName = "startswith";
internal const string EndswithFunctionName = "endswith";
internal const string SubstringofFunctionName = "substringof";
internal const string SubstringFunctionName = "substring";
internal const string LengthFunctionName = "length";
internal const string IndexofFunctionName = "indexof";
internal const string TolowerFunctionName = "tolower";
internal const string ToupperFunctionName = "toupper";
internal const string TrimFunctionName = "trim";
internal const string ConcatFunctionName = "concat";
internal const string YearFunctionName = "year";
internal const string YearsFunctionName = "years";
internal const string MonthFunctionName = "month";
internal const string MonthsFunctionName = "months";
internal const string DayFunctionName = "day";
internal const string DaysFunctionName = "days";
internal const string HourFunctionName = "hour";
internal const string HoursFunctionName = "hours";
internal const string MinuteFunctionName = "minute";
internal const string MinutesFunctionName = "minutes";
internal const string SecondFunctionName = "second";
internal const string SecondsFunctionName = "seconds";
internal const string RoundFunctionName = "round";
internal const string FloorFunctionName = "floor";
internal const string CeilingFunctionName = "ceiling";

我目前正在尝试使用查询字符串参数实现自己的OfType过滤。