Core 项目中的EventHandler 无法从 RazorPages 项目中找到用户以通过 SignalR hub 发送消息

问题描述 投票:0回答:1

有 3 个项目:Core、Persistence(EfCore with SQL Server)和 UI(Razor Pages)。

当用户更新记录时,DomainEvent 会添加到 Core 项目中,并在提交时在持久层中发布,但此时 User 不再存在于 HttpContext 中,并且服务器会抛出错误,因为 User 为 null。

添加新群组成员时会添加事件 MemberAddedEvent。

public class Group 
{
    public List<Contact> Members { get; set; }

    public List<DomainEvent> DomainEvents { get; private set; }
    
    public void AddMember(Contact newMember)
    {
        Members.Add(newMember);
        var memberAddedEvent = new MemberAddedEvent(newMember);
        DomainEvents.Add(memberAddedEvent);
    }
}

该事件在保存时发布在 DbContext 中:


        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken
                = new CancellationToken())
        {
            /*
               truncated for brevity
            */

            var entitiesWithEvents = ChangeTracker
                .Entries()
                .Select(e => e.Entity as BaseEntity<int>)
                .Where(e => e?.DomainEvents != null && e.DomainEvents.Any())
                .ToArray();

            foreach (var entity in entitiesWithEvents)
            {
                var events = entity.DomainEvents.ToArray();
                entity.DomainEvents.Clear();
                foreach (var domainEvent in events)
                {
                    await _mediator.Publish(domainEvent, cancellationToken).ConfigureAwait(false);
                }
            }

            return result;

        }

UI 有一个服务 IUserAccesssor,它返回 HttpContext.User.Identity.Name。

    internal class UserAccessorService(IHttpContextAccessor context) : IUserAccessorService
    {
        public string GetUserName()
        {
            return context.HttpContext.User.Identity.Name;
        }
    }

MemberAddedEventHandler 将通知消息传递到 SignalR MessageHub,以向用户显示漂亮的小 toast 通知。

大多数情况下,这种情况发生得足够快,用户仍然存在于 HttpContextr 中,但有时则不然。

如何保留用户名?我是否需要将其添加到对 AddMember 的初始请求中并将其传递给 DomainEvent?

public class AddMemberCommand : IRequest<AddMemberCommandResponse>
{
    /*
        member properties here
    */ 

    public string UserName { get; set; }

}

public abstract class DomainEvent : INotification
{
    public DomainEvent(string userName)
    {  
        UserName = userName;
    }
    public string UserName { get; private set; }
}
domain-driven-design razor-pages asp.net-core-signalr
1个回答
0
投票

目前我已经在持久层解决了这个问题。我向 DomainEvent 抽象类添加了一个 User 属性。

public abstract class DomainEvent : INotification
{
    public string User { get; set; }
}

我已经在跟踪用户名以记录谁对数据库中的记录进行了更改

        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken
                = new CancellationToken())
        {
            /*
               truncated for brevity
            */

            var entitiesWithEvents = ChangeTracker
                .Entries()
                .Select(e => e.Entity as BaseEntity<int>)
                .Where(e => e?.DomainEvents != null && e.DomainEvents.Any())
                .ToArray();

            foreach (var entity in entitiesWithEvents)
            {
                var events = entity.DomainEvents.ToArray();
                entity.DomainEvents.Clear();
                foreach (var domainEvent in events)
                {
/*
User Name added here to the Domain Event
*/
                    domainEvent.User = userService.UserName();
                    await _mediator.Publish(domainEvent, cancellationToken).ConfigureAwait(false);
                }
            }

            return result;

        }

然后由EventHandler读取并传递给通知服务

    internal class MemberAddedEventHandler(INotifyService notifyService) : INotificationHandler<MemberAddedEvent>
    {
        public async Task Handle(MemberAddedEvent notification, CancellationToken cancellationToken)
        {
            NotificationMessage message = new NotificationMessage(
                user: notification.User,
                message: $"Member added: {notification.Member.FirstName}",
                state: "Success"
                );

            await notifyService.NotifyUserAsync(message);
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.