Попытка захватить Digicert Automation API с помощью Refit HttpClient Factory.
Когда объявлен мой метод интерфейса, который возвращает строку
Task<string> GetAgentList([Body] GetAgentListReq req);
По возвращенной строке я вижу, что получаю ожидаемый результат JSON от API. В частности, член data
возвращает член agentList
с массивом агентов JSON.
Когда я меняю метод интерфейса, чтобы вернуть определенный класс результата
Task<AgentList> GetAgentList([Body] GetAgentListReq req);
Десериализация происходит без создания исключения, но член data.agentList
имеет значение null.
Поскольку прямая десериализация строки с использованием System.Text.Json.JsonSerializer.Deserialize<AgentList>
также возвращает объект с нулевым членом data.agentList
, я буду действовать, исходя из предположения, что мой класс в чем-то неправильный. Если я решу эту проблему, я опубликую ответ.
Вот мой интерфейс и классы:
using Refit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Digicert.Automation.API.Client
{
[Headers("X-DC-DEVKEY: redacted")]
public interface IDigicertAutomation
{
[Post("/agent/basicdetails")]
Task<ApiResponse<IEnumerable<AgentSummary>>> GetAgentSummary(AgentSummaryReq req);
[Post("/agent/list")]
//Task<string> GetAgentList([Body] GetAgentListReq req);
Task<AgentList> GetAgentList([Body] GetAgentListReq req);
}
public class AgentSummaryReq
{
public required string licensekey { get; set; }
public int accountId { get; set; }
public int divisionId { get; set; }
}
public class GetAgentListReq
{
public int accountId { get; set; }
public class Criterion
{
public required string key;
public required string operation;
public required List<string> value;
}
public required Criterion[] searchCriteriaList { get; set; }
public required int[] divisionIds { get; set; }
public int startIndex;
public int pageSize;
public required Dictionary<string, string> sorting { get; set; }
}
public class Error
{
public required string message { get; set; }
public required List<string> detailedMessage { get; set; }
public required string errorCode { get; set; }
}
public class AgentSummary
{
public required Error error { get; set; }
public class Data
{
public required string licenseKey { get; set; }
public required string agentName { get; set; }
public int updatePreference { get; set; }
public required string stateString { get; set; }
public required string agentVersion { get; set; }
public bool updateAvailable { get; set; }
public bool publishUpgradeOption { get; set; }
public required string emailAddresses { get; set; }
}
public required Data data { get; set; }
}
public class AgentList
{
public required string error { get; set; }
public class AgentListdata
{
public required List<AgentInfo> agentList;
}
public required AgentListdata data {get;set;}
}
public class AgentInfo
{
public int agentId { get; set; }
public required string accountId { get; set; }
public required string divisionId { get; set; }
public required string hostname { get; set; }
public required string agentName { get; set; }
public required string status { get; set; }
public required string sensorName { get; set; }
public required string type { get; set; }
public required string agentLicense { get; set; }
public int updatePreference { get; set; }
public bool updateAvailable { get; set; }
}
}
И мое консольное приложение, вызывающее API:
using Microsoft.Extensions.Hosting;
using Refit;
using Digicert.Automation.API;
using Microsoft.Extensions.DependencyInjection;
using Digicert.Automation.API.Client;
using static Digicert.Automation.API.Client.GetAgentListReq;
using System.Diagnostics;
namespace ConsoleApp1
{
internal class Program
{
static async Task Main(string[] args)
{
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
{
services
.AddRefitClient<IDigicertAutomation>()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("https://caas.digicert.com/automationws/v1/"));
}).Build();
var automationClient = host.Services.GetRequiredService<IDigicertAutomation>();
var sorting = new Dictionary<string, string>
{
{ "AGENTNAME", "ASC" },
};
var req = new GetAgentListReq() { accountId = 1349264, searchCriteriaList = Array.Empty<Criterion>(), divisionIds = Array.Empty<int>(), startIndex = 0, pageSize = 50, sorting = sorting };
var results = await automationClient.GetAgentList(req);
//var result = results.Content;
//var x = results.RequestMessage?.Content;
//if (result?.data != null && result?.data.agentList != null)
//{
// foreach (var a in result.data.agentList)
// {
// Console.Out.WriteLine(a.agentName);
// }
//}
}
}
}
Если вы замените возвращаемый тип GetAgentList
на Task<ApiResponse<AgentList>>
, вы сможете получить больше информации о том, почему десериализация не удалась.
Кажется, это общее имя... перезапуск с нуля с ответом второго пилота «дайте мне классы для десериализации этого JSON» вернул меня в нужное русло.
Это был лучший набор классов для десериализации возвращаемого JSON. Некоторые из них помечены как обязательные, а другие помечены как обнуляемые. Обязательные были добавлены сначала для подавления предупреждений, затем, очевидно, некоторые поля отсутствовали в возвращаемом JSON, поэтому мне пришлось вернуть этим свойствам значение nullable.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Digicert.Automation.API.Client
{
using System.Collections.Generic;
using System.Text.Json.Serialization;
public class AgentList
{
public required object Error { get; set; }
public required Data Data { get; set; }
}
public class Data
{
public double totalCount { get; set; }
public double totalPages { get; set; }
public required List<Agent> AgentList { get; set; }
}
public class Agent
{
public double AgentId { get; set; }
public required string AccountId { get; set; }
public required string DivisionId { get; set; }
public required string Hostname { get; set; }
public required string AgentName { get; set; }
public required string Status { get; set; }
public string? SensorLicenseKey { get; set; }
public required string SensorName { get; set; }
public string? HostIp { get; set; }
public required string Type { get; set; }
public string? AgentLicense { get; set; }
public double UpdatePreference { get; set; }
public bool UpdateAvailable { get; set; }
public required string Tag { get; set; }
public string? OsName { get; set; }
// Add additional fields as necessary
}
}
Если вы посмотрите документацию, то увидите, что вам не хватает двух параметров
totalCount
иtotalPages
в типеAgentListdata
.