Auto-filling addresses of existing customers
The approach described on this page extends the customer details step from the second part of the Implementing a checkout process series, and therefore assumes your checkout process is implemented in a similar fashion.
Also note that to implement this feature, you need to have user registration enabled on your site. Learn more in Enabling user registration.
Auto-fill is an option found in web browsers and online applications that allows users to easily input commonly-entered information into a web form.
You might wish to provide a similar functionality on your site to simplify the checkout process for your repeat customers. With some modifications, the method described on this page can be used to auto-fill any form in your live site application.
Implementing auto-fill functionality for existing addresses
To implement auto-filling of existing addresses for registered customers:
Open the controller class facilitating your checkout process in Visual Studio.
This example uses the ShoppingService class initialized in the controller’s constructor. Learn more about IShoppingService and its default implementation, the ShoppingService, in Integrating the shopping cart.
To the DeliveryDetails action, add logic that loads addresses for existing customers.
/// <summary> /// Displays the customer details checkout process step with an address selector for known customers. /// </summary> public ActionResult DeliveryDetailsAddressSelector() { // Gets the current user's shopping cart ShoppingCartInfo cart = shoppingService.GetCurrentShoppingCart(); // If the shopping cart is empty, redirects to the shopping cart view if (cart.IsEmpty) { return RedirectToAction("ShoppingCart"); } // Gets all countries for the country selector SelectList countries = new SelectList(countryInfo.Get(), "CountryID", "CountryDisplayName"); // Gets the current customer CustomerInfo customer = shoppingService.GetCurrentCustomer(); // Gets all customer billing addresses for the address selector IEnumerable<AddressInfo> customerAddresses = Enumerable.Empty<AddressInfo>(); if (customer != null) { customerAddresses = addressInfo.GetByCustomer(customer.CustomerID).ToList(); } // Prepares address selector options SelectList addresses = new SelectList(customerAddresses, "AddressID", "AddressName"); // Gets all enabled shipping options for the shipping option selector SelectList shippingOptions = new SelectList(shippingOption.GetBySite(SiteContext.CurrentSiteID, true).ToList(), "ShippingOptionID", "ShippingOptionDisplayName"); // Loads the customer details DeliveryDetailsViewModel model = new DeliveryDetailsViewModel { Customer = new CustomerViewModel(shoppingService.GetCurrentCustomer()), BillingAddress = new BillingAddressViewModel(shoppingService.GetBillingAddress(), countries, addresses), ShippingOption = new ShippingOptionViewModel(shippingOption.Get(shoppingService.GetShippingOption()), shippingOptions) }; // Displays the customer details step return View(model); }
Add a new POST method to the controller. This method is called from the JavaScript file added in the next step. It retrieves an AddressInfo object based on the provided AddressID and serializes its select properties, allowing the JavaScript fuction to auto-fill the address form fields.
/// <summary> /// Loads information of an address specified by its ID. /// </summary> /// <param name="addressID">ID of the address.</param> /// <returns>Serialized information of the loaded address.</returns> [HttpPost] public JsonResult CustomerAddress(int addressID) { // Gets the address with its ID AddressInfo address = addressInfo.Get(addressID); // Checks whether the address was retrieved if (address == null) { return null; } // Creates a response with all address information var responseModel = new { Line1 = address.AddressLine1, Line2 = address.AddressLine2, City = address.AddressCity, PostalCode = address.AddressZip, CountryID = address.AddressCountryID, StateID = address.AddressStateID, PersonalName = address.AddressPersonalName }; // Returns serialized information of the address return Json(responseModel); }
Add a JavaScript file that loads the selected AddressInfo object based on the AddressID provided from the address selector, and auto-fills the address form fields.
(function () { 'use strict'; // Fills address form fields with the selected address whenever // an address is selected from the address selector drop-down element $('.js-address-selector-div').change(function () { var $selectorDiv = $(this), $addressDiv = $selectorDiv.parent(), $selector = $selectorDiv.find('.js-address-selector'), url = $selectorDiv.data('statelistaction'), postData = { addressId: $selector.val() }; // If the new address option is selected, clears all address form fields if (!postData.addressId) { eraseFields($addressDiv); return; } // Sends a POST request to the 'CustomerAddress' endpoint of the 'CheckoutController' $.post(url, postData, function (data) { fillFields($addressDiv, data); }); }); function fillFields($addressDiv, data) { fillBasicFields($addressDiv, data); fillCountryStateFields($addressDiv, data); } // Fills the 'Address line 1' and '2', 'City', and 'Postal code' // address form fields from the selected address function fillBasicFields($addressDiv, data) { var basicFields = $addressDiv.data('fields'), addressType = $addressDiv.data('addresstype'); $.each(basicFields, function (i, val) { var fieldId = '#' + addressType + '_' + val, fieldVal = data[val]; $(fieldId).val(fieldVal); }); } // Fills the Country and State drop-down selectors from selected address data function fillCountryStateFields($addressDiv, data) { var $countryStateSelector = $addressDiv.find('.js-country-state-selector'), countryField = $countryStateSelector.data('countryfield'), stateField = $countryStateSelector.data('statefield'), $countrySelector = $countryStateSelector.find('.js-country-selector'); // Sets id of the country's state for the 'countryStateSelector' script $countryStateSelector.data('stateselectedid', data[stateField]); // Raises the change event on the country selector drop-down element, // This invokes the 'coutryStateSelector' script that shows the // states drop-down selector with the selected state $countrySelector.val(data[countryField]).change(); } // Clears all address form fields function eraseFields($addressDiv) { var data = {}; fillFields($addressDiv, data); } }());
Add the JavaScript file to the view rendering the customer details form.
Adding the JavaScript file@Scripts.Render("~/Scripts/addressSelector.js")
Modify the customer details view to display the loaded addresses in a selector. For example:
Adding the address selector<div class="js-address-selector-div" data-statelistaction='@Url.Action("CustomerAddress", "Checkout")'> @Html.LabelFor(m => m.BillingAddress.AddressID) @Html.DropDownListFor(m => m.BillingAddress.AddressID, Model.BillingAddress.Addresses, "(new)", new { @class = "js-address-selector" }) <div class="message message-error"> @Html.ValidationMessageFor(m => m.BillingAddress.AddressID) </div> </div>
Customers signed in on your website are now able to select from previously used addresses when entering billing or shipping data during checkout.