In our previous article, we have crated a health-check application. This time we would be trimming down the component list to see what could be impact and how we can fix it.
Go to the /ClientApp/src/app folder and delete the counter and the fetch-data folders, with all the files they contain.
Project build would be successful but when we run the project, we would see these errors;
If we open app.module.ts file inside /ClientApp/src/app, we can see these two offending lines;
We know this file has reference to all of the TypeScript files used by Angular application. Remove these two lines and try to compile.
App module is a way to organize and bootstrap Angular applications. This help developers consolidate their own set of Components, directives and pipes into reusable blocks.
Every application must have at least one module, which is conentionally called a root module and is give the AppModule class name.
As we can see; (1) has bunch of import statements, pointing to all the references. The root NgModule block (2) that server a common purpose: directives, components, pipes, modules, providers. The last one contains the Component we want to bootstrap, which is the main application component, the AppComponent.
This time our application will run without any problems. But when we click on Nav links (Counter and Fetchdata), it will throw errors. We need to fix those by removing them from /ClientApp/src/app/nav-menu/nav-menu.component.html.
We can also change home component html to our liking by getting into /ClientApp/src/app/home/home.component.html
We can remove back-end files becuase we don’t need them any more;
WeatherForecast.cs
Controllers/WeatherForecastController.cs
Now we don’t have any .NET Controller and model in our web applications but that’s ok since we don’t have Angular Components that need to fetch data either.
These are short notes on Angular development using Visual Studio 2022.
To create Angular project;
dotnet new angular -o health-check
If you look at solution there are two projects in it, .NET Core and Angular. The .NET Core section relates to the backend while Angular relates to the front-end.
ClientApp folder has all of angular stuff in it.
The default ASP.NET MVC (/Controllers/ and /Pages/” folders, both has Server side Code
The /ClientApp/Src folder that has client side code
The /ClientApp/E2E folder has testing framework code
The /wwwroot/ folder has client side assets.
On a high level, .NET Core back-end stack is in these folders;
The Dependencies virtual folder that contains all the internal, external, and third-party references to build and run our project. In fact all the references to NuGet.
The /Controllers/ folder, which has been shipped with any MVC-based ASP.NET application
The /Pages/ folder, which contains a single Razor Page – error.cshtml — to handle runtime and/or server errors.
The root level files, program.cs and appsettings.json, which will determine our web application’s configuration, including the modules and middleware, compilation settings, and publishing rules.
The question is, where is the Views folder as we used to see in Razor domain? SPA has replaced them, such a page is the /ClientApp/Src/Folder/index.html file. It’s a static page. The only server-side rendered HTML page is the /Pages/Error.cshtml Razor Page which is used to handle runtime and/or server errors that could happen before the Angular Bootstrap phase.
A Razor page similar to a Razor view, with same syntax and function, but it also contains the controller source code. A Razor page is pretty similar to an old .aspx, .aspx.cs ASP.NET Web Form.
On a high level, Angular front-end has these folders;
The /wwwroot/ folder, which will contain the compiled, ready-to-publish contents of our applications: HTML, JS, and CSS files and everything else we want users to have access to in terms of static files
The /ClientApp/ root folder, which hosts the Angular configuration files
The /Client/App/Src/ folder, which contains the Angular app source code files. If we look at them, all of them has .ts extension
The /ClientApp/e2e/ folder, which has sample end-to-end tests
Angular uses the term workspace for its assets. The Angular workspace is the filesystem place contains the Angular files. This workspace is located within the /ClientApp/ folder, which is defined as workspace root. This workspace is usually created and initialized by CLI command used to create the app.
Any CLI commands operating on the app and/or their libraries (such as adding or updating new packages) will be executed from within the workspace folder.
Angular.json
The most important role within the workspace is played by this file, created by the CLI in the workspace root. This contains workspace-wide and project-specific configuration defaults for all build and development tools.
The first few properties at the top of the file define the workspace and project configuration options:
version: the configuration file version
newProjectRoot: The path where new projects are created
projects: A container item that host a sub-section for each project in the workspace.
Keep in mind that angular.json file follows a standard generic-to-specific cascading rule. All configuration values set at the workspace level will be the default value for any project, and can be overridden by those set at the project level.
Package.json
This is Node Package Manager (npm) configuration files; it basically contains a list of npm packages that developer wants to be restored before the project starts. Think about it as Nuget Package Manager. This file has key/value pairs of different libraries and their are some important prefixes that we should be aware of;
The Tilde (~): A value of “~1.1.4” will match all 1.1.x versions, excluding 1.2.0, 1.0.x and so on.
The Caret (^): A value of “^1.1.4” will match everything above 1.1.4, excluding 2.0.0 and above.
We can install/uninstall or view all these packages within json file in VS. Hover over the bar on the left of packages and it will show pop up menu for these actions.
npm-update can be used to upgrade / downgrade these packages.
tsconfig.json
This is typescript configuration file. Typescript is a programming language developed and maintained by Microsoft that acts as JavaScript superset; It offers built-in IntelliSense, which is a great benefit. Angular source code is written in TypeScript.
Typescript code files included in the /ClientApp/ folder. The most notable section in this file is;
The /ClienApp/src/app/ folder, along with all its subfolders, contains all the TypeScript files related to our Angular app: in other words, the whole client-side application source code is meant to be put here.
The /ClientApp/src/app/assets/ folder is meant to store all the applications’ images and other asset files: these files will be copied and/or updated as-is in the /wwwroot/ folder whenever the application is built.
The /ClientApp/src/app/environment/ folder contains build configuration options that target specific environments: environment.ts for dev and environment.prod.ts for production.
index.html: The main HTML page that is served when someone visits your site. The CLI automatically adds all JavaScript and CSS files here (This is like layout file in MVC Core).
main.ts: The main entry point for your application (like a route declaration in program.cs file in MVC)
The /app/ folder
This folder follows Angular folder structure best practices and contains our projects logic and data, including all Angular Modules, Services, and Components, as well as templates and styles.
AppModule
The basic building block of an Angular application are Ng-Modules, which provides a compilation context for components. The role of NgModules is to collect related code into functional sets: therefore, the whole Angular app is defined by a set of one or more NgModules.
An Angular app requires a root module – conventionally called AppModule – that tells Angular how to assemble the application, thus enabling bootstrapping and starting the initialization life cycle. The remaining modules are known as feature-module and serve a different purpose. The root module also contains a reference list of all available components.
Here is a schema of the standard Angular Initialization Cycle to visualize how it works;
The main.ts file bootstraps app.module.ts (AppModule), which then loads the app.component.ts file (AppComponent); and at last it will load other components whenever the application needs them.
The root module can be found in /ClientApp/src/app/ folder and is defined within the app.module.ts file. It contains a bunch of import statements and some array referencing Components, other modules, providers and so on. The root module is just a reference file.
Server-side AppModule for SSR
The /ClientApp/src/app folder contains app.server.module.ts file, which is used to enable the Angular Universal Server-Side Rendering (SSR), a technology that renders Angular applications on the server, provided that back-end framework supports it. .NET has a native support for such convenient feature.
The following is the improved Angular initialization schema when using SSR.
For more detail on Angular Universal and SSR, Check out the following link;
If NgModules are Angular building blocks, Components can be defined as the bricks used to put the app together, to the extent that we can say that an Angular app is basically a tree of Components working together.
Components define views, which is HTML that use services, which provide specific functionality not directly related to views. Service providers can be injected into Components as dependencies, thus making the app code modular, reusable and efficient.
The cornerstone of these Components is conventionally called AppComponent, which is also the only Component that, according to the Angular folder structure conventions, should be placed in the /app/ root folder. All other components should be put in a sub-folder, which will act as dedicated namespaces.
Our AppComonent consists of two files;
app.comonent.ts: Defines the Component logic, that is, the Component class source code.
app.component.html: Defines the HTML template associated with the AppComponent. Any Angular Component can have an optional HTML file containing its UI layout structure instead of defining it within the Component file itself. This is almost always a good practice unless the Component comes with a very minimal UI.
AppComponent is often lightweight, it doesn’t have other optional files that could be found in other Components such as;
<*>.component.css: Defines the base CSS style sheet for a Component. Just like the .html file, this file is optional and should always be used unless the component doesn’t require UI styling.
– <*>.component.spec.ts: Define a unit test for the Component.
Other Components
Other than AppComponent, our template contains four more components, each one in a dedicated folder;
CounterComponent: Placed in the counter subfolder
FetchDataComponent: Placed in the fetch-data subfolder
HomeComponent: Placed in the home subfolder
NavMenuComponent: Placed in the nav-menu subfolder
Press F5 and see how these components work.
HomeComponent
The HomeComponent could be considered the home page of our app; Since we are dealing with SPA we would call them Views. This word refers to the combined HTML template generated by Angular Component that corresponds to a given navigation route.
NavMenuComponent
Do we have sub-components already? Yes, we do. The NavMenuComponent is a perfect example of that. Since it doesn’t have a dedicated route for itself but is rendered as part of other Components within their corresponding view. It is the top portion of each view.
It is where all first-level navigation routes are implemented that are defined in AppModule, all pointing to a given Angular Component.
First-level navigation routes are thos that we want our users to reach with a single click. In our sample app, there are three;
/home: Pointing to the HomeComponent
/counter: Pointing to the CounterComponent
/fetch-data: Pointing to the FetchDataComponent
These navigation routes have been implemented in the NavMenuComponent by using anchor links.
CounterComponent
This component shows an incrementing counter that we can increase by pressing an Increment button.
FetchDataComponent
This component is an interactive table populated with the JSON array generated by the server-side Web API via WeatherForecastController.
The specs.ts file(s)
If we take a look at the source files within the above Component’s subfolders, we can see that the CounterComponent comes with a counter.component.spec.ts file. Those files, as per Angular naming conventions, are meant to contain unit tests for the counter.component.ts source file and are run using the Jasmine Javascript test framework through the Karma test runner.
VLANs had me confused and running in circles for a while when I was first setting them up too. My understanding of things may not be entirely correct or the “right” way of doing things, but it worked for me. I don’t have experience setting up VLANS in the Unraid interface, but my experience getting VLANs working may help you notice something you overlooked.
I believe you need switches and a router that support VLANs, also known as 802.1q. The switches certainly need support for VLANs and I believe the router may need it to route traffic between VLANs (e.g. from VLAN 4 to VLAN 9), perform network management things like DHCP, and access the Internet. Many consumers routers and basic unmanaged switches don’t support VLANs. Third-party firmware like OpenWRT may be able to add VLAN support to consumer routers. I’m not sure what a “smart unmanaged” switch is, but if it doesn’t have some sort of an interface, be it Web, software, serial/RS-232, or ssh/telnet based, it isn’t smart enough to support VLANs; all VLAN configuration is performed on the device itself via some sort of interface. Check the spec sheets on your gear.
I ended up using Netgear GS108Tv2 and GSS116E switches with a pfSense router running on a Dell 780 SFF PC with a I350-T2V2 network adapter. The fancy network adapter isn’t required. The 116E switch has basic “port-based” configuration, but the 108T doesn’t, so I used “advanced” VLAN configurations.
The first major concept to understand is that network traffic doesn’t have VLAN tags until you turn on VLAN support. Traffic on VLANs has extra data added to it, (the 802.1q header), that requires routers and switches to understand VLAN-formatted traffic.
The second major concept to understand is the Port VLAN ID (PVID). It appears to be the default VLAN ID for a port.
The third major concept to understand is VLAN membership. A port is a member of a VLAN if it’s marked as “tagged” or “untagged” on a VLAN. Most devices, e.g. PCs, game consoles, iPads, etc., don’t understand VLANs and so their traffic does not contain a VLAN tag; their traffic is “untagged” when entering the network. “Untagged” ports assign the PVID of the port to the traffic, giving it the VLAN information needed to move on a VLAN network; traffic inherits the VLAN ID from the port. My networked devices are all “untagged” on once VLAN, making them a member of a single VLAN.
“Tagged” ports appear to be designed to move traffic that is is already tagged. This could theoretically come from a device that understand VLANs or be traffic from an “untagged” port that had a tag added by the switch. Cisco uses a technology called “trunk” ports for passing traffic between switches and routers that Netgear doesn’t have. I use “tagged” ports to accomplish this task. My “trunk” ports are tagged in all VLANs, making them a member of all VLANs and allowing them to communicate with all VLANs while passing traffic between switches and routers.
All my networked device are on “untagged” ports but they they inherit a VLAN ID from the port; they become “tagged” by the switch rather than the original device. Once the traffic from a device is tagged by the switch, it can communicate with any device on the same VLAN. Communicating with devices on a different network switch or communicating with devices on the Internet requires the “trunk” ports that are tagged in multiple VLANs.
I set up VLAN 1, 4, and 9; 1 is used for network management, 4 is for my PCs and such, 9 for my Unraid server.
My only experience is with the Netgear stuff, so some of the terminology may be different with other brands.
So if Port 1 connects the switch to the router, Port 1 would bet marked as tagged on VLAN 1, 4, and 9 in my setup, making it a member of VLAN 1, 4, and 9; this makes it something like a “trunk” port between the switch and router and allows all the traffic can get upstream to the router as needed. My “trunk” ports also got a PVID of 1; they always tagged traffic, so the PVID may not matter.
If Port 2 is connected to my desktop PC, it would get a PVID of 4 and is untagged on VLAN 4 only. This allows the port to only communicate with other devices on VLAN 4.
If Port 3 is connected to my laptop, it would get a PVID of 4 and is untagged on VLAN 4 only. This allows the port to only communicate with other devices on VLAN 4.
If Port 4 is connected to my Unraid server, it would get a PVID of 9 and is untagged on VLAN 9 only. This allows the port to only communicate with other devices on VLAN 9.
The fourth major concept is inter-VLAN routing. My PC and laptop in the example above can talk to each other because they’re both on VLAN 4 and can talk to the router via the trunk on port 1. The Unraid server can talk to the router. However, members of VLAN 4 can’t talk to members of VLAN 9. I remedied this with firewall rules in the router. These rules allow me to control which devices (IP addresses) and services (ports) on VLAN 4 can communicate with which devices and services on VLAN 9. I believe this is a reason why the router needs VLAN support – you’re routing between VLAN networks (e.g. 192.168.4.100 to 192.168.9.10). The router may also need to understand the VLAN-formatted packets so it can strip off the VLAN formatting before forwarding it to the Internet.
So I added firewall rules in pfSense to allow my PC and laptop to access the Unraid web UI, ssh, file sharing ports, Plex ports, etc. of my Unraid server.
nmcli con show "Your Connection Name" to list the current properties of that connection
nmcli con edit "Your Connection Name" to enter edit mode for that connection
nmcli> print ipv4 will show you the ipv4 properties of that connection
To add your static IP address (select ‘yes’ for manual method);
Copy to clipboard
nmcli> set ipv4.addresses 192.168.1.10/24
Do you also want to set 'ipv4.method' to 'manual'? [yes]:
If you like, you can also edit set the dns server and local gateway while you’re here. This is important to do if you are making use of the Adguard add-on:
Copy to clipboard
nmcli> set ipv4.dns 1.1.1.1
nmcli> set ipv4.gateway 192.168.1.1
nmcli> save
nmcli> quit
Finally, you should follow this with a full reboot using
Open up the HassOS console, it won’t work thru the sandboxed ssh container. Log in as “root” At the ha> prompt type “login” to get to the REAL hassos At the # prompt, cd to /etc/NetworkManager/system-connections
Then, using vi or nano editor (it only has the most basic editor it seems) you can modify the config files. I put the “original” in a folder called “hold” in case I messed up.