.NET 6 Web API如何默认开启复杂类型参数绑定?
问题:.NET 6 Web API复杂类型参数默认不绑定JSON请求体内容
我从ASP.NET Framework 4.7 Web API迁移到.NET 6,通过新建Web API模板项目复制类文件,将控制器改为ControllerBase、返回类型改为IActionResult。现在用Postman提交JSON对象时,只有给复杂对象参数Form加上[FromBody]特性,它的属性才有值;不加的话对象不为空,但所有属性都是null。我不想逐个接口加这个特性,因为微软文档表明WebAPI默认支持复杂类型参数绑定JSON格式,担心项目配置存在问题。
示例接口代码
[HttpPost] [Route("~/api/v3/{appid}/chat/rooms/{roomid}/events/{eventid}/react")] public IActionResult PostReaction(string appid, string roomid, string eventid, ReactionFormModel Form) { ... // Form不为空但所有字段值为null }
JSON输入示例
{ "userid": "alfgivemefour", "reaction": "like", "reacted": "true" }
当前Program.cs配置
// How to introduce NLog support: https://medium.com/projectwt/nlog-with-ilogger-in-net-6-0-web-api-fb7072d8ac6c using NLog; using NLog.Web; using talkapi.Common.Caching; using talkapi.Common.Config; using talkapixp.Plumbing; // Create an instance of the logger as per above article on NLogger var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger(); var builder = WebApplication.CreateBuilder(args); IWebHostEnvironment environment = builder.Environment; logger.Debug("[Program] init main using environment: " + environment.EnvironmentName); bool isDevelopment = environment.IsDevelopment(); var configuration = builder.Configuration .SetBasePath(environment.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false) .AddJsonFile($"appsettings.{environment.EnvironmentName}.json", optional: true, reloadOnChange: false) .AddEnvironmentVariables() .Build(); // Insert configuration provider that works with appsettings.{env}.json ConfigManager.SetProvider(new ConfigProviderNetCore(configuration) as IConfigProvider); // Cache Manager needs a provider from the database CacheManager.SetCacheProvider(talkapi.Database.Caching.Factory.GetProvider()); // NLog: Setup NLog for Dependency injection builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); builder.Host.UseNLog(); // Add JSON support when posting to web api so complex objects will deserialize builder.Services.AddControllers().AddNewtonsoftJson(); //other classes that need the logger via dependency injection builder.Services.AddTransient<LogHelper>(); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // Adds MVC support builder.Services.AddMvc(); builder.Services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; options.JsonSerializerOptions.PropertyNamingPolicy = null; }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
问题原因
你的Program.cs中重复调用了AddControllers()方法,导致之前配置的NewtonsoftJson和默认绑定规则被覆盖:
- 先调用
builder.Services.AddControllers().AddNewtonsoftJson();,这一步正确配置了NewtonsoftJson处理请求体绑定。 - 后续又多次调用
builder.Services.AddControllers();和builder.Services.AddMvc();,这些调用会重置控制器服务的配置,覆盖之前的NewtonsoftJson设置,同时破坏了复杂类型默认从请求体绑定的规则。
在.NET 6中,Web API默认对复杂类型参数会尝试从请求体绑定,但配置被重复重置后,这个默认行为就会失效,必须手动添加[FromBody]才能完成绑定。
解决方案
修改Program.cs,合并控制器服务的配置,避免重复调用AddControllers()和AddMvc(),确保只配置一次控制器服务并正确设置JSON序列化:
修改后的关键代码片段:
// NLog: Setup NLog for Dependency injection builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); builder.Host.UseNLog(); //other classes that need the logger via dependency injection builder.Services.AddTransient<LogHelper>(); // 合并控制器服务配置,仅调用一次AddControllers builder.Services.AddControllers() .AddNewtonsoftJson(options => { // 可在此添加NewtonsoftJson的自定义配置,比如忽略循环引用 // options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; }) .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; options.JsonSerializerOptions.PropertyNamingPolicy = null; }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // 移除重复的AddControllers()和AddMvc()调用
额外说明
- 若项目主要使用NewtonsoftJson(Json.NET),建议优先在
AddNewtonsoftJson的选项中设置大小写不敏感、命名策略等,无需单独调用AddJsonOptions(除非同时需要System.Text.Json的配置,一般不需要)。 - 确保请求头
Content-Type设置为application/json,Postman发送JSON时默认会自动设置,若手动修改过需检查。 - 复杂类型参数名称
Form需与JSON属性名称匹配(你已设置PropertyNameCaseInsensitive=true,所以大小写不影响)。
内容的提问来源于stack exchange,提问作者DavidJBerman
相关产品推荐
相关产品推荐

