I can launch to my preferred URL of the Razor page I desire, but this works only in DEVELOPMENT
mode or in debug mode. However, when deploying my Blazor web app on Windows Server 2012 R2 Standard using IIS 8.5, the automatic URL launching functionality is not present, which is a key difference between debug and deployment.
I found out that the configuration in launchSettings.json
file, more specifically, the launchUrl
settings, is applicable only in debug mode.
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"hotReloadEnabled": true,
"launchUrl": "account/login",
"applicationUrl": "http://localhost:5113",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"hotReloadEnabled": true,
"launchUrl": "account/login",
"applicationUrl": "https://localhost:7233;http://localhost:5113",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
So I tried to refactor the App.razor
because of my findings about the launchSettings.json
configurations.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/account/login" />
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["MyProject.styles.css"]" />
<ImportMap />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet />
</head>
<body>
<Routes />
<script src="_framework/blazor.web.js"></script>
<script src="lib/bootstrap/dist/js/bootstrap.min.js"></script>
</body>
</html>
Well, this works, but not in an expected outcome. I mean, the resources such as the client-side scripts are missing. Therefore, I considered this configuration as incorrectly configured. Please note that I'm not using IIS sub-application hosting on my end.
In additional, here's my Program.cs
configurations:
using MyProject.Components;
using Microsoft.EntityFrameworkCore;
using MyProject.Data.SQLite;
using MyProject.Data.SQLServer;
using MyProject.Components.Account;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using MyProject.Data.SQLiteAuth;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContextFactory<SQLServerContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("SQLServerContext") ?? throw new InvalidOperationException("Connection string 'SQLServerContext' not found.")));
builder.Services.AddDbContextFactory<SqliteAuthContext>(options =>
options.UseSqlite(builder.Configuration.GetConnectionString("SqliteAuthContext") ?? throw new InvalidOperationException("Connection string 'SqliteAuthContext' not found.")));
builder.Services.AddQuickGridEntityFrameworkAdapter();
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<IdentityUserAccessor>();
builder.Services.AddScoped<IdentityRedirectManager>();
builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies();
builder.Services.AddIdentityCore<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<BlazorAuthContext>()
.AddSignInManager()
.AddDefaultTokenProviders();
builder.Services.AddSingleton<IEmailSender<IdentityUser>, IdentityNoOpEmailSender>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseMigrationsEndPoint();
}
app.UseHttpsRedirection();
app.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode();
app.MapAdditionalIdentityEndpoints();
app.Run();
Moreover, if I refactor <base href="/account/login" />
into <base href="/" />
, I am not getting the launch URL I wanted (account/login
), it throws this status instead,
This localhost page can’t be found
HTTP ERROR 404
To be more specific, I want to launch the URL {domain}:{port}/account/login
by default upon clicking the site directly from IIS Manager:
Unfortunately, I couldn't get what I wanted.
Answer
This solution is just a workaround that does not guarantee that it is appropriate in the official production phase. However, the good thing about this workaround is that it is working as expected, achieving what I wanted to achieve.
The App.razor
should use the default configuration of <base>
tag through this setting:
<base href="/" />
Lastly, in Program.cs
, add these configurations, for example, above the app.Run();
:
app.Use(async (context, next) =>
{
if (context.Request.Path == "/")
{
context.Response.Redirect("/account/login");
return;
}
await next();
});
app.Run();
This will resolve the error status:
This localhost page can’t be found
HTTP ERROR 404
And also, redirect me to the URL path I desire without any issues (so far).