From 75b01b5dc5771db04fc6d77f7be988fb59b32b25 Mon Sep 17 00:00:00 2001 From: "Eric J. Smith" Date: Wed, 11 Nov 2026 09:54:22 -0600 Subject: [PATCH 1/2] Upgrade to .NET 11 Target net11.0 with SDK 11.0.100 and runtime 11.0.0 across projects, CI, Docker images, and dev tooling, and move framework-aligned packages to 11.0.0. Microsoft.AspNetCore.OpenApi 11 requires Microsoft.OpenApi 3.x, so adapt the transformers to the media type interfaces and keep the published document on OpenAPI 3.1. Fix two advisories published with the November servicing release: move Aspire to 13.6.5 (GHSA-f7vh-h5g3-7jrh) and pin System.Formats.Cbor 11.0.0 over the 9.0.5 that AWSSDK.Extensions.CborProtocol pulls in (GHSA-vmv3-wvjp-wqpj). Refresh OpenTelemetry, ModelContextProtocol, Scalar, MailKit, and test packages. Drop the Microsoft.Extensions.Logging.Abstractions reference now that it ships in the shared framework, and disable static web assets in the test project so the Web and Job hot reload assets don't collide. Add an opt-in UseRuntimeAsync build property that compiles our async methods with .NET 11 runtime async. It stays off by default: A/B runs of the event pipeline and the event, stack, and ingestion endpoints showed no measurable change in time, CPU, or allocations. --- .codex/environments/environment.toml | 2 +- .devcontainer/devcontainer.json | 2 +- .github/workflows/build-arm64.yml | 2 +- .github/workflows/build.yaml | 9 +- .github/workflows/copilot-setup-steps.yml | 2 +- .vscode/launch.json | 4 +- AGENTS.md | 2 +- Dockerfile | 10 +-- README.md | 2 +- build/EmailTemplatePreviews.cs | 2 +- global.json | 2 +- src/Directory.Build.props | 6 +- .../Exceptionless.AppHost.csproj | 12 +-- .../Exceptionless.Core.csproj | 10 +-- .../Exceptionless.Insulation.csproj | 17 ++-- .../Exceptionless.Job.csproj | 12 +-- .../Exceptionless.Web.csproj | 22 +++-- ...dpointDocumentationOperationTransformer.cs | 2 +- ...nlessOpenApiServiceCollectionExtensions.cs | 3 + .../RequestBodyContentOperationTransformer.cs | 6 +- .../Exceptionless.Tests/Api/Data/openapi.json | 90 +++++++++---------- .../Exceptionless.Tests.csproj | 13 +-- .../Jobs/CloseInactiveSessionsJobTests.cs | 8 +- tests/ci/backend-shards.js | 2 +- 24 files changed, 126 insertions(+), 116 deletions(-) diff --git a/.codex/environments/environment.toml b/.codex/environments/environment.toml index 8b525d054a..273aa1d088 100644 --- a/.codex/environments/environment.toml +++ b/.codex/environments/environment.toml @@ -22,7 +22,7 @@ worktree_path="$PWD" echo "Setting up Exceptionless Aspire worktree: $worktree_path" if ! command -v dotnet >/dev/null 2>&1; then - echo "dotnet is not installed or not on PATH. Exceptionless requires .NET 10." >&2 + echo "dotnet is not installed or not on PATH. Exceptionless requires .NET 11." >&2 exit 1 fi diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f94530ef5f..a23d6acaf9 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -66,7 +66,7 @@ "version": "latest" }, "ghcr.io/devcontainers/features/dotnet:2": { - "version": "10.0" + "version": "11.0" }, "ghcr.io/devcontainers/features/node:1": { "nodeGypDependencies": true, diff --git a/.github/workflows/build-arm64.yml b/.github/workflows/build-arm64.yml index 9bde92484d..a69fa8ae5d 100644 --- a/.github/workflows/build-arm64.yml +++ b/.github/workflows/build-arm64.yml @@ -25,7 +25,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v6 with: - dotnet-version: 10.0.402 + dotnet-version: 11.0.100 - name: Build Reason env: GITHUB_EVENT: ${{ toJson(github) }} diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 64c0941bc9..eac99f7a37 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -114,7 +114,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v6 with: - dotnet-version: 10.0.402 + dotnet-version: 11.0.100 - name: Version id: version @@ -156,7 +156,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v6 with: - dotnet-version: 10.0.402 + dotnet-version: 11.0.100 - uses: actions/cache@v6 with: @@ -215,7 +215,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v6 with: - dotnet-version: 10.0.402 + dotnet-version: 11.0.100 - name: Merge coverage run: | @@ -324,8 +324,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v6 with: - dotnet-version: 10.0.402 - dotnet-quality: ga + dotnet-version: 11.0.100 - name: Install Aspire CLI run: | diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index f534b8dd1c..5634b5a32d 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -25,7 +25,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v6 with: - dotnet-version: 10.0.402 + dotnet-version: 11.0.100 - name: Install Aspire CLI run: | diff --git a/.vscode/launch.json b/.vscode/launch.json index b467cd8048..7fa3e5f201 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,7 +12,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "build", - "program": "${workspaceFolder}/src/Exceptionless.Web/bin/Debug/net10.0/Exceptionless.Web.dll", + "program": "${workspaceFolder}/src/Exceptionless.Web/bin/Debug/net11.0/Exceptionless.Web.dll", "args": [], "cwd": "${workspaceFolder}/src/Exceptionless.Web", "stopAtEntry": false, @@ -29,7 +29,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "build", - "program": "${workspaceFolder}/src/Exceptionless.Job/bin/Debug/net10.0/Exceptionless.Job.dll", + "program": "${workspaceFolder}/src/Exceptionless.Job/bin/Debug/net11.0/Exceptionless.Job.dll", "args": [], "cwd": "${workspaceFolder}", "stopAtEntry": false, diff --git a/AGENTS.md b/AGENTS.md index afb0d4d0ec..20b1a02c85 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Exceptionless -Real-time error monitoring platform on .NET 10, Aspire, and Svelte 5. Keep changes readable, narrow, and backwards compatible. +Real-time error monitoring platform on .NET 11, Aspire, and Svelte 5. Keep changes readable, narrow, and backwards compatible. This file is root-scope agent guidance. When working in a subtree, read any nested `AGENTS.md` there too. Prefer nearby repo skills for detailed backend, frontend, testing, repository, and dogfood workflows. diff --git a/Dockerfile b/Dockerfile index a3fd7e30f3..54a0746134 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:10.0.402 AS build +FROM mcr.microsoft.com/dotnet/sdk:11.0.100 AS build ARG MinVerVersionOverride WORKDIR /app @@ -40,7 +40,7 @@ RUN dotnet publish -c Release -o out --no-build # job -FROM mcr.microsoft.com/dotnet/aspnet:10.0.13 AS job +FROM mcr.microsoft.com/dotnet/aspnet:11.0.0 AS job WORKDIR /app COPY --from=job-publish /app/src/Exceptionless.Job/out ./ @@ -59,7 +59,7 @@ RUN dotnet publish -c Release -o out --no-build /p:SkipSpaPublish=true # api -FROM mcr.microsoft.com/dotnet/aspnet:10.0.13 AS api +FROM mcr.microsoft.com/dotnet/aspnet:11.0.0 AS api WORKDIR /app COPY --from=api-publish /app/src/Exceptionless.Web/out ./ @@ -77,7 +77,7 @@ RUN dotnet publish -c Release -o out --no-build # app -FROM mcr.microsoft.com/dotnet/aspnet:10.0.13 AS app +FROM mcr.microsoft.com/dotnet/aspnet:11.0.0 AS app WORKDIR /app COPY --from=app-publish /app/src/Exceptionless.Web/out ./ @@ -145,7 +145,7 @@ USER elasticsearch RUN wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh && \ chmod +x dotnet-install.sh && \ - ./dotnet-install.sh --version 10.0.13 --runtime aspnetcore && \ + ./dotnet-install.sh --version 11.0.0 --runtime aspnetcore && \ rm dotnet-install.sh EXPOSE 8080 9200 diff --git a/README.md b/README.md index 46dd2eedd8..e53da947ee 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ _In appreciation for anyone who submits a non-trivial pull request, we will give Start here: 1. Read the [contributing document](https://github.com/exceptionless/Exceptionless/blob/main/CONTRIBUTING.md). -2. Install [Docker](https://www.docker.com/get-docker), [.NET 10.0](https://dotnet.microsoft.com/), and [Node 24+](https://nodejs.org/). +2. Install [Docker](https://www.docker.com/get-docker), [.NET 11.0](https://dotnet.microsoft.com/), and [Node 24+](https://nodejs.org/). 3. Run the app with one of these entry points: - Visual Studio Code: open the repo root and start the `Aspire` launch configuration. - Visual Studio: open `Exceptionless.slnx`, set `Exceptionless.AppHost` as the startup project, and run it. diff --git a/build/EmailTemplatePreviews.cs b/build/EmailTemplatePreviews.cs index cc0d07f70e..1e88ed5481 100644 --- a/build/EmailTemplatePreviews.cs +++ b/build/EmailTemplatePreviews.cs @@ -1,5 +1,5 @@ #:sdk Microsoft.NET.Sdk -#:property TargetFramework=net10.0 +#:property TargetFramework=net11.0 #:project ../src/Exceptionless.EmailTemplates/Exceptionless.EmailTemplates.csproj // Run from the repository root. diff --git a/global.json b/global.json index ab000ad016..917df2af81 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.100", + "version": "11.0.100", "rollForward": "latestMinor", "allowPrerelease": false }, diff --git a/src/Directory.Build.props b/src/Directory.Build.props index fa0f2d35de..91b94ac2fe 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@ - net10.0 + net11.0 enable Exceptionless true @@ -17,6 +17,10 @@ false true en + + $(Features);runtime-async=on diff --git a/src/Exceptionless.AppHost/Exceptionless.AppHost.csproj b/src/Exceptionless.AppHost/Exceptionless.AppHost.csproj index fb4835ddac..9a4c450051 100644 --- a/src/Exceptionless.AppHost/Exceptionless.AppHost.csproj +++ b/src/Exceptionless.AppHost/Exceptionless.AppHost.csproj @@ -1,7 +1,7 @@ - + Exe - net10.0 + net11.0 enable enable a9c2ddcc-e51d-4cd1-9782-96e1d74eec87 @@ -9,10 +9,10 @@ $(NoWarn);ASPIRECERTIFICATES001 - - - - + + + + diff --git a/src/Exceptionless.Core/Exceptionless.Core.csproj b/src/Exceptionless.Core/Exceptionless.Core.csproj index 80adfbd569..1d72ba9e90 100644 --- a/src/Exceptionless.Core/Exceptionless.Core.csproj +++ b/src/Exceptionless.Core/Exceptionless.Core.csproj @@ -7,14 +7,14 @@ - + - - - + + + - + diff --git a/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj b/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj index e63e29442f..39e68a2232 100644 --- a/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj +++ b/src/Exceptionless.Insulation/Exceptionless.Insulation.csproj @@ -7,20 +7,21 @@ - - - - - - - + + + + + + + + - + diff --git a/src/Exceptionless.Job/Exceptionless.Job.csproj b/src/Exceptionless.Job/Exceptionless.Job.csproj index d279d13aea..ae038a1cbd 100644 --- a/src/Exceptionless.Job/Exceptionless.Job.csproj +++ b/src/Exceptionless.Job/Exceptionless.Job.csproj @@ -9,12 +9,12 @@ - - - - - - + + + + + + diff --git a/src/Exceptionless.Web/Exceptionless.Web.csproj b/src/Exceptionless.Web/Exceptionless.Web.csproj index 805b603d68..736d8d790a 100644 --- a/src/Exceptionless.Web/Exceptionless.Web.csproj +++ b/src/Exceptionless.Web/Exceptionless.Web.csproj @@ -15,25 +15,23 @@ - - - - + + + - + - - - - - - + + + + + + diff --git a/src/Exceptionless.Web/Utility/OpenApi/EndpointDocumentationOperationTransformer.cs b/src/Exceptionless.Web/Utility/OpenApi/EndpointDocumentationOperationTransformer.cs index 169bb5f1d7..be09d9f00f 100644 --- a/src/Exceptionless.Web/Utility/OpenApi/EndpointDocumentationOperationTransformer.cs +++ b/src/Exceptionless.Web/Utility/OpenApi/EndpointDocumentationOperationTransformer.cs @@ -158,7 +158,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform requestBody.Required = true; if (requestBody.Content is not null) { - foreach (var mediaType in requestBody.Content.Values) + foreach (var mediaType in requestBody.Content.Values.OfType()) mediaType.Schema = RemoveNullAlternative(mediaType.Schema); } } diff --git a/src/Exceptionless.Web/Utility/OpenApi/ExceptionlessOpenApiServiceCollectionExtensions.cs b/src/Exceptionless.Web/Utility/OpenApi/ExceptionlessOpenApiServiceCollectionExtensions.cs index 829c3a2243..667623ba32 100644 --- a/src/Exceptionless.Web/Utility/OpenApi/ExceptionlessOpenApiServiceCollectionExtensions.cs +++ b/src/Exceptionless.Web/Utility/OpenApi/ExceptionlessOpenApiServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi; namespace Exceptionless.Web.Utility.OpenApi; @@ -10,6 +11,8 @@ public static IServiceCollection AddExceptionlessOpenApi(this IServiceCollection { services.AddOpenApi(options => { + // ASP.NET Core 11 defaults to OpenAPI 3.2; keep publishing 3.1 for existing client generators. + options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1; options.CreateSchemaReferenceId = SchemaReferenceIdHelper.CreateSchemaReferenceId; options.AddDocumentTransformer(); options.AddDocumentTransformer(); diff --git a/src/Exceptionless.Web/Utility/OpenApi/RequestBodyContentOperationTransformer.cs b/src/Exceptionless.Web/Utility/OpenApi/RequestBodyContentOperationTransformer.cs index f5dec66607..387cabf9f5 100644 --- a/src/Exceptionless.Web/Utility/OpenApi/RequestBodyContentOperationTransformer.cs +++ b/src/Exceptionless.Web/Utility/OpenApi/RequestBodyContentOperationTransformer.cs @@ -32,9 +32,9 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform operation.RequestBody = new OpenApiRequestBody { Required = true, - Content = new Dictionary + Content = new Dictionary { - ["multipart/form-data"] = new() + ["multipart/form-data"] = new OpenApiMediaType { Schema = CreateMultipartSchema(multipartFileUploadAttribute) } @@ -61,7 +61,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform operation.RequestBody = new OpenApiRequestBody { Required = true, - Content = new Dictionary() + Content = new Dictionary() }; foreach (string contentType in contentTypes) diff --git a/tests/Exceptionless.Tests/Api/Data/openapi.json b/tests/Exceptionless.Tests/Api/Data/openapi.json index 88be9cf072..dbca567ca0 100644 --- a/tests/Exceptionless.Tests/Api/Data/openapi.json +++ b/tests/Exceptionless.Tests/Api/Data/openapi.json @@ -1,5 +1,5 @@ { - "openapi": "3.1.1", + "openapi": "3.1.2", "info": { "title": "Exceptionless API", "termsOfService": "https://exceptionless.com/terms/", @@ -16,7 +16,7 @@ }, "servers": [ { - "url": "http://localhost/" + "url": "http://localhost" } ], "paths": { @@ -1434,9 +1434,6 @@ "202": { "description": "Accepted" }, - "413": { - "description": "Payload Too Large" - }, "400": { "description": "No project id specified and no default project was found.", "content": { @@ -1456,6 +1453,9 @@ } } } + }, + "413": { + "description": "Payload Too Large" } }, "deprecated": true @@ -1510,9 +1510,6 @@ "202": { "description": "Accepted" }, - "413": { - "description": "Payload Too Large" - }, "400": { "description": "No project id specified and no default project was found.", "content": { @@ -1532,6 +1529,9 @@ } } } + }, + "413": { + "description": "Payload Too Large" } }, "deprecated": true @@ -3444,8 +3444,8 @@ } } }, - "409": { - "description": "The saved view preferences could not be updated due to a concurrent request.", + "404": { + "description": "The organization could not be found.", "content": { "application/problem\u002Bjson": { "schema": { @@ -3454,8 +3454,8 @@ } } }, - "404": { - "description": "The organization could not be found.", + "409": { + "description": "The saved view preferences could not be updated due to a concurrent request.", "content": { "application/problem\u002Bjson": { "schema": { @@ -3541,8 +3541,8 @@ } } }, - "409": { - "description": "The saved view preferences could not be updated due to a concurrent request.", + "404": { + "description": "The organization could not be found.", "content": { "application/problem\u002Bjson": { "schema": { @@ -3551,8 +3551,8 @@ } } }, - "404": { - "description": "The organization could not be found.", + "409": { + "description": "The saved view preferences could not be updated due to a concurrent request.", "content": { "application/problem\u002Bjson": { "schema": { @@ -4078,8 +4078,8 @@ } } }, - "422": { - "description": "The product tour name is invalid.", + "404": { + "description": "The current user could not be found.", "content": { "application/problem\u002Bjson": { "schema": { @@ -4088,8 +4088,8 @@ } } }, - "404": { - "description": "The current user could not be found.", + "422": { + "description": "The product tour name is invalid.", "content": { "application/problem\u002Bjson": { "schema": { @@ -7744,22 +7744,22 @@ "200": { "description": "OK" }, - "422": { - "description": "The requested status is invalid.", + "404": { + "description": "One or more stacks could not be found.", "content": { "application/problem\u002Bjson": { "schema": { - "$ref": "#/components/schemas/HttpValidationProblemDetails" + "$ref": "#/components/schemas/ProblemDetails" } } } }, - "404": { - "description": "One or more stacks could not be found.", + "422": { + "description": "The requested status is invalid.", "content": { "application/problem\u002Bjson": { "schema": { - "$ref": "#/components/schemas/ProblemDetails" + "$ref": "#/components/schemas/HttpValidationProblemDetails" } } } @@ -9070,9 +9070,6 @@ "202": { "description": "Accepted" }, - "413": { - "description": "Payload Too Large" - }, "400": { "description": "No project id specified and no default project was found.", "content": { @@ -9092,6 +9089,9 @@ } } } + }, + "413": { + "description": "Payload Too Large" } } } @@ -9442,9 +9442,6 @@ "202": { "description": "Accepted" }, - "413": { - "description": "Payload Too Large" - }, "400": { "description": "No project id specified and no default project was found.", "content": { @@ -9464,6 +9461,9 @@ } } } + }, + "413": { + "description": "Payload Too Large" } } } @@ -15185,43 +15185,43 @@ }, "tags": [ { - "name": "AssistantEndpoints" - }, - { - "name": "Project" + "name": "AdminEndpoints" }, { - "name": "AdminEndpoints" + "name": "AssistantEndpoints" }, { - "name": "OAuth" + "name": "Auth" }, { "name": "Event" }, { - "name": "Auth" + "name": "OAuth" }, { - "name": "Token" + "name": "Organization" }, { - "name": "WebHook" + "name": "Project" }, { "name": "SavedView" }, { - "name": "User" + "name": "Source Map" }, { - "name": "Organization" + "name": "Stack" }, { - "name": "Stack" + "name": "Token" }, { - "name": "Source Map" + "name": "User" + }, + { + "name": "WebHook" } ] } diff --git a/tests/Exceptionless.Tests/Exceptionless.Tests.csproj b/tests/Exceptionless.Tests/Exceptionless.Tests.csproj index 98677e9286..aa169912c0 100644 --- a/tests/Exceptionless.Tests/Exceptionless.Tests.csproj +++ b/tests/Exceptionless.Tests/Exceptionless.Tests.csproj @@ -4,6 +4,9 @@ False false true + + false $(InterceptorsNamespaces);Microsoft.AspNetCore.OpenApi.Generated @@ -11,14 +14,14 @@ - + - - + + - + - + diff --git a/tests/Exceptionless.Tests/Jobs/CloseInactiveSessionsJobTests.cs b/tests/Exceptionless.Tests/Jobs/CloseInactiveSessionsJobTests.cs index be9f123ed4..ad5b69d765 100644 --- a/tests/Exceptionless.Tests/Jobs/CloseInactiveSessionsJobTests.cs +++ b/tests/Exceptionless.Tests/Jobs/CloseInactiveSessionsJobTests.cs @@ -317,15 +317,17 @@ public async Task CloseInactiveSessions(int defaultInactivePeriodInMinutes, bool Assert.Equal(2, events.Total); sessionStart = events.Documents.First(e => e.IsSessionStart()); - decimal sessionStartDuration = (decimal)(sessionHeartbeatUpdatedAgoInSeconds.HasValue ? (utcNow.SubtractSeconds(sessionHeartbeatUpdatedAgoInSeconds.Value) - sessionStart.Date.UtcDateTime).TotalSeconds : 0); + // Event values are persisted as doubles, so compare at that precision. + double sessionStartDuration = sessionHeartbeatUpdatedAgoInSeconds.HasValue ? (utcNow.SubtractSeconds(sessionHeartbeatUpdatedAgoInSeconds.Value) - sessionStart.Date.UtcDateTime).TotalSeconds : 0; + double? sessionStartValue = (double?)sessionStart.Value; if (willCloseSession) { - Assert.Equal(sessionStartDuration, sessionStart.Value); + Assert.Equal(sessionStartDuration, sessionStartValue); Assert.True(sessionStart.HasSessionEndTime()); } else { - Assert.Equal(sessionStartDuration, sessionStart.Value); + Assert.Equal(sessionStartDuration, sessionStartValue); Assert.False(sessionStart.HasSessionEndTime()); } } diff --git a/tests/ci/backend-shards.js b/tests/ci/backend-shards.js index 857192387b..ba90243a95 100644 --- a/tests/ci/backend-shards.js +++ b/tests/ci/backend-shards.js @@ -175,7 +175,7 @@ function main() { } function run(args) { - const assembly = resolve(args.assembly ?? join(root, 'tests/Exceptionless.Tests/bin/Release/net10.0/Exceptionless.Tests.dll')); + const assembly = resolve(args.assembly ?? join(root, 'tests/Exceptionless.Tests/bin/Release/net11.0/Exceptionless.Tests.dll')); const discovered = JSON.parse( execFileSync('dotnet', [assembly, '--list-tests', 'json', '--no-ansi'], { encoding: 'utf8', From ebdd60c547d1612e71b59d12cd03ea65351741ca Mon Sep 17 00:00:00 2001 From: "Eric J. Smith" Date: Wed, 11 Nov 2026 15:47:01 -0600 Subject: [PATCH 2/2] Remove the direct Microsoft.OpenApi reference Microsoft.AspNetCore.OpenApi 11.0.0 depends on Microsoft.OpenApi [3.11.0, 4.0.0), so the explicit pin is redundant. --- src/Exceptionless.Web/Exceptionless.Web.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Exceptionless.Web/Exceptionless.Web.csproj b/src/Exceptionless.Web/Exceptionless.Web.csproj index 736d8d790a..f1c53fce69 100644 --- a/src/Exceptionless.Web/Exceptionless.Web.csproj +++ b/src/Exceptionless.Web/Exceptionless.Web.csproj @@ -16,7 +16,6 @@ -