Aore.ApiKit
1.0.0
dotnet add package Aore.ApiKit --version 1.0.0
NuGet\Install-Package Aore.ApiKit -Version 1.0.0
<PackageReference Include="Aore.ApiKit" Version="1.0.0" />
<PackageVersion Include="Aore.ApiKit" Version="1.0.0" />
<PackageReference Include="Aore.ApiKit" />
paket add Aore.ApiKit --version 1.0.0
#r "nuget: Aore.ApiKit, 1.0.0"
#:package Aore.ApiKit@1.0.0
#addin nuget:?package=Aore.ApiKit&version=1.0.0
#tool nuget:?package=Aore.ApiKit&version=1.0.0
Aore.ApiKit
生产环境可直接使用的 .NET 外部接口调用核心库:用统一的链式 API 快速调用外部 HTTP/HTTPS 接口与 SOAP WebService(动态构建协议 XML),内建重试、超时、调用日志(可插拔)、HttpClient 连接复用、XML 安全解析(拒绝 DTD/外部实体)、SSRF 防护开关与凭证脱敏。
版本 1.0.0 | 唯一外部依赖:
Newtonsoft.Json 13.0.3目标框架:netstandard2.0·net462·net472·net48·net8.0·net9.0·net10.0(单包多目标,条件编译消化平台差异)
特性总览
- 链式请求:动词、请求头、查询参数、认证、超时、重试一行搞定(Flurl 风格体验,独立实现)
- 双模式错误处理:异常模式(快速失败)/ Result 模式(
Try*不抛异常,逐调用判定) - 动词 × 正文格式全覆盖:JSON / XML / 表单 / 文本 / multipart,各动词均有专用便捷方法
- 认证全家桶:Basic / Bearer / API Key / Cookie / Windows 集成认证 / OAuth2 客户端凭证(令牌缓存 + 并发单飞)/ 客户端证书(mTLS)
- 重试策略:固定/线性/指数退避 + 抖动 +
Retry-After遵循 + 状态码白名单 +OnRetry回调 - 超时体系:单次尝试超时(每次重试独立计时)+ 总调用超时(覆盖全部尝试与响应体读取);调用方取消与库超时严格区分
- 调用日志:每次调用记录请求参数与响应数据;委托 /
IAoreCallLogger接口 / 内置 Sink(Console/File 按日滚动/Trace/Composite)三种接入;自动脱敏与截断;日志异常永不影响业务调用 - SOAP WebService:SOAP 1.1/1.2 动态报文构建(XmlWriter)、SOAPAction 推导、WS-Security UsernameToken(Digest/Text)、WS-Addressing、Fault 统一解析、
?WSDL自动命名空间、DataSet/DataTable兼容 - 请求模板:
AoreApiKit.Template(baseUrl)——一个服务一个模板,复用协议/IP/头/认证/超时,每个 API 只传路径与参数(MES/ERP 场景) - 三级设置继承:全局 → 命名客户端 → 请求,逐级覆盖(写时复制,纯读取请求零额外深拷贝)
- 同步方法:全 API 同步/异步双形态(同步上下文安全,防死锁)
- 安全内建:scheme 白名单恒开(仅 http/https)、XML 安全解析(拒绝 DOCTYPE/ENTITY/外部实体,不可关闭)、SSRF 私网阻断开关、JSON/XML/表单凭证脱敏
- 质量:0 警告 0 错误构建(
TreatWarningsAsErrors+ 全量分析器)、net8.0 + net48 双平台 250+ 项测试全绿(含真实服务端到端实测)
安装
dotnet add package Aore.ApiKit
<PackageReference Include="Aore.ApiKit" Version="1.0.0" />
常用 using(重要):
using Aore.ApiKit; // AoreApiKit / AoreKitRequest / AoreResponse / 扩展方法
using Aore.ApiKit.Soap; // SoapCaller / SoapParam / SoapVersion / AsDataTable
using Aore.ApiKit.Logging; // IAoreCallLogger / AoreCallLoggers / AoreCallLog
using Aore.ApiKit.Exceptions; // 异常体系
using Aore.ApiKit.Auth; // OAuth2ClientCredentials 等认证扩展
30 秒快速上手
using Aore.ApiKit;
// HTTP:GET + JSON 反序列化(非 2xx 抛 AoreHttpException)
var user = await "https://api.example.com/users/42".GetJsonAsync<User>();
// HTTP:POST JSON
await "https://api.example.com/users".PostJsonAsync(new { name = "tom" });
using Aore.ApiKit.Soap;
// SOAP:动态调用 WebService
var soap = new SoapCaller("http://esb.example.com/OrderService.asmx")
.WithNamespace("http://tempuri.org/");
var r = await soap.CallAsync("GetOrder", new SoapParam("orderNo", "SO2026"));
Console.WriteLine(r.Value("Status"));
HTTP 调用
四种调用入口
// 1) 字符串快捷入口(一行调用)
var dto = await "https://api.example.com/users/42".GetJsonAsync<User>();
// 2) 门面入口(推荐:链式配置后发送)
var resp = await AoreApiKit.Request("https://api.example.com/users")
.SetQueryParam("page", 2)
.WithHeader("X-Trace-Id", traceId)
.GetAsync();
// 3) 命名客户端(连接复用 + 客户端级设置)
var resp2 = await AoreApiKit.Request(url, "mes-service").GetAsync();
// 4) 请求模板(一个服务一个模板,见下文)
var resp3 = await AoreApiKit.Template("http://mes:8080/api/v1").Request("/users/1").GetAsync();
动词 × 参数格式矩阵
| 动词 \ 格式 | URL 查询串 | JSON body | XML body | 表单 | 文本 | multipart |
|---|---|---|---|---|---|---|
| GET | SetQueryParam ✅ |
SendAsync(Get, content)(net8+;netfx 平台限制) |
同左 | — | 同左 | 同左 |
| POST | ✅ | PostJsonAsync[<T>] |
PostXmlAsync |
PostFormAsync |
PostStringAsync |
PostMultipartAsync[<T>] |
| PUT | ✅ | PutJsonAsync[<T>] |
PutXmlAsync |
SendAsync(Put, …) |
同左 | 同左 |
| PATCH | ✅ | PatchJsonAsync[<T>] |
PatchXmlAsync |
SendAsync(Patch, …) |
同左 | 同左 |
| DELETE | ✅ | DeleteJsonAsync[<T>] |
SendAsync(Delete, …) |
同左 | 同左 | 同左 |
| HEAD / OPTIONS | ✅ | — | — | — | — | — |
约定(DR-010):GetAsync 等"返回响应"的方法不因状态码抛异常;GetJsonAsync 等"返回数据"的方法非 2xx 抛 AoreHttpException。矩阵外的组合用万能方法 SendAsync(method, content) / SendAsync(method, () => content工厂, logBody)。
// 读取 201 响应体
var created = await AoreApiKit.Request(url).PostJsonAsync<CreateResult>(new { name = "tom" });
// DELETE 携带 JSON 条件("带条件删除"类接口)
var del = await AoreApiKit.Request(url + "/42").DeleteJsonAsync<DeleteResult>(new { reason = "dup" });
// 表单登录
await AoreApiKit.Request(url + "/login").PostFormAsync(new { username = "tom", password = pwd });
// 原生内容(工厂重载重试安全;第二个参数为日志正文)
var resp = await AoreApiKit.Request(url).SendAsync(
AoreHttpMethod.Post,
() => new StringContent(jsonText, Encoding.UTF8, "application/json"),
jsonText,
cancellationToken);
URL 构建(路径段与查询参数自动转义)
var request = AoreApiKit.Request("https://api.example.com")
.AppendPathSegment("users") // 中文/空格/斜杠自动转义;已整体预编码的片段原样保留
.SetQueryParam("page", 2) // 标量(InvariantCulture)
.SetQueryParam("tag", "a b&c") // 特殊字符自动转义
.SetQueryParams(new { source = "app", debug = true }) // 匿名对象/字典批量
.SetQueryParam("draft", null); // value=null 移除该参数
Console.WriteLine(request.Url); // https://api.example.com/users?page=2&tag=a%20b%26c&source=app&debug=True
request.Url.GetQueryParam("page"); // "2"(取值自动解码)
响应处理(AoreResponse)
var response = await AoreApiKit.Request(url).GetAsync();
using (response) // 实现 IDisposable
{
(int)response.StatusCode; // 状态码
response.IsSuccessStatusCode; // 含 AllowHttpStatus 白名单扩展
response.Headers["Content-Type"]; // 响应头+内容头合并视图
response.ElapsedMs; // 总耗时(毫秒,含重试)
response.CallId; // 调用唯一标识(跨重试不变,与日志对应)
await response.GetStringAsync(); // 文本
await response.GetBytesAsync(); // 字节
await response.GetStreamAsync(); // 流(大响应不整包缓冲)
await response.ReadJson<User>(); // JSON 反序列化(失败抛 AoreParsingException)
await response.ReadXml(); // 安全 XML(拒绝 DTD/实体)
response.EnsureSuccessStatusCode(); // 非 2xx 抛 AoreHttpException(消息含响应体预览)
}
Result 模式与异常体系
var result = await "https://api.example.com/users/42".TryGetJsonAsync<User>();
if (result.IsSuccess)
{
var user = result.Value; // 反序列化数据
}
else
{
var status = (result.Error as AoreHttpException)?.StatusCode; // 分类处理
result.Response?.Dispose(); // HTTP 失败时 Response 保持未释放,由调用方处置
}
// 同族:TrySendAsync / TryPostJsonAsync<T>(及同步版 TrySend / TryGetJson / TryPostJson)
| 异常类型 | 触发场景 |
|---|---|
AoreUrlException |
URL 非法 / scheme 不支持(构造期快速失败) |
AoreSecurityException |
安全策略(SSRF 私网阻断、XML 含 DTD) |
AoreTimeoutException |
请求超时(含单次尝试与总超时) |
AoreTransportException |
网络传输失败(连接拒绝/DNS/中断) |
AoreHttpException |
响应状态码非成功(含响应体预览) |
AoreParsingException |
JSON/XML 解析失败(含 RawPreview 原文预览) |
均继承 AoreApiKitException,统一携带 CallId(与调用日志对应);SOAP Fault 另有 SoapFaultException(携带解析后的 Fault)。
认证
// Basic(自动 Base64)
request.WithBasicAuth("tom", "s3cret");
// Bearer 令牌
request.WithBearerToken("eyJ...");
// API Key(自定义头)
request.WithApiKey("X-Api-Key", "key-1");
// Cookie(多枚自动合并为一个 Cookie 头)
request.WithCookie("session", "abc").WithCookie("locale", "zh-CN");
// Windows 集成认证(内网 IIS + Negotiate)
request.WithCredentials(CredentialCache.DefaultCredentials);
// OAuth2 客户端凭证模式(provider 创建一次跨请求复用;令牌内存缓存、到期前刷新、并发单飞)
var provider = new OAuth2ClientCredentials(
tokenEndpoint, clientId, clientSecret,
scopes: "read write",
authStyle: OAuthTokenAuthStyle.RequestBody); // 或 BasicHeader(凭证放 Basic 头)
request.WithOAuth2(provider); // 每次请求自动附加 Bearer
// 一次性用法:request.WithOAuth2ClientCredentials(endpoint, clientId, clientSecret);
// 双向 TLS / 自签名(net48/net8+;高风险开关仅限测试环境)
request.WithClientCertificate(new X509Certificate2(pfxPath, pwdFromEnv));
request.WithInsecureSkipTlsVerify();
超时、重试与取消
var response = await AoreApiKit.Request(url)
.WithTimeout(TimeSpan.FromSeconds(10)) // 单次尝试超时(每次重试独立计时)
.WithTotalTimeout(TimeSpan.FromSeconds(30)) // 总调用超时:覆盖校验/钩子/全部尝试/重试等待/响应体读取
.WithRetry(3, RetryBackoff.Exponential, policy =>
{
policy.BaseDelay = TimeSpan.FromMilliseconds(200);
policy.MaxDelay = TimeSpan.FromSeconds(5);
policy.Jitter = 0.2; // ±20% 抖动
policy.RetryOnTimeout = false; // 超时重试需显式开启(幂等性由调用方决策)
policy.OnRetry = (attempt, delay, reason) => log(attempt, delay, reason);
})
.GetAsync();
// 重试白名单默认 408/429/500/502/503/504;遵循服务端 Retry-After 头
// 状态码白名单:把额外状态码视为成功
request.AllowHttpStatus(404, 409);
// 调用方取消(与库超时严格区分:取消抛 OperationCanceledException,超时抛 AoreTimeoutException)
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
await AoreApiKit.Request(url).GetJsonAsync<User>(cts.Token);
生产建议:每次业务调用设置
WithTotalTimeout总超时兜底——未设置时单次尝试超时约束到响应头与库内采集,调用方后续的流式读取遵循其传入的取消令牌。
调用日志(记录请求参数与响应数据)
// 方式一:委托(最轻接入;每次调用多条日志,重试时每次尝试各一条,CallId 跨重试不变)
request.WithCallLogger(entry =>
{
entry.Tags["OrderId"] = orderId; // 附加业务标识
logger.Info(entry.Summary()); // 单行摘要(时间/阶段/URL/状态/耗时)
});
// 方式二:内置 Sink
AoreApiKit.Settings.Logger = AoreCallLoggers.File(@"logs\api-call.log"); // 按日滚动 api-yyyyMMdd.log
AoreApiKit.Settings.Logger = AoreCallLoggers.Console(AoreCallLogFormat.Json); // 结构化单行
AoreApiKit.Settings.Logger = AoreCallLoggers.Composite(console, fileLogger); // 组合分发
// 方式三:实现 IAoreCallLogger 对接任意日志平台(库零日志框架依赖,不绑定 Serilog/NLog/MEL)
public sealed class MyCallLogger : IAoreCallLogger
{
public void Log(AoreCallLog entry) => myLogger.Info(entry.Summary());
}
request.WithCallLogger(new MyCallLogger());
日志自动脱敏与截断(可通过 AoreSettings.LogRedaction 配置):
- 请求/响应头:
Authorization/Cookie/Set-Cookie/Proxy-Authorization - XML/SOAP 元素:
Password/Passwd/Nonce/Token/Secret - JSON 键值 / 表单键值:
password/token/api_key/access_token/client_secret等 - 正文超过
MaxLoggedBodyLength(默认 4096 字符)自动截断并标注;日志器抛出的异常被库隔离,绝不影响业务调用
请求模板(一个服务一个模板)
典型场景:调用 MES/ERP 等固定服务——协议、IP、端口、请求头、认证、超时都一样,仅 URL 与参数不同。
// 服务模板:配置一次(并发安全),整组 API 复用
var mes = AoreApiKit.Template("http://mes:8080/api/v1")
.WithHeader("X-App", "mes-gateway")
.WithBasicAuth("svc", "pwd") // 也支持 Bearer/ApiKey/Windows/OAuth2
.WithTimeout(TimeSpan.FromSeconds(10))
.WithTotalTimeout(TimeSpan.FromSeconds(30))
.WithRetry(2)
.WithCallLogger(entry => auditLog.Write(entry.Summary()));
// 每个 API 只传不同路径与参数
var u1 = await mes.Request("/users/1").GetJsonAsync<User>();
var u2 = await mes.Request("/users/2").GetJsonAsync<User>();
// 请求级仍可覆盖模板级(仅覆盖本次请求);传绝对地址则整体覆盖模板地址
var special = await mes.Request("/users/3").WithTimeout(TimeSpan.FromSeconds(3)).GetAsync();
SOAP WebService
var soap = new SoapCaller("http://esb.example.com/OrderService.asmx")
.WithNamespace("http://tempuri.org/") // 已知命名空间推荐显式指定;未知用 WithAutoNamespace()(自动取 ?WSDL 并缓存)
.WithWsSecurity(ws => ws // WS-Security UsernameToken(默认 Digest;Text 依赖 HTTPS 保护)
.Username("svc-user")
.Password("svc-pass", WsPasswordType.Digest))
.WithRetry(2) // SOAP 与 HTTP 共用同一弹性管线
.WithCallLogger(entry => auditLog.Write(entry.Summary())); // Category=SOAP
// 参数类型全集:标量(InvariantCulture)/日期/decimal/复杂对象/集合/字典/XElement/nil
var response = await soap.CallAsync(
"GetOrders",
new SoapParam("beginDate", new DateTime(2026, 1, 1)),
new SoapParam("minAmount", 199.99m),
new SoapParam("pager", new { PageIndex = 1, PageSize = 20 }), // 复杂对象 → 子元素
new SoapParam("statuses", new[] { "NEW", "PAID" }), // 集合 → 同名重复元素
new SoapParam("filter", new Dictionary<string, object?> { ["warehouse"] = "WH01" }));
if (response.HasFault)
{
Console.WriteLine(response.Fault); // Code/Reason/Actor/Node/Detail 统一解析(1.1 与 1.2)
}
else
{
response.Value("Status"); // 值访问器(不区分命名空间与大小写)
response.Value<decimal>("Total"); // 强类型取值(InvariantCulture)
var orders = response.ReadXml<OrderListDto>("GetOrdersResult"); // XmlSerializer 强类型映射
var table = response.Result!.AsDataTable(); // DataTable/DataSet 兼容(net462-48/net8+,绑定 DataGridView)
response.Dispose(); // 读完释放底层 HTTP 响应
}
// 其余能力:WithSoapVersion(SoapVersion.V12) / WithSoapHeader(自定义头) / WithAddressing(WS-Addressing) /
// SendRawAsync(原始信封) / soap.Call(同步) / SOAPAction 显式覆盖 WithSoapAction
SOAP 参数类型映射:标量按 xsd 规范(bool→true/false、DateTime→xsd:dateTime 带时区、byte[]→Base64);匿名对象/实体类按公共可读属性递归;字典键为子元素名;集合同名重复;XElement 原样写入;null → xsi:nil;DataSet/DataTable/IXmlSerializable/带 XmlRoot·XmlType 标注类型 走 XmlSerializer 兜底。参数值全部经 XmlWriter 写入(自动转义),不存在 XML 注入。
同步 API
全 API 同步/异步双形态;同步版内部做了同步上下文安全调度(WinForms/WPF/ASP.NET 经典/控制台均可直接调用)。请勿自行用 .Result / .Wait() 包装本库异步 API,直接用同步版。
var response = AoreApiKit.Request(url).Get(); // 不断言
var dto = AoreApiKit.Request(url).GetJson<User>(); // 断言 + 反序列化
var created = AoreApiKit.Request(url).PostJson<User>(new { name = "tom" });
var result = AoreApiKit.Request(url).TryGetJson<User>(); // Result 模式(不抛异常)
var r = soap.Call("GetOrders", new SoapParam("id", 1)); // SOAP 同步
高级用法
三级设置继承与命名客户端
// 全局(进程级基线)
AoreApiKit.Settings.Timeout = TimeSpan.FromSeconds(15);
// 命名客户端(首次注册生效;同名的所有请求共享连接池,避免套接字耗尽)
AoreApiKit.Clients.GetOrAdd("mes", settings =>
{
settings.Timeout = TimeSpan.FromSeconds(10);
settings.Retry.MaxAttempts = 3;
settings.DefaultHeaders["X-From-Client"] = "gateway";
});
var resp = await AoreApiKit.Request(url, "mes").GetAsync();
// 请求级覆盖(WithClient 切换后已记录的请求级变更自动重放)
await AoreApiKit.Request(url, "mes").WithTimeout(TimeSpan.FromSeconds(5)).GetAsync();
钩子(发送前/响应后)
await AoreApiKit.Request(url)
.OnBeforeRequest((context, ct) => // 每次尝试都会执行(重试也生效);可附加动态签名/令牌头
{
context.AddHeader("X-Signature", Sign(context.CallId));
return Task.CompletedTask;
})
.OnAfterResponse((context, resp, ct) => // 埋点/熔断统计;抛异常会中断调用
{
metrics.Record(resp.StatusCode, resp.ElapsedMs);
return Task.CompletedTask;
})
.GetAsync();
上传与下载
// multipart 上传:文本/JSON 字段 + byte[]/流文件(流式文件重试需可 Seek;稳妥用 byte[])
await AoreApiKit.Request(url).PostMultipartAsync(b =>
{
b.AddString("note", "说明");
b.AddJson("meta", new { owner = "tom" });
b.AddFile("file", "a.txt", fileBytes, "text/plain");
});
// 流式下载:边下边处理不整包缓冲;释放返回的流即释放底层响应
using (var stream = await AoreApiKit.Request(url).GetStreamAsync())
{
await stream.CopyToAsync(File.Create("report.bin"));
}
自定义 HttpClient / 接入 Polly
// 调用方自备 HttpClient(设置仍由本库管理)
request.UsingHttpClient(myHttpClient);
// handler 工厂接入第三方 DelegatingHandler(如 Polly)
var client = new AoreKitClient("polly", settings, () => new PolicyHandler(new HttpClientHandler()));
安全内建
| 能力 | 说明 |
|---|---|
| scheme 白名单 | 仅 http/https,恒开不可关(ftp://、file:// 构造期即拒绝) |
| XML 安全解析 | SafeXml:DtdProcessing=Prohibit + XmlResolver=null + 8M 字符上限,不可关闭,杜绝 XXE |
| SSRF 私网阻断 | settings.Security.BlockPrivateNetworks = true(默认关闭):环回/私有/链路本地/保留地址(IPv4+IPv6 内置网段表)发送前校验;开启后自动禁用重定向 |
| 凭证脱敏 | 日志与异常消息均无 Authorization/Cookie 明文;JSON/XML/表单正文凭证字段掩码 |
| TLS | net462-48 启动时调用 AoreApiKit.EnsureTls12();InsecureSkipTlsVerify 为显式高风险开关(日志标记 insecure_tls) |
已知限制:SSRF 校验与实际建连存在两次 DNS 解析,短 TTL 域名理论上存在 DNS rebinding 窗口,严格场景请用 IP 直连。
生产注意事项
- 总超时兜底:建议每次业务调用
.WithTotalTimeout(...)(见"超时、重试与取消") - 内网地址:SSRF 阻断默认关闭(内网 ESB/WebService 是常态场景);面向不可信输入的服务端应用请开启
- net462-48:启动时调用
AoreApiKit.EnsureTls12();注意System.Net.Http绑定重定向 - netfx GET 携带 body:平台限制会统一包装为
AoreTransportException,此类服务建议改 POST - WSS 摘要:按 OASIS 规范使用 SHA1(互操作要求,不可更换)
- multipart 流式上传:重试要求流可 Seek(不可 Seek 流在重试时显式失败);更稳妥用
AddFile(name, fileName, byte[]) - handler 级设置(TLS 校验/客户端证书/代理/Cookie/凭证/重定向/解压/连接超时)建议直接用命名客户端;请求级覆盖会按指纹缓存专用客户端(证书按 Thumbprint 精确区分)
- 高频调用:日志 Sink 建议自定义异步缓冲实现(内置 File Sink 为锁内写入、常驻 StreamWriter、按日滚动)
- AOT/裁剪:当前基于 Newtonsoft 反射序列化,未声明 NativeAOT 支持
许可证
MIT · Copyright © 2026 WEI.ZHOU (Willis). All rights reserved.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 is compatible. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.6.2
- Newtonsoft.Json (>= 13.0.3)
-
.NETFramework 4.7.2
- Newtonsoft.Json (>= 13.0.3)
-
.NETFramework 4.8
- Newtonsoft.Json (>= 13.0.3)
-
.NETStandard 2.0
- Newtonsoft.Json (>= 13.0.3)
-
net10.0
- Newtonsoft.Json (>= 13.0.3)
-
net8.0
- Newtonsoft.Json (>= 13.0.3)
-
net9.0
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 86 | 9/26/2026 |