Свойство IFormFile в .NET Core ViewModel, вызывающее остановку запроса AJAX

Я даю пользователям возможность добавлять изображения для розничного продукта внутри модального окна «Добавить/редактировать продукт».

Модальная модель представления:

public class ProductModalViewModel
{
    public ProductModalViewModel()
    {
        Product = new ProductDTO();
        Images = new List<ProductImageViewModel>();
    }

    public ProductDTO Product { get; set; }

    public List<ProductImageViewModel> Images { get; set; }
}

Каждое изображение продукта содержится в собственной ViewModel, как показано ниже:

Модель представления изображения:

public class ProductImageViewModel
{
    public ProductImageViewModel()
    {
        ProductImage = new ProductImageDTO();
    }

    public ProductImageDTO ProductImage { get; set; }

    [DataType(DataType.Upload)]
    public IFormFile ImageFile { get; set; }
}

После отправки формы для сохранения продукта (и любых добавленных изображений) мой запрос зависает и отображается как «ожидающий» в инструментах разработки Chrome. Мое действие контроллера никогда не достигается.

Это происходит только тогда, когда я включаю ProductImage Fields/ViewModel/Logic в свой проект. Этого не происходило до добавления этой функциональности в модальное окно, и оно отлично работает, если я удалю все поля ProductImage Fields/ViewModel/Logic, а затем отправлю снова.

Есть ли что-то изначально неправильное с включением моего IFormFile во вложенную ViewModel? Или это может быть что-то другое. Остальная часть моего соответствующего кода приведена ниже.

Контроллер:

[HttpPost]
public IActionResult SaveProduct([FromForm]ProductModalViewModel model)
{
    //save code    
}

Вид (модальный):

<form id = "formSaveProduct" onsubmit = "SaveProduct(event)" enctype = "multipart/form-data">
//Other product fields removed for brevity
    <div class = "row">
        <div class = "col-md-12">
            <ul class = "list-group" id = "image-list-group">
                @for (int i = 0; i < Model.Images.Count(); i++)
                {
                    <partial name = "_ImageListItem" for = "Images[i]" />
                }
            </ul>
        </div>
    </div>
</form>

Частичный вид (ProductImage):

<li class = "list-group-item my-1">
    <input type = "hidden" asp-for = "ProductImage.Id" class = "image-id" />
    <input type = "hidden" asp-for = "ProductImage.ProductId" class = "image-productid" />

    <div class = "row">
        <div class = "col-3">
            <input type = "text" readonly asp-for = "ProductImage.Order" class = "image-order" />
        </div>
        <div class = "col-6">
            <img src = "..\@Model.ProductImage.Path" class = "image-display" />
        </div>
    </div>
</li>

Скрипт:

function SaveProduct(e) {

    e.preventDefault();  // prevent standard form submission

    $.ajax({
        url: "@Url.Action("SaveProduct", "ProductManagement", new { Area = "Admin" })",
        method: "post",
        data: new FormData($('#formSaveProduct')[0]),
        contentType: false,
        processData: false,
        cache: false,
        success: function (result) {
            //removed for brevity
        }
    });
}

для функции Ajax добавьте contentType: multipart/form-data и попробуйте еще раз, я не уверен, поможет это или нет.

BeiBei ZHU 28.05.2019 03:48

Какое определение для ProductImageDTO? Есть ли демо, чтобы воспроизвести вашу проблему? Есть ли ошибка на вкладке консоли веб-разработчика?

Edward 29.05.2019 04:15
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
356
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Во-первых, вам это не нужно

[DataType(DataType.Upload)]
public IFormFile ImageFile { get; set; }

поэтому вы можете изменить свой код на

 public IFormFile ImageFile { get; set; }

И в свой сценарий вы должны добавить contentType

function SaveProduct(e) {

    e.preventDefault();  // prevent standard form submission

    $.ajax({
        url: "@Url.Action("SaveProduct", "ProductManagement", new { Area = "Admin" })",
        method: "post",
        data: new FormData($('#formSaveProduct')[0]),
        contentType: false,
        processData: false,
        cache: false,
        contentType: "multipart/form-data", //here
        success: function (result) {
            if (result.success) {
                $("#exampleModal").modal('toggle');
                location.reload();
            }
            else {
                $(".modal-body").html(result);
            }
        }
    });
}

Спасибо за ответ. Я считаю, что добавление contentType приводит к тому, что [FromForm] в моем действии контроллера больше не работает. Запрос больше не зависает, но действие контроллера никогда не достигается. Должен ли я также вносить изменения в действие?

Graham Meehan 28.05.2019 13:57

я думаю, вы можете использовать [FromBody]

Tony Ngo 28.05.2019 15:40
Ответ принят как подходящий

На этот вопрос был прекрасно дан ответ в моем концептуальном вопросе в следующем посте:

IFormFile как вложенное свойство ViewModel

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