为了账号安全,请及时绑定邮箱和手机立即绑定

Postman 表单数据到 ASP.NET Core 2.2 控制器未绑定到具有私有设置器的命令

Postman 表单数据到 ASP.NET Core 2.2 控制器未绑定到具有私有设置器的命令

C#
慕沐林林 2023-04-16 10:05:25
工具视觉工作室 2017ASP.NET 核心 2.2邮递员 v7.2.0我想做什么将 FormData 从 Postman 发送到 ASP.NET Core 控制器,并将来自请求的数据绑定到具有私有设置器属性的命令类。我已经使用相同的设置(私有设置器)毫无问题地发送了 JSON 数据。该FromBody属性将 JSON 字符串反序列化为模型而不会出现错误。问题如果模型具有私有设置器,则原始类型的属性不会绑定。但是,复杂类型与访问修饰符无关。控制器[HttpPost][ProducesResponseType((int)HttpStatusCode.OK)][ProducesResponseType((int)HttpStatusCode.BadRequest)]public async Task<IActionResult> CreateItemAsync([FromForm]CreateItemCommand command){    bool result = false;    commandResult = await _mediator.Send(command);    if (!commandResult)    {        return BadRequest();    }    return Ok();}命令注意:该Title属性已被故意保留为 public setter 以说明行为[DataContract]public class CreateItemCommand    :IRequest<bool>{    [DataMember]    public string Title { get; set; }    [DataMember]    public string Description { get; private set; }    [DataMember]    public int Count { get; private set; }    [DataMember]    public HashSet<string> Tags { get; private set; }    [DataMember]    public string ItemDate { get; private set; }    [DataMember]    public List<IFormFile> Documents { get; private set; }    public CreateItemCommand()    {        Skills = new HashSet<string>();        Systems = new HashSet<string>();    }    public CreateItemCommand(string title, string description,         int count, HashSet<string> tags, string itemDate,         List<IFormFile> documents)        : this()    {        Title = title;        Description = description;        Count = count        Tags = tags;        ItemDate = itemDate;        Documents = documents;    }}在 Postman 中,我现在将请求设置如下:我不得不混淆一些信息,但您可以看到没有设置带有私有 setter 的原始类型。问题为什么属性访问修饰符只影响原始类型的属性?为什么参数属性设置为时会出现这种情况,FromForm设置为时却不会FromBody
查看完整描述

1 回答

?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

为什么属性访问修饰符只影响原始类型的属性?

对于 Asp.Net Core ModelBinder,它将通过下面的ComplexTypeModelBinder代码检查该属性是否为私有访问设置器:

protected virtual object CreateModel(ModelBindingContext bindingContext)

{

    if (bindingContext == null)

    {

        throw new ArgumentNullException(nameof(bindingContext));

    }


    // If model creator throws an exception, we want to propagate it back up the call stack, since the

    // application developer should know that this was an invalid type to try to bind to.

    if (_modelCreator == null)

    {

        // The following check causes the ComplexTypeModelBinder to NOT participate in binding structs as

        // reflection does not provide information about the implicit parameterless constructor for a struct.

        // This binder would eventually fail to construct an instance of the struct as the Linq's NewExpression

        // compile fails to construct it.

        var modelTypeInfo = bindingContext.ModelType.GetTypeInfo();

        if (modelTypeInfo.IsAbstract || modelTypeInfo.GetConstructor(Type.EmptyTypes) == null)

        {

            var metadata = bindingContext.ModelMetadata;

            switch (metadata.MetadataKind)

            {

                case ModelMetadataKind.Parameter:

                    throw new InvalidOperationException(

                        Resources.FormatComplexTypeModelBinder_NoParameterlessConstructor_ForParameter(

                            modelTypeInfo.FullName,

                            metadata.ParameterName));

                case ModelMetadataKind.Property:

                    throw new InvalidOperationException(

                        Resources.FormatComplexTypeModelBinder_NoParameterlessConstructor_ForProperty(

                            modelTypeInfo.FullName,

                            metadata.PropertyName,

                            bindingContext.ModelMetadata.ContainerType.FullName));

                case ModelMetadataKind.Type:

                    throw new InvalidOperationException(

                        Resources.FormatComplexTypeModelBinder_NoParameterlessConstructor_ForType(

                            modelTypeInfo.FullName));

            }

        }


        _modelCreator = Expression

            .Lambda<Func<object>>(Expression.New(bindingContext.ModelType))

            .Compile();

    }


    return _modelCreator();

}

为什么当参数属性设置为 FromForm 时会出现这种情况,而设置为 FromBody 时不会出现这种情况


对于FromBody,它用于JsonInputFormatter从正文请求中绑定模型,它用于JsonConvert.DeserializeObject反序列化对象并Newtonsoft.Json支持从 json 字符串中反序列化包含私有 setter 的对象。


查看完整回答
反对 回复 2023-04-16
  • 1 回答
  • 0 关注
  • 88 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信