Search code examples
.netmasstransitconsumermediator

MassTransit RespondAsync Cannot Return null Value


I am using Masstransit

The following code returns null and Context.RespondAsync Cannot return null

When City Not Found I Want Return Null And In Controller I Check if response is null then return Not Found

Controller :

 var request = _mediator.CreateRequestClient<TGetQuery>();

 GetCityQuery getQuery = _mapper.Map<GetCityQuery>(id);

 var result = await request.GetResponse<CityViewModel>(getQuery, cancellationToken);
 if (result.Message == null)
 {
      return NotFound();
 }
 return Ok(result.Message);

And Consumer :

public async Task Consume(ConsumeContext<GetCityQuery> context)
    {
        var cancellationToken = context.CancellationToken;
        var request = context.Message;
        var entity = await _cityRepository.TableNoTracking
            .ProjectTo<CityViewModel>(_mapper.ConfigurationProvider)
            .SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken);

        await context.RespondAsync(entity);
    }

So Masstransit Throw System.ArgumentNullException: Value cannot be null. (Parameter 'message') at MassTransit.Context.BaseConsumeContext.RespondAsync[T](T message)

Is there any way to overcome this problem?


Solution

  • You cannot use null as a message. If you want to use multiple response types for a request client, you can specify the types separately:

    var request = _mediator.CreateRequestClient<TGetQuery>();
    
     GetCityQuery getQuery = _mapper.Map<GetCityQuery>(id);
    
     var result = await request.GetResponse<CityViewModel, NotFound>(getQuery, cancellationToken);
     if (result.Is(out Response<CityViewModel> response)
     {
         return Ok(response.Message);
     }
    
    return NotFound();
    

    You'd need to define the message type:

    public class NotFound
    {
    }
    

    Then, in your consumer:

    public async Task Consume(ConsumeContext<GetCityQuery> context)
    {
         var request = context.Message;
         var entity = await _cityRepository.TableNoTracking
              .ProjectTo<CityViewModel>(_mapper.ConfigurationProvider)
              .SingleOrDefaultAsync(x => x.Id == request.Id, context.CancellationToken);
         if(entity == null)
              await context.RespondAsync(new NotFound());
         else
              await context.RespondAsync(entity);
    }