Wednesday, June 28, 2017

Troubleshooting ASP.NET Core startup error

By Steve Endow

This morning I deployed a new release of an ASP.NET Core API for Dynamics GP.  I've released 3 versions previously, so I expected that this fourth release would be pretty straightforward.  But alas, when we tried to access the new version of the web site, we saw this error message.


"An error occurred while starting the application."

Unfortunately, this error doesn't provide any useful information, and I didn't have developer debug logging enabled in the site code.

Because the site wasn't starting up, my application logging wasn't yet loaded or able to log any errors.  So we had no application log files to work with.

And because of the way that ASP.NET Core web sites work (when using the Kestrel server), IIS logs provide no information--they just showed that we had tried to access the web site URL, with no additional information about the error that was occurring.

After some digging, I found that this is a fairly common issue, and that there is a method of having Kestrel write its own web server logs.  To enable this logging, I edited the web.config file.


I changed stdoutLogEnabled to true, and then verified the location where I wanted the log files to be written.

Once you make that change, you shouldn't need to restart IIS--it looks like Kestrel detects the changes and restarts automatically.  You can then access your site and a log file should be created.


I was then able to open the new log file and see what was causing my site to fail to load.


And the error made sense.  In my latest release, I had added the DataProtection library to my API to provide encryption and decryption, and it was logging this error.

Access to the path 'C:\Windows\system32\config\systemprofile\AppData\Local\ASP.NET\DataProtection-Keys' is denied.

After researching this error and a few others, I discovered that the DataProtection library can be a hassle to deploy, so I removed it and used another encryption class that I have used in the past.

After making that change, the site started working again.

Steve Endow is a Microsoft MVP in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter, YouTube, and Google+



Thursday, June 22, 2017

ASP.NET Core EF Core error: No database provider has been configured for this DbContext

by Steve Endow

Here is the full text of the error:

No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.


There are many potential causes of this error, depending on how your ASP.NET code is structured, but here is one possible cause that required a fair amount of searching for me to resolve.

I load my SQL connection settings from my appsettings.json, so in my ConfigureServices method, I have this code:

services.Configure<APIConfig>(options => Configuration.GetSection("APIConfig").Bind(options));
                    
//Retrieve SQL connection info from config in appsettings
var config = Configuration.GetSection("APIConfig").Get<APIConfig>();
string gpServer = config.GPServer;
string gpCompanyDB = config.GPCompanyDB;
string gpSystemDB = config.GPSystemDB;

var connectionStringGPCompany = $@"Server={gpServer};Database={gpCompanyDB};Trusted_Connection=True;";
var connectionStringGPSystem = $@"Server={gpServer};Database={gpSystemDB};Trusted_Connection=True;";

services.AddDbContext<GPContext>(o => o.UseSqlServer(connectionStringGPCompany));

services.AddDbContext<GPSysContext>(o => o.UseSqlServer(connectionStringGPSystem));


This should setup my DB contexts properly, so I couldn't figure out why I was still getting the "no database provider has been configured" error.

Well, notice that the the AddDbContext is using options.UseSQLServer() to pull in the connection string.  That's all good.

But if you look at my DbContext class, you might notice something is missing:


I certainly didn't notice it, because I wouldn't have known what to look for.

The thing that is missing is a constructor that will allow dependency injection.


The constructor allows the DbContextOptions object to be passed in via DI.  In hindsight, this makes sense and I understand it, but being new to ASP.NET Core and EF Core, I would have never figured this out.

Fortunately I found this StackOverflow post where some genius spotted the issue:

https://stackoverflow.com/questions/38338475/no-database-provider-has-been-configured-for-this-dbcontext-on-signinmanager-p


Looking at the error message again, we see this text:

"also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext"


Sure enough, the error message did recommend the solution, but like I said, I'm new to this stuff, so I could have read that message 50 times and it wouldn't have meant anything to me.

But now I know...until the next time I forget to add the constructor to my DbContext class...


You can also find him on Twitter, YouTube, and Google+




ASP.NET Core and EF Core: Build failed / Failed to build the project

By Steve Endow

While working in Visual Studio on an ASP.NET Core project that uses EF Core, I attempted to run Scaffold-DbContext, and received this error:


I thought that this message indicated that the scaffolding process failed.  After several minutes of research, I learned that this message means that the project build failed.  This error isn't directly related to Scaffold-DbContext--it is the result of Visual Studio's attempt to automatically build the project before performing the scaffolding operation.

I reviewed me code and found that I had a half-finished line of code that was preventing the build from completing.  I commented out the code, and the Scaffold-DbContext command ran successfully.

I later encountered a similar error when adding a controller to my project using the Add Controller feature in Visual Studio.


Same situation.  I had some unfinished code that prevented the project from building.  Once I cleaned up the code to the point where the project would build, the Add Controller process worked properly.


Steve Endow is a Microsoft MVP in Los Angeles.  He is the owner of Precipio Services, which provides Dynamics GP integrations, customizations, and automation solutions.

You can also find him on Twitter, YouTube, and Google+

http://www.precipioservices.com