Search code examples
asp.net-mvcasp.net-corecqrsmediatr

.Net problem with posting Command. Values showing as null


I am having the following issue when trying to make a post request to my orders controller. I am informed that certain fields are required, even though I have filled them in. Can anyone correct me on where I am going wrong here?

Here is my controller method:

 public class OrdersController : ApiControllerBase
{
    [HttpGet]
    public async Task<ActionResult<OrdersViewModel>> GetOrderAsync()
    {
        return await Mediator.Send(new GetOrdersQuery());
    }

    
    [HttpPost]
    [Produces("application/json")]
    public async Task<ActionResult<bool>> Create(CreateOrderCommand command)
    {
        return  await Mediator.Send(command);
    }
}

Here is the CreateOrderCommand and its Handler:

 [DataContract]
public class CreateOrderCommand : IRequest<bool>
{
    [DataMember]
    public string UserId { get; private set; }
    [DataMember]
    public string UserName { get; private set; }
    [DataMember]
    public string Street { get; private set; }
    [DataMember]
    public string City { get; private set; }
    [DataMember]
    public string Country { get; private set; }
    [DataMember]
    public string PostCode { get; private set; }
    [DataMember]
    public string CardNumber { get; private set; }
    [DataMember]
    public string CardHolderName { get; private set; }
    [DataMember]
    public DateTime ExpiryDate { get; private set; }
    [DataMember]
    public string CardSecurityNumber { get; private set; }
    [DataMember]
    public CardTypeEnum CardType { get; private set; }
    [DataMember]
    private readonly List<OrderItemDTO> _orderItems;
    [DataMember]
    public IEnumerable<OrderItemDTO> OrderItems => _orderItems;

    public CreateOrderCommand()
    {
        _orderItems = new List<OrderItemDTO>();
    }

    public CreateOrderCommand(List<OrderItemDTO> orderItems, string userId, string userName, string city, string street, string country, string postcode, 
        string cardNumber, string cardHolderName, DateTime expiryDate, string cardSecurityNumber, CardTypeEnum cardType) : this()
    {
        _orderItems = orderItems;
        UserId = userId;
        UserName = userName;
        City = city;
        Street = street;
        Country = country;
        PostCode = postcode;
        CardNumber = cardNumber;
        CardHolderName = cardHolderName;
        ExpiryDate = expiryDate;
        CardSecurityNumber = cardSecurityNumber;
        CardType = cardType;
    }
}
public record OrderItemDTO
{
    public decimal BookPrice { get; init; }
    public string BookTitle { get; init; }
    public int Quantity { get; init; }
    public int BookCatalogueId { get; init; }
    public string BookImageUrl { get; init; }
}
public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, bool>
{
    private readonly IOrderRepository _orderRepository;
    private readonly ILogger<CreateOrderCommandHandler> _logger;
    public CreateOrderCommandHandler(IOrderRepository orderRepository, ILogger<CreateOrderCommandHandler> logger)
    {
        _orderRepository = orderRepository;
        _logger = logger;   
    }

    public async Task<bool> Handle(CreateOrderCommand command, CancellationToken cancellationToken)
    {
        var deliveryAddress = new DeliveryAddress(command.Street, command.City, command.Country, command.PostCode);
        var userId = (!string.IsNullOrEmpty(command.UserId)) ? command.UserId : "1";
        var userName = (!string.IsNullOrEmpty(command.UserName)) ? command.UserName : "Christopher";
        var order = new Order(userId, userName, deliveryAddress, command.CardType, command.CardNumber, command.CardSecurityNumber, command.CardHolderName, command.ExpiryDate);
        if (order == null)
            throw new NotFoundException();

        foreach (var item in command.OrderItems)
        {
            order.AddOrderItem(item.BookCatalogueId, item.BookTitle, item.BookPrice, item.BookImageUrl, item.Quantity);
        }
        _logger.LogInformation("----- Creating Order - Order: {@Order}", order);

         _orderRepository.Add(order);

        return await _orderRepository.UnitOfWork
       .SaveEntitiesAsync(cancellationToken);
    }
}

}

Here is how I have registered my services:

 public static IServiceCollection AddApplicationServices(this IServiceCollection services)
    {
        services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
        services.AddMediatR(Assembly.GetExecutingAssembly());
      
        return services;
    }

Here is my problem when I try to post a request to my controller:

enter image description here


Solution

  • If you use the private setter, you cannot get the value. Change your model like below:

    [DataContract]
    public class CreateOrderCommand : IRequest<bool>
    {
        [DataMember]
        public string UserId { get;  set; }       //remove all the private accessor...
        [DataMember]
        public string UserName { get;  set; }
        [DataMember]
        public string Street { get;  set; }
        [DataMember]
        public string City { get;  set; }
        [DataMember]
        public string Country { get;  set; }
        [DataMember]
        public string PostCode { get;  set; }
        [DataMember]
        public string CardNumber { get;  set; }
        [DataMember]
        public string CardHolderName { get;  set; }
        [DataMember]
        public DateTime ExpiryDate { get;  set; }
        [DataMember]
        public string CardSecurityNumber { get;  set; }
        [DataMember]
        public CardTypeEnum CardType { get; set; }
        [DataMember]
        private List<OrderItemDTO> _orderItems;   //remove readonly
        [DataMember]
        public List<OrderItemDTO> OrderItems      //change here..
        {
            get { return _orderItems; }
            set { _orderItems = value; }
        }
    
        public CreateOrderCommand()
        {
            _orderItems = new List<OrderItemDTO>();
        }
    
        public CreateOrderCommand(List<OrderItemDTO> orderItems, string userId, string userName, string city, string street, string country, string postcode,
            string cardNumber, string cardHolderName, DateTime expiryDate, string cardSecurityNumber,CardTypeEnum cardType) : this()
        {
            _orderItems = orderItems;
            UserId = userId;
            UserName = userName;
            City = city;
            Street = street;
            Country = country;
            PostCode = postcode;
            CardNumber = cardNumber;
            CardHolderName = cardHolderName;
            ExpiryDate = expiryDate;
            CardSecurityNumber = cardSecurityNumber;
            CardType = cardType;
        }
    }