Как установить заголовок Content-Type для запроса HttpClient с MultipartFormDataContent? - PullRequest
0 голосов
/ 23 мая 2018

Я посмотрел исходный код MS в соответствии с их интерпретацией: сам HttpClient не имеет «Content-Type», только контент должен иметь content-type.Кажется логичным, за исключением случаев, когда вы имеете дело с MultipartFormDataContent.MultipartFormDataContent полностью игнорирует следующий код:

string boundary = "--" + GenerateRandomString();
using (var content = new MultipartFormDataContent(boundary))
{
    content.Headers.ContentType = new MediaTypeHeaderValue($"multipart/form-data");
    content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("boundry", boundary));
    ...
}

В запросе отсутствует «Content-Type».И также игнорирует:

string boundary = "--" + GenerateRandomString();
using (var content = new MultipartFormDataContent(boundary))
{
    content.Headers.Remove("Content-Type");
    content.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary);
    ...
}    

При попытке установить его на HttpClient

client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary);

выдает следующую ошибку:

System.InvalidOperationException: 'Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.'

Я могу найти множество примеров того, как сделать это с помощью StringContent, но ни одного с MultipartFormDataContent.MultipartFormDataContent позволяет устанавливать Content-Type и Content-Disposition для каждого поля, мне это нужно больше на уровне клиента.Мне нужен заголовок, который выглядит примерно так:

accept: application/json
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Authorization: Basic ZXlKbGRDSTZJakUxTWpZNU9UTXpOTnpkMjl5WkNJNklqa3haRGxtWkdKa1lUazRaVEJqWmpsalpUaGxNV1V3TXpOalxuWmpCbE1tVXhJaXdpZFhObGNpSTZJbUZrYldsdUluMD1cbjo=
Cache-Control: no-cache

Многие API сторонних разработчиков требуют тега border, чтобы он мог различать отдельные поля отправляемых данных.Проверка здесь по запросу кажется немного чрезмерной.Даже TryAddWithoutValidation не работает (может быть, ошибка?).Я понимаю, что, возможно, можно интерпретировать RFC7578 так, чтобы он говорил, что он не должен быть обязательным, но упрямый, не позволяя, чтобы он мне тоже не казался правильным.Кто-нибудь еще сталкивался с этой проблемой и решал ее.

1 Ответ

0 голосов
/ 24 мая 2018

Изначально я думал, что это ошибка HttpClient.Я добавил протоколирование, чтобы захватить запрос и ответ.В этом журнале отсутствовали заголовки, что заставило меня поверить, что отсутствующий заголовок контента «multi-part / form-data» был проблемой, и причина, по которой используемый мной API продолжал говорить мне, что он не может найти обязательное поле.Оказывается, проблема заключается в том, как API обрабатывает отправляемые данные, когда они состоят из нескольких частей / данных формы.После сравнения моего запроса HttpWebRequest и запроса HttpClient в fiddler я обнаружил следующее различие в отправляемых данных:

HttpWebRequest

----vekhftkcthxr
Content-Disposition: form-data; name="name";

d30-20180524

HttpClient

----bcgifxyjkmkw
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=name

d30-20180524

Я создаю запрос HttpWebRequest вручную, поэтому я включил кавычки и конечные точки с запятой.Запрос HttpClient построен для меня и не включает в себя дополнительные кавычки и точку с запятой.Поэтому используемый мной API не очень хорошо работает с запросом, генерируемым HttpClient, даже если запрос технически корректен.

Спасибо Panagiotis Kanavos за то, что показали мне мою ошибку.

...