【问题标题】:Cannot subscribe to events from an ASP.NET Core 6.0 API NServiceBus endpoint无法从 ASP.NET Core 6.0 API NServiceBus 端点订阅事件
【发布时间】: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;
    }
}

【问题讨论】:

    标签: asp.net-core-webapi nservicebus .net-6.0


    【解决方案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
    • 我正在创建一个简单的演示并将其放在那里,没有其他原因。我实际上并不想让我的控制器和事件处理程序混合在一起,因为它们的用途截然不同,但现在我知道它无法做到,我想知道为什么。
    猜你喜欢
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多