从 Blazor 组件 (.razor) 重定向到 Razor 页面 (.cshtml) [服务器端]
Posted
技术标签:
【中文标题】从 Blazor 组件 (.razor) 重定向到 Razor 页面 (.cshtml) [服务器端]【英文标题】:Redirect from Blazor Component(.razor) to Razor Page(.cshtml) [ServerSide] 【发布时间】:2021-11-10 02:51:01 【问题描述】:这是我的用例。我有一个持有全局站点状态的单例对象。我的网站上有一个按钮,单击该按钮会在全局站点状态对象上触发一个事件。我有一个正在侦听此事件的 Blazor 组件(剃刀)。它通过这样做来响应事件
var path = "siteupdate".AddInitialQueryStringArg("returnUrl", _navManager.Uri);
_navManager.NavigateTo(path,true);
这个想法是将所有在线用户重定向到 Razor 页面 (.cshtml),其中显示“网站正在更新,稍后再回来”的消息。当服务器因更新而暂时停机并失去与 SignalR 集线器的连接时,这是提供良好用户体验的必要条件。
在执行之后,它看起来好像导航器试图导航到 siteupdate
页面,但它最终被拒绝并重置回我拨打电话时所在的任何组件。类似于您尝试手动更新浏览器中的 url 并且 navmanager 将其重置。在我的 Razor 页面中放置断点我可以看出 OnGet
方法大部分时间都会被调用,但它的响应似乎不是被确认或什么?我尝试了以下方法:
尝试通过 javascript 设置窗口位置
var path = "/update".AddInitialQueryStringArg("returnUrl", _navManager.Uri);
JSRuntime.InvokeVoidAsync("BlazorHelpers.RedirectTo", path);
尝试不使用强制重新加载,这会导致 404
var path = "/siteupdate".AddInitialQueryStringArg("returnUrl", _navManager.Uri);
_navManager.NavigateTo(path);
作为参考,我在下面有 Razor 页面
Pages/SiteUpdate/UpdateLandingPage.cshtml
我尝试将它放在 Pages 文件夹下,但正如我之前所说,OnGet
方法被调用,因此路由器似乎正在找到它,但似乎框架以某种方式覆盖了 URL。
谢谢
【问题讨论】:
您可以从新的浏览器窗口访问站点更新页面吗?如果没有,请检查您的路由/端点配置 好问题,是的,如果我打开一个新标签并手动输入地址,它就可以正常工作。 您是否在浏览器开发工具网络选项卡中监控了浏览器请求 - 查看正在发生的请求/响应? 我得到一个奇怪的“被阻止”或在重新加载前一页时立即消失的东西。我认为@Quarango 在 blazor 组件(.razor)和 razor 页面(.cshtml)之间的导航在这种情况下有点复杂。 您可以在浏览器开发工具中勾选一个框以保留历史记录(在 Edge 中称为“保留日志”),这样您就不会丢失捕获的请求 - 您需要查看发生了什么 - 这听起来像siteupdate 页面正在立即重定向,但您可以通过捕获响应来确认 【参考方案1】:您的问题有两个部分:所有用户都可以看到的通用更新服务,以及用户在更新发生时设置重定向时所在的单个页面。这些将分别需要 Singleton
和 Scoped
上下文。
我通过创建两个服务对此进行了测试:
UpdateService.cs
/// <summary>
/// A singleton service that alerts users about updates
/// </summary>
public class UpdateService
/// <summary>
/// Event raised when an update starts
/// </summary>
public event Action OnUpdate;
public void TriggerUpdate()
// trigger the event
OnUpdate?.Invoke();
这有一个事件OnUpdate
,消费者可以在更新发生时订阅该事件。
RedirectService.cs
/// <summary>
/// Redirect service (user-scoped)
/// </summary>
public class RedirectService : IDisposable
private readonly NavigationManager navigationManager;
private readonly UpdateService updateService;
public RedirectService(NavigationManager navigationManager,
UpdateService updateService)
this.navigationManager = navigationManager;
this.updateService = updateService;
// register for updates
this.updateService.OnUpdate += HandleUpdate;
private void HandleUpdate()
// get user's current URL
var uri = new Uri(navigationManager.Uri);
if (!uri.PathAndQuery.StartsWith("/siteupdate", StringComparison.CurrentCultureIgnoreCase))
// redirect
navigationManager.NavigateTo($"/siteupdate?redirectUrl=uri.PathAndQuery");
// Cleanup
public void Dispose()
updateService.OnUpdate -= HandleUpdate;
此服务使用 UpdateService
并侦听 OnUpdate
事件。如果当前 URL 还不是“/siteupdate”,它会重定向用户。
在Startup.cs
你注册这两个服务
// a singleton service - all users share this
services.AddSingleton<UpdateService>();
// scoped service for the redirect
services.AddScoped<RedirectService>();
顺序很重要,因为RedirectService
需要UpdateService
。
为了触发它,我刚刚在MainLayout.razor
中注入了服务:
@inherits LayoutComponentBase
@inject Data.RedirectService redirectService
为了测试这一点,我在Index.razor
上放置了一个按钮,当点击该用户时,不同页面/浏览器上的所有其他用户都重定向到新页面。
这意味着任何页面上的任何用户除了 /siteupdate
将被重定向。如果这不是您的用例(例如,只有一些页面/用户应该重定向),您可以相应地进行调整。
【讨论】:
您项目中的 siteupdate 端点是剃刀页面还是 blazor 组件?仍然得到与以前相同的结果,如果我尝试在没有强制重新加载参数的情况下导航,导航管理器似乎期望端点是一个 blazor 组件,因此返回找不到页面。通过强制重新加载,它会访问正确的页面,但会以某种方式重置回原始页面。 SiteUpdate 是一个 Blazor 页面:SiteUpdate.razor
,开头带有 @page "/siteupdate"
路由。此技术仅适用于 Blazor 页面 - 如果您还想重定向 Razor 页面(即.cshtml
),则需要使用某种推送技术(如 SignalR)的基于 JS 的系统。这要复杂得多
@GeorgeFabish 我能否澄清一下:您是否尝试在 Razor 页面 (.cshtml) 中使用 NavigationManager
? NavigationManager
是 Blazor 路由服务:不适用于 cshtml
正如标题所说,我想从 blazor 组件导航到 Razor 页面 .cshtml。抱歉,如果不够清楚。我不能只导航到另一个 blazor 组件的原因是,当网站因更新而脱机时,用户失去了他们的 SignalR 连接,因此登录页面在这种情况下对他们没有好处。
否 - 因为 JSinterop 将成为 Blazor 的一部分,它不起作用.. 所以它不起作用。你需要一个完全不同的解决方案以上是关于从 Blazor 组件 (.razor) 重定向到 Razor 页面 (.cshtml) [服务器端]的主要内容,如果未能解决你的问题,请参考以下文章
如何将可操作的控制字符从 JSON 文本元素传递到 razor 组件 Blazor 变量
重定向到 Blazor WebAssembly 中的 403 禁止组件
C#:如何在 Blazor Wasm 托管中将动态 Razor 组件从服务器发送到客户端?
如何从服务器端 Blazor 应用程序中的 Blazor 组件调用 razor 页面而不导致页面刷新