You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用IRequestClient从状态机获取结果时MassTransit报错排查

问题排查:通过API+MediatR获取状态机结果时超时并返回404

问题场景

尝试通过API结合MediatR模式获取状态机存储在数据库中的结果,但调用后出现超时异常,最终返回404错误。

代码示例

namespace Play.Trading.Purchases.GetPurchase
{
    public record GetPurchaseStateCommand(Guid CorrelationId) : ICommand<GetPurchaseStateResult>;

    public record GetPurchaseStateResult(PurchaseDto PurchaseDto);

    public class GetPurchaseStateHandler(IRequestClient<GetPurchaseState>) : ICommandHandler<GetPurchaseStateCommand, GetPurchaseStateResult>
    {
        public async Task<GetPurchaseStateResult> Handle(GetPurchaseStateCommand command, CancellationToken cancellationToken)
        {
            var response = await purchaseClient.GetResponse<PurchaseState>(new GetPurchaseStateRequest(command.CorrelationId), cancellationToken);

            if (response.Message.CorrelationId != command.CorrelationId) 
                throw new NotFoundException($"No data with {command.CorrelationId} was fpund");

            return new GetPurchaseStateResult(new PurchaseDto(response.Message.UserId,
                response.Message.ItemId, response.Message.PurchaseTotal, response.Message.Quantity,
                response.Message.CurrentState, response.Message.ErrorMessage, response.Message.Received, response.Message.LastUpdated));
        }
    }
}

错误日志

System.InvalidOperationException: ExceptionHandlerOptions配置的异常处理程序返回了404状态响应。由于这通常是ExceptionHandlingPath配置错误导致的,因此抛出包含原始异常的InvalidOperationException。如果预期异常处理程序返回404状态响应,请将AllowStatusCode404Response设置为true。
 ---&gt; MassTransit.RequestException: 处理GetPurchaseState请求时发生异常
 ---&gt; System.ArgumentException: 消息类型没有可用的无参构造函数(参数'TMessage')
   在 MassTransit.Initializers.MessageFactoryCache`1.Cached.CreateMessageFactory()
   在 System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   在 System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   在 System.Lazy`1.CreateValue()
   在 MassTransit.Initializers.MessageFactoryCache`1.get_Factory()
   在 MassTransit.Initializers.Factories.MessageInitializerBuilder`2.Build()
   在 MassTransit.Initializers.Factories.MessageInitializerFactory`2.CreateMessageInitializer()
   在 MassTransit.Initializers.MessageInitializerCache`1.CreateMessageInitializer(Type inputType)
   在 MassTransit.Initializers.MessageInitializerCache`1.&lt;&gt;c__DisplayClass2_0.&lt;MassTransit.Initializers.IMessageInitializerCache&lt;TMessage&gt;.GetInitializer&gt;b__0()
   在 System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   在 System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   在 System.Lazy`1.CreateValue()
   在 MassTransit.Initializers.MessageInitializerCache`1.MassTransit.Initializers.IMessageInitializerCache&lt;TMessage&gt;.GetInitializer(Type inputType)
   在 MassTransit.Initializers.MessageInitializerCache`1.GetInitializer(Type inputType)
   在 MassTransit.Clients.PublishRequestSendEndpoint`1.Send(Guid requestId, Object values, IPipe`1 pipe, CancellationToken cancellationToken)
   在 MassTransit.Clients.RequestClient`1.&lt;&gt;c__DisplayClass9_0`1.&lt;&lt;GetResponse&gt;g__Request|0&gt;d.MoveNext()
--- 之前位置的堆栈跟踪结束 ---
   在 MassTransit.Clients.ClientRequestHandle`1.SendRequest()
   --- 内部异常堆栈跟踪结束 ---
   在 MassTransit.Clients.ClientRequestHandle`1.SendRequest()
   在 MassTransit.Clients.ResponseHandlerConnectHandle`1.GetTask()
   在 MassTransit.Clients.RequestClient`1.GetResponseInternal[T](SendRequestCallback request, CancellationToken cancellationToken, RequestTimeout timeout, RequestPipeConfiguratorCallback`1 callback)
   在 Play.Trading.Purchases.GetPurchase.GetPurchaseStateHandler.Handle(GetPurchaseStateCommand command, CancellationToken cancellationToken) 位置 C:\Users\USER\source\repos\EshopMicroservices\src\Play.Catalog\Play.Trading\Purchases\GetPurchase\GetPurchaseStateHandler.cs:行号 17
   在 buildingBlock.Behaviours.LoggingBehaviour`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken) 位置 C:\Users\USER\source\repos\EshopMicroservices\src\buildingBlock\buildingBlock\Behaviours\LoggingBehaviour.cs:行号 22
   在 buildingBlock.Behaviours.ValidationBehaviour`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken) 位置 C:\Users\USER\source\repos\EshopMicroservices\src\buildingBlock\buildingBlock\Behaviours\ValidationBehaviour.cs:行号 20
   在 Play.Trading.Purchases.GetPurchase.GetPurchaseStateEndPoint.GetPurchaseStatus(GetPurchaseStateRequest request, ISender sender) 位置 C:\Users\USER\source\repos\EshopMicroservices\src\Play.Catalog\Play.Trading\Purchases\GetPurchase\GetPurchaseStateEndPoint.cs:行号 28
   在 Microsoft.AspNetCore.Http.RequestDelegateFactory.ExecuteTaskResult[T](Task`1 task, HttpContext httpContext)
   在 Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   在 Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   在 Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.&lt;Invoke&gt;g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
   --- 内部异常堆栈跟踪结束 ---
   在 Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
   在 Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.&lt;Invoke&gt;g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
   在 Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

问题根源与解决步骤

核心问题

最内层的ArgumentException是触发所有连锁错误的根源:MassTransit无法初始化消息类型,因为对应的消息类(GetPurchaseStateRequest或PurchaseState)没有无参构造函数。外层的超时、404及InvalidOperationException都是这个异常引发的后续问题。

解决步骤

  1. 为消息类添加无参构造函数

    • 如果是class类型:添加public无参构造,同时保留带参数的构造逻辑
      public class GetPurchaseStateRequest
      {
          public Guid CorrelationId { get; set; }
          // 无参构造
          public GetPurchaseStateRequest() {}
          // 带参构造
          public GetPurchaseStateRequest(Guid correlationId)
          {
              CorrelationId = correlationId;
          }
      }
      
    • 如果是record类型:可以通过重载构造函数实现
      public record GetPurchaseStateRequest(Guid CorrelationId)
      {
          // 无参构造,默认值可按需调整
          public GetPurchaseStateRequest() : this(Guid.Empty) {}
      }
      

    同理检查PurchaseState类,确保它也符合要求。

  2. 修正代码拼写错误
    将throw new NotFoundException($"No data with {command.CorrelationId} was fpund");中的fpund改为found。

  3. 调整异常中间件配置(可选)
    如果确实需要在异常场景返回404,在Program.cs/Startup.cs中修改ExceptionHandler配置:

    app.UseExceptionHandler(options =>
    {
        options.AllowStatusCode404Response = true;
        // 其他自定义异常处理逻辑
    });
    

内容的提问来源于stack exchange,提问作者Vondella21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 10:15:54