首页 > 解决方案 > 如何使用 ASP.NET 样板实现多个通知程序?

问题描述

我正在使用 ASP.NET 样板(带有 .NET Core)。我正在尝试实现Multiple Notifiers官方文档中提到的通知系统,但我遇到了:

System.NullReferenceException:“对象引用未设置为对象的实例。”

我的问题与异常本身无关。我想知道在实现示例之前是否有任何预请求配置或设置,或者我的代码是否遗漏了一些东西:

public class MessageAppService: AsyncCrudAppService<Message, MessageDto, long, PagedAndSortedResultRequestDto, CreateMessageDto, UpdateMessageDto, ReadMessageDto>, IRealTimeNotifier, ITransientDependency
{
    private readonly IRepository<Message, long> _repository;

    private readonly IDbContextProvider<MySystemDbContext> _dbContextProvider;
    private MySystemDbContext db => _dbContextProvider.GetDbContext();

    IHubContext<MyChatHub> _hubContext; // This for online chat

    private readonly IEmailSender _emailSender;
    private readonly UserManager _userManager;

    private readonly INotificationSubscriptionManager _notificationSubscriptionManager;

    public MessageAppService(
        IDbContextProvider<MySystemDbContext> dbContextProvider,
        IRepository<Message, long> repository, 
        IHubContext<MyChatHub> hubContext /* This for online chat */,
        INotificationSubscriptionManager notificationSubscriptionManager,
        IEmailSender emailSender,
        UserManager userManager
    ) : base(repository)
    {
        _repository = repository;
        _dbContextProvider = dbContextProvider;
        _hubContext = hubContext; // This for online chat 
        _notificationSubscriptionManager = notificationSubscriptionManager;
        _emailSender = emailSender;
        _userManager = userManager;
    }

    public override async Task<MessageDto> CreateAsync(CreateMessageDto input)
    {
        var test = await base.CreateAsync(input);
        UserNotification userNotifications = new UserNotification();
        userNotifications.UserId = 10010;
        //
        userNotifications.Notification.TenantId = AbpSession.TenantId;
        userNotifications.Notification.NotificationName = "test";

        UserNotification[] notificationList = new UserNotification[1];
        notificationList[0] = userNotifications;
        await SendNotificationsAsync(notificationList);
        return test;
    }

    public async Task SendNotificationsAsync(UserNotification[] userNotifications)
    {
        foreach (var userNotification in userNotifications)
        {
            if (userNotification.Notification.Data is MessageNotificationData data)
            {
                var user = await _userManager.GetUserByIdAsync(userNotification.UserId);

                _emailSender.Send(
                    to: "testg@gmail.com",
                    subject: "You have a new notification!",
                    body: data.Message,
                    isBodyHtml: true
                );
            }
        }
    }

    void IRealTimeNotifier.SendNotifications(UserNotification[] userNotifications)
    {
        throw new NotImplementedException();
    }
}

我在 .Application 模块的 PreInitialize() 函数中添加了以下内容:

Configuration.Notifications.Notifiers.Add<MessageAppService>();

更新

我知道如何避免这种异常,但我想知道我在代码中实现的步骤是否足以获得通知。


更新 2:

我已经在aaron提到的问题中应用了代码。我有另一个例外:

WARN  2020-07-05 13:30:06,907 [9    ] fications.DefaultNotificationDistributer - System.Net.Mail.SmtpException: Failure sending mail.
 ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10061): No connection could be made because the target machine actively refused it. [::ffff:127.0.0.1]:25
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   --- End of inner exception stack trace ---
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at Abp.Net.Mail.Smtp.SmtpEmailSender.SendEmail(MailMessage mail)
   at Abp.Net.Mail.EmailSenderBase.Send(MailMessage mail, Boolean normalize)
   at Abp.Net.Mail.EmailSenderBase.Send(String to, String subject, String body, Boolean isBodyHtml)
   at MySystem.ChatAppService.MessageAppService.SendNotificationsAsync(UserNotification[] userNotifications) in D:\WorkSpace\MySystem\aspnet-core\src\MySystem.Application\ChatAppService\MessageAppService.cs:line 172
   at Abp.Notifications.DefaultNotificationDistributer.NotifyAsync(UserNotification[] userNotifications)
System.Net.Mail.SmtpException: Failure sending mail.
 ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10061): No connection could be made because the target machine actively refused it. [::ffff:127.0.0.1]:25
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   --- End of inner exception stack trace ---
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at Abp.Net.Mail.Smtp.SmtpEmailSender.SendEmail(MailMessage mail)
   at Abp.Net.Mail.EmailSenderBase.Send(MailMessage mail, Boolean normalize)
   at Abp.Net.Mail.EmailSenderBase.Send(String to, String subject, String body, Boolean isBodyHtml)
   at MySystem.ChatAppService.MessageAppService.SendNotificationsAsync(UserNotification[] userNotifications) in D:\WorkSpace\MySystem\aspnet-core\src\MySystem.Application\ChatAppService\MessageAppService.cs:line 172
   at Abp.Notifications.DefaultNotificationDistributer.NotifyAsync(UserNotification[] userNotifications)
WARN  2020-07-05 13:30:09,049 [10   ] fications.DefaultNotificationDistributer - System.Net.Mail.SmtpException: Failure sending mail.
 ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10061): No connection could be made because the target machine actively refused it. [::ffff:127.0.0.1]:25
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   --- End of inner exception stack trace ---
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at Abp.Net.Mail.Smtp.SmtpEmailSender.SendEmail(MailMessage mail)
   at Abp.Net.Mail.EmailSenderBase.Send(MailMessage mail, Boolean normalize)
   at Abp.Net.Mail.EmailSenderBase.Send(String to, String subject, String body, Boolean isBodyHtml)
   at MySystem.ChatAppService.MessageAppService.SendNotificationsAsync(UserNotification[] userNotifications) in D:\WorkSpace\MySystem\aspnet-core\src\MySystem.Application\ChatAppService\MessageAppService.cs:line 172
   at Abp.Notifications.DefaultNotificationDistributer.NotifyAsync(UserNotification[] userNotifications)
System.Net.Mail.SmtpException: Failure sending mail.
 ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10061): No connection could be made because the target machine actively refused it. [::ffff:127.0.0.1]:25
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   --- End of inner exception stack trace ---
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at Abp.Net.Mail.Smtp.SmtpEmailSender.SendEmail(MailMessage mail)
   at Abp.Net.Mail.EmailSenderBase.Send(MailMessage mail, Boolean normalize)
   at Abp.Net.Mail.EmailSenderBase.Send(String to, String subject, String body, Boolean isBodyHtml)
   at MySystem.ChatAppService.MessageAppService.SendNotificationsAsync(UserNotification[] userNotifications) in D:\WorkSpace\MySystem\aspnet-core\src\MySystem.Application\ChatAppService\MessageAppService.cs:line 172
   at Abp.Notifications.DefaultNotificationDistributer.NotifyAsync(UserNotification[] userNotifications)
ERROR 2020-07-05 13:30:28,176 [10   ] Mvc.ExceptionHandling.AbpExceptionFilter - Failure sending mail.
System.Net.Mail.SmtpException: Failure sending mail.
 ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10061): No connection could be made because the target machine actively refused it. [::ffff:127.0.0.1]:25
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   --- End of inner exception stack trace ---
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at Abp.Net.Mail.Smtp.SmtpEmailSender.SendEmail(MailMessage mail)
   at Abp.Net.Mail.EmailSenderBase.Send(MailMessage mail, Boolean normalize)
   at Abp.Net.Mail.EmailSenderBase.Send(String to, String subject, String body, Boolean isBodyHtml)
   at MySystem.ChatAppService.MessageAppService.CreateAsync(CreateMessageDto input) in D:\WorkSpace\MySystem\aspnet-core\src\MySystem.Application\ChatAppService\MessageAppService.cs:line 153
   at Abp.Authorization.AuthorizationInterceptor.InternalInterceptAsynchronous[TResult](IInvocation invocation)
   at Abp.Domain.Uow.UnitOfWorkInterceptor.InternalInterceptAsynchronous[TResult](IInvocation invocation)
   at Abp.Auditing.AuditingInterceptor.InternalInterceptAsynchronous[TResult](IInvocation invocation)
   at Abp.Runtime.Validation.Interception.ValidationInterceptor.InternalInterceptAsynchronous[TResult](IInvocation invocation)
   at lambda_method(Closure , Object )
   at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

标签: c#aspnetboilerplateasp.net-boilerplate

解决方案


你没有向我们展示足够的信息。UserNotification类包含什么?这是你自己的类还是 ABP 框架的代码?

我看到的第一个明显错误是这段代码:

UserNotification userNotifications = new UserNotification();
userNotifications.UserId = 10010;
//
userNotifications.Notification.TenantId = AbpSession.TenantId;
userNotifications.Notification.NotificationName = "test";

Notification属性似乎没有被初始化。我希望看到类似的东西:

UserNotification userNotification = new UserNotification
{
   UserId = 10010,
   Notification = new Notification 
   {
     TenantId = AbpSession.TenantId,
     NotificationName = "test"
   }
};
    

推荐阅读