Данные POST JSON с HttpWebRequest

У меня был код ниже для вызова метода POST с телом json, но я получаю The remote server returned an error: (400) Bad Request., когда он выполняет код using (var response = (HttpWebResponse)request.GetResponse()).

Мой код работал нормально только в том случае, если необработанные данные не требуются.

Пример json

{"redirect":"www.google.com","subscriptionTypeId":76670001,"marketingCampaign":{"conversionId":12345,"agency":"","medium":"","name":"","source":""}}

Мой код

public static bool HTTPRequest(string URL, RequestMethod CallMethod, Hashtable RequestHeaders, string json, ref StringBuilder httpRequestHeader, ref string jsonResponse, bool preparepurchaseFlag)
    {
        try
        {
            var request = (HttpWebRequest)WebRequest.Create(URL);
            request.Method = CallMethod.ToString();
            request.ContentLength = 0;

            //Header
            if (RequestHeaders != null)
            {
                foreach (string ParamKey in RequestHeaders.Keys)
                {
                    if (ParamKey == "Content-Type")
                    {
                        request.ContentType = RequestHeaders[ParamKey].ToString();
                    }
                    else if (ParamKey.ToLower() == "accept")
                    {
                        request.Accept = RequestHeaders[ParamKey].ToString();
                    }
                    else
                    {
                        request.Headers[ParamKey] = RequestHeaders[ParamKey].ToString();
                        
                    }
                }
            }
            //Body
            if (!string.IsNullOrEmpty(json))
            {
                var encoding = new UTF8Encoding();
                var bytes = Encoding.GetEncoding("UTF-8").GetBytes(json);

                request.ContentLength = bytes.Length;
                using (var writeStream = request.GetRequestStream())
                {
                    writeStream.Write(bytes, 0, bytes.Length);
                }
            }
            //Log Request Header
            httpRequestHeader.AppendLine("curl --location --request " + request.Method.ToString());
            httpRequestHeader.AppendLine(request.RequestUri.ToString());

            foreach (string ParamKey in RequestHeaders.Keys)
            {
                httpRequestHeader.Append("--header ");
                httpRequestHeader.AppendLine(ParamKey + ": " + RequestHeaders[ParamKey].ToString());
            }

            if (preparepurchaseFlag)
            {
                httpRequestHeader.Append("--data-raw ");
                httpRequestHeader.AppendLine(json);
            }

            using (var response = (HttpWebResponse)request.GetResponse())
            {
                var responseValue = string.Empty;
                if (response.StatusCode != HttpStatusCode.OK)
                {
                    var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
                    throw new Exception(message);
                }

                var httpWebResponse = (HttpWebResponse)request.GetResponse();
                using (var responseStream = httpWebResponse.GetResponseStream())
                {
                    if (responseStream != null)
                        using (var reader = new StreamReader(responseStream))
                        {
                            responseValue = reader.ReadToEnd();
                        }
                }
                jsonResponse = responseValue;
                return true;
            }
        }
        catch (WebException e)
        {
            //catch
            return false;
        }
        catch (Exception ex)
        {
            //catch
        }
    }
catch (WebException e) -> почему бы вам не прочитать ответ в улове и не посмотреть, что сервер говорит о вашем запросе?
ProgrammingLlama 13.10.2022 09:33

@ProgrammingLlama хммм, я думаю, вы указываете на очень ценный комментарий для меня, потому что плохих запросов много, спасибо.

RogerSK 13.10.2022 10:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Использование HttpWebRequest для новых разработок не рекомендуется Microsoft. Вместо этого вы должны использовать класс HttpClient, который значительно упрощает процесс.

Вот краткая оболочка, которую я создал, чтобы помочь вам начать работу.

public class HttpClientWrapper
{
    private readonly HttpClient _httpClient;

    public HttpClientWrapper(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<T> SendRequestAsync<T>(
        string relativeUrl,
        HttpMethod method,
        object? payload,
        IDictionary<string, string>? queryParameters,
        IDictionary<string, string>? headers)
    {
        if (string.IsNullOrEmpty(relativeUrl))
        {
            throw new ArgumentNullException(nameof(relativeUrl));
        }

        string relativeUrlWithArguments = AddArgumentsToUrl(relativeUrl, queryParameters);

        HttpRequestMessage requestMessage = CreateHttpRequestMessage(relativeUrlWithArguments, method, payload, headers);

        var response = await _httpClient.SendAsync(requestMessage);

        response.EnsureSuccessStatusCode();

        var textResponse = await response.Content.ReadAsStringAsync();

        if (string.IsNullOrEmpty(textResponse))
        {
            throw new InvalidOperationException("Empty response returned by server.");
        }

        T? data = JsonSerializer.Deserialize<T>(textResponse);

        if (data == null)
        {
            throw new InvalidOperationException("Failed to deserialize the response to your model.");
        }

        return data;
    }

    private static string AddArgumentsToUrl(string url, IDictionary<string, string>? queryParameters)
    {
        queryParameters ??= new Dictionary<string, string>();
        string argumentsString = string.Join("&", queryParameters.Select(arg => $"{arg.Key} = {arg.Value}"));
        return !string.IsNullOrEmpty(argumentsString) ? $"{url}?{argumentsString}" : url;
    }

    private static HttpRequestMessage CreateHttpRequestMessage(string relativeUrl,
                                                               HttpMethod method,
                                                               object? payload,
                                                               IDictionary<string, string>? headers)
    {
        var httpRequestMessage = new HttpRequestMessage(method, relativeUrl)
        {
            Content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")
        };

        if (headers != null)
        {
            foreach (var header in headers)
            {
                httpRequestMessage.Headers.Add(header.Key, header.Value);
            }
        }

        return httpRequestMessage;
    }
}

Простое использование класса выше может быть:

private static HttpClient httpClient = new HttpClient();
var httpClientWrapper = new HttpClientWrapper(httpClient);
var response = httpClientWrapper.SendRequestAsync<ResponseClass>(
    relativeUrl: "http://myurl.com",
    method: HttpMethod.Post,
    payload: YourObjectThatWillBeSerializedToJson,
    queryParameters: new Dictionary<string, string>
    {
        { "query1", "value1" }
    },
    headers: new Dictionary<string, string>
    {
        { "Accept", "AcceptValue" },
        { "Header2", "Header2Value" }
    });

Где ResponseClass — это тип, в который будет десериализован ответ JSON. Для payload вы должны отправить свой объект, который будет сериализован в JSON. Параметры запроса и заголовки являются необязательными и могут быть переданы как словарь. Вы можете изменить функциональность этой оболочки по своему вкусу. Например, если вы хотите передать уже сериализованный JSON в качестве полезной нагрузки, вам придется немного изменить метод CreateHttpRequestMessage.

Важное примечание: рекомендуется использовать IHttpClientFactory для управления экземплярами HttpClient. Я создал статический HttpClient в своем примере, что тоже может подойти. Но важная часть здесь заключается в том, чтобы НЕ создавать новый экземпляр HttpClient для каждого вашего запроса.

Привет, сэр, я попробую, однако могу ли я узнать причину или какое-либо сравнение, говорящее о том, почему Microsoft рекомендует не использовать HttpWebRequest для новой разработки.

RogerSK 14.10.2022 05:25

Другие вопросы по теме