locked
Blazor WebAssembly With SignalR RRS feed

  • Question

  • User2041008840 posted

    Hello, 
    I got the code from 

    https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr-blazor-webassembly?view=aspnetcore-5.0&tabs=visual-studio 
    and its works fine. 
    But I already have data in my database and I retrieve on page load but its does not show unless I save into database. 
    how to do I solve this problem? 

    private HubConnection hubConnection;
     protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder().WithUrl(NavigationManager.ToAbsoluteUri("/RealTimeHub")).Build();
            hubConnection.On("ReceivedMessage", () =>
            {
                CallOutData();
                StateHasChanged();
            });
            await hubConnection.StartAsync();
        }
    
        private void CallOutData()
        {
    
            Task.Run(async () =>
            {
                await LoadData();
            });
        }
        private async Task LoadData()
        {
            employees = await HttpClient.GetFromJsonAsync<List<Employee>>("api/Employees"); //this does not show on page load till i save the data then the list will show and work live
            StateHasChanged();
        }
        public void Dispose()
        { _ = hubConnection.DisposeAsync(); }

    Create.razor

    protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder().WithUrl(NavigationManager.ToAbsoluteUri("/RealTimeHub")).Build();
    
            await hubConnection.StartAsync();
        }
        public bool IsConnected => hubConnection.State == HubConnectionState.Connected;
        private async Task Save()
        {
            await HttpClient.PostAsJsonAsync("api/Employees",Employee);
            if (IsConnected)
                await SendMessage();
        }
        Task SendMessage() => hubConnection.SendAsync("SendMessage");
        public void Dispose()
        { _ = hubConnection.DisposeAsync(); }




    Monday, December 21, 2020 7:30 PM

Answers

  • User-1330468790 posted

    Hi Prathamesh shende,

     

    The reason is that you put the "CallOutData()" into "hubConnection.On()" which will only be triggered as a callback function from server.

    In short, the CallOutData() method will be called after:

    1. The client sends message and call server side method "SendMessage" in the hub
    2. Then the "RealTimeHub" will call the client side with a name "ReceivedMessage" and parameters.

     

    If you want to render something after the first page load, you should add relevant functions in the method:

    protected override async Task OnInitializedAsync()

    not in 

    hubConnection.On()

      

    You could refer to below demo which I made to show how to load the data and then update it.

    Server - weather hub 

     public class WeatherHub : Hub
        {
            public async Task SendMessage()
            {
                await Clients.All.SendAsync("ReceiveMessage");
            }
        }

    Server - Controller (Randomly give a weather list):

    [ApiController]
        [Route("[controller]")]
        public class WeatherForecastController : ControllerBase
        {
            private static readonly string[] Summaries = new[]
            {
                "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
            };
    
            private readonly ILogger<WeatherForecastController> _logger;
    
            public WeatherForecastController(ILogger<WeatherForecastController> logger)
            {
                _logger = logger;
            }
    
            [HttpGet]
            public IEnumerable<WeatherForecast> Get()
            {
                var rng = new Random();
                return Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = rng.Next(-20, 55),
                    Summary = Summaries[rng.Next(Summaries.Length)]
                })
                .ToArray();
            }

    Shared -  Weather model

     public class WeatherForecast
        {
            public DateTime Date { get; set; }
    
            public int TemperatureC { get; set; }
    
            public string Summary { get; set; }
    
            public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
        }

    Client - Index:

    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    
    <div class="form-group">
        <label>
            Loading weather:
        </label>
        @if (forecasts == null)
        {
            <p><em>Loading...</em></p>
        }
        else
        {
            <table class="table">
                <thead>
                    <tr>
                        <th>Date</th>
                        <th>Temp. (C)</th>
                        <th>Temp. (F)</th>
                        <th>Summary</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var forecast in forecasts)
                    {
                        <tr>
                            <td>@forecast.Date.ToShortDateString()</td>
                            <td>@forecast.TemperatureC</td>
                            <td>@forecast.TemperatureF</td>
                            <td>@forecast.Summary</td>
                        </tr>
                    }
                </tbody>
            </table>
        }
    
    
    </div>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        private WeatherForecast[] forecasts;
    
    
    
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/weatherhub"))
                .Build();
            // Update the weather list every time click the button
            hubConnection.On("ReceiveMessage", () =>
            {
                CallOutData();
                StateHasChanged();
            });
            // Add weather forecasts in the beginning
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
    
            await hubConnection.StartAsync();
        }
    
        private void CallOutData()
        {
    
            Task.Run(async () =>
            {
                await LoadData();
            });
        }
    
        private async Task LoadData()
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
            StateHasChanged();
        }
    
        Task Send() =>
    hubConnection.SendAsync("SendMessage");
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            await hubConnection.DisposeAsync();
        }
    }

    Demo:

     

    Hope this can help you.

    Best regards,

    Sean

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, December 22, 2020 8:51 AM

All replies

  • User-1330468790 posted

    Hi Prathamesh shende,

     

    The reason is that you put the "CallOutData()" into "hubConnection.On()" which will only be triggered as a callback function from server.

    In short, the CallOutData() method will be called after:

    1. The client sends message and call server side method "SendMessage" in the hub
    2. Then the "RealTimeHub" will call the client side with a name "ReceivedMessage" and parameters.

     

    If you want to render something after the first page load, you should add relevant functions in the method:

    protected override async Task OnInitializedAsync()

    not in 

    hubConnection.On()

      

    You could refer to below demo which I made to show how to load the data and then update it.

    Server - weather hub 

     public class WeatherHub : Hub
        {
            public async Task SendMessage()
            {
                await Clients.All.SendAsync("ReceiveMessage");
            }
        }

    Server - Controller (Randomly give a weather list):

    [ApiController]
        [Route("[controller]")]
        public class WeatherForecastController : ControllerBase
        {
            private static readonly string[] Summaries = new[]
            {
                "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
            };
    
            private readonly ILogger<WeatherForecastController> _logger;
    
            public WeatherForecastController(ILogger<WeatherForecastController> logger)
            {
                _logger = logger;
            }
    
            [HttpGet]
            public IEnumerable<WeatherForecast> Get()
            {
                var rng = new Random();
                return Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = rng.Next(-20, 55),
                    Summary = Summaries[rng.Next(Summaries.Length)]
                })
                .ToArray();
            }

    Shared -  Weather model

     public class WeatherForecast
        {
            public DateTime Date { get; set; }
    
            public int TemperatureC { get; set; }
    
            public string Summary { get; set; }
    
            public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
        }

    Client - Index:

    <button @onclick="Send" disabled="@(!IsConnected)">Send</button>
    
    
    <div class="form-group">
        <label>
            Loading weather:
        </label>
        @if (forecasts == null)
        {
            <p><em>Loading...</em></p>
        }
        else
        {
            <table class="table">
                <thead>
                    <tr>
                        <th>Date</th>
                        <th>Temp. (C)</th>
                        <th>Temp. (F)</th>
                        <th>Summary</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var forecast in forecasts)
                    {
                        <tr>
                            <td>@forecast.Date.ToShortDateString()</td>
                            <td>@forecast.TemperatureC</td>
                            <td>@forecast.TemperatureF</td>
                            <td>@forecast.Summary</td>
                        </tr>
                    }
                </tbody>
            </table>
        }
    
    
    </div>
    
    <hr>
    
    <ul id="messagesList">
        @foreach (var message in messages)
        {
            <li>@message</li>
        }
    </ul>
    
    @code {
        private HubConnection hubConnection;
        private List<string> messages = new List<string>();
        private string userInput;
        private string messageInput;
    
        private WeatherForecast[] forecasts;
    
    
    
    
        protected override async Task OnInitializedAsync()
        {
            hubConnection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/weatherhub"))
                .Build();
            // Update the weather list every time click the button
            hubConnection.On("ReceiveMessage", () =>
            {
                CallOutData();
                StateHasChanged();
            });
            // Add weather forecasts in the beginning
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
    
            await hubConnection.StartAsync();
        }
    
        private void CallOutData()
        {
    
            Task.Run(async () =>
            {
                await LoadData();
            });
        }
    
        private async Task LoadData()
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
            StateHasChanged();
        }
    
        Task Send() =>
    hubConnection.SendAsync("SendMessage");
    
        public bool IsConnected =>
            hubConnection.State == HubConnectionState.Connected;
    
        public async ValueTask DisposeAsync()
        {
            await hubConnection.DisposeAsync();
        }
    }

    Demo:

     

    Hope this can help you.

    Best regards,

    Sean

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, December 22, 2020 8:51 AM
  • User2041008840 posted

    thank you so much. Your solution work. 

    btw 
    forums moving to microsoft q&A that will be the one for the best move from microsoft. 
    .NET forums are moving to a new home on Microsoft Q&A, we encourage you to go to Microsoft Q&A for .NET for posting new questions and get involved today.

    Tuesday, December 22, 2020 10:52 AM