无法从 ASP.NET Core 6.0 API NServiceBus 端点订阅事件

Posted

技术标签:

【中文标题】无法从 ASP.NET Core 6.0 API NServiceBus 端点订阅事件【英文标题】:Cannot subscribe to events from an ASP.NET Core 6.0 API NServiceBus endpoint 【发布时间】:2022-01-22 22:06:06 【问题描述】:

我想让我的 API 既发布事件(在任何传入消息处理程序之外,例如来自操作方法)又订阅事件。发布活动有效。我使用旧版本的ProgramStartup 进行集成,使用GenericHostIMessageSession 成功注入到构造函数中。

但是,当激活注释掉的代码让API订阅和处理事件时,在初始化主机和运行应用程序时突然抛出了注入IMessageSession的异常。

TestController.cs

namespace TestContext

    [Route("api/[controller]")]
    [ApiController]
    public class TestController : ControllerBase/*, IHandleMessages<ReceivedEvent>*/
    
        private IMessageSession _session;

        public TestController(IMessageSession session)
        
            _session = session;
        
        /*
        [NonAction]
        public Task Handle(ReceivedEvent message, IMessageHandlerContext context)
        
            throw new NotImplementedException();
        */

        [HttpPost]
        public async Task<ActionResult> Test()
        
            await _session.Publish(new PublishedEvent());
            return Ok();
        
    

Program.cs

public class Program

    public static void Main(string[] args)
    
        CreateHostBuilder(args).Build().Run();
    
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseNServiceBus(context =>
            
                var endpointConfiguration = new EndpointConfiguration("Test");
                var transport = endpointConfiguration.UseTransport<LearningTransport>();
                
                return endpointConfiguration;
            )
            .ConfigureWebHostDefaults(webBuilder =>
            
                webBuilder.UseStartup<Startup>();
            );

例外

为什么会抛出异常以及如何让 API 订阅和处理事件?

编辑

从单独的服务类处理事件时,不会抛出异常。

public class HandlerService : IHandleMessages<ReceivedEvent>

    public Task Handle(ReceivedEvent message, IMessageHandlerContext context)
    
        Console.WriteLine(message);
        return Task.CompletedTask;
    

【问题讨论】:

【参考方案1】:

这里的异常信息其实还不错。大多数 NServiceBus 异常消息都是。

不应从容器解析接口 IMessageSession 或 IEndpointInstance 以启用从 saga 或消息处理程序中发送或发布消息。而是使用 TestController.Handle 方法上的 context 参数来发送或发布消息。

首先,不要在控制器中混合处理程序。它需要是一个单独的类。

然后,不要注入 IMessageSession。该接口明确用于控制器操作等您没有现有的“正在处理消息”并且您想要发送消息的事情。

相反,如果您想在处理程序中发送或发布,请使用上下文:

不要这样做

public class MyHandler : IHandleMessages<ReceivedEvent>

    private IMessageSession session;

    public MyHandler(IMessageSession session)
    
        // Won't work! Don't inject IMessageSession!
        this.session = session;
    

    public async Task Handle(ReceivedEvent message, IMessageHandlerContext context)
    
        // NOPE!
        session
    

改为这样做

public class MyHandler : IHandleMessages<ReceivedEvent>

    public async Task Handle(ReceivedEvent message, IMessageHandlerContext context)
    
        context.Send(new CommandToSend());
        context.Publish(new EventToPublish());
    

【讨论】:

是的,将处理程序与控制器分离是可行的!您能否详细介绍一下 - 为什么处理程序不能是控制器方法?是否与此处提到的单独 DI 实例有关:docs.particular.net/nservicebus/hosting/… 我会转过头来问你为什么想要一个与控制器混合的处理程序?控制器是由 ASP.NET 实例化的用于服务 Web 请求的类。 NServiceBus 处理程序是由 NServiceBus 实例化的用于处理消息的类。为什么要混合它们?另外,en.wikipedia.org/wiki/Single-responsibility_principle 我正在创建一个简单的演示并将其放在那里,没有其他原因。我实际上并不想让我的控制器和事件处理程序混合在一起,因为它们的用途截然不同,但现在我知道它无法做到,我想知道为什么。

以上是关于无法从 ASP.NET Core 6.0 API NServiceBus 端点订阅事件的主要内容,如果未能解决你的问题,请参考以下文章

从 ASP.NET MVC 项目调用 .NET CORE 5 Web API 微服务时无法检索 BadRequest 错误

ASP.NET Core 2.1 MVC - 无法设置从 Web api 响应接收到的 cookie

无法在 ASP.Net Core Web api 中启用 CORS

基于ASP.NET Core 6.0的整洁架构,asp.net core 6.0 功能

ASP.NET 6.0 Core 迁移 ASP.NET Core 7.0

在 ASP.NET Core 6.0 中使用 Serilog