RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.76k stars 1.29k forks source link

AddDbContext: Violates the constraint of type parameter 'TContext' #2309

Open bhaidar opened 5 years ago

bhaidar commented 5 years ago

Hi, I have an ASP.NET Core 2.2 Web API app running fine in the browser. When I try to generate Typescript files in NSwagStudio, I get the following errors:

System.Security.VerificationException: 

Method Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContext: 

type argument 'MovieWatcher.Server.Models.MovieTrackerContext' violates the constraint of type parameter 'TContext'.

Runtime: NetCore22
   at MovieWatcher.Server.Startup.ConfigureServices(IServiceCollection services)

--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.Initialize()
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
   at NSwag.Commands.Generation.OpenApiGeneratorCommandBase`1.CreateWebHostAsync(AssemblyLoader assemblyLoader) in C:\projects\nswag\src\NSwag.Commands\Commands\Generation\OpenApiGeneratorCommandBase.cs:line 318
   at NSwag.Commands.Generation.AspNetCore.AspNetCoreToSwaggerCommand.RunIsolatedAsync(AssemblyLoader assemblyLoader) in C:\projects\nswag\src\NSwag.Commands\Commands\Generation\AspNetCore\AspNetCoreToOpenApiCommand.cs:line 309
   at NSwag.Commands.IsolatedCommandBase`1.IsolatedCommandAssemblyLoader`1.Run(String commandType, String commandData, String[] assemblyPaths, String[] referencePaths) in C:\projects\nswag\src\NSwag.Commands\Commands\IsolatedCommandBase.cs:line 71
   at NSwag.Commands.IsolatedCommandBase`1.<>c__DisplayClass17_0.<RunIsolatedAsync>b__0() in C:\projects\nswag\src\NSwag.Commands\Commands\IsolatedCommandBase.cs:line 61
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)

--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)

--- End of stack trace from previous location where exception was thrown ---
   at NSwag.Commands.IsolatedCommandBase`1.RunIsolatedAsync(String configurationFile)
   at NSwag.Commands.IsolatedSwaggerOutputCommandBase`1.RunAsync(CommandLineProcessor processor, IConsoleHost host) in C:\projects\nswag\src\NSwag.Commands\Commands\IsolatedSwaggerOutputCommandBase.cs:line 47
   at NSwag.Commands.Generation.AspNetCore.AspNetCoreToSwaggerCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in C:\projects\nswag\src\NSwag.Commands\Commands\Generation\AspNetCore\AspNetCoreToOpenApiCommand.cs:line 94
   at NSwag.Commands.NSwagDocumentBase.GenerateSwaggerDocumentAsync() in C:\projects\nswag\src\NSwag.Commands\NSwagDocumentBase.cs:line 279
   at NSwag.Commands.NSwagDocument.ExecuteAsync() in C:\projects\nswag\src\NSwag.Commands\NSwagDocument.cs:line 81
   at NSwag.Commands.Document.ExecuteDocumentCommand.ExecuteDocumentAsync(IConsoleHost host, String filePath) in C:\projects\nswag\src\NSwag.Commands\Commands\Document\ExecuteDocumentCommand.cs:line 85
   at NSwag.Commands.Document.ExecuteDocumentCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in C:\projects\nswag\src\NSwag.Commands\Commands\Document\ExecuteDocumentCommand.cs:line 32
   at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input)
   at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input)
   at NConsole.CommandLineProcessor.Process(String[] args, Object input)
   at NSwag.Commands.NSwagCommandProcessor.Process(String[] args) in C:\projects\nswag\src\NSwag.Commands\NSwagCommandProcessor.cs:line 56

Here's the DbContext I have:

public class MovieTrackerContext : IdentityDbContext<ApplicationUser>
    {
        public MovieTrackerContext(DbContextOptions<MovieTrackerContext> options)
           : base(options)
        { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Movie>(entity =>
            {
                entity.Property(e => e.Id).ValueGeneratedOnAdd();
                entity.Property(e => e.Title).IsRequired();
                entity.Property(e => e.WatchedOn).IsRequired().HasColumnType("date");
                entity.Property(e => e.Rating).HasDefaultValue(0);
            });

            modelBuilder.Entity<Movie>().HasData(
                new Movie() { Id = 1, Title = "The Shawshank Redemption", WatchedOn = new DateTime(2016, 11, 4), Genre = "Drama", Rating = 4 },
                new Movie() { Id = 2, Title = "The Godfather", WatchedOn = new DateTime(2017, 10, 2), Genre = "Drama", Rating = 2 },
                new Movie() { Id = 3, Title = "The Dark Knight", WatchedOn = new DateTime(2018, 12, 1), Genre = "Drama, Action", Rating = 3 },
                new Movie() { Id = 4, Title = "The Godfather: Part II ", WatchedOn = new DateTime(2019, 2, 4), Genre = "Drama", Rating = 1 },
                new Movie() { Id = 5, Title = "The Lord of the Rings: The Return of the King", WatchedOn = new DateTime(2019, 4, 2), Genre = "Adventure, Drama, Fantasy", Rating = 5 },
                new Movie() { Id = 6, Title = "Pulp Fiction", WatchedOn = new DateTime(2019, 3, 27), Genre = "Crime, Drama", Rating = 3 });

            base.OnModelCreating(modelBuilder);
        }

        public DbSet<Movie> Movies { get; set; }
    }
RicoSuter commented 5 years ago

There's a problem with running the generator from the "openapi" context (in CLI)... you need to somehow change the settings/exclude this EF registration when running NSwag from cli

bhaidar commented 5 years ago

@RicoSuter I am using NSwagStudio and not the command line.

RicoSuter commented 5 years ago

This also uses the cli

bhaidar commented 5 years ago

@RicoSuter OK thanks.

Can you illustrate more on this pls?

you need to somehow change the settings/exclude this EF registration

RicoSuter commented 5 years ago

When generating via CLI it might not find the appsettings.json and some services might not register correctly. An option is to check whether it's running in the nswag context and not register unnecessary services or use an nswag only startup.cs (a second one), just catch the exception and use that to find out in which context it's running, etc.

LarsKemmann commented 1 year ago

I had this same issue when trying to use the LazyCache library - see https://github.com/alastairtree/LazyCache/issues/186. In that case, it turned out to be because LazyCache expects to be the first library to register an IMemoryCache singleton in its recommended services.AddLazyCache() call in Startup.cs, whereas the NSwag generation process injects its own IMemoryCache into the DI container before my Startup.cs is ever called. The workaround in my case was to ensure that LazyCache gets its own IMemoryCache instance rather than using the default DI-based setup process: https://github.com/CareTogether/CareTogetherCMS/commit/076200d81c4c8ca868fd9f83c2d8122fd6339ff4