Angular base-href and parametrized routes
In my previous post I wrote about how to make paths work for your ASP .NET Core backend / Angular frontend application, if the directory where it lives is different in production and in the development environment. This post is about an unexpected (and completely preventable) “gotcha” it caused.
As in my previous post, the application I use as an example was based on a skeleton application that Visual Studio 2019 created from a template for an ASP.NET Core web application with Angular frontend. It uses Angular 8, but the problem is probably applicable to a wider variety of Angular versions. The ASP.NET Core backend is not important for the purposes of this problem.
Weeks after configuring the application for publishing to a subdirectory in production, I added parameterized routes. And then I ran into a problem.
The parameterized route I added was as simple as it gets:
{ path: 'weather-forecast/:id', component: WeatherForecastComponent }
It only takes one parameter, id
The routing part of my app.module.ts
looked like this:
RouterModule.forRoot([ { path: 'weather-forecast/:id', component: WeatherForecastComponent }, { path: 'fetch-data', component: FetchDataComponent } ], { enableTracing: true }),
The route 'fetch-data'
was already there from the template application, since the ASP.NET Core / Angular application template in Visual Studio 2019 creates a skeleton application with a few routes, among them fetch-data
. It returns a list of "weather forecasts". So I wrote a WeatherForecastComponent
that displays just one weather forecast, and added a route 'weather-forecast/:id'
. This route has a parameter id
, and it displays the forecast by id
.
Here is the problem. If I clicked on a link to an individual forecast in the forecast list, the route worked fine. But if I attempted to call the route directly by going to its URL, it would fail. The application would not load at all. In the Chrome Developer Tools I would see a message such as
Document 4b3582bc-88a5-459f-8194-a228061e38d6 200 document Other 964 B 2.02 s Stylesheet styles.css (canceled) stylesheet 4b3582bc-88a5-459f-8194-a228061e38d6 0 B 2.06 s Stylesheet css?family=Roboto:300,400,500&display=swap 200 stylesheet 4b3582bc-88a5-459f-8194-a228061e38d6 (disk cache) 5 ms Stylesheet icon?family=Material+Icons 200 stylesheet 4b3582bc-88a5-459f-8194-a228061e38d6 (disk cache) 6 ms Script runtime.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 292 B 2.05 s Script polyfills.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 197 B 2.08 s Script vendor.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 202 B 2.08 s Script main.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 200 B 2.08 s Script runtime.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 223 B 2.02 s
The most puzzling error messages were these
Script runtime.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 292 B 2.05 s Script polyfills.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 197 B 2.08 s Script vendor.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 202 B 2.08 s Script main.js 404 script 4b3582bc-88a5-459f-8194-a228061e38d6 200 B 2.08 s
Why was the browser getting the 404 / Not Found on files runtime.js
, polyfills.js
, vendor.js
and main.js
?
Why was the browser getting the 404 / Not Found on files runtime.js
, polyfills.js
, vendor.js
and main.js
?
As I mentioned in passing in the previous post, I had removed this line
<base href="/">
from the
element of the index.html
file, thinking that the hardcoded value might "interfere" with the injected one. It turned out to be necessary.
When I try to access a route with a parameter, such as
localhost://<port_number>/weather-forecast/1
the browser thinks the application's base URL is localhost://<port_number>/weather-forecast
. So it looks for the files runtime.js
, polyfills.js
, vendor.js
and main.js
in a non-existent directory weather-forecast
. Naturally, it can't find them.
That's why it's important to leave
<base href="/">
in index.html
.