Невозможно определить тип оболочки платформы. Пожалуйста, установите переменную SHELL_EXCUTE_FLAG env

Простой, меньше кода, нет модели-обертки

. Более простое решение, сильно вдохновленное ответом Andrius . Используя ModelBinderAttribute, вам не нужно указывать поставщика модели или связующего. Это экономит много кода. Действие вашего контроллера будет выглядеть так:

public IActionResult Upload(
    [ModelBinder(BinderType = typeof(JsonModelBinder))] SomeObject value,
    IList files)
{
    // Use serialized json object 'value'
    // Use uploaded 'files'
}

Реализация

Код за JsonModelBinder (или использовать полный пакет NuGet ):

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;

public class JsonModelBinder : IModelBinder {
    public Task BindModelAsync(ModelBindingContext bindingContext) {
        if (bindingContext == null) {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        // Check the value sent in
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult != ValueProviderResult.None) {
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            // Attempt to convert the input value
            var valueAsString = valueProviderResult.FirstValue;
            var result = Newtonsoft.Json.JsonConvert.DeserializeObject(valueAsString, bindingContext.ModelType);
            if (result != null) {
                bindingContext.Result = ModelBindingResult.Success(result);
                return Task.CompletedTask;
            }
        }

        return Task.CompletedTask;
    }
}

Пример запроса

Ниже приведен пример необработанного HTTP-запроса, принятого действием контроллера Upload выше.

Запрос multipart/form-data разделен на несколько частей, каждая из которых разделена указанным boundary=12345. Каждая часть получила имя, назначенное в Content-Disposition -header. С этими именами по умолчанию ASP.Net-Core знает, какая часть связана с каким параметром в действии контроллера.

Файлы, привязанные к IFormFile, дополнительно должны указать filename, как во второй части запрос. Content-Type не требуется.

Еще одна вещь, которую следует отметить, состоит в том, что части json должны быть десериализуемыми в типы параметров, как определено в действии контроллера. Поэтому в этом случае тип SomeObject должен иметь свойство key типа string.

POST http://localhost:5000/home/upload HTTP/1.1
Host: localhost:5000
Content-Type: multipart/form-data; boundary=12345
Content-Length: 218

--12345
Content-Disposition: form-data; name="value"

{"key": "value"}
--12345
Content-Disposition: form-data; name="files"; filename="file.txt"
Content-Type: text/plain

This is a simple text file
--12345--

Тестирование с помощью Postman

Почтальон может использоваться для вызова действия и проверки кода на стороне сервера. Это довольно просто и, в основном, пользовательский интерфейс. Создайте новый запрос и выберите данные формы в Body-Tab. Теперь вы можете выбрать между текстом и file для каждой части запроса.

0
задан WangHongjian 28 March 2019 в 01:31
поделиться