Skip to content

Commit 24bd01b

Browse files
committed
Replace SwashBuckle with Scalar, Replace JSON.NET from API Surface with STJ
1 parent 26ee2ff commit 24bd01b

32 files changed

+3534
-1031
lines changed

build/generate-client.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
curl -X POST https://generator3.swagger.io/api/generate \
22
-H 'content-type: application/json' \
33
-d '{
4-
"specURL" : "https://collector.exceptionless.io/docs/v2/swagger.json",
4+
"specURL" : "https://collector.exceptionless.io/docs/v2/openapi.json",
55
"lang" : "typescript-fetch",
66
"type" : "CLIENT",
77
"options" : {
@@ -11,4 +11,4 @@ curl -X POST https://generator3.swagger.io/api/generate \
1111
}
1212
},
1313
"codegenVersion" : "V3"
14-
}' --output exceptionless-ts.zip
14+
}' --output exceptionless-ts.zip

src/Exceptionless.Core/Configuration/AppOptions.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
using System.Diagnostics;
2+
using System.Text.Json.Serialization;
23
using Exceptionless.Core.Configuration;
34
using Exceptionless.Core.Extensions;
45
using Microsoft.Extensions.Configuration;
5-
using Newtonsoft.Json;
6-
using Newtonsoft.Json.Converters;
76

87
namespace Exceptionless.Core;
98

@@ -26,7 +25,7 @@ public class AppOptions
2625
/// </summary>
2726
public string? ExceptionlessServerUrl { get; internal set; }
2827

29-
[JsonConverter(typeof(StringEnumConverter))]
28+
[JsonConverter(typeof(JsonStringEnumConverter))]
3029
public AppMode AppMode { get; internal set; }
3130
public string AppScope { get; internal set; } = null!;
3231

src/Exceptionless.Core/Configuration/EmailOptions.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
using Exceptionless.Core.Extensions;
1+
using System.Text.Json.Serialization;
2+
using Exceptionless.Core.Extensions;
23
using Exceptionless.Core.Utility;
34
using Microsoft.Extensions.Configuration;
4-
using Newtonsoft.Json;
5-
using Newtonsoft.Json.Converters;
65

76
namespace Exceptionless.Core.Configuration;
87

@@ -26,7 +25,7 @@ public class EmailOptions
2625

2726
public int SmtpPort { get; internal set; }
2827

29-
[JsonConverter(typeof(StringEnumConverter))]
28+
[JsonConverter(typeof(JsonStringEnumConverter))]
3029
public SmtpEncryption SmtpEncryption { get; internal set; }
3130

3231
public string? SmtpUser { get; internal set; }

src/Exceptionless.Core/Models/Stack.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using System.Collections.ObjectModel;
22
using System.Diagnostics;
33
using System.Runtime.Serialization;
4+
using System.Text.Json.Serialization;
45
using Foundatio.Repositories.Models;
5-
using Newtonsoft.Json;
66
using Newtonsoft.Json.Converters;
77

88
namespace Exceptionless.Core.Models;
@@ -123,13 +123,26 @@ public static class KnownTypes
123123
}
124124
}
125125

126-
[JsonConverter(typeof(StringEnumConverter))]
126+
[JsonConverter(typeof(JsonStringEnumConverter))]
127+
[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
127128
public enum StackStatus
128129
{
129-
[EnumMember(Value = "open")] Open,
130-
[EnumMember(Value = "fixed")] Fixed,
131-
[EnumMember(Value = "regressed")] Regressed,
132-
[EnumMember(Value = "snoozed")] Snoozed,
133-
[EnumMember(Value = "ignored")] Ignored,
134-
[EnumMember(Value = "discarded")] Discarded
130+
[JsonStringEnumMemberName("open")]
131+
[EnumMember(Value = "open")]
132+
Open,
133+
[JsonStringEnumMemberName("fixed")]
134+
[EnumMember(Value = "fixed")]
135+
Fixed,
136+
[JsonStringEnumMemberName("regressed")]
137+
[EnumMember(Value = "regressed")]
138+
Regressed,
139+
[JsonStringEnumMemberName("snoozed")]
140+
[EnumMember(Value = "snoozed")]
141+
Snoozed,
142+
[JsonStringEnumMemberName("ignored")]
143+
[EnumMember(Value = "ignored")]
144+
Ignored,
145+
[JsonStringEnumMemberName("discarded")]
146+
[EnumMember(Value = "discarded")]
147+
Discarded
135148
}

src/Exceptionless.Web/Controllers/EventController.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Exceptionless.Web.Extensions;
1919
using Exceptionless.Web.Models;
2020
using Exceptionless.Web.Utility;
21+
using Exceptionless.Web.Utility.OpenApi;
2122
using FluentValidation;
2223
using Foundatio.Caching;
2324
using Foundatio.Queues;

src/Exceptionless.Web/Controllers/StackController.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
using McSherry.SemanticVersioning;
2222
using Microsoft.AspNetCore.Authorization;
2323
using Microsoft.AspNetCore.Mvc;
24-
using Newtonsoft.Json.Linq;
24+
using System.Text.Json;
2525

2626
namespace Exceptionless.Web.Controllers;
2727

@@ -131,14 +131,14 @@ public async Task<ActionResult> MarkFixedAsync(string ids, string? version = nul
131131
[HttpPost("mark-fixed")]
132132
[Consumes("application/json")]
133133
[ApiExplorerSettings(IgnoreApi = true)]
134-
public async Task<ActionResult> MarkFixedAsync(JObject data)
134+
public async Task<ActionResult> MarkFixedAsync(JsonDocument data)
135135
{
136136
string? id = null;
137-
if (data.TryGetValue("ErrorStack", out var value))
138-
id = value.Value<string>();
137+
if (data.RootElement.TryGetProperty("ErrorStack", out var errorStackProp))
138+
id = errorStackProp.GetString();
139139

140-
if (data.TryGetValue("Stack", out value))
141-
id = value.Value<string>();
140+
if (data.RootElement.TryGetProperty("Stack", out var stackProp))
141+
id = stackProp.GetString();
142142

143143
if (String.IsNullOrEmpty(id))
144144
return NotFound();
@@ -215,22 +215,22 @@ public async Task<IActionResult> AddLinkAsync(string id, ValueFromBody<string?>
215215
[HttpPost("add-link")]
216216
[Consumes("application/json")]
217217
[ApiExplorerSettings(IgnoreApi = true)]
218-
public async Task<IActionResult> AddLinkAsync(JObject data)
218+
public async Task<IActionResult> AddLinkAsync(JsonDocument data)
219219
{
220220
string? id = null;
221-
if (data.TryGetValue("ErrorStack", out var value))
222-
id = value.Value<string>();
221+
if (data.RootElement.TryGetProperty("ErrorStack", out var errorStackProp))
222+
id = errorStackProp.GetString();
223223

224-
if (data.TryGetValue("Stack", out value))
225-
id = value.Value<string>();
224+
if (data.RootElement.TryGetProperty("Stack", out var stackProp))
225+
id = stackProp.GetString();
226226

227227
if (String.IsNullOrEmpty(id))
228228
return NotFound();
229229

230230
if (id.StartsWith("http"))
231231
id = id.Substring(id.LastIndexOf('/') + 1);
232232

233-
string? url = data.GetValue("Link")?.Value<string>();
233+
string? url = data.RootElement.TryGetProperty("Link", out var linkProp) ? linkProp.GetString() : null;
234234
return await AddLinkAsync(id, new ValueFromBody<string?>(url));
235235
}
236236

src/Exceptionless.Web/Controllers/WebHookController.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
using Foundatio.Repositories;
1212
using Microsoft.AspNetCore.Authorization;
1313
using Microsoft.AspNetCore.Mvc;
14-
using Newtonsoft.Json.Linq;
14+
using System.Text.Json;
1515

1616
namespace Exceptionless.App.Controllers.API;
1717

@@ -101,10 +101,10 @@ public Task<ActionResult<WorkInProgressResult>> DeleteAsync(string ids)
101101
[HttpPost("~/api/v1/projecthook/subscribe")]
102102
[Consumes("application/json")]
103103
[ApiExplorerSettings(IgnoreApi = true)]
104-
public async Task<ActionResult<WebHook>> SubscribeAsync(JObject data, int apiVersion = 1)
104+
public async Task<ActionResult<WebHook>> SubscribeAsync(JsonDocument data, int apiVersion = 1)
105105
{
106-
string? eventType = data.GetValue("event")?.Value<string>();
107-
string? url = data.GetValue("target_url")?.Value<string>();
106+
string? eventType = data.RootElement.TryGetProperty("event", out var eventProp) ? eventProp.GetString() : null;
107+
string? url = data.RootElement.TryGetProperty("target_url", out var urlProp) ? urlProp.GetString() : null;
108108
if (String.IsNullOrEmpty(eventType) || String.IsNullOrEmpty(url))
109109
return BadRequest();
110110

@@ -139,9 +139,9 @@ public async Task<ActionResult<WebHook>> SubscribeAsync(JObject data, int apiVer
139139
[HttpPost("~/api/v1/projecthook/unsubscribe")]
140140
[Consumes("application/json")]
141141
[ApiExplorerSettings(IgnoreApi = true)]
142-
public async Task<IActionResult> UnsubscribeAsync(JObject data)
142+
public async Task<IActionResult> UnsubscribeAsync(JsonDocument data)
143143
{
144-
string? targetUrl = data.GetValue("target_url")?.Value<string>();
144+
string? targetUrl = data.RootElement.TryGetProperty("target_url", out var urlProp) ? urlProp.GetString() : null;
145145

146146
// don't let this anon method delete non-zapier hooks
147147
if (targetUrl is null || !targetUrl.StartsWith("https://hooks.zapier.com"))

src/Exceptionless.Web/Exceptionless.Web.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
<PackageReference Include="NEST.JsonNetSerializer" Version="7.17.5" />
2121
<PackageReference Include="OAuth2" Version="0.10.3" />
2222
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.0" />
23+
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.0" />
24+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
25+
<PackageReference Include="MiniValidation" Version="0.9.2" />
26+
<PackageReference Include="NEST.JsonNetSerializer" Version="7.17.5" />
27+
<PackageReference Include="OAuth2" Version="0.10.3" />
28+
<PackageReference Include="Scalar.AspNetCore" Version="2.11.1" />
2329
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
2430
<PackageReference Include="Serilog.Enrichers.Span" Version="3.1.0" />
2531
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
@@ -35,6 +41,7 @@
3541
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.14.0" />
3642
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.14.0-beta.2" />
3743
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="10.1.0" />
44+
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.13.0-beta.1" />
3845
</ItemGroup>
3946
<ItemGroup>
4047
<ProjectReference Include="..\Exceptionless.Insulation\Exceptionless.Insulation.csproj" />

src/Exceptionless.Web/Hubs/WebSocketConnectionManager.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using System.Collections.Concurrent;
22
using System.Net.WebSockets;
33
using System.Text;
4+
using System.Text.Json;
45
using Exceptionless.Core;
5-
using Newtonsoft.Json;
6+
using Exceptionless.Web.Utility;
67

78
namespace Exceptionless.Web.Hubs;
89

@@ -11,12 +12,15 @@ public class WebSocketConnectionManager : IDisposable
1112
private static readonly ArraySegment<byte> _keepAliveMessage = new(Encoding.ASCII.GetBytes("{}"), 0, 2);
1213
private readonly ConcurrentDictionary<string, WebSocket> _connections = new();
1314
private readonly Timer? _timer;
14-
private readonly JsonSerializerSettings _serializerSettings;
15+
private readonly JsonSerializerOptions _serializerOptions;
1516
private readonly ILogger _logger;
1617

17-
public WebSocketConnectionManager(AppOptions options, JsonSerializerSettings serializerSettings, ILoggerFactory loggerFactory)
18+
public WebSocketConnectionManager(AppOptions options, ILoggerFactory loggerFactory)
1819
{
19-
_serializerSettings = serializerSettings;
20+
_serializerOptions = new JsonSerializerOptions
21+
{
22+
PropertyNamingPolicy = LowerCaseUnderscoreNamingPolicy.Instance
23+
};
2024
_logger = loggerFactory.CreateLogger<WebSocketConnectionManager>();
2125
if (!options.EnableWebSockets)
2226
return;
@@ -119,7 +123,7 @@ private Task SendMessageAsync(WebSocket socket, object message)
119123
if (!CanSendWebSocketMessage(socket))
120124
return Task.CompletedTask;
121125

122-
string serializedMessage = JsonConvert.SerializeObject(message, _serializerSettings);
126+
string serializedMessage = JsonSerializer.Serialize(message, _serializerOptions);
123127
Task.Factory.StartNew(async () =>
124128
{
125129
if (!CanSendWebSocketMessage(socket))
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
using System.ComponentModel.DataAnnotations;
2-
using Newtonsoft.Json;
3-
using Newtonsoft.Json.Serialization;
2+
using System.Text.Json.Serialization;
43

54
namespace Exceptionless.Web.Models;
65

76
// NOTE: This will bypass our LowerCaseUnderscorePropertyNamesContractResolver and provide the correct casing.
8-
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
97
public record ExternalAuthInfo
108
{
119
[Required]
10+
[JsonPropertyName("clientId")]
1211
public required string ClientId { get; init; }
1312

1413
[Required]
14+
[JsonPropertyName("code")]
1515
public required string Code { get; init; }
1616

1717
[Required]
18+
[JsonPropertyName("redirectUri")]
1819
public required string RedirectUri { get; init; }
1920

21+
[JsonPropertyName("inviteToken")]
2022
public string? InviteToken { get; init; }
2123
}

0 commit comments

Comments
 (0)