Starting a new project using the VS.NET 2017 latest release installed templates.
I end up with the following directory structure for hosting both my asp.net project as well as my angular client app.
The template is equivalent to creating an ASP.NET Core project to act as an API backend and an Angular CLI project to act as a UI. The template offers the convenience of hosting both project types in a single app project. Consequently, the app project can be built and published as a single unit. The project template creates an ASP.NET Core app and an Angular app. The ASP.NET Core app is intended to be used for data access, authorization, and other server-side concerns. The Angular app, residing in the ClientApp subdirectory, is intended to be used for all UI concerns.
The ClientApp directory contains a standard Angular CLI app. See the official Angular documentation for more information.
Running ng commands – open command prompt, cd to the ClientApp directory. If you have Angular CLI installed globally you can any of its commands i.e. ng lint, ng test etc. (if you do not have Angular CLI installed you can run via npm run ng (or npm run ng lint or npm run ng test). These npm commands reference the scripts setup in the package.json file
As we started this from an ASP.NET Core ‘Angular’ template – there is no need to run ng serve. Yes, read that again. The ASP.NET Core application has already been setup to serve both the c# ASP.NET Core parts as well as your client-side parts of the app. How? Take a look at the Startup.cs file around app.UseSpa which starts both the Angular and ASP.NET sides of this application when you hit F5 (debug-run). The project is configured to start its own instance of the Angular CLI server in the background when the ASP.NET Core app starts in development mode. This makes it convenient as you don’t have to run a separate server manually (one for client app and one for the ASP.NET side)
The downside of letting VS.NET/ASP.NET Core run both sides, is that anytime c# is modified you will have to startup both the web and backend. This can be time consuming, as it does take some time to restart the web server. “The project is configured to start its own instance of the Angular CLI server in the background when the ASP.NET Core app starts in development mode”
To run Angular CLI server externally, independently of the ASP.NET Core process you can open a command prompt, navigate to the Clientapp directory and type npm start which as mentioned above can be found as a script within the package.json. Runs the following: “start” : “ng-serve --extract-css"
As a side note: Installing the Angular CLI Globally
npm --g @angluar/cli
ng new –help
Now if you try to start the Angular CLI web server from the command prompt referencing the global CLI you will see typical error/warning
Your global Angular CLI version (7.0.5) is greater than your local
version (1.7.0). The local Angular CLI version is used.
Okay, so what is going on here. Yes my global version is 7.0.5 while my version in this solution can be found by looking at the package.json where you can see my local version within this project is "@angular/cli": "~1.7.0".
Back to using npm start to launch the Angular CLI development server which will use the cli installed within the project i.e. version 1.7.0 (the configuration in package.json is respected)
Now I can open a browser and navigate to http://localhost:4200/ and my Hello World application/page if visible.
Okay, one more option (these different approach are getting confusing). You can modify your ASP.NET Core app to use the external Angular CLI running instance instead of launching a new one on every F5 (debug-run). In your Startup.cs class, replace spa.UseAngularCliServer with the following: spa.UseProxyToSpaDevelopmentServer(“https://localhost:4200”); After making this change, and pressing F5 it opens a browser to this address https://localhost:44399/ (I thought it would have been localhost:4200). Don’t fret, it is using the externally started server. You can validate this by closing the previously opened command prompt (that was started from npm start), then refresh the https://locahost:44399 and you will see exceptions like …SocketException: No connection could be made because the target machine actively refused it…
So, the pattern at this moment is
1. Modify Startup.cs (comment out the UseAngluarCliServer and add the UseProxyToSpaDevelopmentServer methods below)
2. Open command prompt, cd to ClientApp and type npm start (starts the web server, which will remain open while I code in VS.NET and pressing F5 will compile my c# and server it up in the existing web server created from npm start
Interestingly, you do not have to hit F5 all the time. So in this case, you started the Angular server with npm start, you did not start debugging with F5 however you can just open a browser and use the https://localhost:44399/ address to view your page. At this moment my code is not in debug mode. How can I attach a debugger so I can once again step into the code (without hitting F5)? Yes you can. Open Debug – Attach To Process (and select dotnet.exe)
Refresh your page and now any breakpoints will be hit allowing you to step through your code.
With this template, navigation/pages are not served through MVC (controllers), your ASP.NET Core solution is really setup to server data through AJAX or Rest End Points only. This is a big change from ASP.NET Web Projects where navigating to a page would open a controller which would return a View (cshtml). This is a big change! This approach is very much inline with a true SPA (where one page is loaded and navigation between pages is performed locally within the html/js via client-side routing)
One more thing for this post. With your browser open to the home of the application, open ClientApp/src/home/home.component.html in VS.NET. With both the browser and VS.NET visible modify Welcome to Welcome! and save the file. Notice that the browser was aware of the html/js modification automatically, and refreshed the page. Now Welcome shows Welcome! all automatically.
This does not occur with a deployed web application in production. In production, the apps files are optimized for performance. When you publish the build configuration emits a minified, ahead-of-time (AOT) compiled build of your client side code.
As a test I published my project to a local folder. Watching the Output window, I can see it creates a directory within my project …\obj\Release\netcoreapp2.1\PubTmp\Out then runs the following:
npm run build --prod
ng build --extract-css “—prod”
Creating directory Publish\ClientApp\dist, copies file and finished.
How did it know to do all those commands? Open the .csproj, there you will find build steps integrated. This is beyond the scope of this post, however reading up on MSBuild documents may help. I do feel there is a lot to learn here however.