asp.net-corerabbitmqmasstransitcarter

Why MassTransit throws an error when I use IRequestClient to get result from state machine


I try to get state machine result through API using MediatR pattern but I get a timeout exception and finally 404 - I wonder what I was doing wrong here.

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));
        }
    }
}

I was expecting to get results as per data that saved in database but I get the following errors after I consume my API:

System.InvalidOperationException: The exception handler configured on ExceptionHandlerOptions produced a 404 status response. This InvalidOperationException containing the original exception was thrown since this is often due to a misconfigured ExceptionHandlingPath. If the exception handler is expected to return 404 status responses then set AllowStatusCode404Response to true.
 ---> MassTransit.RequestException: An exception occurred while processing the GetPurchaseState request
 ---> System.ArgumentException: No default constructor available for message type (Parameter 'TMessage')
   at MassTransit.Initializers.MessageFactoryCache`1.Cached.CreateMessageFactory()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at MassTransit.Initializers.MessageFactoryCache`1.get_Factory()
   at MassTransit.Initializers.Factories.MessageInitializerBuilder`2.Build()
   at MassTransit.Initializers.Factories.MessageInitializerFactory`2.CreateMessageInitializer()
   at MassTransit.Initializers.MessageInitializerCache`1.CreateMessageInitializer(Type inputType)
   at MassTransit.Initializers.MessageInitializerCache`1.<>c__DisplayClass2_0.<MassTransit.Initializers.IMessageInitializerCache<TMessage>.GetInitializer>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at MassTransit.Initializers.MessageInitializerCache`1.MassTransit.Initializers.IMessageInitializerCache<TMessage>.GetInitializer(Type inputType)
   at MassTransit.Initializers.MessageInitializerCache`1.GetInitializer(Type inputType)
   at MassTransit.Clients.PublishRequestSendEndpoint`1.Send(Guid requestId, Object values, IPipe`1 pipe, CancellationToken cancellationToken)
   at MassTransit.Clients.RequestClient`1.<>c__DisplayClass9_0`1.<<GetResponse>g__Request|0>d.MoveNext()
--- End of stack trace from previous location ---
   at MassTransit.Clients.ClientRequestHandle`1.SendRequest()
   --- End of inner exception stack trace ---
   at MassTransit.Clients.ClientRequestHandle`1.SendRequest()
   at MassTransit.Clients.ResponseHandlerConnectHandle`1.GetTask()
   at MassTransit.Clients.RequestClient`1.GetResponseInternal[T](SendRequestCallback request, CancellationToken cancellationToken, RequestTimeout timeout, RequestPipeConfiguratorCallback`1 callback)
   at Play.Trading.Purchases.GetPurchase.GetPurchaseStateHandler.Handle(GetPurchaseStateCommand command, CancellationToken cancellationToken) in C:\Users\USER\source\repos\EshopMicroservices\src\Play.Catalog\Play.Trading\Purchases\GetPurchase\GetPurchaseStateHandler.cs:line 17
   at buildingBlock.Behaviours.LoggingBehaviour`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken) in C:\Users\USER\source\repos\EshopMicroservices\src\buildingBlock\buildingBlock\Behaviours\LoggingBehaviour.cs:line 22
   at buildingBlock.Behaviours.ValidationBehaviour`2.Handle(TRequest request, RequestHandlerDelegate`1 next, CancellationToken cancellationToken) in C:\Users\USER\source\repos\EshopMicroservices\src\buildingBlock\buildingBlock\Behaviours\ValidationBehaviour.cs:line 20
   at Play.Trading.Purchases.GetPurchase.GetPurchaseStateEndPoint.GetPurchaseStatus(GetPurchaseStateRequest request, ISender sender) in C:\Users\USER\source\repos\EshopMicroservices\src\Play.Catalog\Play.Trading\Purchases\GetPurchase\GetPurchaseStateEndPoint.cs:line 28
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.ExecuteTaskResult[T](Task`1 task, HttpContext httpContext)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.HandleException(HttpContext context, ExceptionDispatchInfo edi)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

Solution

  • No default constructor available for message type, should be your first clue.

    Your request client type doesn't match what you're passing to GetResponse, so it's using a message initializer. Likely also related.