Возможно ли, чтобы HttpClient отправил контент или тело для запроса GET?

В настоящее время для отправки параметризованного запроса GET в интерфейс API я пишу следующий код:

api/master/city/filter?cityid=1&citycode='ny'

Но я вижу, что существует ограничение на длину URL-адреса 2083 символа.

Чтобы этого избежать, я хотел бы отправить параметры в формате json в тело контента для запроса GET.

Однако я вижу, что ни один из методов Get для HttpClient не позволяет отправить тело контента. Для POST я видел, что в HttpClient с именем PostAsync существует метод, который позволяет использовать тело контента.

Есть ли способ отправить параметры для запроса GET не в URL-адресе, чтобы избежать ограничения длины URL-адреса?

Ответ 1

Пожалуйста, прочтите предостережения в конце этого ответа о том, почему запросы HTTP GET с телами, как правило, не рекомендуется.


  • Если вы используете .NET Core, стандартный HttpClient может сделать это "из коробки". Например, чтобы отправить запрос GET с телом JSON:

    HttpClient client = ...
    
    ...
    
    var request = new HttpRequestMessage
    {
        Method = HttpMethod.Get,
        RequestUri = new Uri("some url"),
        Content = new StringContent("some json", Encoding.UTF8, ContentType.Json),
    };
    
    var response = await client.SendAsync(request).ConfigureAwait(false);
    response.EnsureSuccessStatusCode();
    
    var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    
  • .NET Framework не поддерживает это из коробки (вы получите исключение ProtocolViolationException если попробуете приведенный выше код). К счастью, Microsoft предоставила пакет System.Net.Http.WinHttpHandler, который поддерживает эту функциональность - просто установите и используйте его вместо стандартного HttpClientHandler при создании ваших экземпляров HttpClient:

    var handler = new WinHttpHandler();
    var client = new HttpClient(handler);
    
    <rest of code as above>
    

    Ссылка: https://github.com/dotnet/corefx/issues/28135#issuecomment-467261945


Предостережения:

  • HTTP GET с телом является несколько необычной конструкцией, которая попадает в серую область спецификации HTTP - конечный результат заключается в том, что многие более старые части программного обеспечения либо вообще не могут обработать такой запрос, либо явно отклонят его, потому что считают, что быть уродливым. Вы должны быть уверены, что конечная точка, для которой вы пытаетесь отправить такой запрос, поддерживает его, или в лучшем случае вы получите код ошибки HTTP; в худшем случае тело будет молча выброшено. Это может привести к некоторой головокружительной отладке!
  • Кэширующие прокси-серверы, особенно старые, могут кэшировать GET-запросы, основываясь только на URL, потому что они не ожидают присутствия тела. Это может привести либо к тому, что самый последний запрос будет кешироваться навсегда (что приведет к поломке вашего программного обеспечения), либо к тому, что единственный когда-либо кешированный запрос - самый последний выданный (что помешает кешированию работать должным образом). Опять же, это может быть очень больно, чтобы понять.