Search code examples
signalr-hubsignalr.clientasp.net-core-signalr

Try to use SignalR in my cshtml to update schedule time table in background with out refresh browser ,but got an error in Hub class


every thing is fine when i try to connect to signalR and gave me a token and Connection is stablished but when client call the hub class and i i want to invoke my updated json data to client got error and never found what happend .

my project is an asp.net core web app razor page with .net 7 i have a TimeTable.cshtml that shows scheduleTime Table and must update every 1 minute at least so , i connect to signalR via javascript

here is my code in hub class


using Dapper;
using GameFest.Model;
using GameFest.Web.Data;
using GameFest.Web.Helpers;
using GameFest.Web.Services.Contracts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System.Data;
using System.Threading.Tasks;
using Timer = System.Timers.Timer;

namespace GameFest.Web.Areas.Portal.Services
{
    [Authorize]`your text`
    public class BtlNetHub : Hub
    {
        private readonly ApplicationDbContext _db;
       
        private readonly IConfiguration _config;
        private Timer _timer;

        public BtlNetHub(ApplicationDbContext db, IConfiguration config)
        {
            _db = db;
            _config = config;

            // set up the timer
            _timer = new Timer();
            _timer.Interval = IntervalInMilliseconds;
            _timer.Elapsed += _timer_Elapsed;
            _timer.Enabled = true;
           
        }

        public void Dispose()
        {
            _timer?.Dispose();
        }

        private const int IntervalInMilliseconds = 60000;

        // define method as an endpoint
        [HubMethodName("updateSchedule")]
        public async Task UpdateSchedule()
        {
            using IDbConnection connection = new SqlConnection(_config.GetConnectionString("GameFestConnection"));
            using var data = await connection.QueryMultipleAsync("p_GameFest_Events_AllSchedule", new { },
                    commandType: CommandType.StoredProcedure);
            ScheduleTimeTableDto Schedule = new ScheduleTimeTableDto();
            try
            {
                var holdings = (await data.ReadAsync<ScheduleHoldingDto>()).ToList();

                if (holdings == null)
                {
                    // handle null value
                    Console.WriteLine("holdings is null");
                }
                else
                {
                    List<EventHoldingDto> hl = new List<EventHoldingDto>();
                    foreach (var evnt in holdings)
                    {
                        hl.Add(new EventHoldingDto
                        {
                            HoldingCode = evnt.HoldingCode,
                            EventID = evnt.EventID,
                            StartDate = DateTimeConverter.ConvertToDateTime(evnt.StartDate),
                            Status = evnt.Status,
                            OrgFirstName = evnt.OrgFirstName,
                            EventTitle = evnt.EventTitle,
                            ShortDesc = evnt.ShortDesc,
                            StatusTitle = StatusComponents.ShowStatusTitle(evnt.Status, "holding"),
                            EndDate = DateTimeConverter.ConvertToDateTime(evnt.EndDate),
                            OrgImageUrl = evnt.OrgImageUrl,
                            OrgLastName = evnt.OrgLastName,
                            ParticipantQty = evnt.ParticipantQty,
                            OrganizerID = evnt.OrganizerID,
                            PlayerQty = evnt.ParticipantQty - evnt.PlayerQty
                        });
                    }

                    Schedule.Holdings = hl;
                }

                if (Schedule != null)
                {                    
                    await Clients.All.SendAsync("updateSchedule", Schedule);
                }
                else
                {
                    await Clients.All.SendAsync("showErrorMessage", "خطا در بروزرسانی برنامه‌زمانی رخ داده است.");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                await Clients.Caller.SendAsync("showErrorMessage", ex.Message);
            }
        }

        private async Task CallUpdateSchedule()
        {
            using (var hub = new BtlNetHub(_db, _config))
            {
                if (hub != null && _timer.Enabled)
                {
                    await hub.UpdateSchedule();
                }
            }
        }

        private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                // update the schedule on the client
                _ = CallUpdateSchedule();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw;
            }
        }
    }
}


await Clients.All.SendAsync("updateSchedule", Schedule);

this code got error null exception and i am sure that Schedule is not null and something wrong with Clinets . this function call every less than 60 second and couldn't send data to client(My cshtml page via javascript) please give me someway to figure it out thanks


Solution

  • As I said, the client object was equal to null and had nothing to do with the data schedule. That's why I looked for why this happens. As a result, I realized that I should use the IHubContext interface for clients that are context

     public BtlNetHub(ApplicationDbContext db, IConfiguration config,IHubContext<BtlNetHub> hubContext)
        {
            _db = db;
            _config = config;
           _hubContext = hubContext;
    
            // set up the timer
            _timer = new Timer();
            _timer.Interval = IntervalInMilliseconds;
            _timer.Elapsed += _timer_Elapsed;
            _timer.Enabled = true;
           
        }
    
        public void Dispose()
        {
            _timer?.Dispose();
        }
    
        private const int IntervalInMilliseconds = 60000;
    
        // define method as an endpoint
        [HubMethodName("updateSchedule")]
        public async Task UpdateSchedule()
        {
            using IDbConnection connection = new SqlConnection(_config.GetConnectionString("GameFestConnection"));
            using var data = await connection.QueryMultipleAsync("p_GameFest_Events_AllSchedule", new { },
                    commandType: CommandType.StoredProcedure);
            ScheduleTimeTableDto Schedule = new ScheduleTimeTableDto();
            try
            {
                var holdings = (await data.ReadAsync<ScheduleHoldingDto>()).ToList();
    
                if (holdings == null)
                {
                    // handle null value
                    Console.WriteLine("holdings is null");
                }
                else
                {
                    List<EventHoldingDto> hl = new List<EventHoldingDto>();
                    foreach (var evnt in holdings)
                    {
                        hl.Add(new EventHoldingDto
                        {
                            HoldingCode = evnt.HoldingCode,
                            EventID = evnt.EventID,
                            StartDate = DateTimeConverter.ConvertToDateTime(evnt.StartDate),
                            Status = evnt.Status,
                            OrgFirstName = evnt.OrgFirstName,
                            EventTitle = evnt.EventTitle,
                            ShortDesc = evnt.ShortDesc,
                            StatusTitle = StatusComponents.ShowStatusTitle(evnt.Status, "holding"),
                            EndDate = DateTimeConverter.ConvertToDateTime(evnt.EndDate),
                            OrgImageUrl = evnt.OrgImageUrl,
                            OrgLastName = evnt.OrgLastName,
                            ParticipantQty = evnt.ParticipantQty,
                            OrganizerID = evnt.OrganizerID,
                            PlayerQty = evnt.ParticipantQty - evnt.PlayerQty
                        });
                    }
    
                    Schedule.Holdings = hl;
                }
    
                if (Schedule != null)
                {                    
                    await  _hubContext.Clients.All.SendAsync("updateSchedule", Schedule);
                }
                else
                {
                    await Clients.All.SendAsync("showErrorMessage", "Error");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                await  _hubContext.Clients.All.SendAsync("showErrorMessage", ex.Message);
            }
        }