diff --git a/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Configuration/ServiceCollectionExtensions.cs index 65bf465ce..f82fcd3f2 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,