先執行 dotnet aspnet-codegenerator
命令,查看用法
G:\Projects\api1>dotnet aspnet-codegenerator
Usage: aspnet-codegenerator [arguments] [options]
Arguments:
generator Name of the generator. Check available generators below.
Options:
-p|--project Path to .csproj file in the project.
-n|--nuget-package-dir
-c|--configuration Configuration for the project (Possible values: Debug/ Release)
-tfm|--target-framework Target Framework to use. (Short folder name of the tfm. eg. net46)
-b|--build-base-path
--no-build
No code generators are available in this project.Add Microsoft.VisualStudio.Web.CodeGeneration.Design package to the project as a NuGet package reference.
RunTime 00:00:02.02
這段說明訊息的重點在這裡:
No code generators are available in this project. Add Microsoft.VisualStudio.Web.CodeGeneration.Design package to the project as a NuGet package reference.
簡單來說,你需要額外安裝 Microsoft.VisualStudio.Web.CodeGeneration.Design
套件,才可以使用這套工具。
就算你使用 Visual Studio 2019 來產生 Controllers 或 Views,其實背後也是幫你安裝相同的套件!
請用以下命令安裝:
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
建立新版本
git add . && git commit -m "dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design"
示範如何快速建立 CoursesController
控制器(沒有 Views 頁面)
請先嘗試執行以下命令:
dotnet aspnet-codegenerator controller -name CoursesController -async -api -m Course -dc ContosouniversityContext -outDir Controllers
個別參數說明請自行參考 dotnet aspnet-codegenerator controller --help
說明文件。
Usage: aspnet-codegenerator [arguments] [options]
Arguments:
generator Name of the generator. Check available generators below.
Options:
-p|--project Path to .csproj file in the project.
-n|--nuget-package-dir
-c|--configuration Configuration for the project (Possible values: Debug/ Release)
-tfm|--target-framework Target Framework to use. (Short folder name of the tfm. eg. net46)
-b|--build-base-path
--no-build
Selected Code Generator: controller
Generator Options:
--controllerName|-name : Name of the controller
--useAsyncActions|-async : Switch to indicate whether to generate async controller actions
--noViews|-nv : Switch to indicate whether to generate CRUD views
--restWithNoViews|-api : Specify this switch to generate a Controller with REST style API, noViews is assumed and any view related options are ignored
--readWriteActions|-actions : Specify this switch to generate Controller with read/write actions when a Model class is not used
--model|-m : Model class to use
--dataContext|-dc : DbContext class to use
--referenceScriptLibraries|-scripts : Switch to specify whether to reference script libraries in the generated views
--layout|-l : Custom Layout page to use
--useDefaultLayout|-udl : Switch to specify that default layout should be used for the views
--force|-f : Use this option to overwrite existing files
--relativeFolderPath|-outDir : Specify the relative output folder path from project where the file needs to be generated, if not specified, file will be generated in the project folder
--controllerNamespace|-namespace : Specify the name of the namespace to use for the generated controller
--useSqlite|-sqlite : Flag to specify if DbContext should use SQLite instead of SQL Server.
這段命令其實會產生以下錯誤:
Building project ...
Finding the generator 'controller'...
Running the generator 'controller'...
Generating a new DbContext class 'ContosouniversityContext'
Attempting to compile the application in memory with the added DbContext.
Attempting to figure out the EntityFramework metadata for the model and DbContext: 'Course'
The entity type 'CourseInstructor' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'. StackTrace:
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateNonNullPrimaryKeys(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.SqlServer.Internal.SqlServerModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.ValidatingConvention.ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext`1 context)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalized(IConventionModelBuilder modelBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalized(IConventionModelBuilder modelBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
The entity type 'CourseInstructor' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.DbContextActivator.CreateInstance(Type contextType, Assembly startupAssembly, IOperationReportHandler reportHandler)
at Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.EntityFrameworkModelProcessor.TryCreateContextUsingAppCode(Type dbContextType, Type startupType)
at Microsoft.VisualStudio.Web.CodeGeneration.ActionInvoker.<BuildCommandLine>b__6_0()
at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
at Microsoft.VisualStudio.Web.CodeGeneration.ActionInvoker.Execute(String[] args)
at Microsoft.VisualStudio.Web.CodeGeneration.CodeGenCommand.Execute(String[] args)
這個錯誤其實非常難以理解,而且會誤導偵錯方向。
事實上,只是資料內容類別的名稱打錯而已 (也就是 -dc
參數),而且執行錯誤後,你原本的 appsettings.json
也會被多新增一個連接字串名為 ContosouniversityContext
(打錯的名稱),這個是多餘的,應該手動刪除多餘的連接字串。
這點真的非常地雷,各位務必要特別注意類別名稱大小寫必須正確輸入!
正確:ContosoUniversityContext
錯誤:ContosouniversityContext
正確的命令如下:
dotnet aspnet-codegenerator controller -name CoursesController -async -api -m Course -dc ContosoUniversityContext -outDir Controllers
Building project ...
Finding the generator 'controller'...
Running the generator 'controller'...
Attempting to compile the application in memory.
Attempting to figure out the EntityFramework metadata for the model and DbContext: 'Course'
Added Controller : '\Controllers\CoursesController.cs'.
RunTime 00:00:10.15
如此一來,完整的 CoursesController
就自動產生了! 👍