Inheritance: DotLiquid.Drop, ILoadSlice
        public static Customer AsWebModel(this Contact contact)
        {
            var customer = new Customer();

            int index = 1;
            foreach (var address in contact.Addresses)
            {
                var customerAddress = address.AsWebModel();
                customerAddress.Id = index.ToString();

                customer.Addresses.Add(customerAddress);
                index++;
            }

            if (!string.IsNullOrEmpty(contact.FullName))
            {
                var splittedName = contact.FullName.Split(' ');

                customer.FirstName = splittedName[0];
                customer.LastName = splittedName[1];
            }

            customer.DefaultAddress = customer.Addresses.FirstOrDefault();

            customer.AcceptsMarketing = true; // TODO
            customer.Email = contact.Emails.FirstOrDefault();
            customer.HasAccount = true; // TODO
            customer.Id = contact.Id;

            return customer;
        }
        public async Task UpdateCustomerAsync(Customer customer)
        {
            var contact = await this.GetContactAsync(customer.Email);

            contact.Addresses = new List<Address>();

            foreach (var customerAddress in customer.Addresses)
            {
                contact.Addresses.Add(customerAddress.AsServiceModel());
            }

            await this._customerClient.UpdateContactAsync(contact);
        }
        public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationFormModel formModel)
        {
            var form = GetForm(formModel.Id);

            if (form != null)
            {
                var formErrors = GetFormErrors(ModelState);

                if (formErrors == null)
                {
                    form.PostedSuccessfully = true;

                    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

                    if (loginInfo == null)
                    {
                        Context.ErrorMessage = "External login info was not found";

                        return View("error");
                    }

                    var user = new ApplicationUser { UserName = formModel.Email, Email = formModel.Email };
                    user.Logins = new List<UserLoginInfo>
                    {
                        new UserLoginInfo
                        {
                            LoginProvider = loginInfo.Login.LoginProvider,
                            ProviderKey = loginInfo.Login.ProviderKey
                        }
                    };

                    var result = await SecurityService.CreateUserAsync(user);

                    if (result.Succeeded)
                    {
                        form.PostedSuccessfully = true;

                        user = await SecurityService.GetUserByNameAsync(formModel.Email);

                        var customer = new Customer
                        {
                            Id = user.Id,
                            Email = formModel.Email
                        };

                        Context.Customer = await this.CustomerService.CreateCustomerAsync(customer);

                        var identity = SecurityService.CreateClaimsIdentity(user.UserName);
                        AuthenticationManager.SignIn(identity);

                        return RedirectToLocal(formModel.ReturnUrl);
                    }
                    else
                    {
                        form.Errors = new SubmitFormErrors("form", result.Errors.First());
                        form.PostedSuccessfully = false;

                        return View("external_login_confirmation");
                    }
                }
                else
                {
                    form.Errors = formErrors;
                    form.PostedSuccessfully = false;

                    return View("external_login_confirmation");
                }
            }

            Context.ErrorMessage = "Liquid error: Form context was not found.";

            return View("error");
        }
        public async Task<ActionResult> Register(RegisterFormModel formModel)
        {
            var dynamicProperties = await PopulateDynamicPropertiesAsync(formModel.Properties);
            ValidateDynamicProperties(dynamicProperties);

            var customer = new Customer
            {
                Email = formModel.Email,
                FirstName = formModel.FirstName,
                LastName = formModel.LastName,
                DynamicProperties = dynamicProperties
            };

            var form = Service.GetForm(SiteContext.Current, formModel.Id);

            if (form != null)
            {
                var formErrors = GetFormErrors(ModelState);

                if (formErrors == null)
                {
                    form.PostedSuccessfully = true;

                    var user = new ApplicationUser
                    {
                        Email = formModel.Email,
                        Password = formModel.Password,
                        UserName = formModel.Email
                    };

                    var result = await SecurityService.CreateUserAsync(user);

                    if (result.Succeeded)
                    {
                        user = await SecurityService.GetUserByNameAsync(user.UserName);

                        customer.Id = user.Id;

                        Context.Customer = await this.CustomerService.CreateCustomerAsync(customer);

                        await SecurityService.PasswordSingInAsync(formModel.Email, formModel.Password, false);

                        var identity = SecurityService.CreateClaimsIdentity(formModel.Email);
                        AuthenticationManager.SignIn(identity);

                        return RedirectToAction("Index", "Account");
                    }
                    else
                    {
                        form.Errors = new SubmitFormErrors("form", result.Errors.First());
                        form.PostedSuccessfully = false;
                    }
                }
                else
                {
                    form.Errors = formErrors;
                    form.PostedSuccessfully = false;
                }
            }
            else
            {
                return View("error");
            }

            Context.Customer = customer;

            return View("customers/register");
        }
        public async Task<Customer> CreateCustomerAsync(Customer customer)
        {
            Contact contact = null;

            if (string.IsNullOrEmpty(customer.FirstName) && string.IsNullOrEmpty(customer.LastName))
            {
                contact = new Contact { FullName = customer.Email };
            }
            else
            {
                contact = new Contact { FullName = string.Format("{0} {1}", customer.FirstName, customer.LastName) };
            }

            contact.Emails = new List<string> { customer.Email };

            if (customer.Addresses != null)
            {
                contact.Addresses = new List<Address>();

                foreach (var address in customer.Addresses)
                {
                    contact.Addresses.Add(address.AsServiceModel());
                }
            }

            contact.Id = customer.Id;
            contact.DynamicProperties = customer.DynamicProperties.Select(p => p.ToServiceModel()).ToArray();
            contact = await this._customerClient.CreateContactAsync(contact);

            return contact.AsWebModel();
        }