Как я могу передать словарь в MultipartFormData? - PullRequest
2 голосов
/ 27 марта 2019

У меня есть контроллер, который принимает как IFormFile, так и объект (класс с именем Document), используя данные формы.

Это контроллер:

[HttpPost]
public async Task<IActionResult> Post(IFormFile file, [FromForm] Document document, CancellationToken token = default)
{
    ...
}

Вот как выглядит класс Document:

public class Document
{
    public Guid DocumentId { get; set; }
    public string Name { get; set; }
    public DocumentType DocumentType { get; set; } = DocumentType.Unsorted;
    public Dictionary<string, string> Metadata { get; set; } = new Dictionary<string, string>();
}

И это код, который POST s передает данные указанному контроллеру:

using (var multipartContent = new MultipartFormDataContent())
{
    multipartContent.Add(new StringContent(document.DocumentId.ToString()), FormDataKeys.DocumentId);
    multipartContent.Add(new StringContent(document.DocumentType.ToString()), FormDataKeys.DocumentType);
    multipartContent.Add(new StreamContent(file), FormDataKeys.File, document.Name);

    using (var apiResult = await _httpClient.PostAsync("api/documents", multipartContent, token))
    {
        var content = await apiResult.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<StoreDocumentResult>(content);
    }
}

Это работает, оба IFormFile и свойства параметра [FromForm] Document в контроллере заполняются при отправке запроса POST.Только я не знаю, как мне заполнить Metadata свойство Document?Как я могу передать Dictionary<string, string> в MultipartFormData?

1 Ответ

2 голосов
/ 27 марта 2019

Самый простой способ - сериализовать словарь в строку с JSON и затем десериализовать его.

     var settings = new JsonSerializerSettings();
    settings.Formatting = Formatting.Indented;
    settings.ContractResolver = new DictionaryAsArrayResolver();

    // serialize
    string json = JsonConvert.SerializeObject(Document.Metadata, settings);

, а затем

   multipartContent.Add(new StringContent(json ), FormDataKeys.Metadata );

Для десериализации вы можете использовать что-то вроде этого:

var d  = JsonConvert.DeserializeObject<Dictionary<String,String>>(json, settings);

Другим вариантом является создание подкласса HttpContent и переопределение метода SerializeToStreamAsync.В этом случае вы можете записать в предоставленный буфер все, что захотите.

class DictionaryContent: HttpContent
{
   public Object Value { get; }

   public DictionaryContent( Object value)
   {
       Value = value;
       Headers.ContentType = .. You must provide the desired content type.
   }

   protected override Task SerializeToStreamAsync( Stream stream, TransportContext context )
   {
        using ( var buffer = new BufferStreamWriter( stream, 4096 ) )
        {
            var writer = new JsonWriter( buffer, JsonSettings.Default );
            writer.WriteValue( Value ); // HERE You can do anything that you want.
        }

        return Task.CompletedTask;
   }
}
...