Skip to content

Commit f6a5805

Browse files
committed
Replace SwashBuckle with Scalar, Replace JSON.NET from API Surface with STJ
1 parent 7458f0b commit f6a5805

33 files changed

+4769
-2726
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/ClientApp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"format": "npm run format:prettier && npm run format:eslint",
1616
"format:eslint": "eslint . --fix --concurrency=auto",
1717
"format:prettier": "prettier --write .",
18-
"generate-models": "swagger-typescript-api generate -p http://localhost:5200/docs/v2/swagger.json -o ./src/lib/generated -n api.ts --no-client --templates api-templates",
18+
"generate-models": "swagger-typescript-api generate -p http://localhost:5200/docs/v2/openapi.json -o ./src/lib/generated -n api.ts --no-client --templates api-templates",
1919
"generate-templates": "swagger-typescript-api generate-templates -o api-templates",
2020
"test:e2e": "playwright test",
2121
"test:unit": "vitest run",

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

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

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

144144
if (String.IsNullOrEmpty(id))
145145
return NotFound();
@@ -217,22 +217,22 @@ public async Task<IActionResult> AddLinkAsync(string id, ValueFromBody<string?>
217217
[HttpPost("add-link")]
218218
[Consumes("application/json")]
219219
[ApiExplorerSettings(IgnoreApi = true)]
220-
public async Task<IActionResult> AddLinkAsync(JObject data)
220+
public async Task<IActionResult> AddLinkAsync(JsonDocument data)
221221
{
222222
string? id = null;
223-
if (data.TryGetValue("ErrorStack", out var value))
224-
id = value.Value<string>();
223+
if (data.RootElement.TryGetProperty("ErrorStack", out var errorStackProp))
224+
id = errorStackProp.GetString();
225225

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

229229
if (String.IsNullOrEmpty(id))
230230
return NotFound();
231231

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

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

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

@@ -105,10 +105,10 @@ public Task<ActionResult<WorkInProgressResult>> DeleteAsync(string ids)
105105
[HttpPost("~/api/v1/projecthook/subscribe")]
106106
[Consumes("application/json")]
107107
[ApiExplorerSettings(IgnoreApi = true)]
108-
public async Task<ActionResult<WebHook>> SubscribeAsync(JObject data, int apiVersion = 1)
108+
public async Task<ActionResult<WebHook>> SubscribeAsync(JsonDocument data, int apiVersion = 1)
109109
{
110-
string? eventType = data.GetValue("event")?.Value<string>();
111-
string? url = data.GetValue("target_url")?.Value<string>();
110+
string? eventType = data.RootElement.TryGetProperty("event", out var eventProp) ? eventProp.GetString() : null;
111+
string? url = data.RootElement.TryGetProperty("target_url", out var urlProp) ? urlProp.GetString() : null;
112112
if (String.IsNullOrEmpty(eventType) || String.IsNullOrEmpty(url))
113113
return BadRequest();
114114

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

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

src/Exceptionless.Web/Exceptionless.Web.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
<PackageReference Include="Exceptionless.AspNetCore" Version="6.1.0" />
1717
<PackageReference Include="Joonasw.AspNetCore.SecurityHeaders" Version="6.0.0" />
1818
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.0" />
19+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
1920
<PackageReference Include="MiniValidation" Version="0.9.2" />
2021
<PackageReference Include="NEST.JsonNetSerializer" Version="7.17.5" />
2122
<PackageReference Include="OAuth2" Version="0.10.3" />
22-
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.0.1" />
23+
<PackageReference Include="Scalar.AspNetCore" Version="2.11.1" />
2324
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
2425
<PackageReference Include="Serilog.Enrichers.Span" Version="3.1.0" />
2526
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
@@ -34,7 +35,6 @@
3435
<PackageReference Include="OpenTelemetry.Instrumentation.ElasticsearchClient" Version="1.13.0-beta.1" />
3536
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.14.0" />
3637
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.13.0-beta.1" />
37-
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="10.0.1" />
3838
</ItemGroup>
3939
<ItemGroup>
4040
<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))

0 commit comments

Comments
 (0)