Составная запись AspNetCore3 с файлом и словарем не работает должным образом - PullRequest
1 голос
/ 04 октября 2019

У меня есть метод post в контроллере AspNetCore3, который принимает как файл, так и словарь с метаданными. Проблема, с которой я сталкиваюсь, состоит в том, что словарь не десериализуется автоматически, и я должен сделать это вручную

        /// <summary>Upload an attachment</summary>
        [HttpPost("{id}")]
        [DisableRequestSizeLimit]
        public async Task<ActionResult> UploadAttachment(
            [FromRoute] string id, 
            IFormFile file, 
            [FromForm] Dictionary<string, string> metadata)
        {
            // TODO figure out why the metadata isn't loaded/deserialized from the form data
            Dictionary<string, string> dict = null;
            if (Request.Form.TryGetValue(nameof(metadata), out var values))
            {
                try
                {
                    dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(values);
                }
                catch { /* ignore */ }
            }

            await m_service.UploadAttachment(id, file, dict);
            return Ok();
        }

У кого-нибудь есть идея, почему десериализация по умолчанию не работает?

1 Ответ

1 голос
/ 04 октября 2019

Зависит от того, как вы делаете почтовый запрос. Если вы используете Почтальон, то он должен выглядеть следующим образом в соответствии с вашей подписью действия UploadAttachment ()

enter image description here

, вот необработанный запрос или запрос:

POST / HTTP/1.1
Host: localhost:62117
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Host: localhost:62117
Content-Length: 294    

Content-Disposition: form-data; name="metadata[key1]"

value1
------WebKitFormBoundary7MA4YWxkTrZu0gW--,
Content-Disposition: form-data; name="metadata[key1]"

value1
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Content-Disposition: form-data; name="metadata[key2]"

value2
------WebKitFormBoundary7MA4YWxkTrZu0gW--

Если вы хотите передать содержимое json, например

enter image description here

, вам необходимо добавить пользовательское связующее для модели

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

        if (bindingContext.HttpContext.Request.HasFormContentType)
        {
            var form = bindingContext.HttpContext.Request.Form;
            var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(form[bindingContext.FieldName].ToString());
            bindingContext.Result = ModelBindingResult.Success(data);
        }
    }
}

тогда

public async Task<ActionResult> UploadAttachment(
  [FromRoute] string id, 
  IFormFile file, 
  [FromForm][ModelBinder(typeof(DictionaryBinder))] Dictionary<string, string> metadata)
...