添加OData后ASP.NET Core 2.1 Web API无法拉取数据、Swagger返回204问题咨询
问题排查及解决方法
核心问题点
- 重复配置MVC服务:你先后调用了
AddMvc和AddMvcCore,AddMvc本身已包含AddMvcCore的全部核心功能,单独调用AddMvcCore会覆盖默认的输入输出格式化器配置,导致常用媒体类型(包括你用到的application/json-patch+json)未被注册,请求参数无法绑定、返回值无法序列化,最终返回204无内容。 - OData配置不完整:你仅启用了OData查询选项,未配置OData必需的EDM(实体数据模型)和路由映射,OData序列化逻辑无法正常工作,也会导致无返回值。
- 中间件顺序错误:你将CORS、HTTPS重定向中间件放在了Swagger和MVC之后,跨域请求、HTTPS重定向逻辑无法提前生效,可能导致请求处理异常。
- Swagger与OData兼容缺失:ASP.NET Core 2.1版本的原生Swagger生成器未适配OData路由和参数规则,生成的接口调用参数、路径可能不符合后端要求。
修复步骤
- 合并MVC配置,移除重复的
AddMvcCore调用,将格式化器配置合并到AddMvc中,同时添加application/json-patch+json支持:
public void ConfigureServices(IServiceCollection services) { services.AddOData(); services.AddCors(); services.AddMvc(opt => { opt.UseGeneralRoutePrefix("BookManagement"); opt.SslPort = SettingsLoader<AppSettings>.Settings.SslPort; // 新增:添加json-patch媒体类型支持 opt.InputFormatters.OfType<JsonInputFormatter>().First().SupportedMediaTypes.Add( new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/json-patch+json")); opt.OutputFormatters.OfType<JsonOutputFormatter>().First().SupportedMediaTypes.Add( new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/json-patch+json")); // 保留你原有的自定义媒体类型配置 foreach (var outputFormatter in opt.OutputFormatters.OfType<OutputFormatter>().Where(x => x.SupportedMediaTypes.Count == 0)) { outputFormatter.SupportedMediaTypes.Add(new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/prs.odatatestxx-odata")); } foreach (var inputFormatter in opt.InputFormatters.OfType<InputFormatter>().Where(x => x.SupportedMediaTypes.Count == 0)) { inputFormatter.SupportedMediaTypes.Add(new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("application/prs.odatatestxx-odata")); } }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1); // 移除原来的AddMvcCore调用 // 其余原有配置保持不变:IHttpContextAccessor、自定义控制器激活、SwaggerGen等 }
- 补全OData EDM模型和路由配置,在
Configure方法的UseMvc配置中添加OData路由映射:
// 新增:构造EDM模型的方法 private static IEdmModel GetEdmModel() { var builder = new ODataConventionModelBuilder(); // 替换为你的实际实体类配置 builder.EntitySet<Book>("Books"); return builder.GetEdmModel(); } // 修改UseMvc配置 app.UseMvc(routeBuilder => { // 新增OData路由映射 routeBuilder.MapODataServiceRoute("odata", "odata", GetEdmModel()); routeBuilder.EnableDependencyInjection(); routeBuilder.Expand().Select().Count().OrderBy().Filter(); });
- 调整中间件顺序,保证前置逻辑先执行:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { Kernel = RegisterApplicationComponents(app); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // 移到最前面:HTTPS重定向 app.UseRewriter(new RewriteOptions().AddRedirectToHttps(StatusCodes.Status301MovedPermanently, SettingsLoader<AppSettings>.Settings.SslPort)); // 移到Swagger之前:CORS app.UseCors(builder => { builder.AllowAnyOrigin(); builder.AllowAnyMethod(); builder.AllowAnyHeader(); }); if (SettingsLoader<AppSettings>.Settings.AutoUpdateDatabase) { IDatabaseLogic databaseLogic = new DatabaseLogic(Kernel.Get<IDatabasePersistence>()); databaseLogic.UpgradeDatabase(); } InitiateMessageReprocess(); #if !NO_AUTH ISingleSignOnLogic singleSignOnLogic = Kernel.Get<ISingleSignOnLogic>(); app.UseMiddleware<AuthenticationFilter>(singleSignOnLogic); #endif // Swagger配置保持不变 app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint($"/swagger/v{AppVersion.cVersion}/swagger.json", $"Books Microservice API v{AppVersion.cVersion}"); c.RoutePrefix = string.Empty; }); // MVC放在最后 app.UseMvc(routeBuilder => { routeBuilder.MapODataServiceRoute("odata", "odata", GetEdmModel()); routeBuilder.EnableDependencyInjection(); routeBuilder.Expand().Select().Count().OrderBy().Filter(); }); LogProvider.Instance.LogInformation("Started application"); }
- 适配Swagger对OData的支持,在
AddSwaggerGen配置中添加操作过滤器,处理OData的查询参数、路由规则适配,避免Swagger生成错误的接口调用格式。
内容的提问来源于stack exchange,提问作者CPK_2011
相关产品推荐
相关产品推荐

