【问题标题】:Notify all clients of added student and update ui通知所有客户添加的学生并更新用户界面
【发布时间】:2020-03-09 13:37:57
【问题描述】:

我有一个 blazor Web 程序集项目和一个 signal r 服务项目,我想在添加学生时调用对 ui 的更改。 目前我必须刷新页面才能看到添加内容。

StudentService.cs

public class StudentService
{
    public HubConnection connection;

    public StudentServicen()
    {    
        connection = new HubConnectionBuilder()                                            
                     .WithUrl(".../StudentsHub")
                     .Build();

        connection.StartAsync();
    }

    public async Task<List<Students>> GetAllStudents() => 
    await connection.InvokeAsync<List<Students>>("GetAllStudents"));    

    public async Task<Boolean> AddStudent(StudentData student) => 
    await connection.InvokeAsync<Boolean>("AddStudent", student);

}

Students.razor

@inject StudentService StudentService

<ul >

    @foreach (var student in students)
    {
       <li>@student.Name</li>
    } 

</ul>

@code {  

private List<Students> students = new List<Students>();  

protected override async Task OnInitializedAsync()
{
    students = await StudentService.GetAllStudents();        
}

另一个项目的学生中心。

public class StudentsHub : Hub
{
    public Task<List<Students>> GetAllStudents() => 
    Task.FromResult(getAllStudents.GetAll());

    public Boolean AddStudent(StudentData student) => 
    studentService.AddStudent(student);
}

【问题讨论】:

  • 你说这个实现需要刷新页面才能调用getAllStudents?
  • 是的,我希望它显示来自 getAllStudents.GetAll() 的更新的学生详细信息。 Students.razor 是一个显示所有学生详细信息的组件。

标签: c# asp.net signalr blazor blazor-server-side


【解决方案1】:

您已经提供了部分代码 sn-ps,因此我创建了一个正在运行的小示例,并使用自定义服务访问服务器集线器,并将值返回给注入自定义服务的 razor 组件。

请注意,当您使用服务和回调时,您必须使用 InvokeAsync 方法,该方法调度到 Blazor 的 SynchronizationContext,这是一个强制执行单个逻辑线程的对象。

这是完整的代码,复制并测试它,看看它是否可以帮助你的应用程序......

用户服务.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.SignalR.Client;

namespace BlazorSignalRApp.Client
{
    public class UserService
   {
        public event Action Notify;
        public string User { get; set; }
        public string Message { get; set; }
        HubConnection hubConnection;

        public UserService(NavigationManager navigationManager) 
        {
             hubConnection = new HubConnectionBuilder()
            .WithUrl(navigationManager.ToAbsoluteUri("/chatHub"))
            .Build();

             hubConnection.On<string, string>("ReceiveMessage", (user, 
                                                               message) =>
             {
                User = user;
                Message = message;

                if (Notify != null)
                {
                   Notify?.Invoke();
                }
             });

              hubConnection.StartAsync();
              hubConnection.SendAsync("SendMessage", null, null);
      }

      public void Send(string userInput, string messageInput) => 
          hubConnection.SendAsync("SendMessage", userInput, messageInput);

      public bool IsConnected => hubConnection.State == 
                                             HubConnectionState.Connected;
   }
}

Index.razor

@page "/"

@inject UserService UserService
@implements IDisposable

<div>
    <label for="userInput">User:</label>
    <input id="userInput" @bind="@userInput" />
</div>
<div class="form-group">
    <label for="messageInput">Message:</label>
    <input id="messageInput" @bind="@messageInput" />
</div>
<button @onclick="@(() => UserService.Send(userInput, messageInput))" 
             disabled="@(!UserService.IsConnected)">Send Message</button>

<hr />

<ul id="messagesList">
    @foreach (var message in messages)
    {
        <li>@message</li>
    }
</ul>

@code {

    List<string> messages = new List<string>();
    string userInput;
    string messageInput;

    protected override void OnInitialized()
    {
        UserService.Notify += OnNotify;

    }

    public void OnNotify()
    {
        if (!string.IsNullOrEmpty(UserService.User))
        {
            var encodedMsg = UserService.User + " says " + 
                                                        UserService.Message;
            messages.Add(encodedMsg);
        }

        InvokeAsync(() =>
        {
            StateHasChanged();
        });
    }


    public void Dispose()
    {
        UserService.Notify -= OnNotify;
    }

}

ChatHub.cs(将此文件放在服务器项目的 Hubs 文件夹中)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;

namespace BlazorSignalRApp.Server.Hubs
{
    public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }
}

Program.cs(客户端项目)

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using Microsoft.AspNetCore.Blazor.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Components;

namespace BlazorSignalRApp.Client
{
   public class Program
   {
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);

            builder.Services.AddSingleton<UserService>();

            builder.RootComponents.Add<App>("app");

            await builder.Build().RunAsync();
        }
   }
 }

希望这会有所帮助...

【讨论】:

  • 嗨@enet,这是一个很好的例子。我想知道您是否认为这是在模型更改时更新客户端的最佳方式,或者是否还有其他更好的做法?我对 SignalR 的担忧是您必须在服务器上维护大量套接字,而这对于大型应用程序的维护成本很高。
猜你喜欢
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多