首页 > 解决方案 > Microsoft.AspNet.OData [EnableQueryAttribute] 与 [Route] 属性结合时失败

问题描述

我正在使用 nuget 包 Microsoft.AspNet.OData 6.1.0。创建启用 odata 的操作。我在以下设置中遇到了 [Route] 属性的问题。

    // The Setup 
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // configure non odata ...

            //OData support
            config.AddODataQueryFilter();
            config.EnableDependencyInjection();

            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.EnableLowerCamelCase(NameResolverOptions.ProcessReflectedPropertyNames | NameResolverOptions.ProcessExplicitPropertyNames);

            builder.EntitySet<MixedRealityCatalogItem>("KISS");

            var edmModel = builder.GetEdmModel();

            config.MapODataServiceRoute("ODataRoute", "/", edmModel);

            config.Count().Filter().OrderBy().Select().MaxTop(2000);
        }
    }


   // The Controller
    public class KISSController : ApiController
    {
        public KISSController(IRepository<MixedRealityCatalogItem> repository)
        {
            this.Repository = repository ?? throw new ArgumentNullException(nameof(repository));
        }

        private IRepository<MixedRealityCatalogItem> Repository { get; set; }

        [EnableQuery(PageSize = 2000, MaxAnyAllExpressionDepth = 2)]
        [HttpGet]
        [Route("KISS")] // <-- this causes and exception
        public IEnumerable<MixedRealityCatalogItem> GetAll(ODataQueryOptions<MixedRealityCatalogItem> options)
        {

            IQueryable<MixedRealityCatalogItem> results = this.Repository.GetAll();

            var settings = new ODataQuerySettings
            {
                HandleNullPropagation = HandleNullPropagationOption.False,
                EnableConstantParameterization = false,
                EnsureStableOrdering = false
            };
            //Builds, but does not execute the Iqueryable
            IQueryable finalQuery = options.ApplyTo(results, settings);

            var finalResults = new List<MixedRealityCatalogItem>();

            //Will actually execute the query against the DB
            foreach (MixedRealityCatalogItem item in finalQuery)
            {
                finalResults.Add(item);
            }
            return finalResults;
        }
    }

如果我注释掉 Route 属性,则 GetAll 操作适用于所有查询,但如果存在 route 属性,则当我每个用户使用一个评估“任何”语句的过滤器时,我都会收到以下异常。

{
  "Message": "An error has occurred.",
  "ExceptionMessage": "Value cannot be null.\r\nParameter name: type",
  "ExceptionType": "System.ArgumentNullException",
  "StackTrace": "   at System.Linq.Expressions.Expression.Parameter(Type type, String name)\r\n   at System.Web.OData.Query.Expressions.FilterBinder.HandleLambdaParameters(IEnumerable`1 rangeVariables)\r\n   at System.Web.OData.Query.Expressions.FilterBinder.BindAnyNode(AnyNode anyNode)\r\n   at System.Web.OData.Query.Expressions.FilterBinder.BindExpression(SingleValueNode expression, RangeVariable rangeVariable, Type elementType)\r\n   at System.Web.OData.Query.Expressions.FilterBinder.BindFilterClause(FilterBinder binder, FilterClause filterClause, Type filterType)\r\n   at System.Web.OData.Query.FilterQueryOption.ApplyTo(IQueryable query, ODataQuerySettings querySettings)\r\n   at System.Web.OData.Query.ODataQueryOptions.ApplyTo(IQueryable query, ODataQuerySettings querySettings)\r\n   at AssetManager.Api.Controllers.Contracts.KISSController.GetAll(ODataQueryOptions`1 options) in D:\\git\\LSource\\AssetManagerAPI\\src\\AssetManager.Web\\Controllers\\Contracts\\AssetManagerBaseApiController.cs:line 48\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.AuthenticationFilterResult.<ExecuteAsync>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}

我究竟做错了什么?在这个简单的示例中,路由属性不是必需的,但在我的实际情况下它很重要。

笔记:

标签: asp.net-web-apiodata

解决方案


事实证明存在与 DataContract 属性相关的错误,该错误已在 7.0.0 版中修复

修复错误的拉取请求:https ://github.com/OData/WebApi/pull/1484

带有错误修复的 Nuget 版本:https ://www.nuget.org/packages/Microsoft.AspNet.OData/7.0.0


推荐阅读