diff --git a/.gitignore b/.gitignore index b1b117ab..8c1fe97e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ *.user *.userosscache *.sln.docstates +appsettings.Local.json # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/Northwind.Persistence/Infrastructure/DesignTimeDbContextFactoryBase.cs b/Northwind.Persistence/Infrastructure/DesignTimeDbContextFactoryBase.cs new file mode 100644 index 00000000..48d356e6 --- /dev/null +++ b/Northwind.Persistence/Infrastructure/DesignTimeDbContextFactoryBase.cs @@ -0,0 +1,53 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; +using System; +using System.IO; + +namespace Northwind.Persistence.Infrastructure +{ + public abstract class DesignTimeDbContextFactoryBase : + IDesignTimeDbContextFactory where TContext : DbContext + { + private const string ConnectionStringName = "NorthwindDatabase"; + private const string AspNetCoreEnvironment = "ASPNETCORE_ENVIRONMENT"; + + public TContext CreateDbContext(string[] args) + { + return Create(Directory.GetCurrentDirectory(), Environment.GetEnvironmentVariable(AspNetCoreEnvironment)); + } + + protected abstract TContext CreateNewInstance(DbContextOptions options); + + private TContext Create(string basePath, string environmentName) + { + var configuration = new ConfigurationBuilder() + .SetBasePath(basePath + "\\..\\Northwind..WebUI") + .AddJsonFile("appsettings.json") + .AddJsonFile($"appsettings.Local.json", optional: true) + .AddJsonFile($"appsettings.{environmentName}.json", optional: true) + .AddEnvironmentVariables() + .Build(); + + var connectionString = configuration.GetConnectionString(ConnectionStringName); + + return Create(connectionString); + } + + private TContext Create(string connectionString) + { + if (string.IsNullOrEmpty(connectionString)) + { + throw new ArgumentException($"Connection string '{ConnectionStringName}' is null or empty.", nameof(connectionString)); + } + + Console.WriteLine($"DesignTimeDbContextFactoryBase.Create(string): Connection string: '{connectionString}'."); + + var optionsBuilder = new DbContextOptionsBuilder(); + + optionsBuilder.UseSqlServer(connectionString); + + return CreateNewInstance(optionsBuilder.Options); + } + } +} diff --git a/Northwind.Persistence/Northwind.Persistence.csproj b/Northwind.Persistence/Northwind.Persistence.csproj index ac7d2a84..bb32686e 100644 --- a/Northwind.Persistence/Northwind.Persistence.csproj +++ b/Northwind.Persistence/Northwind.Persistence.csproj @@ -12,6 +12,9 @@ + + + diff --git a/Northwind.Persistence/NorthwindDbContextFactory.cs b/Northwind.Persistence/NorthwindDbContextFactory.cs new file mode 100644 index 00000000..55e74700 --- /dev/null +++ b/Northwind.Persistence/NorthwindDbContextFactory.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore; +using Northwind.Persistence.Infrastructure; + +namespace Northwind.Persistence +{ + public class NorthwindDbContextFactory : DesignTimeDbContextFactoryBase + { + protected override NorthwindDbContext CreateNewInstance(DbContextOptions options) + { + return new NorthwindDbContext(options); + } + } +} diff --git a/Northwind.WebUI/.gitignore b/Northwind.WebUI/.gitignore deleted file mode 100644 index 0d10972f..00000000 --- a/Northwind.WebUI/.gitignore +++ /dev/null @@ -1,233 +0,0 @@ -/Properties/launchSettings.json - -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -build/ -bld/ -bin/ -Bin/ -obj/ -Obj/ - -# Visual Studio 2015 cache/options directory -.vs/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Microsoft Azure ApplicationInsights config file -ApplicationInsights.config - -# Windows Store app package directory -AppPackages/ -BundleArtifacts/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -orleans.codegen.cs - -/node_modules - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe - -# FAKE - F# Make -.fake/ diff --git a/Northwind.WebUI/Program.cs b/Northwind.WebUI/Program.cs index 468cf619..0f2e7b9f 100644 --- a/Northwind.WebUI/Program.cs +++ b/Northwind.WebUI/Program.cs @@ -1,10 +1,11 @@ -using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Northwind.Persistence; using Microsoft.EntityFrameworkCore; using System; +using System.IO; +using Microsoft.Extensions.Configuration; namespace Northwind.WebUI { @@ -26,14 +27,31 @@ public static void Main(string[] args) catch (Exception ex) { var logger = scope.ServiceProvider.GetRequiredService>(); - logger.LogError(ex, "An error occurred while migrating the database."); + logger.LogError(ex, "An error occurred while migrating or initializing the database."); } } host.Run(); } + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) + new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .ConfigureAppConfiguration((hostingContext, config) => + { + var env = hostingContext.HostingEnvironment; + config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile($"appsettings.Local.json", optional: true, reloadOnChange: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); + config.AddEnvironmentVariables(); + }) + .ConfigureLogging((hostingContext, logging) => + { + logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); + logging.AddConsole(); + logging.AddDebug(); + }) .UseStartup(); } } diff --git a/Northwind.WebUI/Properties/launchSettings.json b/Northwind.WebUI/Properties/launchSettings.json new file mode 100644 index 00000000..11d6227b --- /dev/null +++ b/Northwind.WebUI/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:52467/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Northwind.WebUI": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:52468/" + } + } +} \ No newline at end of file diff --git a/Northwind.WebUI/appsettings.json b/Northwind.WebUI/appsettings.json index d37e8019..69f9f63d 100644 --- a/Northwind.WebUI/appsettings.json +++ b/Northwind.WebUI/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "NorthwindDatabase": "Server=.;Database=NorthwindTraders;Trusted_Connection=True;Application Name=NorthwindTraders;" + "NorthwindDatabase": "Server=(localdb)\\mssqllocaldb;Database=NorthwindTraders;Trusted_Connection=True;Application Name=NorthwindTraders;" }, "Logging": { "LogLevel": {