private static Site SetSite(Site site, dynamic model)
        {
            Debug.Assert(site != null);
            Debug.Assert((bool)(model != null));

            DynamicHelper.If((object)model.name, v => { site.Name = v; });

            site.ServerAutoStart = DynamicHelper.To <bool>(model.server_auto_start) ?? site.ServerAutoStart;

            string physicalPath = DynamicHelper.Value(model.physical_path);

            if (physicalPath != null)
            {
                if (!Directory.Exists(System.Environment.ExpandEnvironmentVariables(physicalPath)))
                {
                    throw new ApiArgumentException("physical_path", "Directory does not exist.");
                }

                var rootApp = site.Applications["/"];
                if (rootApp == null)
                {
                    throw new ApiArgumentException("site/physical_path", "Root application does not exist.");
                }

                var rootVDir = rootApp.VirtualDirectories["/"];
                if (rootVDir == null)
                {
                    throw new ApiArgumentException("site/physical_path", "Root virtual directory does not exist.");
                }

                rootVDir.PhysicalPath = physicalPath.Replace('/', '\\');
            }

            string enabledProtocols = DynamicHelper.Value(model.enabled_protocols);

            if (enabledProtocols != null)
            {
                var rootApp = site.Applications["/"];

                if (rootApp != null)
                {
                    rootApp.EnabledProtocols = enabledProtocols;
                }
            }

            // Limits
            if (model.limits != null)
            {
                dynamic limits = model.limits;

                site.Limits.MaxBandwidth   = DynamicHelper.To(limits.max_bandwidth, 0, uint.MaxValue) ?? site.Limits.MaxBandwidth;
                site.Limits.MaxConnections = DynamicHelper.To(limits.max_connections, 0, uint.MaxValue) ?? site.Limits.MaxConnections;

                if (site.Limits.Schema.HasAttribute(MaxUrlSegmentsAttribute))
                {
                    site.Limits.MaxUrlSegments = DynamicHelper.To(limits.max_url_segments, 0, 16383) ?? site.Limits.MaxUrlSegments;
                }

                long?connectionTimeout = DynamicHelper.To(limits.connection_timeout, 0, ushort.MaxValue);
                site.Limits.ConnectionTimeout = (connectionTimeout != null) ? TimeSpan.FromSeconds(connectionTimeout.Value) : site.Limits.ConnectionTimeout;
            }

            // Bindings
            if (model.bindings != null)
            {
                IEnumerable <dynamic> bindings = (IEnumerable <dynamic>)model.bindings;

                // If the user passes an object for the bindings property rather than an array we will hit an exception when we try to access any property in
                // the foreach loop.
                // This means that the bindings collection won't be deleted, so the bindings are safe from harm.

                List <Binding> newBindings = new List <Binding>();

                // Iterate over the bindings to create a new binding list
                foreach (dynamic binding in bindings)
                {
                    // Extract data from binding
                    string ipAddress = DynamicHelper.Value(binding.ip_address);
                    long?  port      = DynamicHelper.To(binding.port, 1, 65535);
                    string hostname  = DynamicHelper.Value(binding.hostname) ?? "";

                    bool?  isHttps              = DynamicHelper.To <bool>(binding.is_https);
                    string certificateHash      = null;
                    string certificateStoreName = null;

                    byte[] hashBytes = null;

                    // Validate that data forms valid binding
                    if (ipAddress == null)
                    {
                        throw new ApiArgumentException("binding.ip_address");
                    }
                    else if (port == null)
                    {
                        throw new ApiArgumentException("binding.port");
                    }
                    else if (isHttps == null)
                    {
                        throw new ApiArgumentException("binding.is_https");
                    }

                    if (isHttps.Value)
                    {
                        if (binding.certificate == null || !(binding.certificate is JObject))
                        {
                            throw new ApiArgumentException("certificate");
                        }

                        dynamic certificate = binding.certificate;
                        string  uuid        = DynamicHelper.Value(certificate.id);

                        if (string.IsNullOrEmpty(uuid))
                        {
                            throw new ApiArgumentException("certificate.id");
                        }

                        CertificateId id = new CertificateId(uuid);
                        certificateHash      = id.Thumbprint;
                        certificateStoreName = Enum.GetName(typeof(StoreName), id.StoreName);

                        List <byte> bytes = new List <byte>();

                        // Decode the hex string of the certificate hash into bytes
                        for (int i = 0; i < id.Thumbprint.Length; i += 2)
                        {
                            bytes.Add(Convert.ToByte(id.Thumbprint.Substring(i, 2), 16));
                        }

                        hashBytes = bytes.ToArray();
                    }

                    // Create binding
                    Binding newBinding = site.Bindings.CreateElement();

                    // If format of the information is incorrect throws ArgumentException but does not populate ParamName
                    newBinding.BindingInformation = $"{ipAddress}:{port}:{hostname}";
                    newBinding.Protocol           = isHttps.Value ? "https" : "http";

                    // Attempting to get or set the certificate hash when the protocol is not https will raise an error -msdn
                    if (isHttps.Value)
                    {
                        // The specified certificate must be in the store with a private key or else there will be an exception when we commit
                        newBinding.CertificateHash      = hashBytes;
                        newBinding.CertificateStoreName = certificateStoreName;
                    }

                    // Add to bindings list
                    newBindings.Add(newBinding);
                }

                // All bindings have been verified and added to the list
                // Clear the old list, and add the new
                site.Bindings.Clear();
                newBindings.ForEach(binding => site.Bindings.Add(binding));
            }

            // Set the app pool
            if (model.application_pool != null)
            {
                // Extract the uuid from the application_pool object provided in model
                string appPoolUuid = DynamicHelper.Value(model.application_pool.id);

                // It is an error to provide an application pool object without specifying its id property
                if (appPoolUuid == null)
                {
                    throw new ApiArgumentException("application_pool.id");
                }

                // Create application pool id object from uuid provided, use this to obtain the application pool
                AppPools.AppPoolId appPoolId = AppPoolId.CreateFromUuid(appPoolUuid);
                ApplicationPool    pool      = AppPoolHelper.GetAppPool(appPoolId.Name);

                Application rootApp = site.Applications["/"];

                if (rootApp == null)
                {
                    throw new ApiArgumentException("application_pool", "Root application does not exist.");
                }

                // REVIEW: Should we create the root application if it doesn't exist and they specify an application pool?
                // We decided not to do this for physical_path.
                // Application pool for a site is extracted from the site's root application
                rootApp.ApplicationPoolName = pool.Name;
            }

            return(site);
        }
        private static Site SetSite(Site site, dynamic model)
        {
            Debug.Assert(site != null);
            Debug.Assert((bool)(model != null));

            //
            // Name
            DynamicHelper.If((object)model.name, v => { site.Name = v; });

            //
            // Server Auto Start
            site.ServerAutoStart = DynamicHelper.To <bool>(model.server_auto_start) ?? site.ServerAutoStart;


            //
            // Physical Path
            string physicalPath = DynamicHelper.Value(model.physical_path);

            if (physicalPath != null)
            {
                if (!Directory.Exists(System.Environment.ExpandEnvironmentVariables(physicalPath)))
                {
                    throw new ApiArgumentException("physical_path", "Directory does not exist.");
                }

                var rootApp = site.Applications["/"];
                if (rootApp == null)
                {
                    throw new ApiArgumentException("site/physical_path", "Root application does not exist.");
                }

                var rootVDir = rootApp.VirtualDirectories["/"];
                if (rootVDir == null)
                {
                    throw new ApiArgumentException("site/physical_path", "Root virtual directory does not exist.");
                }

                rootVDir.PhysicalPath = physicalPath.Replace('/', '\\');
            }

            //
            // Enabled Protocols
            string enabledProtocols = DynamicHelper.Value(model.enabled_protocols);

            if (enabledProtocols != null)
            {
                var rootApp = site.Applications["/"];

                if (rootApp != null)
                {
                    rootApp.EnabledProtocols = enabledProtocols;
                }
            }

            //
            // Limits
            if (model.limits != null)
            {
                dynamic limits = model.limits;

                site.Limits.MaxBandwidth   = DynamicHelper.To(limits.max_bandwidth, 0, uint.MaxValue) ?? site.Limits.MaxBandwidth;
                site.Limits.MaxConnections = DynamicHelper.To(limits.max_connections, 0, uint.MaxValue) ?? site.Limits.MaxConnections;

                if (site.Limits.Schema.HasAttribute(MaxUrlSegmentsAttribute))
                {
                    site.Limits.MaxUrlSegments = DynamicHelper.To(limits.max_url_segments, 0, 16383) ?? site.Limits.MaxUrlSegments;
                }

                long?connectionTimeout = DynamicHelper.To(limits.connection_timeout, 0, ushort.MaxValue);
                site.Limits.ConnectionTimeout = (connectionTimeout != null) ? TimeSpan.FromSeconds(connectionTimeout.Value) : site.Limits.ConnectionTimeout;
            }

            //
            // Bindings
            if (model.bindings != null)
            {
                IEnumerable <dynamic> bindings = (IEnumerable <dynamic>)model.bindings;

                // If the user passes an object for the bindings property rather than an array we will hit an exception when we try to access any property in
                // the foreach loop.
                // This means that the bindings collection won't be deleted, so the bindings are safe from harm.

                List <Binding> newBindings = new List <Binding>();

                // Iterate over the bindings to create a new binding list
                foreach (dynamic b in bindings)
                {
                    Binding binding = site.Bindings.CreateElement();
                    SetBinding(binding, b);

                    foreach (Binding addedBinding in newBindings)
                    {
                        if (addedBinding.Protocol.Equals(binding.Protocol, StringComparison.OrdinalIgnoreCase) &&
                            addedBinding.BindingInformation.Equals(binding.BindingInformation, StringComparison.OrdinalIgnoreCase))
                        {
                            throw new AlreadyExistsException("binding");
                        }
                    }

                    // Add to bindings list
                    newBindings.Add(binding);
                }

                // All bindings have been verified and added to the list
                // Clear the old list, and add the new
                site.Bindings.Clear();
                newBindings.ForEach(binding => site.Bindings.Add(binding));
            }

            //
            // App Pool
            if (model.application_pool != null)
            {
                // Extract the uuid from the application_pool object provided in model
                string appPoolUuid = DynamicHelper.Value(model.application_pool.id);

                // It is an error to provide an application pool object without specifying its id property
                if (appPoolUuid == null)
                {
                    throw new ApiArgumentException("application_pool.id");
                }

                // Create application pool id object from uuid provided, use this to obtain the application pool
                AppPools.AppPoolId appPoolId = AppPoolId.CreateFromUuid(appPoolUuid);
                ApplicationPool    pool      = AppPoolHelper.GetAppPool(appPoolId.Name);

                Application rootApp = site.Applications["/"];

                if (rootApp == null)
                {
                    throw new ApiArgumentException("application_pool", "Root application does not exist.");
                }

                // REVIEW: Should we create the root application if it doesn't exist and they specify an application pool?
                // We decided not to do this for physical_path.
                // Application pool for a site is extracted from the site's root application
                rootApp.ApplicationPoolName = pool.Name;
            }

            return(site);
        }