It seems EntityFrameworkServices.GetModelMetadata will fail at the step _Attempting to figure out the EntityFramework metadata for the model and DbContext_ when building the application services in EntityFrameworkServices.TryCreateContextUsingAppCode, if the Startup class adds some middleware with required options being populated from the secret manager.
I have created a new ASP.Net Core 1.0.0 project using the default Web Application template adding individual accounts authentication.
Then I have added the google authentication middleware:
"Microsoft.AspNetCore.Authentication.Google": "1.0.0"
I have updated my startup class with the Google middleware, where the ClientId and Secret are read from the SecretManager tool:
app.UseGoogleAuthentication(new GoogleOptions
{
ClientId = Configuration["GoogleClientId"],
ClientSecret = Configuration["GoogleClientSecret"]
});
If I then:
ApplicationDbContext or create a new dbContext classI get the following error:
C:\Program Files\dotnet\dotnet.exe aspnet-codegenerator --project "C:\Users\Daniel.Garcia\Documents\Github\WebApplication3\src\WebApplication3" controller --force --controllerName ArticlesController --model WebApplication3.Models.Article --dataContext WebApplication3.Data.ApplicationDbContext --relativeFolderPath Controllers --controllerNamespace WebApplication3.Controllers --referenceScriptLibraries --useDefaultLayout
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: Article
info: Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]
User profile is available. Using 'C:\Users\Daniel.Garcia\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
The 'ClientId' option must be provided. StackTrace:There was an error creating the DbContext instance to get the model. No parameterless constructor defined for this object.
at Microsoft.AspNetCore.Authentication.OAuth.OAuthMiddleware`1..ctor(RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions`1 sharedOptions, IOptions`1 options)
No parameterless constructor defined for this object. at Microsoft.AspNetCore.Authentication.Google.GoogleMiddleware..ctor(RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions`1 sharedOptions, IOptions`1 options)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
at Microsoft.VisualStudio.Web.CodeGeneration.ActionInvoker.<BuildCommandLine>b__6_0() at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass3_0.<UseMiddleware>b__0(RequestDelegate next)
at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args) at Microsoft.AspNetCore.Builder.Internal.ApplicationBuilder.Build()
at Microsoft.VisualStudio.Web.CodeGeneration.CodeGenCommand.Execute(String[] args) at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
at Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.EntityFrameworkServices.TryCreateContextUsingAppCode(Type dbContextType, ModelType startupType)
RunTime 00:00:07.10
It seems to me the environment isn't set as Development when building the app in EntityFrameworkServices.TryCreateContextUsingAppCode. If I update my Startup constructor to always call builder.AddUserSecrets(); regardless of whether the environment is Development or not, then the scaffolding works fine.
//if (env.IsDevelopment())
//{
// builder.AddUserSecrets();
//}
builder.AddUserSecrets();
Another quick workaround would be setting things up so there are some dummy non-null values that will be overwritten in the dev environment with the values from the user secrets.
Just adding some dummy values to appsettings.json or registering the options like this:
app.UseGoogleAuthentication(new GoogleOptions
{
ClientId = Configuration["GoogleClientId"] ?? "MissingClientId",
ClientSecret = Configuration["GoogleClientSecret"] ?? "MissingClientSecret",
});
This is fixed in 1.0.0-msbuild2-final and later
Even with 1.0.0-msbuild2-final I still got the issue. @DaniJG solution worked for me.
Thanks for this @DaniJG, had me stumped for a while and all packages up to date
Most helpful comment
Another quick workaround would be setting things up so there are some dummy non-null values that will be overwritten in the dev environment with the values from the user secrets.
Just adding some dummy values to
appsettings.jsonor registering the options like this: