无法从 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 既发布事件(在任何传入消息处理程序之外,例如来自操作方法)又订阅事件。发布活动有效。我使用旧版本的Program
和Startup
进行集成,使用GenericHost
和IMessageSession
成功注入到构造函数中。
但是,当激活注释掉的代码让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 功能