public async Task <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 = await _customerApiService.GetCustomerEntityByIdAsync(customerDelta.Dto.Id); if (currentCustomer == null) { return(Error(HttpStatusCode.NotFound, "customer", "not found")); } customerDelta.Merge(currentCustomer); if (customerDelta.Dto.RoleIds.Count > 0) { await AddValidRolesAsync(customerDelta, currentCustomer); } if (customerDelta.Dto.Addresses.Count > 0) { var currentCustomerAddresses = (await CustomerService.GetAddressesByCustomerIdAsync(currentCustomer.Id)).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 { await CustomerService.InsertCustomerAddressAsync(currentCustomer, addressEntity); } } } await CustomerService.UpdateCustomerAsync(currentCustomer); await InsertFirstAndLastNameGenericAttributesAsync(customerDelta.Dto.FirstName, customerDelta.Dto.LastName, currentCustomer); if (!string.IsNullOrEmpty(customerDelta.Dto.LanguageId) && int.TryParse(customerDelta.Dto.LanguageId, out var languageId) && await _languageService.GetLanguageByIdAsync(languageId) != null) { await _genericAttributeService.SaveAttributeAsync(currentCustomer, NopCustomerDefaults.LanguageIdAttribute, languageId); } //password if (!string.IsNullOrWhiteSpace(customerDelta.Dto.Password)) { await AddPasswordAsync(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. await PopulateAddressCountryNamesAsync(updatedCustomer); var attributes = await _genericAttributeService.GetAttributesForEntityAsync(currentCustomer.Id, typeof(Customer).Name); // 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 = attributes.FirstOrDefault(x => x.Key == "FirstName"); if (firstNameGenericAttribute != null) { updatedCustomer.FirstName = firstNameGenericAttribute.Value; } var lastNameGenericAttribute = attributes.FirstOrDefault(x => x.Key == "LastName"); if (lastNameGenericAttribute != null) { updatedCustomer.LastName = lastNameGenericAttribute.Value; } var languageIdGenericAttribute = attributes.FirstOrDefault(x => x.Key == "LanguageId"); if (languageIdGenericAttribute != null) { updatedCustomer.LanguageId = languageIdGenericAttribute.Value; } //activity log await CustomerActivityService.InsertActivityAsync("UpdateCustomer", await LocalizationService.GetResourceAsync("ActivityLog.UpdateCustomer"), currentCustomer); var customersRootObject = new CustomersRootObject(); customersRootObject.Customers.Add(updatedCustomer); var json = JsonFieldsSerializer.Serialize(customersRootObject, string.Empty); return(new RawJsonActionResult(json)); }