Ali*_*Ali 6 c# signalr asp.net-web-api asp.net-core blazor-webassembly
我有一个 Blazor webasemmbly 应用程序,它使用 asp.net core 作为后端,使用 Blazor wasm 作为前端。我有一个类可以检查 HTTP 问题,例如 notfound、BadReqest 和...
public class HttpInterceptorService
{
private readonly HttpClientInterceptor _interceptor;
private readonly NavigationManager _navManager;
private readonly RefreshTokenService _refreshTokenService;
public HttpInterceptorService(HttpClientInterceptor interceptor,
NavigationManager navManager,
RefreshTokenService refreshTokenService)
{
_interceptor = interceptor;
_navManager = navManager;
_refreshTokenService = refreshTokenService;
}
public void RegisterEvent() => _interceptor.AfterSend += HandleResponse;
public void RegisterBeforeSendEvent() =>
_interceptor.BeforeSendAsync += InterceptBeforeSendAsync;
public void DisposeEvent()
{
_interceptor.AfterSend -= HandleResponse;
_interceptor.BeforeSendAsync -= InterceptBeforeSendAsync;
}
private async Task InterceptBeforeSendAsync(object sender,
HttpClientInterceptorEventArgs e)
{
var absolutePath = e.Request.RequestUri.AbsolutePath;
if (!absolutePath.Contains("token") && !absolutePath.Contains("account"))
{
var token = await _refreshTokenService.TryRefreshToken();
if (!string.IsNullOrEmpty(token))
{
e.Request.Headers.Authorization =
new AuthenticationHeaderValue("bearer", token);
}
}
}
private void HandleResponse(object sender, HttpClientInterceptorEventArgs e)
{
if (e.Response == null)
{
_navManager.NavigateTo("/PageError");
throw new HttpResponseException("Server not available.");
}
var message = "";
if (!e.Response.IsSuccessStatusCode)
{
switch (e.Response.StatusCode)
{
case HttpStatusCode.NotFound:
_navManager.NavigateTo("/Page404");
break;
case HttpStatusCode.BadRequest:
break;
case HttpStatusCode.Unauthorized:
_navManager.NavigateTo("/unauthorized");
break;
default:
_navManager.NavigateTo("/PageError");
break;
}
throw new HttpResponseException(message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个 HTTP 拦截器做得很好,但问题是当客户端应用程序 (wasm) 失去与服务器的连接时(由于任何原因,如没有互联网,或服务器停止运行......),它不起作用,并且不会有用的。当服务器运行得不好时。
所以搜索后我发现我们必须检查 signalR 连接状态,但我找不到有关如何实现它的示例或教程。
我想将其全局添加到应用程序中。
检查互联网是否可用的 SignalR 方式有很多缺点。
还有一种方法可以通过一段JS代码来判断用户是否离线:
window.navigator.onLine
Run Code Online (Sandbox Code Playgroud)
更多讨论这里:检测互联网连接是否离线? 但通过这种方法,您应该能够了解用户离线时的大多数情况。
如何将其实现到您的代码中?创建一个名为Connection.razor的组件并将其放在那里:
@inject IJSRuntime _jsRuntime;
@implements IAsyncDisposable
@if (IsOnline)
{
@Online
}
else
{
@Offline
}
@code {
[Parameter]
public RenderFragment Online { get; set; }
[Parameter]
public RenderFragment Offline { get; set; }
public bool IsOnline { get; set; }
[JSInvokable("Connection.StatusChanged")]
public void OnConnectionStatusChanged(bool isOnline)
{
if (IsOnline != isOnline)
{
IsOnline = isOnline;
}
StateHasChanged();
}
protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync();
await _jsRuntime.InvokeVoidAsync("Connection.Initialize", DotNetObjectReference.Create(this));
}
public async ValueTask DisposeAsync() {
await _jsRuntime.InvokeVoidAsync("Connection.Dispose");
}
}
Run Code Online (Sandbox Code Playgroud)
然后创建一个JS文件Connection.js,代码如下:
let handler;
window.Connection = {
Initialize: function (interop) {
handler = function () {
interop.invokeMethodAsync("Connection.StatusChanged", navigator.onLine);
}
window.addEventListener("online", handler);
window.addEventListener("offline", handler);
handler(navigator.onLine);
},
Dispose: function () {
if (handler != null) {
window.removeEventListener("online", handler);
window.removeEventListener("offline", handler);
}
}
};
Run Code Online (Sandbox Code Playgroud)
然后将此 JS 链接到您的index.html中:
<body>
<div id="app" style="height: 100%;">Loading...</div>
<script src="_framework/blazor.webassembly.js"></script>
<script src="js/Connection.js"></script>
</body>
Run Code Online (Sandbox Code Playgroud)
最后在MainLayout.razor中使用此组件,例如:
<Connection>
<Online>
<h1 style="color: green">Online</h1>
</Online>
<Offline>
<h1 style="color: red">Offline</h1>
</Offline>
</Connection>
Run Code Online (Sandbox Code Playgroud)
通过这种方法,您可以通知用户如果其连接不可用。
来源:
https://www.patrickrobin.co.uk/articles/showing-connection-status-in-blazor-webassembly/
https://www.neptuo.com/blog/2019/12/blazor-network-status/
https://code-maze.com/use-browser-functionalities-with-blazor-webassembly/
Run Code Online (Sandbox Code Playgroud)
首先,在您的服务器项目中创建一个集线器。
https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-5.0
启动.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
}
public void Configure(IApplicationBuilder app)
{
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MyHub>("/myhub");
});
}
Run Code Online (Sandbox Code Playgroud)
我的中心
public class MyHub : Hub
{
}
Run Code Online (Sandbox Code Playgroud)
然后,在您的 WASM 客户端中创建一个服务来管理集线器连接:
public class SignalRClientService
{
HubConnection MyHubConnection;
NavigationManager NavigationManager;
public SignalRClientService(NavigationManager navigationManager)
{
NavigationManager = navigationManager;
OpenHub();
}
public void OpenHub()
{
MyHubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/myhub")
.Build();
MyHubConnection.Closed += async (error) =>
{
// Do what you need to do ...
// e.g. 1) Inject this service into your razor component
// 2) Raise an event from here that connection closed
// 3) Listen for event in razor component
// 4) Tell user that connection is closed.
// You could then try to reinitialize the connection here
// and raise and event that connection is reestablished.
}
}
}
Run Code Online (Sandbox Code Playgroud)
在Program.cs中注册服务
builder.Services.AddSingleton<SignalRClientService>();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4772 次 |
| 最近记录: |