This is a little guide for anyone wanting to deploy a .NET Core Web site to IIS, locally or otherwise. It includes a few pitfalls you may or may not run into.
I have both the .NET Core SDK and .NET Core WebHosting for IIS package installed.
First step, I created a Website. I planned to deploy to “c:\netcore” so this folder was created previously and the web application is set to use that folder.
I let the Website creation create the Application Pool.
Next, I modified the Application Pool. It must be set to not run managed code.
I have my ASPNETCORE_ENVIRONMENT set up to be recognized as “Staging” and have an appSettings.Staging.json file in my VS project.
Next, I ran the basic file system publish in VS2017 pointing it to “c:\netcore.” This, of course, failed initially.
There are a few prerequisites. The primary thing that failed for me is the “bower install” with a code of 9000. I installed this globally (npm install -g bower) and got rid of that error. Next, though, I got a code 1. It dawned on me that the .NET Core Templates I’ve made, I don’t actually use bower. I removed this line in the PrepublishScript section of the *.csproj:
<Exec Command="bower install" />
After that, I got an error due to file access. I modified the security on “c:\netcore” to give users full control. Obviously, if you’re using a build agent, you’d probably want to give the build agent full control rather than all users.
However, I still got some weird error. Apparently, there was a tooling reference needed in the *.csproj. I added this line within the ItemGroup that already had a DotNetCliToolReference.
<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.2.281" />
Once those modifications were made, my publish succeeded. Huzzah! And I could see all of my files in the IIS Manager Console:
I also set up the site bindings to listen on port 44380 for SSL and to use the already installed IIS Express Development Certificate (how convenient!).
Browsing to the site, though, I ran into immediate failure.. (ugh!)
I dug into the Windows Event Viewer to see IIS Errors and saw this one.
“0x80004005” is access denied or file missing. When “dotnet publish” bundles up an application for use in IIS, a web.config file is created and placed within the IIS folder. The easiest fix is to add the path to the dotnet.exe to your PATH environment variable, but if you don’t want to, you can place it directly in the published web.config. Again, this isn’t ideal for publishing and republishing.
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="C:\Program Files\dotnet\dotnet.exe" arguments=".\Netcore.Template.Web.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" /> </system.webServer> </configuration>
Changing this though, still didn’t fix my problem. Also, even if I enabled logging (stdoutLogEnabled), I got no log. You can run the program (dotnet.exe Netcore.Template.Web.dll, in my case) directly to get a meaningful message, though. I immediately saw that the publish procedure doesn’t deploy the “hosting.json” file that I use for Kestrel.
Unhandled Exception: System.IO.FileNotFoundException: The configuration file 'Properties/hosting.json' was not found and is not optional. The physical path is 'C:\netcore\Properties\hosting.json'. at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload) at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers) at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build() at Netcore.Template.Web.Program.Main(String args) in C:\Users\stephen.long\github\personal\aspnet-core-template\Netcore.Template.Web\Program.cs:line 17
This makes sense, since the Kestrel hosting file is not needed when hosting with IIS. It did require me to modify the Program.cs to only load/require it if it exists (check with System.IO.File.Exists && Environment check) and republish.
Finally, after republishing, everything worked and I was able to login through my single-sign on OAuth provider.