/// <summary>
        /// Updates the portal branding.
        /// </summary>
        /// <param name="updatedBrandingConfiguration">The new portal branding.</param>
        /// <returns>The updated portal branding.</returns>
        public async Task <BrandingConfiguration> UpdateAsync(BrandingConfiguration updatedBrandingConfiguration)
        {
            updatedBrandingConfiguration.AssertNotNull(nameof(updatedBrandingConfiguration));

            await this.NormalizeAsync(updatedBrandingConfiguration);

            var portalBrandingBlob = await this.GetPortalBrandingBlobAsync();

            await portalBrandingBlob.UploadTextAsync(JsonConvert.SerializeObject(updatedBrandingConfiguration));

            // invalidate the cache, we do not update it to avoid race condition between web instances
            await this.ApplicationDomain.CachingService.ClearAsync(PortalBranding.PortalBrandingCacheKey);

            return(updatedBrandingConfiguration);
        }
        /// <summary>
        /// Updates the portal branding.
        /// </summary>
        /// <param name="updatedBrandingConfiguration">The new portal branding.</param>
        /// <returns>The updated portal branding.</returns>
        public async Task <BrandingConfiguration> UpdateAsync(BrandingConfiguration updatedBrandingConfiguration)
        {
            updatedBrandingConfiguration.AssertNotNull(nameof(updatedBrandingConfiguration));

            await NormalizeAsync(updatedBrandingConfiguration).ConfigureAwait(false);

            CloudBlockBlob portalBrandingBlob = await GetPortalBrandingBlobAsync().ConfigureAwait(false);

            await portalBrandingBlob.UploadTextAsync(JsonConvert.SerializeObject(updatedBrandingConfiguration)).ConfigureAwait(false);

            // invalidate the cache, we do not update it to avoid race condition between web instances
            await ApplicationDomain.CachingService.ClearAsync(PortalBrandingCacheKey).ConfigureAwait(false);

            // re-initialize the telemetry service because the configuration might have changed.
            await ApplicationDomain.TelemetryService.InitializeAsync().ConfigureAwait(false);

            return(updatedBrandingConfiguration);
        }
        /// <summary>
        /// Applies business rules to <see cref="BrandingConfiguration"/> instances.
        /// </summary>
        /// <param name="brandingConfiguration">A branding configuration instance.</param>
        /// <returns>A task.</returns>
        private async Task NormalizeAsync(BrandingConfiguration brandingConfiguration)
        {
            brandingConfiguration.AssertNotNull(nameof(brandingConfiguration));

            brandingConfiguration.OrganizationName.AssertNotEmpty("OrganizationName");

            if (brandingConfiguration.ContactUs == null)
            {
                throw new PartnerDomainException(ErrorCode.InvalidInput, "ContactUs section not found in portal branding configuration").AddDetail("Field", "ContactUs");
            }

            brandingConfiguration.ContactUs.Email.AssertNotEmpty("Email");

            try
            {
                new MailAddress(brandingConfiguration.ContactUs.Email);
            }
            catch (FormatException)
            {
                throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid contact us email address").AddDetail("Field", "ContactUs.Email");
            }

            try
            {
                brandingConfiguration.ContactUs.Phone.AssertNotEmpty("ContactUs.Phone");
            }
            catch (ArgumentException)
            {
                throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid contact us phone").AddDetail("Field", "ContactUs.Phone");
            }

            if (brandingConfiguration.ContactSales == null)
            {
                // default the contact sales to the contact us information
                brandingConfiguration.ContactSales = new ContactUsInformation()
                {
                    Email = brandingConfiguration.ContactUs.Email,
                    Phone = brandingConfiguration.ContactUs.Phone
                };
            }
            else
            {
                if (string.IsNullOrWhiteSpace(brandingConfiguration.ContactSales.Email))
                {
                    brandingConfiguration.ContactSales.Email = brandingConfiguration.ContactUs.Email;
                }
                else
                {
                    try
                    {
                        new MailAddress(brandingConfiguration.ContactSales.Email);
                    }
                    catch (FormatException)
                    {
                        throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid contact sales email address").AddDetail("Field", "ContactSales.Email");
                    }
                }

                if (string.IsNullOrWhiteSpace(brandingConfiguration.ContactSales.Phone))
                {
                    brandingConfiguration.ContactSales.Phone = brandingConfiguration.ContactUs.Phone;
                }
                else
                {
                    try
                    {
                        brandingConfiguration.ContactSales.Phone.AssertNotEmpty("ContactSales.Phone");
                    }
                    catch (ArgumentException)
                    {
                        throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid contact sales phone").AddDetail("Field", "ContactSales.Phone");
                    }
                }
            }

            if (brandingConfiguration.OrganizationLogoContent != null)
            {
                // there is an logo image specified, upload it to BLOB storage and setup the URI property to point to it
                brandingConfiguration.OrganizationLogo = await this.UploadStreamToBlobStorageAsync(
                    "OrganizationLogo",
                    brandingConfiguration.OrganizationLogoContent);

                brandingConfiguration.OrganizationLogoContent = null;
            }

            if (brandingConfiguration.HeaderImageContent != null)
            {
                // there is a header image specified, upload it to BLOB storage and setup the URI property to point to it
                brandingConfiguration.HeaderImage = await this.UploadStreamToBlobStorageAsync(
                    "HeaderImage",
                    brandingConfiguration.HeaderImageContent);

                brandingConfiguration.HeaderImageContent = null;
            }
        }