public IActionResult UpdateCustomer([ModelBinder(typeof(JsonModelBinder <CustomerDto>))] Delta <CustomerDto> customerDelta) { // Here we display the errors if the validation has failed at some point. if (!ModelState.IsValid) { return(Error()); } // Updateting the customer var currentCustomer = _customerApiService.GetCustomerEntityById(customerDelta.Dto.Id); if (currentCustomer == null) { return(Error(HttpStatusCode.NotFound, "customer", "not found")); } customerDelta.Merge(currentCustomer); if (customerDelta.Dto.RoleIds.Count > 0) { // Remove all roles while (currentCustomer.CustomerRoles.Count > 0) { currentCustomer.CustomerRoles.Remove(currentCustomer.CustomerRoles.First()); } AddValidRoles(customerDelta, currentCustomer); } if (customerDelta.Dto.Addresses.Count > 0) { var currentCustomerAddresses = currentCustomer.Addresses.ToDictionary(address => address.Id, address => address); foreach (var passedAddress in customerDelta.Dto.Addresses) { var addressEntity = passedAddress.ToEntity(); if (currentCustomerAddresses.ContainsKey(passedAddress.Id)) { _mappingHelper.Merge(passedAddress, currentCustomerAddresses[passedAddress.Id]); } else { currentCustomer.Addresses.Add(addressEntity); } } } CustomerService.UpdateCustomer(currentCustomer); InsertFirstAndLastNameGenericAttributes(customerDelta.Dto.FirstName, customerDelta.Dto.LastName, currentCustomer); if (!string.IsNullOrEmpty(customerDelta.Dto.LanguageId) && int.TryParse(customerDelta.Dto.LanguageId, out var languageId) && _languageService.GetLanguageById(languageId) != null) { _genericAttributeService.SaveAttribute(currentCustomer, NopCustomerDefaults.LanguageIdAttribute, languageId); } //password if (!string.IsNullOrWhiteSpace(customerDelta.Dto.Password)) { AddPassword(customerDelta.Dto.Password, currentCustomer); } // TODO: Localization // Preparing the result dto of the new customer // We do not prepare the shopping cart items because we have a separate endpoint for them. var updatedCustomer = currentCustomer.ToDto(); // This is needed because the entity framework won't populate the navigation properties automatically // and the country name will be left empty because the mapping depends on the navigation property // so we do it by hand here. PopulateAddressCountryNames(updatedCustomer); // Set the fist and last name separately because they are not part of the customer entity, but are saved in the generic attributes. var firstNameGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) .FirstOrDefault(x => x.Key == "FirstName"); if (firstNameGenericAttribute != null) { updatedCustomer.FirstName = firstNameGenericAttribute.Value; } var lastNameGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) .FirstOrDefault(x => x.Key == "LastName"); if (lastNameGenericAttribute != null) { updatedCustomer.LastName = lastNameGenericAttribute.Value; } var languageIdGenericAttribute = _genericAttributeService.GetAttributesForEntity(currentCustomer.Id, typeof(Customer).Name) .FirstOrDefault(x => x.Key == "LanguageId"); if (languageIdGenericAttribute != null) { updatedCustomer.LanguageId = languageIdGenericAttribute.Value; } //activity log CustomerActivityService.InsertActivity("UpdateCustomer", LocalizationService.GetResource("ActivityLog.UpdateCustomer"), currentCustomer); var customersRootObject = new CustomersRootObject(); customersRootObject.Customers.Add(updatedCustomer); var json = JsonFieldsSerializer.Serialize(customersRootObject, string.Empty); return(new RawJsonActionResult(json)); }