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

问题描述 投票:0回答:2

我正在使用.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(图像)。

我测试了评论这部分

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

当被注释掉时,代码就可以工作了。

我需要更改什么才能正确设置所有属性,包括

SecondLevel

c# jquery ajax api
2个回答
1
投票

修改参数名称:

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

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


0
投票

啊MVC绑定,我真的不喜欢这种默认行为。

当绑定顶级对象时,例如控制器属性或函数参数,绑定器将首先查找具有相同名称的提交值。

如果找到具有该名称的值,则该对象的子属性或集合将与该前缀绑定。

因为在您的情况下,您的参数称为

level
并且您提交的值以
Level
开头。那么binder就期待你提交;

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()));
© www.soinside.com 2019 - 2024. All rights reserved.