. Более простое решение, сильно вдохновленное ответом 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--
Почтальон может использоваться для вызова действия и проверки кода на стороне сервера. Это довольно просто и, в основном, пользовательский интерфейс. Создайте новый запрос и выберите данные формы в Body-Tab. Теперь вы можете выбрать между текстом и file для каждой части запроса.