skip to Main Content

I am using AutoMapper and this is my code to update the details of an existing customer but when I update one field the rest of the fields get nulled.

public async Task<ResponseModel> Update(CustomerDTO customer, int id)
{
        ResponseModel responseModel = new ResponseModel();

        try
        {
            Customer? existingCustomer = await _dbContext.FindAsync<Customer>(id);

            if (existingCustomer == null)
            {
                return new ResponseModel()
                {
                    IsSuccess = false,
                    Message = $"Customer doesn't exist!"
                };
            }

            _mapper.Map(customer, existingCustomer);

            if (await _dbContext.SaveChangesAsync() > 0)
            {
                responseModel.Message = "Customer Updated Successfully";
                responseModel.IsSuccess = true;
            }
        }
        catch (Exception ex)
        {
            responseModel.IsSuccess = false;
            responseModel.Message = $"Error:{ex.Message}";
        }

        return responseModel;
}

Here’s the mapper profile:

using AutoMapper;
using static MGApi.Services.CustomerService;

namespace MGApi.Models
{
    public class CustomerProfile : Profile
    {
        public CustomerProfile()
        {
            CreateMap<CustomerDTO, Customer>();
        }
    }
}

I tried adding using ForAllOtherMembers but it is deprecated. I’m not sure how to solve this.

Here is the Customer Model:

using System.ComponentModel.DataAnnotations;

namespace MGApi.Models
{
    public class Customer
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(50)]
        [RegularExpression(@"^d{10}$", ErrorMessage = "Invalid phone number")]

        public string? PhoneNumber { get; set; }

        [Required]
        [StringLength(50)]
        public string? Name { get; set; }

        [StringLength(100)]
        [EmailAddress]
        public string? Email { get; set; }

        [StringLength(10)]
        public string? Gender { get; set; }

        [DataType(DataType.Date)]
        public DateTime DateOfBirth { get; set; }
        public ICollection<CustomerData>? CustomerData { get; set; }

    }
}

Now below we have the CustomerData Model which has a foreign key based on the primary key of the Customer Model:

using System.ComponentModel.DataAnnotations;

namespace MGApi.Models
{
    public class CustomerData
    {
        [Key]
        public int Id { get; set; }
        public int CustomerId { get; set; }

        public double Sugar { get; set; }

        public double BP { get; set; }

        public double Height { get; set; }

        public double Weight { get; set; }

        public DateTime Timestamp { get; set; } = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("India Standard Time"));

        public Customer? Customer { get; set; }
    }
}

2

Answers


  1. So most of the data on your Customer is nullable, you haven’t added CustomerDTO but I can assume that names of properties are same as in Customer. You are only passing one value in body of your request lets say

    {
       "Name": John
    }
    

    So CustomerDTO that is created from it will look something like that:

    {
        PhoneNumber = null,
        Name = "John",
        Email = null,
        Gender = null,
        DateOfBirth = new DateTime(), // not nullable so assigns default value 01/01/0001 00:00:00,
        CustomerData = null
    }
    

    After mapping that you perform values will be same and will be saved to the database like that as well. This is how update request works in general. You’re taking old object, change one(or more) value and pass new object with changed value(s).

    If you want to change one value like you do right now you should look into:
    https://learn.microsoft.com/en-us/aspnet/core/web-api/jsonpatch?view=aspnetcore-7.0

    In my opinion implementing JsonPatch is not worth the time unless you need to ensure that changes made by two users won’t be overwriten. In other cases simple update is enough and you should just change how you consumer your API – pass all the needed data.

    Login or Signup to reply.
  2. I think it is because of your nullable fields in Customer and CustomerDtoand bunch of fields of CustomerDto instance are null.
    I have two solutions for your problem:
    First, use JsonPatch for partial updating.

    Second, prevent mapping null values from source to destination by changing you mapping profile as follows:

    CreateMap<CustomerDTO, Customer>().ForAllMembers(options => options.Condition((src, dest, srcMember) => srcMember != null)); 
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search