ASP.NET OData传递int数组作为Action路由参数报错如何解决
问题原因
OData路由系统在校验路径模板时,会匹配EDM模型中注册的函数/操作元数据,你遇到报错的核心原因有两个:
- 未在EDM模型中显式声明
GetForNumbers函数的numbers参数为集合类型,路由系统无法识别数组/IEnumerable<int>类型的参数,判定模板语法非法 - 部分尝试的路由模板中自行添加了
[]符号,路由模板仅需要声明参数占位符,[]属于实际请求时参数值的语法规范,不应该出现在路由模板中
正确实现方案
第一步:注册EDM模型元数据
在你的OData服务配置处,显式声明该函数的参数类型:
private static IEdmModel GetEdmModel() { var builder = new ODataConventionModelBuilder(); // 你的其他实体集注册 builder.EntitySet<IAmAnAppropriateResponse>("IWantMeSomeNumbers"); // 声明集合函数 var getNumbersFunc = builder.EntityType<IAmAnAppropriateResponse>().Collection .Function("GetForNumbers"); // 显式指定参数为int集合类型 getNumbersFunc.Parameter<IEnumerable<int>>("numbers"); getNumbersFunc.ReturnsCollection<IAmAnAppropriateResponse>(); return builder.GetEdmModel(); }
在服务注册时引用该EDM模型即可,以ASP.NET Core为例:
builder.Services.AddControllers().AddOData(opt => { opt.Select().Filter().OrderBy().Expand().Count().SetMaxTop(null); opt.AddRouteComponents("odata", GetEdmModel()); });
第二步:编写控制器Action
[HttpGet] [ODataRoute("IWantMeSomeNumbers/GetForNumbers(numbers={numbers})")] public IQueryable<IAmAnAppropriateResponse> GetForNumbers([FromODataUri] IEnumerable<int> numbers) { // 你的业务逻辑 }
第三步:正确发起请求
请求URL中数组参数需要用[]包裹,元素用逗号分隔,示例:
GET https://你的服务地址/odata/IWantMeSomeNumbers/GetForNumbers(numbers=[1,2,3,4,5])
轻量替代方案(无需修改EDM)
如果不想调整EDM配置,可以将参数改为字符串类型接收,后端自行解析为int数组:
[HttpGet] [ODataRoute("IWantMeSomeNumbers/GetForNumbers(numbersStr={numbersStr})")] public IQueryable<IAmAnAppropriateResponse> GetForNumbers([FromODataUri] string numbersStr) { var numbers = numbersStr.Trim('[', ']') .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(int.Parse) .ToList(); // 你的业务逻辑 }
请求示例:
GET https://你的服务地址/odata/IWantMeSomeNumbers/GetForNumbers(numbersStr="[1,2,3,4,5]")
内容的提问来源于stack exchange,提问作者SmithPlatts
相关产品推荐
相关产品推荐

