You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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和默认绑定规则被覆盖:

  1. 先调用builder.Services.AddControllers().AddNewtonsoftJson();,这一步正确配置了NewtonsoftJson处理请求体绑定。
  2. 后续又多次调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 15:05:32