Чтобы изменить IFormFile на IList<IFormFile> и отправить запрос $http.post. AngularJS, ядро ​​ASP.NET

Мой пример работает только с одним файлом. Мне нужен массив файлов. Я использую angularJS 1.7 и asp.net-core 2.0.

HTML

 <div class = "post">
    <form>
        <textarea ng-model = "Headline" name = "Headline" rows = "2" cols = "63" class = "form-control"></textarea>

        <textarea ng-model = "BodyText" name = "BodyText" rows = "4" cols = "63" class = "form-control"></textarea>

        <input type = "file" file-model = "myFile" multiple/>

        <input id = "Submit" class = "btn btn-default" ng-click = "createPost()" type = "submit" value = "Пост" />
    </form>
</div>

Метод creatPost в контроллере AgularJs

 $scope.createPost = function () {
        var model = {
            Headline: $scope.Headline,
            BodyText: $scope.BodyText,
            ImgPost: $scope.myFile
        }
        $http({
                method: 'POST',
                url: '/api/Blog/create-post/',
                headers: {
                    'Content-Type': undefined
                },
                data: model,
                transformRequest: function (data, headersGetter) {
                    var formData = new FormData();
                    angular.forEach(data, function (value, key) {
                        formData.append(key, value);
                    });

                    return formData;
                }
            })
            .then(function onSuccess(response) {
                if (response.data = "Ok") {
                    $window.location.reload();
                }
            })


            .catch(function onError(response) {
                console.info("Error")
            });
    }

Модель на С#

[ScaffoldColumn(false)]
    public int Id { get; set; }

    [ScaffoldColumn(false)]
    public string User { get; set; }

    [Required(ErrorMessage = "")]
    [StringLength(100, MinimumLength = 1, ErrorMessage = "")]
    public string Headline { get; set; }

    [Required(ErrorMessage = "")]
    [StringLength(1000, MinimumLength = 1, ErrorMessage = "")]
    public string BodyText { get; set; }

    [ScaffoldColumn(false)]
    public DateTime? Date_Time { get; set; }

    public IFormFile ImgPost { get; set; }

И подпись метода

    [HttpPost]
    [Route("create-post")]
    public async Task<object> PostSaveOnFile(PostViewModel model)
    {

Как мне изменить модель в # public IFormFile ImgPost { get; набор; } И внесите изменения в мой контроллер angularJS, и я смогу отправить массив файлов. Спасибо.

Как я понял проблема в моей директиве fileReader

(function (angular) {
    angular.module('app').directive('fileModel', ['$parse', function ($parse) {
      return {
         restrict: 'A',
         link: function(scope, element, attrs) {
            var model = $parse(attrs.fileModel);
            var modelSetter = model.assign;

            element.bind('change', function() {
               scope.$apply(function() {
                  modelSetter(scope, element[0].files[0]);
               });
            });
         }
      };
   }]);
})(window.angular);

Если я изменю свою модель С# на IList или IEnumerable, это будет только первый файл. Я не понимал, как изменить мою директиву на массив

Знаете ли вы, что директивы являются одной из самых мощных и универсальных функций Angular?
Знаете ли вы, что директивы являются одной из самых мощных и универсальных функций Angular?
Директивы позволяют расширять HTML новыми элементами и атрибутами и даже создавать собственные структурные директивы для манипулирования DOM. С...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
1
0
557
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

I did nor understand how to change my derective to array

app.directive('fileModel', ['$parse', function ($parse) {
  return {
     restrict: 'A',
     link: function(scope, element, attrs) {
        var model = $parse(attrs.fileModel);
        var modelSetter = model.assign;

        element.bind('change', function() {
           scope.$apply(function() {
              ̶m̶o̶d̶e̶l̶S̶e̶t̶t̶e̶r̶(̶s̶c̶o̶p̶e̶,̶ ̶e̶l̶e̶m̶e̶n̶t̶[̶0̶]̶.̶f̶i̶l̶e̶s̶[̶0̶]̶)̶;̶
              modelSetter(scope, element[0].files);
           });
        });
     }
  };
}]);

Измените вызов modelSetter, чтобы он возвращал массив.

Не помогло. Теперь в моей модели ImgPost null в контроллере API :(

FX_Sektor 02.03.2019 23:50
Ответ принят как подходящий

Сначала вам нужно обновить директиву fileModel, чтобы установить массив файлов вместо одного файла. Вы можете использовать этот ответ, но результирующий массив будет иметь тип FileList, и я предлагаю вам преобразовать его в Array, потому что он будет более гибким в сочетании с другими изменениями в коде.

app.directive('fileModel', ['$parse', function ($parse) {
  return {
     restrict: 'A',
     link: function(scope, element, attrs) {
        var model = $parse(attrs.fileModel);
        var modelSetter = model.assign;

        element.bind('change', function() {
           scope.$apply(function() {
              modelSetter(scope, Array.from(element[0].files));
           });
        });
     }
  };
}]);

Чтобы позволить ASP.NET Core правильно связать Array (или List), вам нужно добавить все значения массива с одним и тем же ключом в FormData. Например, если у вас есть

public List<string> Strings { get; set; }

вам нужно будет добавить значения с помощью клавиши Strings

formData.append("Strings", "value1");
formData.append("Strings", "value2");
formData.append("Strings", "value3");

Поэтому вам нужно обновить функцию transformRequest, чтобы правильно добавить массив файлов в FormData.

function (data, headersGetter) {
    var formData = new FormData();
    angular.forEach(data, function (value, key) {
        //you could check if value is FileList
        //but your model can hold array of primitive values like ["val1", "val2", "val3"]
        //this single check for Array covers all cases
        //and you don't need to have different check for FileList
        if (value instanceof Array) {
            for (var i = 0; i < value.length; i++) {
                formData.append(key, value[i]);
            }
            return;
        }

        formData.append(key, value);
    });

    return formData;
}

Другие вопросы по теме