如何在Blazor服务端重定向到不同的路由

24
在 Blazor 客户端中,可以使用重定向实现。
using Microsoft.AspNetCore.Blazor.Browser.Services;
(...)
BrowserUriHelper.Instance.NavigateTo("/route")

但是,在 Blazor Server 项目中,这种方法不起作用,因为它会生成以下错误:

无法将类型为“Microsoft.AspNetCore.Blazor.Server.Circuits.RemoteJSRuntime”的对象强制转换为类型“Microsoft.JSInterop.IJSInProcessRuntime”。

Blazor-Server 中的重定向是什么样子的?


问题是,为什么要在服务器上将重定向到另一个控制器?你不能简单地执行所需的方法吗?而不是路由到新的HttpContext?否则,您需要呈现部分视图并将其作为某种可访问数据传递回来,以便可以再次呈现。 - Greg
当你创建一个服务器端项目时,你会得到服务器和客户端项目。我想在 Razor 页面的客户端应用程序中执行此操作。当用户点击按钮时,将发送一个请求到服务器,并根据响应,要么重定向到不同的页面,要么保留当前页面。 - mikeyy
是的,但当客户端触发事件以在客户端内导航时,您会从客户端触发服务器端事件。客户端应用程序根据服务器提供的响应进行导航。然后,客户端将根据服务器提供的响应使用适当的组件视图。 - Greg
那么服务器必须实际告诉客户端导航到另一个页面?那么如何在我的情况下实现呢?您知道是否有示例吗? - mikeyy
对于非服务器端托管的 Blazor 实现,是的。对于 Blazor,目前还需要进一步尝试。 - Greg
3个回答

56

如果您可以在 Razor 页面上触发,您可以使用以下内容:

@page "/YourPageName"
@inject NavigationManager NavigationManager

<h1>xxx</h1>
.
.
.


@code {

    void MethodToTriggerUrl()
    {
        NavigationManager.NavigateTo("PageToRedirect");
    }
}

4
不要使用 MethodToTriggerUrl(),因为它当然不会自动调用。相反,您可以将 NavigationManager.NavigateTo("/PageToRedirect"); 放入 protected override void OnInitialized(){} 中,这将触发自动重定向。 - goodfellow
1
是的,你说得对,这完全取决于你的设计。如果你想要自动重定向,你可以这样做。你甚至可以放置一些倒计时,然后重定向。问题的答案就是 NavigationManager.NavigateTo() :) - Mehmet Taha Meral

10
经过多次试验,我发现在服务器端这个是有效的:
using Microsoft.AspNetCore.Blazor.Services;
(...)
UriHelper.NavigateTo("/route");

虽然看起来几乎相同,但在Blazor 0.8中确实能够发挥作用。


2
在0.9版本中,至少对我而言,我需要使用@inject IUriHelper UriHelper。 - Andy Mehalick
26
在Microsoft.AspNetCore.Components命名空间中,UriHelper已被更名为NavigationManager:@inject NavigationManager NavigationManager; NavigationManager.NavigateTo("route", false); - adaraz
4
我有一个 Blazor 服务器应用程序,需要重定向到一个独立的 Blazor 组件库中的页面,但 NavigationManager 是无效的。由于某种原因它没有被初始化,我无法从服务器项目中的页面导航到库项目中的页面。 - ataraxia

3

虽然不是您想要的完全解决方案,但仍然是“一种解决方案”。目前我似乎找不到一种类似于Response.Redirect的服务器端方式来完成此操作,但是可以使用jsinterop,在您希望能够从中重定向的组件中使用以下内容。请注意,我也很好奇,并且知道这对我自己也很重要,因此我执行了以下操作:

因此,基于具有服务器端项目模板的示例应用程序...

index.cshtml

@using Microsoft.JSInterop;

 <a href="#" class="btn btn-primary" onclick="@GoSomewhere">Go somewhere with Blazor</a>

@functions {
    protected void GoSomewhere()
    {
        RedirectTo("/FetchData");  //or any other "page" in your pages folder
    }

    public static Task<string> RedirectTo(string path)
    {
        return JSRuntime.Current.InvokeAsync<string>(
            "clientJsfunctions.RedirectTo", path);
    }    
}

然后,在wwwroot文件夹下,放置一个带有以下内容的JavaScript文件:

window.clientJsfunctions = {       
    RedirectTo: function (path) {
        window.location = path;
    }
};

最后,在你的引导文件 index.html 中,放置一个对这个 js 文件的引用。
<body>
    <app>Loading...</app>

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

    <script src="scripts/ClientUtil.js"></script>
</body>

更好的做法是将像上面“RedirectTo”这样的方法放在一个单独的类中,并将其用作大多数组件页面的基类。
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor.Components;
using Microsoft.JSInterop;

namespace MyApp.Web.App.Shared
{
    public class MycomponentBase : BlazorComponent
    {
        public static Task<string> RedirectTo(string path)
        {
            return JSRuntime.Current.InvokeAsync<string>(
                "clientJsfunctions.RedirectTo", path);
        }
    }
}

同时,请记得在每个组件的顶部加入以下代码:

@inherits MycomponentBase;

现在,您应该拥有一个“Redirect”方法,可以从任何派生自您基础组件类的组件中调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接