To host my angular 2 application (fpnAngled) from the last post, I used standard asp.net framework (4.6). However, as I was getting ready to implement IdentityServer, I realized that asp.net and angular 2 routing were not working together. I could not get the html5 URL format in angular 2 to route properly through asp.net, despite changing web.config to include rewrite rules for filename and directory. The angular app would route well, until the browser window was refreshed – then it would not be able to find dependencies or reload. So after hours of tinkering, I explored using asp.net core to host the angular app. In retrospect (see below), I might have seen success with the old asp.net framework by changing the index.html base href.
The new asp.net core framework works very well on development machines. Great new features, simplified structure, nice integrated web server – all in a small package. As usual, Visual Studio works well for core development.
So I was surprised, when I attempted deployment. This should be simple. Well – simple by MS standards. Creating and configuring IIS virtual directories with correct permissions always seems to take me an hour of tinkering. Often the problem is in setting security for the virtual directory to allow “IIS APPPool\MyNewPool” in addition to network service, my admin account and now WDeployAdmin. Why isn’t some of this automatic when you make a web application? Why is the apppool not even listed in the potential users to add in the security tab (and why do I need to click through 5 windows to get the list of users to add to the folder security). Sure, I could use Azure, and trade one complicated set of controls for another; at least with IIS, it is not all a magic black box. I do sometimes wonder if Microsoft is trying to upsell Azure, by keeping IIS unnecessarily complicated. And sure, I could work on learning server admin and IIS, but I find it hard enough to keep up with application development. I do typically get IIS sites eventually working after a period of trial and error, and without opening too many security holes.
With asp.net core, I expected to build, publish, run a kestrel console app via IIS. I am not even crossing platforms – this is Windows Server 2012; this should flow easily just as in the 5 minute demo videos (of which at this point there are very few on asp.net core deployment to IIS).
I followed the deployment instructions on the official asp.net core site (which is much improved over the typical less readable MS technical documentation). Still, the documentation is not exactly sequential and key setup information is found on subsequent pages. Surprisingly, a large part of the instruction page is devoted to setting-up IIS for first-time web hosting and the more difficult aspects are sparsely documented.
So, I initially missed the required installation of asp.net core on the server (it was right below how to make IIS serve websites). I then tried VS Web Deploy but received a cryptic error, so I tried deploying a zipped file package and extracting on the server. But what should be at the app root: Content folder? website folder?. Clearly the zipped file did not have the right deployment structure, so I deleted files in the directory to start over. But even deleting files/folders was a chore, since one of the folders needed admin permission to delete (content folder) and win explorer running under the admin account on the server does not have admin permission. Even trying to change folder security to grant me permission to delete did not work. Fortunately, powershell worked with remove-item. This by the way, reminds me of trying to delete multiple nested node-module directories in windows explorer which also does not work and requires work-arounds. Why is explorer so anemic sometimes? Why, MS, why do you cause me this pain?
So I returned to web deploy method and realized that the HttpPlatformHandler and Web Deploy v3.6 were first needed on the server. Installed these and then web deploy did not like either a self signed server certificate or my SSL certificate. Tried making the certificates trusted with MMC.exe.
Tried allowing untrusted certificates, but could not find the correct pubxml at first (which is by the way under project/properties). Still did not work (fixed the certificate error, but now had a new cryptic error – disallowed user). Ultimately, using Rick Stahl’s recommendations for PublishMethod and AuthType, and I was able to find the following settings in pubxml that did work (and did not require allowing untrusted certificates):
Really MS? Rick Stahl published his fix >3-4 months ago and the pubxml default is still not correct. On the bright side, once web deploy worked, everything fell into line. The root publish directory now has the web.config, all the DLLs, and 2 folders: refs and wwroot. And now the deployed asp.net core site works: static files and the api.
At this point, I was still stuck with my original problem – not being able to navigate to a URL within the angular app. asp.net would intercept the URL first, or the angular app would start loading and would look for dependencies at the same level of the passed URL (which would be too deep). Then I hard coded the base href to the full start directory (//mywebsite.com/myVirtualDir/), and it all worked. Will need to see if I can set the index.html base href dynamically (based on prod vs dev settings). I also used Ben Cull’s recommendations to use file server. Not sure if all of this is needed, but it works.
Hours wasted on the seemingly simple goal of passing routing through asp.net back to an angular application to manage. Nearly a full day wasted, and with the scattered litter of failed trial/error attempts. Solved, but not without scrapes and bruises, and a frustrating unnecessary waste of time.
Log files are also key to digging into the “500: Internal Server Errors”. By adding NLog Extensions to the asp.net core app, log files are saved to the dir of your choice (c:\temp\) by default.
I do not typically bash Microsoft’s development tooling. Sure – I have NOT spoken kindly of MS Outlook, MS browsers, Win 8, pocket pcs…. BUT I am a true fan of Visual Studio, VS Code, any language Anders H. wrote (turbo Pascal, C#, Typescript; I never used Delphi). I even like Powershell (although I use only the simple parts).
So why, Microsoft, why do you make deployment so hard (even to your own windows servers).
Ran into more trouble after upgrading to asp.net core 1.1. The 1.1 version works very well on the development machine, but not so much on the server on deployment.
On the server, I could not get the command tools to work. First, I could not migrate/update the database (“dotnet ef …”) from the command line. After much fiddling, I had to manually import database via sql server management studio.
Still on the server, I then tried from the command line, “dotnet myapp.dll”. This should run the app in Kestrel and give me lots of debug info for problems that arise. Unfortunately, I kept getting this critical error:
I made sure nothing atypical was being called in startup.cs or program.cs. I updated all Core SDK and Runtime on the server to 1.1 (and uninstalled 1.0). I looked around for CLI updates – but it looked like with “Dotnet –info”, I am using the same cli version (1.0.0-preview2-003121) on both my server and the developer machine (where the CLI run command works). The Kestrel error could have been a bit more descriptive. As a last Hail Mary, I tried calling the api via IIS using the URL, and it worked!
I have no idea why CLI Kestrel would not load (yet work via IIS) and why the CLI database tools (dotnet ef…) would not migrate/update the database. But I’ll add it to my baffled list and move on.
I do not consider 1.1 releases to be extra-early adoption (these are not beta or alpha), but I feel that has been a painful adoption of fully released product. Asp.net core is a great overall product, but watch out for its sharp edges.
One other issue that can be painful to overcome, especially in testing, is CORS. Rick Stahl has a nice summary of working with this in asp.net core here.