---
title: "Создание вспомогательных классов JsonRequestSender для отправки запросов JSON"
canonical: https://ontargit.com/kz/sozdanie-jsonrequestsender/
date: 2021-04-21 17:30:57
description: "Создание вспомогательных классов JsonRequestSender для отправки запросов JSON для уменьшения количества кода, требуемого для подключения"
keywords: "JsonRequestSender"
categories: [ERP]
---

# Описание

Для уменьшения количества кода, требуемого для подключения к любым JSON веб-сервисам, мною были написаны классы отправляющие JSON запросы. Один из них называется RequestSender, и используется для подключения к веб-сервисам не требующим аутентификации OAuth. Второй называется RequestSender_OAuth, — это наследник RequestSender, который используется с теми веб-сервисами, где необходима аутентификация OAuth, в том числе и с веб-сервисами D365O.

# Подготовительный этап

- __

1. Подключить ссылку на проект, содержащий классы AuthenticationUtility из статьи ****[**«Создание классов AuthenticationUtility»**.](https://ontargit.com/sozdanie-klassov-authentication-utility/)

- __

2. Добавить пакет Newtonsoft.JSON как описано в статье **«Добавление пакета Newtonsoft.Json»**.

# Принцип работы

Для начала работы с классами RequestSender и RequestSender_OAuth, нужно создать объект одного из этих классов. В случае с RequestSender, в конструктор необходимо передать базовый URL ресурса, на котором развернут веб-сервис. В случае с RequestSender_OAuth, конструктор вызывается без аргументов, а базовый URL берется из AuthenticationUtility Microsoft.

Классы RequestSender и RequestSender_OAuth содержат два публичных метода. Рассмотрим функционал и переменные каждого из них.

Copy to Clipboard
Syntax Highlighterpublic OutputContract sendGETRequest(string requestMessageText)

Метод отправляет запрос типа GET на веб сервис.

При вызове нужно указать на месте дженерика класс контракта, в который будет преобразована полученая в ответе JSON строка.

Также в качестве аргумента нужно передать requestMessageText – строку текста запроса. Содержит относительный URL запроса и, характерные для GET запросов, значения переменных запроса, передаваемые прямо в строке URL.

Copy to Clipboard
Syntax Highlighterpublic OutputContract sendPOSTRequest_(

string requestMessageText,

InputContract inputContract)

Метод отправляет запрос типа POST на веб сервис.

При вызове нужно указать на месте дженериков и классы контрактов, – один будет отправлен на вход вебсервиса, а во второй будет преобразована полученая в ответе JSON строка.

Также в качестве параметров нужно передать следующее:

Copy to Clipboard
Syntax Highlighter	HttpClient client = new HttpClient();

Для этой переменной задается базовый адрес запроса.

Copy to Clipboard
Syntax Highlighterclient.BaseAddress = baseAddress;

Если вебсервис требует OAuth аутентификации, как в случае с сервисами D365O, к переменной клиента добавляется хедер аутентификации, как один из параметров массива DefaultRequestHeaders.

Copy to Clipboard
Syntax Highlightertry

 {

 client.DefaultRequestHeaders.Add(

 OAuthHelper.OAuthHeader,

 OAuthHelper.GetAuthenticationHeader());

 }

 catch (Exception ex)

 {

 throw new Exception(

 string.Format(

 “Error. Authorization failed with exception ‘{0}'”,

 ex.Message));

 }

Как видно, для генерации хедера используется метод из AuthenticationUtility Microsoft. Если введенные в классе ClientConfiguration логин и пароль неверные, или же если пользователь не имеет доступа к приложению Azure, ID которого указан в том же классе, программа прекратит работу.

Далее создается переменная класса HttpRequestMessage, отвечающая за запрос, отправляемый клиентом. При создании переменной запроса, нужно указать тип запроса и относительный адрес метода веб-сервиса.

Например для запроса типа GET:

Copy to Clipboard
Syntax HighlighterHttpRequestMessage requestMessage = new HttpRequestMessage(

 HttpMethod.Get,

 requestMessageText);

В случае запроса типа POST, в теле запроса должны быть переданы данные в формате JSON. Для этого производится сериализация класса контракта, содержащего эти данные.

Copy to Clipboard
Syntax HighlighterHttpRequestMessage request = new HttpRequestMessage(

 HttpMethod.Post,

 requestMessageText);

 request.Content = new StringContent(

 JsonConvert.SerializeObject(inputContract),

 Encoding.UTF8,

 “application/json”);

Далее с помощью переменной клиента вызывается метод веб-сервиса, на который настроен запрос. При этом вызов метода делается в блоке try-catch, что предотвращает падение программы в случае ошибки подключения к веб-сервису по указаному URL.

Copy to Clipboard
Syntax HighlighterHttpResponseMessage responseMessage = null;

 try

 {

 responseMessage = client.SendAsync(requestMessage).Result;

 }

 catch (Exception ex)

 {

 throw new Exception(

 string.Format(

 “Error. JSON request failed with exception ‘{0}'”,

 ex.Message));

 }

Полученный результат содержит в себе, в частности, статус выполнения (успешно/неуспешно), а также выходные данные веб-сервиса, или сообщение с текстом ошибки, если что-то пошло не так. Для обработки результата проверяется статус выполнения запроса, после чего считывается его содержимое. Как в случае с получением выходных данных, так и в случае с получением текста ошибки, эта информация получается в виде строки JSON.

Copy to Clipboard
Syntax Highlighterif (responseMessage.IsSuccessStatusCode)

 {

 string responseMessageResult = responseMessage.Content.ReadAsStringAsync().Result;

Для преобразования полученной строки JSON в объекты контрактов используется класс JsonConvert.

Copy to Clipboard
Syntax Highlightertry

 {

 outputContract = JsonConvert.DeserializeObject(

 responseMessageResult,

 new JsonSerializerSettings()

 {

 MissingMemberHandling = MissingMemberHandling.Error

 });

 }

 catch (Exception ex)

 {

 throw new Exception(

 string.Format(

 “Error. Output JSON parse failed with exception ‘{0}’. JSON in response message: ‘{1}'”,

 ex.Message,

 responseMessageResult));

 }

Как видно, в классе JsonConvert вызывается метод DeserializeObject. При этом передается дженерик класс (или примитивный тип), в который необходимо преобразовать строку JSON, и два аргумента, – строка JSON и параметры преобразования. В параметрах преобразования, в том числе, можно выбрать реакцию на несоответствие дженерик класса со структурой строки JSON. Если, как в примере, параметр MissingMemberHandling равен MissingMemberHandling.Error, метод бросит ошибку при несоответствии структур.

Десериализацию строки JSON лучше производить в блоке try-catch.

Copy to Clipboard
Syntax Highlightertry

 {

 outputContract = JsonConvert.DeserializeObject(

 responseMessageResult,

 new JsonSerializerSettings()

 {

 MissingMemberHandling = MissingMemberHandling.Error

 });

 }

 catch (Exception ex)

 {

 throw new Exception(

 string.Format(

 “Error. Output JSON parse failed with exception ‘{0}’. JSON in response message: ‘{1}'”,

 ex.Message,

 responseMessageResult));

 }

# Программный код

Copy to Clipboard
Syntax Highlighterusing Newtonsoft.Json;

using System;

using System.Net.Http;

using System.Text;

namespace JsonRequestSender

{

 public class RequestSender

 {

 protected Uri baseAddress;

 public RequestSender(Uri baseAddress)

 {

 this.baseAddress = baseAddress;

 }

 public OutputContract sendGETRequest(string requestMessageText)

 {

 HttpClient client = this.buildHttpClient();

 HttpRequestMessage requestMessage = this.buildGETHttpRequestMessage(requestMessageText);

 return this.getResponse(

 client,

 requestMessage);

 }

 public OutputContract sendPOSTRequest(

 string requestMessageText,

 InputContract inputContract)

 {

 HttpClient client = this.buildHttpClient();

 HttpRequestMessage requestMessage = this.buildPOSTHttpRequestMessage(

 requestMessageText,

 inputContract);

 return this.getResponse(

 client,

 requestMessage);

 }

 protected virtual HttpClient buildHttpClient()

 {

 HttpClient client = new HttpClient();

 client.BaseAddress = baseAddress;

 return client;

 }

 protected HttpRequestMessage buildGETHttpRequestMessage(string requestMessageText)

 {

 return new HttpRequestMessage(

 HttpMethod.Get,

 requestMessageText);

 }

 protected HttpRequestMessage buildPOSTHttpRequestMessage(

 string requestMessageText,

 InputContract inputContract)

 {

 HttpRequestMessage request = new HttpRequestMessage(

 HttpMethod.Post,

 requestMessageText);

 request.Content = new StringContent(

 JsonConvert.SerializeObject(inputContract),

 Encoding.UTF8,

 “application/json”);

 return request;

 }

 protected OutputContract getResponse(

 HttpClient client,

 HttpRequestMessage requestMessage)

 {

 OutputContract outputContract = default(OutputContract);

 HttpResponseMessage responseMessage = null;

 try

 {

 responseMessage = client.SendAsync(requestMessage).Result;

 }

 catch (Exception ex)

 {

 throw new Exception(

 string.Format(

 “Error. JSON request failed with exception ‘{0}'”,

 ex.Message));

 }

 if (responseMessage.IsSuccessStatusCode)

 {

 string responseMessageResult = responseMessage.Content.ReadAsStringAsync().Result;

 try

 {

 outputContract = JsonConvert.DeserializeObject(

 responseMessageResult,

 new JsonSerializerSettings()

 {

 MissingMemberHandling = MissingMemberHandling.Error

 });

 }

 catch (Exception ex)

 {

 throw new Exception(

 string.Format(

 “Error. Output JSON parse failed with exception ‘{0}’. JSON in response message: ‘{1}'”,

 ex.Message,

 responseMessageResult));

 }

 }

 else

 {

 if (responseMessage.StatusCode == System.Net.HttpStatusCode.Unauthorized)

 {

 throw new Exception(

 string.Format(

 “Error. JSON request failed with status code ‘{0}’. Probably user’s security role doesn’t have enough rights to call this webservice”,

 responseMessage.StatusCode));

 }

 else if (responseMessage.StatusCode == System.Net.HttpStatusCode.InternalServerError)

 {

 throw new Exception(

 string.Format(

 “Error. JSON request failed with status code ‘{0}’. Probably JSON structure is wrong”,

 responseMessage.StatusCode));

 }

 else

 {

 throw new Exception(

 string.Format(

 “Error. JSON request failed with status code ‘{0}'”,

 responseMessage.StatusCode));

 }

 }

 return outputContract;

 }

 }

} 

using AuthenticationUtility;

using System;

using System.Net.Http;

namespace JsonRequestSender

{

 public class RequestSender_OAuth : RequestSender

 {

 public RequestSender_OAuth() : base(new Uri(ClientConfiguration.Default.UriString)) { }

 protected override HttpClient buildHttpClient()

 {

 HttpClient client = base.buildHttpClient();

 try

 {

 client.DefaultRequestHeaders.Add(

 OAuthHelper.OAuthHeader,

 OAuthHelper.GetAuthenticationHeader());

 }

 catch (Exception ex)

 {

 throw new Exception(

 string.Format(

 “Error. Authorization failed with exception ‘{0}'”,

 ex.Message));

 }

 return client;

 }

 }

}

_

# Подготовил статью:

ДыкухаБорис Александрович

Senior Software Developer, OntargIT

[](https://www.linkedin.com/in/borys-dykukha-59a7a2a9)