简体   繁体   中英

Notify all clients of added student and update ui

I have a blazor web assembly project and a signal r service project I would like to invoke the changes to the ui when I add a student. Currently I have to refesh the page to see the addition.

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();        
}

Students hub in another project.

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

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

You've provided partial code snippets, so I created a small sample which is working, and using a custom service to access the server hub, and return values to a razor component into which the custom service is injected.

Note that when you use services and call backs you must use the InvokeAsync method, which dispatches to Blazor's SynchronizationContext, an object that enforces a single logical thread of execution.

Here's the complete code, copy and test it, and see if it can help you with your app...

UserService.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 (Put this file in a Hubs folder in the Server project)

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 (Client project)

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();
        }
   }
 }

Hope this helps...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM