public static ManageSiteResult ValidateSite(IisSite site, IisSite originalSite) { var certificates = SiteManager.GetCertificates(); var result = new ManageSiteResult(); if (!site.Bindings.Any()) { result.Errors.Add("Minimum one binding is required."); } if (string.IsNullOrWhiteSpace(site.Name)) result.Errors.Add("Name is required."); IisSite existingSite = SiteManager.GetSiteByName(site.Name); if (originalSite == null) { originalSite = new IisSite() { IisId = 0}; } if (site.Name != null && existingSite != null && site.Name.ToLower() == existingSite.Name.ToLower() && existingSite.IisId != originalSite.IisId) result.Errors.Add("There's already a site with this name."); if (string.IsNullOrWhiteSpace(site.SitePath)) result.Errors.Add("Site path is required."); else { if (!FileSystemHelper.IsPathValid(site.SitePath)) { result.Errors.Add("Path cannot contain the following characters: ?, ;, :, @, &, =, +, $, ,, |, \", <, >, *."); } else { if (!FileSystemHelper.DirectoryExists(site.SitePath)) { FileSystemHelper.CreateDirectory(site.SitePath); } } if (!FileSystemHelper.IsPathValid(site.LogFileDirectory)) { result.Errors.Add("Log File Directory cannot contain the following characters: ?, ;, :, @, &, =, +, $, ,, |, \", <, >, *."); } else { if (!FileSystemHelper.DirectoryExists(site.LogFileDirectory)) { FileSystemHelper.CreateDirectory(site.LogFileDirectory); } } } result.Result = result.Errors.Any() ? SiteResult.ValidationError : SiteResult.Success; return result; }
public static ManageSiteResult CreateSite(IisSite site) { var validationResult = Validators.ValidateSite(site, null); if (validationResult.Errors.Any()) { return validationResult; } var result = new ManageSiteResult(); var bindingInformations = site.Bindings.Select(x => x.ToIisBindingInformation()).ToList(); // Check bindings var bindingInUse = GetBindingInUse(0, bindingInformations); // 0 never exists if (bindingInUse != null) { result.Result = SiteResult.BindingAlreadyInUse; return result; } using (var manager = new ServerManager()) { if (manager.Sites.Any(x => x.Name == site.Name)) { result.Result = SiteResult.NameAlreadyInUse; return result; } // Create site manager.Sites.Add(site.Name, "http", bindingInformations.First(), site.SitePath); var iisSite = manager.Sites.SingleOrDefault(x => x.Name == site.Name); // Add bindings iisSite.Bindings.Clear(); foreach (var binding in bindingInformations) iisSite.Bindings.Add(binding, "http"); // Set/create application pool if (string.IsNullOrWhiteSpace(site.ApplicationPool)) // Auto create application pool { var appPoolName = site.Name; var existingApplicationPoolNames = manager.ApplicationPools.Select(x => x.Name).ToList(); var newNameCount = 1; while (existingApplicationPoolNames.Contains(appPoolName)) { appPoolName = site.Name + "_" + newNameCount; newNameCount++; } manager.ApplicationPools.Add(appPoolName); iisSite.ApplicationDefaults.ApplicationPoolName = appPoolName; } else { iisSite.ApplicationDefaults.ApplicationPoolName = site.ApplicationPool; } //Add Virtual apps/directories foreach (var application in site.Applications) { if (!application.Path.StartsWith("/")) application.Path = "/" + application.Path; if (application.IsApplication) { if (application.Path.EndsWith("/")) { application.Path.Remove(application.Path.Length - 1, 1); } iisSite.Applications.Add(application.Path, application.DiskPath); } else // Directory { iisSite.Applications.First().VirtualDirectories.Add(application.Path, application.DiskPath); } } manager.CommitChanges(); var created = false; var sw = new Stopwatch(); sw.Start(); while (!created && sw.Elapsed.TotalSeconds < 3) { try { if (iisSite.State == ObjectState.Started || iisSite.State == ObjectState.Stopped) { created = true; } } catch (COMException) { System.Threading.Thread.Sleep(100); } } sw.Stop(); if (created) { result.Result = SiteResult.Success; result.IisSiteId = (int) iisSite.Id; } else { result.Result = SiteResult.Failed; } return result; } }
public static ManageSiteResult UpdateSite(IisSite site) { var result = new ManageSiteResult { IisSiteId = site.IisId }; using (var manager = new ServerManager()) { var iisSite = manager.Sites.SingleOrDefault(x => x.Id == site.IisId); if (iisSite == null) { result.Result = SiteResult.UnknownSiteId; return result; } var iisSiteWithSameName = manager.Sites.SingleOrDefault(x => x.Id != site.IisId && x.Name == site.Name); if (iisSiteWithSameName != null) { result.Result = SiteResult.NameAlreadyInUse; return result; } var mainApplication = iisSite.Applications.First(); var rootPathDirectory = mainApplication.VirtualDirectories.SingleOrDefault(x => x.Path == "/"); if (rootPathDirectory == null) { mainApplication.VirtualDirectories.Add("/", site.SitePath); } else { rootPathDirectory.PhysicalPath = site.SitePath; } // In some scenarios Microsoft.Web.Administation fails to save site if property-set is detected with same name. //I believe it deletes and insert sites on updates and this makes a name conflict. Fixed by the hack below: if(site.Name != iisSite.Name) iisSite.Name = site.Name; // If the application pool does not exists on the server, create it if (manager.ApplicationPools.SingleOrDefault(x => x.Name == site.ApplicationPool) == null) { manager.ApplicationPools.Add(site.ApplicationPool); } mainApplication.ApplicationPoolName = site.ApplicationPool; // Update log file path iisSite.LogFile.Directory = site.LogFileDirectory; // Commits bindings iisSite.Bindings.Clear(); foreach (var binding in site.Bindings) { if (binding.Protocol == Protocol.https) { var certificate = GetCertificates().Single(x => x.Thumbprint == binding.CertificateThumbprint); iisSite.Bindings.Add(binding.ToIisBindingInformation(), certificate.Hash, "My"); } else iisSite.Bindings.Add(binding.ToIisBindingInformation(), binding.Protocol.ToString()); } // Deletes virtual applications var applicationsToDelete = iisSite.Applications.Skip(1).Where(application => !site.Applications.Where(x => x.IsApplication).Select(a => a.Path).Contains(application.Path)).ToList(); foreach (var application in applicationsToDelete) { application.Delete(); iisSite.Applications.Remove(application); // Bug in Microsoft.Web.Administration when changing from directory - application } // Deletes virtual directories var directoriesToDelete = mainApplication.VirtualDirectories.Where(directory => directory.Path != "/" && !site.Applications.Where(x => !x.IsApplication).Select(a => a.Path).Contains(directory.Path)).ToList(); // Exclude "/" because it's the root application's directory. foreach (var directory in directoriesToDelete) { directory.Delete(); mainApplication.VirtualDirectories.Remove(directory); // Bug in Microsoft.Web.Administration when changing from directory - application } //Intelligently updates virtual applications + directories foreach (var application in site.Applications) { if (!application.Path.StartsWith("/")) application.Path = "/" + application.Path; if (application.IsApplication) { if (application.Path.EndsWith("/")) { application.Path = application.Path.Substring(0, application.Path.Length - 1); } var iisApp = iisSite.Applications.SingleOrDefault(x => x.Path == application.Path); if (iisApp == null) { iisSite.Applications.Add(application.Path, application.DiskPath); iisApp = iisSite.Applications.Single(x => x.Path == application.Path); } iisApp.VirtualDirectories[0].PhysicalPath = application.DiskPath; iisApp.ApplicationPoolName = application.ApplicationPool; } else // Directory { var virtualDirectory = mainApplication.VirtualDirectories.SingleOrDefault(x => x.Path == application.Path); if (virtualDirectory == null) { mainApplication.VirtualDirectories.Add(application.Path, application.DiskPath); } else { virtualDirectory.PhysicalPath = application.DiskPath; } } } manager.CommitChanges(); } return result; }
public static ManageSiteResult ValidateSite(Site site, Site originalSite) { var certificates = SiteManager.GetCertificates(); var result = new ManageSiteResult(); if (!site.Bindings.Any()) { result.Errors.Add("Minimum one binding is required."); } if (string.IsNullOrWhiteSpace(site.Name)) { result.Errors.Add("Name is required."); } var existingSite = SiteManager.GetSiteByName(site.Name); if (originalSite == null) { originalSite = new Site() { IisId = 0 }; } if (site.Name != null && existingSite != null && site.Name.ToLower() == existingSite.Name.ToLower() && existingSite.IisId != originalSite.IisId) { result.Errors.Add("There's already a site with this name."); } if (string.IsNullOrWhiteSpace(site.SitePath)) { result.Errors.Add("Site path is required."); } else { if (!FileSystemHelper.IsPathValid(site.SitePath)) { result.Errors.Add("Path cannot contain the following characters: ?, ;, :, @, &, =, +, $, ,, |, \", <, >, *."); } else { if (!FileSystemHelper.DirectoryExists(site.SitePath)) { FileSystemHelper.CreateDirectory(site.SitePath); } } if (!FileSystemHelper.IsPathValid(site.LogFileDirectory)) { result.Errors.Add("Log File Directory cannot contain the following characters: ?, ;, :, @, &, =, +, $, ,, |, \", <, >, *."); } else { if (!FileSystemHelper.DirectoryExists(site.LogFileDirectory)) { FileSystemHelper.CreateDirectory(site.LogFileDirectory); } } } result.Result = result.Errors.Any() ? SiteResult.ValidationError : SiteResult.Success; return(result); }
public static ManageSiteResult UpdateSite(Site site) { var result = new ManageSiteResult { IisSiteId = site.IisId }; using (var manager = new ServerManager()) { var iisSite = manager.Sites.SingleOrDefault(x => x.Id == site.IisId); if (iisSite == null) { result.Result = SiteResult.UnknownSiteId; return(result); } var iisSiteWithSameName = manager.Sites.SingleOrDefault(x => x.Id != site.IisId && x.Name == site.Name); if (iisSiteWithSameName != null) { result.Result = SiteResult.NameAlreadyInUse; return(result); } var mainApplication = iisSite.Applications.First(); var rootPathDirectory = mainApplication.VirtualDirectories.SingleOrDefault(x => x.Path == "/"); if (rootPathDirectory == null) { mainApplication.VirtualDirectories.Add("/", site.SitePath); } else { rootPathDirectory.PhysicalPath = site.SitePath; } // In some scenarios Microsoft.Web.Administation fails to save site if property-set is detected with same name. //I believe it deletes and insert sites on updates and this makes a name conflict. Fixed by the hack below: if (site.Name != iisSite.Name) { iisSite.Name = site.Name; } // If the application pool does not exists on the server, create it if (manager.ApplicationPools.SingleOrDefault(x => x.Name == site.ApplicationPool) == null) { manager.ApplicationPools.Add(site.ApplicationPool); } mainApplication.ApplicationPoolName = site.ApplicationPool; // Update log file path iisSite.LogFile.Directory = site.LogFileDirectory; // Commits bindings iisSite.Bindings.Clear(); foreach (var binding in site.Bindings) { if (binding.Protocol == Protocol.https) { var certificate = GetCertificates().Single(x => x.Thumbprint == binding.CertificateThumbprint); iisSite.Bindings.Add(binding.ToIisBindingInformation(), certificate.Hash, "My"); } else { iisSite.Bindings.Add(binding.ToIisBindingInformation(), binding.Protocol.ToString()); } } // Deletes virtual applications var applicationsToDelete = iisSite.Applications.Skip(1).Where(application => !site.Applications.Where(x => x.IsApplication).Select(a => a.Path).Contains(application.Path)).ToList(); foreach (var application in applicationsToDelete) { application.Delete(); iisSite.Applications.Remove(application); // Bug in Microsoft.Web.Administration when changing from directory - application } // Deletes virtual directories var directoriesToDelete = mainApplication.VirtualDirectories.Where(directory => directory.Path != "/" && !site.Applications.Where(x => !x.IsApplication).Select(a => a.Path).Contains(directory.Path)).ToList(); // Exclude "/" because it's the root application's directory. foreach (var directory in directoriesToDelete) { directory.Delete(); mainApplication.VirtualDirectories.Remove(directory); // Bug in Microsoft.Web.Administration when changing from directory - application } //Intelligently updates virtual applications + directories foreach (var application in site.Applications) { if (!application.Path.StartsWith("/")) { application.Path = "/" + application.Path; } if (application.IsApplication) { if (application.Path.EndsWith("/")) { application.Path = application.Path.Substring(0, application.Path.Length - 1); } var iisApp = iisSite.Applications.SingleOrDefault(x => x.Path == application.Path); if (iisApp == null) { iisSite.Applications.Add(application.Path, application.DiskPath); iisApp = iisSite.Applications.Single(x => x.Path == application.Path); } iisApp.VirtualDirectories[0].PhysicalPath = application.DiskPath; iisApp.ApplicationPoolName = application.ApplicationPool; } else // Directory { var virtualDirectory = mainApplication.VirtualDirectories.SingleOrDefault(x => x.Path == application.Path); if (virtualDirectory == null) { mainApplication.VirtualDirectories.Add(application.Path, application.DiskPath); } else { virtualDirectory.PhysicalPath = application.DiskPath; } } } manager.CommitChanges(); } return(result); }
public static ManageSiteResult CreateSite(IisSite site) { var validationResult = Validators.ValidateSite(site, null); if (validationResult.Errors.Any()) { return(validationResult); } var result = new ManageSiteResult(); var bindingInformations = site.Bindings.Select(x => x.ToIisBindingInformation()).ToList(); // Check bindings var bindingInUse = GetBindingInUse(0, bindingInformations); // 0 never exists if (bindingInUse != null) { result.Result = SiteResult.BindingAlreadyInUse; return(result); } using (var manager = new ServerManager()) { if (manager.Sites.Any(x => x.Name == site.Name)) { result.Result = SiteResult.NameAlreadyInUse; return(result); } // Create site manager.Sites.Add(site.Name, "http", bindingInformations.First(), site.SitePath); var iisSite = manager.Sites.SingleOrDefault(x => x.Name == site.Name); // Add bindings iisSite.Bindings.Clear(); foreach (var binding in bindingInformations) { iisSite.Bindings.Add(binding, "http"); } // Set/create application pool if (string.IsNullOrWhiteSpace(site.ApplicationPool)) // Auto create application pool { var appPoolName = site.Name; var existingApplicationPoolNames = manager.ApplicationPools.Select(x => x.Name).ToList(); var newNameCount = 1; while (existingApplicationPoolNames.Contains(appPoolName)) { appPoolName = site.Name + "_" + newNameCount; newNameCount++; } manager.ApplicationPools.Add(appPoolName); iisSite.ApplicationDefaults.ApplicationPoolName = appPoolName; } else { iisSite.ApplicationDefaults.ApplicationPoolName = site.ApplicationPool; } //Add Virtual apps/directories foreach (var application in site.Applications) { if (!application.Path.StartsWith("/")) { application.Path = "/" + application.Path; } if (application.IsApplication) { if (application.Path.EndsWith("/")) { application.Path.Remove(application.Path.Length - 1, 1); } iisSite.Applications.Add(application.Path, application.DiskPath); } else // Directory { iisSite.Applications.First().VirtualDirectories.Add(application.Path, application.DiskPath); } } manager.CommitChanges(); var created = false; var sw = new Stopwatch(); sw.Start(); while (!created && sw.Elapsed.TotalSeconds < 3) { try { if (iisSite.State == ObjectState.Started || iisSite.State == ObjectState.Stopped) { created = true; } } catch (COMException) { System.Threading.Thread.Sleep(100); } } sw.Stop(); if (created) { result.Result = SiteResult.Success; result.IisSiteId = (int)iisSite.Id; } else { result.Result = SiteResult.Failed; } return(result); } }