El Hippo
El Hippo

Reputation: 389

Blazor base-tag and @page instruction in .razor files

I am getting started with Blazor server-side and I don't get the routing right. I don't understand the need for the base tag in _host.cshtml. If I still have to add the base url in every Blazor component, for example: I want to have a base address of /app/ and the @page directive for the example Counter with a value of "/counter" does not "compile" to "/app/counter". I have to set the @page to "/app/counter" which makes sense but that means that the base Tag in _host.cshtml is useless...

What am I getting wrong here?

Upvotes: 6

Views: 11532

Answers (7)

Simon Gymer
Simon Gymer

Reputation: 516

In Blazor .NET 8 Interactive Server (no idea if this works in other rendering modes or .NET versions) you can do this with no configuration required. Then it works in development and wherever you deploy it...

In App.razor:

<base href="@BaseUrl" />

In the App razor code:

[CascadingParameter] private HttpContext HttpContext { get; set; }
private string BaseUrl => $"{HttpContext.Request.PathBase}/";

Upvotes: 4

Matthias R.
Matthias R.

Reputation: 41

I had the same problem because I needed to host multiple apps under one Nginx server.

Very important: you have to set the PathBase BEFORE any other configuration of the ApplicationBuilder in Startup.cs. To set the path dynamically it is read from the appsettings

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UsePathBase(Configuration.GetValue<string>("PATH_BASE") ?? "/");
    ...
}

appsettings.json

{
    ...
    "PATH_BASE": "/mycustompath",
    ...
}

_Host.cshtml

<head>
    <base href="~/" />
    ...
</head>

All links to navigation and resources must be relative, e.g.

<script src="_framework/blazor.server.js"></script>
or
<script src="_framework/blazor.server.js"></script>

Upvotes: 4

mif
mif

Reputation: 591

Just <base href='/app/' > + dotnet run --pathbase=/app (from there)

Upvotes: 0

Nick Kovalsky
Nick Kovalsky

Reputation: 6452

In case of Blazor WebAssembly you have to deal with index.html only.

When you publish your site to some subfolder in production (ex: yoursite.com/couch/web) put this code instead of <base href="/"> inside head tag and replace "/couch/web/" with your own sub:

<script type="text/javascript">
    var appBase = document.createElement('base');
    appBase.href = "/couch/web/";
    if (window.location.href.indexOf("localhost") > -1)
    {
        appBase.href = "/";
    }
    document.head.appendChild(appBase);
</script>

The result is <base href="/couch/web/"> being automatically generated in production and <base href="/"> when developing from localhost.

Later one can access this base href that was set via a read-only NavigationManager.BaseUri.

Upvotes: 5

McFrank
McFrank

Reputation: 351

To get this working completely I had to combine Softlion fix

In the startup.cs file this is also required. It also needs to be the first line in the configure method, else bad things happen

        app.UsePathBase("/app");

This is so that your relative links will also work. For example I had a link to a login page.

        <a href="~/Login">Login</a>

-------------Edit extra information-------

I just found out blazer is really picky with casing. This happens both in IIS and visual studio

        <base href="/app/" />
        app.UsePathBase("/app");

is not the same as

        <base href="/App/" />
        app.UsePathBase("/App");

you have to get these to match up. Not only that you have to navigate to your Web application with the same casing as well.

I have made a github issue due to the urls not being the same and throwing issues in the javascript debugger

localhost:5001/App

https://github.com/dotnet/aspnetcore/issues/23107

Upvotes: 1

Softlion
Softlion

Reputation: 12595

The solution is there

  1. Add app.UsePathBase("/app"); in Startup.Configure
  2. Add <base href="/app/"> below <head> in _Host.cshtml

Upvotes: 0

itminus
itminus

Reputation: 25350

The <base href='' > is a client side technology that specifies the base URL for all relative URLs in current document. Many SPA frameworks , e.g. Angular, will use this element.

I have to set the @page to "/app/counter"

Actually, you don't have to and should never do that. One of the most important advantages when using <base> is that it allows us to create an app without letting the components know about the base url.

Assuming you've changed the base href from '/' to '/app/', and also changed the other relative urls:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>BlazorApp</title>
    <base href="/app/" />
    <link rel="stylesheet" href="/css/bootstrap/bootstrap.min.css" />
    <link href="/css/site.css" rel="stylesheet" />
</head>
<body>
    <app>
        @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
    </app>

    <script src="/_framework/blazor.server.js"></script>
</body>
</html>

Don't forget to prepend the default Blazor Hub url with a /app/ :

app.UseEndpoints(endpoints =>
{
    endpoints.MapBlazorHub("/app/_blazor");
    endpoints.MapFallbackToPage("/_Host");
});

That's all. There's no need to change the routes from @page "/counter" to @page "/app/counter" at all.

Demo

Here's a demo that we don't change the @page routes for components:

enter image description here

Upvotes: 10

Related Questions