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

7

5

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?

Hu answered 12/11, 2019 at 22:55 Comment(0)
C
10

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

Checked answered 13/11, 2019 at 9:7 Comment(7)
Hi, I tried that and it doesn't work. Thanks anyway for your effort! I will look further and if I find something I am going to post it here.Hu
It seems that the base-TAg does not work locally on my local machine.Hu
@ElHippo IMO, the statement of "does not work" but without the details won't help solve the issue. It would be nice if you show us your code so that we can find the issue.Checked
Hi, sorry. I changed my startup.cs and my _host.cshtml exactly according to your examples but the components where not found without adding /app/ to the @page directives. But I am not sure if I misunderstand the issue totally. Meanwhile I found a workaround so that I can work with „/„ as base path. Thanks for your efforts!Hu
Have you figured it our yet? I have a similar problem but i want to add the /app/ directory only if the code runs on my Development machineCalorifacient
Did you manage to do this? I changed like this in example but I am getting errors in the console: Error: Failed to complete negotiation with the server: Error and Error: Cannot send data if the connection is not in the 'Connected' State.Sudiesudnor
The base href is great in most cases, but there's still an issue wih local anchors. Indeed, your can't use href starting with # in a page down in the app tree (i.e: /app/packages/1/packageItem/2). This will redirect you to the base href localtion with the anchor. To make it work, you'll have to use the absolute path from NavigationManager, which will cause issues with client features such as Bootstrap scrollspy.Snowonthemountain
D
5

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.

Daman answered 23/7, 2020 at 13:11 Comment(0)
E
4

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>
Examine answered 27/2, 2021 at 17:35 Comment(0)
S
3

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}/";
Southwestwardly answered 19/4 at 13:21 Comment(0)
V
1

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

Violative answered 18/6, 2020 at 20:14 Comment(0)
N
0

The solution is there

  1. Add app.UsePathBase("/app"); in Startup.Configure
  2. Add <base href="/app/"> below <head> in _Host.cshtml
Nu answered 17/1, 2020 at 10:53 Comment(2)
this didnt work for me either. when trying the dotnet command mention in the documentation, all my routs still go to localhost:{port} not localhost:{port}/app. in fact nothing seems to be served up at the /app location.Violative
it looks like I may be doing something wrong. I created a new project and the above sort of worked for me. I still having issue and had to fix a few non relative paths to relative paths. <link rel="stylesheet" href="/css/bootstrap/bootstrap.min.css" /> <link href="/css/site.css" rel="stylesheet" /> <script src="/_framework/blazor.server.js"></script> There is still and error on the counter page as wellViolative
J
0

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

Jenifferjenilee answered 9/9, 2020 at 5:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.