Как установить Content-Type при создании HttpRequest? [Дубликат]

Еще один подход к возврату значения из асинхронной функции - передать объект, который сохранит результат от асинхронной функции.

Вот пример того же:

var async = require("async");

// This wires up result back to the caller
var result = {};
var asyncTasks = [];
asyncTasks.push(function(_callback){
    // some asynchronous operation
    $.ajax({
        url: '...',
        success: function(response) {
            result.response = response;
            _callback();
        }
    });
});

async.parallel(asyncTasks, function(){
    // result is available after performing asynchronous operation
    console.log(result)
    console.log('Done');
});

Я использую объект result для хранения значения во время асинхронной операции. Это позволяет получить результат даже после асинхронного задания.

Я использую этот подход много. Мне было бы интересно узнать, насколько хорошо этот подход работает, когда задействован результат обратно через последовательные модули.

479
задан Nikolai Samteladze 14 May 2015 в 17:36
поделиться

9 ответов

Тип содержимого - это заголовок содержимого, а не запроса, поэтому это не работает. AddWithoutValidation, как предложил Роберт Леви, может работать, но вы также можете установить тип содержимого при создании самого содержимого запроса (обратите внимание, что фрагмент кода добавляет «application / json» в двух местах - для заголовков Accept и Content-Type):

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://example.com/");
client.DefaultRequestHeaders
      .Accept
      .Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "relativeAddress");
request.Content = new StringContent("{\"name\":\"John Doe\",\"age\":33}",
                                    Encoding.UTF8, 
                                    "application/json");//CONTENT-TYPE header

client.SendAsync(request)
      .ContinueWith(responseTask =>
      {
          Console.WriteLine("Response: {0}", responseTask.Result);
      });
598
ответ дан Adel Helal 25 August 2018 в 02:02
поделиться
var content = new HttpContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", "utf-8"));
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("IEEE754Compatible", "true"));

Это все, что вам нужно.

0
ответ дан Alejandro 25 August 2018 в 02:02
поделиться

Для тех, кто не видел комментария Джонса к решению carlos ...

req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
106
ответ дан archgl 25 August 2018 в 02:02
поделиться

.Net пытается заставить вас подчиняться определенным стандартам, а именно, что заголовок Content-Type может быть указан только в запросах, имеющих контент (например, POST, PUT и т. д.). Поэтому, как указывали другие, предпочтительный способ установки заголовка Content-Type - через свойство HttpContent.Headers.ContentType .

С учетом сказанного некоторые API (такие как LiquidFiles Api , начиная с 2016-12-19) требует установки заголовка Content-Type для запроса GET. .Net не позволит устанавливать этот заголовок на самом запросе - даже используя TryAddWithoutValidation. Кроме того, вы не можете указать Content для запроса - даже если он имеет нулевую длину. Единственный способ, которым я мог бы обойти это, - прибегнуть к размышлениям. Код (в случае, если ему это еще нужно)

var field = typeof(System.Net.Http.Headers.HttpRequestHeaders)
    .GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static) 
  ?? typeof(System.Net.Http.Headers.HttpRequestHeaders) 
    .GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (field != null)
{
  var invalidFields = (HashSet<string>)field.GetValue(null);
  invalidFields.Remove("Content-Type");
}
_client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "text/xml");

Редактировать:

Как отмечено в комментариях, это поле имеет разные имена в разных версиях dll. В исходном коде на GitHub поле в настоящее время называется s_invalidHeaders. Пример был изменен для учета этого в предположении @David Thompson.

13
ответ дан erdomke 25 August 2018 в 02:02
поделиться

Дополнительная информация о .NET Core (после прочтения сообщения erdomke о настройке приватного поля для предоставления контента для запроса, который не имеет содержимого) ...

После отладки моего кода , Я не вижу, как частное поле устанавливается через отражение - поэтому я решил попробовать эту проблему.

Я пробовал следующий код, используя .Net 4.6:

HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, @"myUrl");
httpRequest.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpClient client = new HttpClient();
Task<HttpResponseMessage> response =  client.SendAsync(httpRequest);  //I know I should have used async/await here!
var result = response.Result;

И, как и ожидалось, я получаю агрегатное исключение с контентом "Cannot send a content-body with this verb-type."

Однако, если я делаю то же самое с .NET Core (1.1) - я не получаю исключения , Моя просьба была удовлетворительно удовлетворена моим серверным приложением, и тип контента был поднят.

Я был приятно удивлен этим, и я надеюсь, что это кому-то поможет!

11
ответ дан Jay 25 August 2018 в 02:02
поделиться

Вызовите AddWithoutValidation вместо Add (см. эту ссылку MSDN ).

В качестве альтернативы, я предполагаю, что API, который вы используете, действительно требует только этого для POST или PUT (не обычные запросы GET). В этом случае, когда вы вызываете HttpClient.PostAsync и передаете в HttpContent, установите это в свойстве Headers этого объекта HttpContent.

15
ответ дан Keith Pinson 25 August 2018 в 02:02
поделиться

попытайтесь использовать TryAddWithoutValidation

  var client = new HttpClient();
  client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
26
ответ дан SharpCoder 25 August 2018 в 02:02
поделиться

Если вы не возражаете против небольшой зависимости от библиотеки, Flurl.Http [раскрытие: я автор] делает этот uber-простой. Его метод PostJsonAsync выполняет как сериализацию содержимого, так и установку заголовка content-type, а ReceiveJson десериализует ответ. Если требуется заголовок accept, вам нужно будет установить это самостоятельно, но Flurl также предоставляет довольно чистый способ:

using Flurl.Http;

var result = await "http://example.com/"
    .WithHeader("Accept", "application/json")
    .PostJsonAsync(new { ... })
    .ReceiveJson<TResult>();

Flurl использует HttpClient и Json.NET под капотом, и это PCL, поэтому он будет работать на разных платформах.

PM> Install-Package Flurl.Http
38
ответ дан Todd Menier 25 August 2018 в 02:02
поделиться

Хорошо, это не HTTPClient, но если вы можете его использовать, WebClient довольно легко:

using (var client = new System.Net.WebClient())
 {
    client.Headers.Add("Accept", "application/json");
    client.Headers.Add("Content-Type", "application/json; charset=utf-8");
    client.DownloadString(...);
 }
0
ответ дан Ziba Leah 25 August 2018 в 02:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: