jquery 如何将具有对象作为属性的类传递给C# API

inb24sb2  于 2023-08-04  发布在  jQuery
关注(0)|答案(2)|浏览(133)

我使用的是.NET Core 7.0。我在API控制器中有此端点:

[HttpPost("add")]
public string Add([FromForm] LevelData level)
{
    return "";
}

字符串
这是该方法接收的类:

public class LevelData
{
    //
    public List<IFormFile> NewImageFiles{ get; set; } = new();

    public string HomePlanId { get; set; } = "";
    public SecondLevel Level { get; set; } = new SecondLevel();
}

public class SecondLevel
{
    public string HomePlanId2 { get; set; } = "";
}


无论我使用swagger页面还是 AJAX 调用,我总是得到所有的属性为空

curl -X 'POST' \
  'https://localhost:7018/api/Level/add' \
  -H 'accept: text/plain' \
  -H 'Content-Type: multipart/form-data' \
  -F 'HomePlanId=1' \
  -F 'Level.HomePlanId2=2'
var formData = new FormData();

// Append the properties of the LevelData object
formData.append('HomePlanId', 'your_home_plan_id');
formData.append('Level.HomePlanId2', 'your_home_plan_id_2');

// Make the AJAX call to the C# API
$.ajax({
            url: '/api/level/add',
            type: 'POST', 
            contentType: false, 
            processData: false
            data: formData, 
            success: function (data) {
                // Handle the API response here if needed
                console.log("API response:", data);
            },
            error: function (error) {
                // Handle errors here if the API call fails
                console.error("API error:", error);
            }
});

的字符串


的数据
我想使用FromForm来传递FormFile(images)。
我做了测试评论这一部分

public SecondLevel Level { get; set; } = new SecondLevel();


当被注解掉时,代码可以工作。
我需要更改什么才能使所有属性正确设置,包括SecondLevel

dsekswqp

dsekswqp1#

修改参数的名称:

[HttpPost("add")]
 //level=>levelData
 public string Add([FromForm] LevelData levelData)
 {
            return "";
 }

字符串
必须避免将参数命名为与嵌套模型属性相同的名称

whitzsjs

whitzsjs2#

啊,MVC绑定,我真的不喜欢这种默认行为。
当绑定顶级对象时,例如控制器属性或函数参数,绑定器将首先查找具有相同名称的提交值。
如果找到具有该名称的值,则该对象的子属性或集合将与该前缀绑定。
因为在你的例子中,你的参数被称为level,你提交了一个以Level开头的值。然后活页夹期待你会提交;

Level.HomePlanId=your_home_plan_id&Level.Level.HomePlanId2=your_home_plan_id_2

字符串
然后,如果没有找到同名的值,绑定器将尝试不带前缀地绑定该对象。所以如果你把你的论点重命名为别的东西,你可以提交;

HomePlanId=your_home_plan_id&Level.HomePlanId2=your_home_plan_id_2


但是如果客户端提交了一个与你的变量同名的额外值,那么绑定就会失败。
我发现当你的顶级对象包含一个Dictionary<>,而你试图提交一个空集合时,这种行为特别烦人。在这种情况下,您为另一个顶级对象提交的任何其他值都将作为键添加到字典中。
您可以通过向每个参数添加显式绑定前缀来覆盖此行为。或者通过定义一个自定义的IBindingMetadataProvider来全局化。

public class BindingProvider : IBindingMetadataProvider {
    public void CreateBindingMetadata(BindingMetadataProviderContext context)
    {
        IModelNameProvider nameAttrib = null;
        if (context.BindingMetadata.BinderModelName == null 
            && context.BindingMetadata.IsBindingAllowed
            && (nameAttrib = context.Attributes.OfType<IModelNameProvider>().FirstOrDefault())!=null
            && nameAttrib.Name == null)
            context.BindingMetadata.BinderModelName = 
                context.Key.PropertyInfo?.Name
                ?? context.Key.ParameterInfo?.Name;
    }
}
services.AddMvc(o => o.ModelMetadataDetailsProviders.Add(new BindingProvider()));

相关问题