Для JSON структура построения кода несколько иная. Нам необходимо подготовить строку текста в некотором формате, затем вызвать сервис, передав ему эту строку, после чего получить ответ также в виде строки и разобрать полученную строку.
Тем не менее, нам также нужно создать проект на C# типа Console Application (или любого типа, который может быть запущен напрямую пользователем)
Процедура аутенфикации такая же, поэтому также необходимо добавлять в проект ссылку на библиотеку Microsoft.IdentityModel.Clients.ActiveDirectory путем выполнения команды
Цитата:
Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
в Package Manager Console
Строку можно готовить (сериализовать) и разбирать (десериализовать) как "ручками", так и при помощи библиотеки Newtonsoft.Json, которую аналогичным способом (как и Microsoft.IdentityModel.Clients.ActiveDirectory) можно добавить в Package Manager Console путем выполнения команды
Цитата:
Install-Package Newtonsoft.Json
Также в проект необходимо добавить из заготовок от Microsoft следующие файлы:
ClientConfiguration.cs (с правками по параметрам авторизации)
OAuthHelper.cs (без правок)
А теперь начинаются различия.
Для начала нам понадобится класс JsonUtil, который будет генерировать нам URL-адрес, добавляя в него группу сервисов, сам сервис и операции сервиса.
X++:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tutorial_ConsumeServiceJSON
{
public class JsonUtil
{
public const string OAuthHeader = "Authorization";
public static string GetJsonServiceGroupURL(string aosUriString, string serviceGroupName)
{
var serviceUriStringTemplate = "{0}/api/services/{1}";
var serviceUriString = string.Format(serviceUriStringTemplate, aosUriString.TrimEnd('/'), serviceGroupName);
return serviceUriString;
}
public static string GetJsonServiceNameURL(string aosUriString, string serviceGroupName, string serviceName)
{
var serviceUriStringTemplate = "{0}/{1}";
var serviceUriString = string.Format(serviceUriStringTemplate, GetJsonServiceGroupURL(aosUriString, serviceGroupName), serviceName);
return serviceUriString;
}
public static string GetJsonOperationURL(string aosUriString, string serviceGroupName, string serviceName, string functionName)
{
var serviceUriStringTemplate = "{0}/{1}";
var serviceUriString = string.Format(serviceUriStringTemplate, GetJsonServiceNameURL(aosUriString, serviceGroupName, serviceName), functionName);
return serviceUriString;
}
}
}
Далее, нам нужно:
1. Описать класс-контракт, описанный на X++, т.к. в отличие от SOAP - здесь не передаются объекты, а значит для получения карточки клиента - нам потребуется повторное описание полей карточки.
Это делается так:
X++:
public class Tutorial_CustServiceContract
{
public string parmCustAccount { get; set; }
[JsonProperty("parmCustAccountName")]
public string custAccountName { get; set; }
public string parmCustGroupId { get; set; }
}
Здесь при помощи атрибута JsonProperty мы можем определять названия переменных, которые не соответствуют названиям переменных, приходящих из сервиса (из сервиса нам приходят parmCustAccountName, а мы не обязаны использовать внутри C# именно такое название. Зато если мы используем именно такое название, то мы не обязаны использовать атрибут JsonProperty)
2. Библиотека Newtonsoft.Json умеет сериализовать / десериализовать только классы, поэтому если нам надо передать в сервис обычное значение (например, код клиента), то чтобы вручную не формировать строку JSON - нужно создать классы, состоящие из одной этой переменной:
X++:
public class ParmCustAccount
{
[JsonProperty("_custAccount")]
public string custAccount { get; set; }
}
public class ParmCustGroupId
{
[JsonProperty("_custGroupId")]
public string custGroupId { get; set; }
}
3. При передаче строки JSON в сервис - необходимо устанавливать свойство SendChunked в true для корректной обработки символов в Юникоде.
В итоге у меня получилось 2 класса:
JsonServices, который вызывает веб-сервис
X++:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using AuthenticationUtility;
namespace Tutorial_ConsumeServiceJSON
{
public class Tutorial_CustServiceContract
{
public string parmCustAccount { get; set; }
[JsonProperty("parmCustAccountName")]
public string custAccountName { get; set; }
public string parmCustGroupId { get; set; }
}
public class ParmCustAccount
{
[JsonProperty("_custAccount")]
public string custAccount { get; set; }
}
public class ParmCustGroupId
{
[JsonProperty("_custGroupId")]
public string custGroupId { get; set; }
}
public class JsonServices
{
public const string serviceGroupName = "Tutorial_CustServiceGroup";
public const string serviceName = "Tutorial_CustService";
public const string getCustDetailName = "getCustDetail";
public const string getCustListOfGroupName = "getCustListOfGroup";
string aosUriString;
string bearerKey;
[JsonProperty("return")]
public Tutorial_CustServiceContract[] serviceContracts { get; set; }
[JsonProperty("return")]
public Tutorial_CustServiceContract serviceContract { get; set; }
public JsonServices()
{
aosUriString = ClientConfiguration.Default.ActiveDirectoryResource;
bearerKey = OAuthHelper.GetAuthenticationHeader(true);
}
private HttpWebRequest CreateRequest(string _address)
{
HttpWebRequest webRequest;
webRequest = (HttpWebRequest)HttpWebRequest.Create(_address);
webRequest.Method = "POST";
// the request will be empty.
webRequest.ContentLength = 0;
webRequest.Headers.Set(JsonUtil.OAuthHeader, bearerKey);
return webRequest;
}
private string ReadJsonResponse(HttpWebRequest _request)
{
string jsonString;
using (HttpWebResponse webResponse = (HttpWebResponse)_request.GetResponse())
{
using (Stream stream = webResponse.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
jsonString = reader.ReadToEnd();
}
}
}
return jsonString;
}
public Tutorial_CustServiceContract getCustDetail(string _custAccount)
{
string operationURL = JsonUtil.GetJsonOperationURL(aosUriString, serviceGroupName, serviceName, getCustDetailName);
ParmCustAccount parmCustAccount = new ParmCustAccount();
parmCustAccount.custAccount = _custAccount;
string jsonCustAccount = JsonConvert.SerializeObject(parmCustAccount);
HttpWebRequest webRequest;
webRequest = CreateRequest(operationURL);
webRequest.SendChunked = true;
using (Stream stream = webRequest.GetRequestStream())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(jsonCustAccount);
writer.Flush();
}
}
string jsonResponse = ReadJsonResponse(webRequest);
serviceContract = JsonConvert.DeserializeObject<Tutorial_CustServiceContract>(jsonResponse);
return serviceContract;
}
public Tutorial_CustServiceContract[] getCustListOfGroup(string _custGroupId)
{
string operationURL = JsonUtil.GetJsonOperationURL(aosUriString, serviceGroupName, serviceName, getCustListOfGroupName);
ParmCustGroupId parmCustGroupId = new ParmCustGroupId();
parmCustGroupId.custGroupId = _custGroupId;
string jsonCustGroupId = JsonConvert.SerializeObject(parmCustGroupId);
HttpWebRequest webRequest;
webRequest = CreateRequest(operationURL);
webRequest.SendChunked = true;
using (Stream stream = webRequest.GetRequestStream())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(jsonCustGroupId);
writer.Flush();
}
}
string jsonResponse = ReadJsonResponse(webRequest);
serviceContracts = JsonConvert.DeserializeObject<Tutorial_CustServiceContract[]>(jsonResponse);
return serviceContracts;
}
}
}
Program, который вызывает JsonServices
X++:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using AuthenticationUtility;
namespace Tutorial_ConsumeServiceJSON
{
class Program
{
static void Main(string[] args)
{
JsonServices jsonServices = new JsonServices();
Tutorial_CustServiceContract contract;
Tutorial_CustServiceContract[] contracts;
contract = jsonServices.getCustDetail("RUMF-000001");
Console.WriteLine(string.Format("{0} | {1} | {2}", contract.parmCustAccount, contract.custAccountName, contract.parmCustGroupId));
contracts = jsonServices.getCustListOfGroup("Орг");
foreach (Tutorial_CustServiceContract iterator in contracts)
{
Console.WriteLine(string.Format("{0} | {1} | {2}", iterator.parmCustAccount, iterator.custAccountName, iterator.parmCustGroupId));
}
Console.ReadLine();
}
}
}
Соответственно, билдим, запускаем, смотрим.
Результат, как и в случае с SOAP должен быть таким же