如何在 ASP.net 核心 Web 应用程序中的 SignalR 中实现组

时间:2021-04-12 06:23:29

标签: asp.net-web-api signalr signalr-hub signalr.client asp.net-core-signalr

我正在使用 signalR 组,每当用户更改数据时,组中的每个用户都可以实时看到更改的数据。

我在这个项目中使用了 ASP.net 核心 Web 应用程序模板。

控制器的代码是:

public class PatientCollectionsController : ControllerBase
{
    private readonly IHubContext<GroupHub> groupHub;

    public PatientCollectionsController(Func<string, IPatientCollectionsService> serviceResolver, IConfiguration configuration, ILogger<PatientCollectionsModel> logger,
        IHubContext<GroupHub> grpHub)
    {
        this.dbservice = serviceResolver(configuration.GetValue<string>("CollectionsDbChoice").ToLower());
        this.logger = logger;
        this.groupHub = grpHub;
    }

    // GET: api/<PatientCollectionsController>
    [HttpGet]
    public IActionResult Get()
    {
        HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);

        try
        {
            return Ok(dbservice.GetPatientCollections());
        }
        catch (Exception ex)
        {
            logger.LogError("failed to get Patient Collections", ex.Message, ex.StackTrace);
            logger.LogInformation(ex.Message, ex.StackTrace);
            return StatusCode(500, "Internal server error");
        }
    }
    
    // PUT api/<PatientCollectionsController>/5
    [HttpPut("{id}")]
    public void Put(string id, [FromBody] PatientCollectionsModel value)
    {
        try
        { 
            dbservice.PutPatientCollection(value);
        }
        catch(Exception ex)
        {
            logger.LogError("failed to put Patient Collections", ex.Message, ex.StackTrace);
            logger.LogInformation(ex.Message, ex.StackTrace);
            StatusCode(500, "Internal server error");
        }
    }


    static readonly string[] scopeRequiredByApi = new string[] { "access_as_signedin_user" };
    private IPatientCollectionsService dbservice;
    private ILogger<PatientCollectionsModel> logger;
}

服务代码为:

public class PatientCollectionsDBService : IPatientCollectionsService
{
    #region ctor
    public PatientCollectionsDBService(IDatabaseSettings settings)
    {
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(settings.ConnectionString);
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
        patientCollectionsTable = tableClient.GetTableReference("PatientCollections");
        patientCollectionsTable.CreateIfNotExists();
    }
    #endregion

    #region IPatientCollectionsService Impl
    public List<PatientCollectionsModel> GetPatientCollections()
    {
        TableContinuationToken token = null;
        var pc = new List<PatientCollectionsModel>();
        do
        {
            var tableQuery = new TableQuery<DynamicTableEntity>
            {
                FilterString = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "current")
            };
            var queryResult = patientCollectionsTable.ExecuteQuerySegmented(tableQuery, token);
            foreach (var entity in queryResult)
            {
                pc.Add(new PatientCollectionsModel
                {
                    Id = entity.RowKey,
                    FirstName = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.FirstName)]),
                    PtId = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.PtId)]),
                    DOS = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.DOS)]),
                    PatientBalance = (float)entity.Properties[nameof(PatientCollectionsModel.PatientBalance)].DoubleValue,
                    EOB = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.EOB)]),
                    PhoneNo = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.PhoneNo)]),
                    BalanceCurrent = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.BalanceCurrent)]),
                    BalanceThirtyPlus = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.BalanceThirtyPlus)]),
                    BalanceThirtyPlusCall = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.BalanceThirtyPlusCall)]),
                    BalanceSixtyPlus = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.BalanceSixtyPlus)]),
                    BalanceSixtyPlusCall = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.BalanceSixtyPlusCall)]),
                    Notes = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.Notes)]),
                    BalanceNinetyPlus = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.BalanceNinetyPlus)]),
                    CollectionOneTwentyPlus = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.CollectionOneTwentyPlus)]),
                    CollectionOneTwentyPlusCall = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.CollectionOneTwentyPlusCall)]),
                    Notes2 = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.Notes2)]),
                    Notes3 = Convert.ToString(entity.Properties[nameof(PatientCollectionsModel.Notes3)])
                });
            }

        } while (token != null);

        return pc;
    }

    public async Task<bool> PutPatientCollection(PatientCollectionsModel pc)
    {
        DynamicTableEntity newOne = new DynamicTableEntity { PartitionKey = "current", RowKey = pc.PtId };
        Dictionary<string, EntityProperty> props = new Dictionary<string, EntityProperty>()
        {
            {nameof(PatientCollectionsModel.FirstName), new EntityProperty(pc.FirstName) },
            {nameof(PatientCollectionsModel.PtId), new EntityProperty(pc.PtId) },
            {nameof(PatientCollectionsModel.PatientBalance), new EntityProperty(pc.PatientBalance) },
            {nameof(PatientCollectionsModel.EOB), new EntityProperty(pc.EOB) },
            {nameof(PatientCollectionsModel.PhoneNo), new EntityProperty(pc.PhoneNo) },
            {nameof(PatientCollectionsModel.BalanceCurrent), new EntityProperty(pc.BalanceCurrent) },
            {nameof(PatientCollectionsModel.BalanceThirtyPlus), new EntityProperty(pc.BalanceThirtyPlus) },
            {nameof(PatientCollectionsModel.BalanceThirtyPlusCall), new EntityProperty(pc.BalanceThirtyPlusCall) },
            {nameof(PatientCollectionsModel.DOS), new EntityProperty(pc.DOS) },
            {nameof(PatientCollectionsModel.BalanceSixtyPlus), new EntityProperty(pc.BalanceSixtyPlus) },
            {nameof(PatientCollectionsModel.BalanceSixtyPlusCall), new EntityProperty(pc.BalanceSixtyPlusCall) },
            {nameof(PatientCollectionsModel.Notes), new EntityProperty(pc.Notes) },
            {nameof(PatientCollectionsModel.BalanceNinetyPlus), new EntityProperty(pc.BalanceNinetyPlus) },
            {nameof(PatientCollectionsModel.CollectionOneTwentyPlus), new EntityProperty(pc.CollectionOneTwentyPlus) },
            {nameof(PatientCollectionsModel.CollectionOneTwentyPlusCall), new EntityProperty(pc.CollectionOneTwentyPlusCall) },
            {nameof(PatientCollectionsModel.Notes2), new EntityProperty(pc.Notes2) },
            {nameof(PatientCollectionsModel.Notes3), new EntityProperty(pc.Notes3) }
        };
        newOne.Properties = props;
        newOne.ETag = "*";

        TableOperation updateDenial = TableOperation.Replace(newOne);
        var tableResult = await patientCollectionsTable.ExecuteAsync(updateDenial);

        return tableResult.HttpStatusCode == (int)HttpStatusCode.OK
            || tableResult.HttpStatusCode == (int)HttpStatusCode.NoContent;
    }

然后我创建了一个集线器:

[Authorize]
public class GroupHub : Hub
{
    public async Task JoinGroup(string group)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, group);
        await Clients.Group(group).SendAsync("Send", $"{Context.ConnectionId} has joined the group {group}.");
    }

    public async Task LeaveGroup(string group)
    {
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, group);
    }

}

任何人都可以建议我应该怎么做才能使其正常工作,以及如何将用户发送到不同的组。

1 个答案:

答案 0 :(得分:0)

<块引用>
await Groups.AddToGroupAsync(Context.ConnectionId, group);
await Groups.RemoveFromGroupAsync(Context.ConnectionId, group);

众所周知,连接通过 AddToGroupAsyncRemoveFromGroupAsync 方法添加到组或从组中删除。因此,要管理(添加/删除)组中的用户,首先您应该获取用户的 ConnectionID

在 Hub 的 OnConnectedAsync 方法中,您可以通过上下文获取 ConnectionID。然后,将 ConnectionIDUserName 存储到数据库中。

在 Hub 的 OnDisconnectedAsync 方法中,如果用户断开连接,则从表中删除该用户。

之后,您可以根据 UserName 找到 ConnectionID 并使用 AddToGroupAsyncRemoveFromGroupAsync 方法将用户添加/删除到组中。

//require using Microsoft.AspNetCore.SignalR;
//require using Microsoft.AspNetCore.Authorization;
[Authorize]
public class ChatHub : Hub
{ 
    private readonly ApplicationDbContext _context; //DB context

    public ChatHub(ApplicationDbContext context)
    {
        _context = context;
    }
    public override Task OnConnectedAsync()
    { 
        //get Logged user name.
        var IdentityName = Context.User.Identity.Name;

        SignalRUser user = new SignalRUser() { ConnectionID = Context.ConnectionId, UserName = IdentityName };
        _context.SignalRUser.Add(user);
        _context.SaveChanges();

        return base.OnConnectedAsync();
    } 
    public override async Task OnDisconnectedAsync(Exception exception)
    {
        var IdentityName = Context.User.Identity.Name; 
        var user =  _context.SignalRUser.Where(c => c.UserName == IdentityName).FirstOrDefault();
        //remove user if user disconnected
        if(user != null)
        {
            _context.SignalRUser.Remove(user);
            _context.SaveChanges();
        }

        await base.OnDisconnectedAsync(exception);
    }
}
相关问题