From 09be3b3f60a5e28dbc556ce47eac37165d716389 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Tue, 21 Oct 2025 01:27:05 +0200 Subject: [PATCH] Throw at startup when different OpenAPI version is loaded --- .../ServiceCollectionExtensions.cs | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs index 65bf465ce3..f82fcd3f23 100644 --- a/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs +++ b/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs @@ -1,3 +1,4 @@ +using System.Reflection; using JetBrains.Annotations; using JsonApiDotNetCore.Errors; using JsonApiDotNetCore.Repositories; @@ -13,6 +14,16 @@ public static class ServiceCollectionExtensions { private static readonly TypeLocator TypeLocator = new(); + /// + /// Configures JsonApiDotNetCore by registering resources from an Entity Framework Core model. + /// + public static IServiceCollection AddJsonApi(this IServiceCollection services, Action? options = null, + Action? discovery = null, Action? resources = null, IMvcCoreBuilder? mvcBuilder = null) + where TDbContext : DbContext + { + return AddJsonApi(services, options, discovery, resources, mvcBuilder, [typeof(TDbContext)]); + } + /// /// Configures JsonApiDotNetCore by registering resources manually. /// @@ -23,20 +34,33 @@ public static IServiceCollection AddJsonApi(this IServiceCollection services, Ac #pragma warning restore AV1553 // Do not use optional parameters with default value null for strings, collections or tasks { ArgumentNullException.ThrowIfNull(services); + AssertCompatibleOpenApiVersion(); SetupApplicationBuilder(services, options, discovery, resources, mvcBuilder, dbContextTypes ?? Array.Empty()); return services; } - /// - /// Configures JsonApiDotNetCore by registering resources from an Entity Framework Core model. - /// - public static IServiceCollection AddJsonApi(this IServiceCollection services, Action? options = null, - Action? discovery = null, Action? resources = null, IMvcCoreBuilder? mvcBuilder = null) - where TDbContext : DbContext + private static void AssertCompatibleOpenApiVersion() { - return AddJsonApi(services, options, discovery, resources, mvcBuilder, [typeof(TDbContext)]); + Version thisAssemblyVersion = typeof(IJsonApiOptions).Assembly.GetName().Version!; + Version? openApiAssemblyVersion = TryGetOpenApiAssemblyVersion(); + + if (openApiAssemblyVersion != null && openApiAssemblyVersion != thisAssemblyVersion) + { + throw new InvalidOperationException( + $"JsonApiDotNetCore v{thisAssemblyVersion.ToString(3)} is incompatible with JsonApiDotNetCore.OpenApi.Swashbuckle v{openApiAssemblyVersion.ToString(3)}. " + + $"Reference a matching (preview) version of the JsonApiDotNetCore.OpenApi.Swashbuckle NuGet package."); + } + } + + private static Version? TryGetOpenApiAssemblyVersion() + { + Assembly? openApiAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(assembly => + assembly.FullName?.StartsWith("JsonApiDotNetCore.OpenApi.Swashbuckle", StringComparison.Ordinal) == true && + assembly.GetName().Name == "JsonApiDotNetCore.OpenApi.Swashbuckle"); + + return openApiAssembly?.GetType("JsonApiDotNetCore.OpenApi.Swashbuckle.ServiceCollectionExtensions", false)?.Assembly.GetName().Version; } private static void SetupApplicationBuilder(IServiceCollection services, Action? configureOptions,