Данные формы почтальона для контроллера ASP.NET Core 2.2 не привязаны к команде с частными установщиками - PullRequest
1 голос
/ 17 июня 2019

Инструменты

  • Visual Studio 2017
  • ASP.NET Core 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 оставлено для общего доступа намеренно, чтобы проиллюстрировать свойства

[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;
    }
}

В Почтальоне я теперь настраиваю запрос следующим образом:

enter image description here

Мне пришлось запутать некоторую информацию, но вы можете видеть, что примитивные типы с закрытыми сеттерами не установлены.

enter image description here

Вопросы

  1. Почему модификатор доступа к свойствам влияет только на свойства с примитивными типами?
  2. Почему это происходит, когда атрибут параметра установлен на FromForm, но не когда он установлен на FromBody

1 Ответ

1 голос
/ 18 июня 2019

Почему модификатор доступа к свойствам влияет только на свойства с примитивными типами?

Для 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...