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

ASP.NET Core嵌套模型[FromForm]无法绑定问题咨询

问题描述

有以下两个模型类:

public class TokenRequestModel
{
    [FromHeader(Name = HeaderName.RequestId)]
    public Guid? RequestId { get; set; }

    [FromHeader(Name = HeaderName.Authorization), Required, SwaggerParameter(DocConstants.Authorization, Required = true)]
    public required string Authorization { get; set; }

    [FromRoute(Name = RouteConstants.AuthorizationServerId)]
    public required string AuthorizationServerId { get; set; }
}

public class TokenRequest
{
    [FromForm(Name = "code")]
    public string? Code { get; set; }

    [FromForm(Name = "refresh_token")]
    public string? RefreshToken { get; set; }

    [FromForm(Name = "grant_type")]
    public required string GrantType { get; set; }

    [FromForm(Name = "redirect_uri")]
    public string? RedirectUri { get; set; }
}

当将两个模型分别作为Action参数传入时,绑定可正常完成:

public async Task<ActionResult<TokenResponse>> Exchange(
    TokenRequestModel tokenRequestModel,
    [FromForm]
    TokenRequest tokenRequest)        
{ }

但将TokenRequest作为属性嵌套到TokenRequestModel中后,绑定失败:

public class TokenRequestModel
{
    [FromHeader(Name = HeaderName.RequestId)]
    public Guid? RequestId { get; set; }

    [FromHeader(Name = HeaderName.Authorization)]
    public required string Authorization { get; set; }

    [FromRoute(Name = RouteConstants.AuthorizationServerId)]
    public required string AuthorizationServerId { get; set; }

    [FromForm]
    public TokenRequest? TokenRequest { get; set; }
}

对应的Action方法:

public async Task<ActionResult<TokenResponse>> Exchange(
    TokenRequestModel tokenRequestModel)        
{ }

预期通过URL编码表单数据,使用[FromForm]将数据绑定到TokenRequest属性,但该属性始终为null。此前使用[FromBody]处理JSON数据时绑定正常,询问该场景是否不被支持还是操作有误。

问题原因与解决方案

这是ASP.NET Core表单绑定的命名规则导致的问题,并非场景不被支持。

原因分析

当使用嵌套对象进行表单绑定时,ASP.NET Core默认会期望表单字段名采用父属性名+子属性名的格式(比如TokenRequest.Code),但当前提交的表单字段是code、grant_type这类平级名称,和绑定规则不匹配,所以TokenRequest属性无法被正确赋值,始终为null。

而使用[FromBody]处理JSON时,JSON的层级结构天然匹配嵌套对象,所以绑定正常;分开作为参数时,[FromForm]直接作用在TokenRequest上,会直接匹配平级的表单字段,因此也能正常绑定。

解决方案

有两种可行的处理方式:

  1. 修改表单提交的字段名
    提交表单时,将字段名改为嵌套格式,比如:

    • TokenRequest.Code
    • TokenRequest.GrantType
    • TokenRequest.RefreshToken
    • TokenRequest.RedirectUri
  2. 手动映射属性
    如果无法修改提交的字段格式,可以在TokenRequestModel中添加与表单字段对应的直接属性,然后手动映射到TokenRequest对象中,示例:

    public class TokenRequestModel
    {
        [FromHeader(Name = HeaderName.RequestId)]
        public Guid? RequestId { get; set; }
    
        [FromHeader(Name = HeaderName.Authorization)]
        public required string Authorization { get; set; }
    
        [FromRoute(Name = RouteConstants.AuthorizationServerId)]
        public required string AuthorizationServerId { get; set; }
    
        [FromForm(Name = "code")]
        public string? Code { get; set; }
    
        [FromForm(Name = "refresh_token")]
        public string? RefreshToken { get; set; }
    
        [FromForm(Name = "grant_type")]
        public required string GrantType { get; set; }
    
        [FromForm(Name = "redirect_uri")]
        public string? RedirectUri { get; set; }
    
        public TokenRequest? TokenRequest => new TokenRequest
        {
            Code = Code,
            RefreshToken = RefreshToken,
            GrantType = GrantType,
            RedirectUri = RedirectUri
        };
    }
    

内容的提问来源于stack exchange,提问作者Mark Good

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:57:21