Sampel Provisi di C#
oleh Walter Oliver
Gambaran Umum
Selama bertahun-tahun, menjadi mudah bagi pengguna Web tingkat lanjut untuk membuat situs Web mereka sendiri. Setelah pengguna akhir mendaftarkan nama domain mereka, ada berbagai jenis hoster untuk dipilih. Hoster web tersedia di seluruh dunia untuk memenuhi permintaan pelanggan akhir. Tetapi terlepas dari hoster mana yang dipilih, skenario mendaftar dan membuat situs web serupa dalam semua kasus.
Awalnya, akun pengguna baru perlu dibuat untuk pengguna. Setelah akun disiapkan, pengguna akhir memutuskan fitur dan opsi apa yang harus dimasukkan situs: misalnya, berapa banyak ruang disk, kemampuan FTP, pembuatan direktori virtual, apakah database diperlukan atau tidak, dll. Hoster membangun panel kontrol atau aplikasi dasbor yang memungkinkan pengguna akhir untuk membuat dan mengelola fitur-fitur ini.
Ada sejumlah cara agar kemampuan ini dapat diimplementasikan ke dalam panel kontrol. Di bagian ini, kita melihat penerapan aspek provisi fitur-fitur ini melalui kode terkelola. Kerangka fiturnya adalah sebagai berikut:
Memprovisikan Akun Pengguna Baru
Pemilik situs yang mengelola dan memelihara situs memerlukan akun pengguna baru. Akun dapat berupa akun Direktori Aktif® atau akun pengguna lokal. Fragmen kode berikut menunjukkan pembuatan akun lokal. Perhatikan bahwa namespace layanan System.DirectoryServices harus ditentukan.
public static bool CreateLocalUserAccount(string userName, string password)
{
try
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName", "Invalid User Name.");
if (string.IsNullOrEmpty(password))
throw new ArgumentNullException("password", "Invalid Password.");
DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" +
Environment.MachineName + ",computer");
bool userFound = false;
try
{
if (directoryEntry.Children.Find(userName, "user") != null)
userFound = true;
}
catch
{
userFound = false;
}
if (!userFound)
{
DirectoryEntry newUser = directoryEntry.Children.Add(userName, "user");
newUser.Invoke("SetPassword", new object[] { password });
newUser.Invoke("Put", new object[] { "Description", "Application Pool User Account" });
newUser.CommitChanges();
newUser.Close();
}
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return true;
}
Membuat Penyimpanan Konten
Situs Web memerlukan lokasi pada sistem file tempat pengguna dapat mengunggah isi untuk situs tersebut. Kelas Direktori Microsoft® .NET menyediakan antarmuka pemrograman aplikasi (API) untuk membuat direktori pada sistem file.
Directory.CreateDirectory(parentPath + "\\" + directoryName);
Penyimpanan konten memerlukan izin khusus yang dikonfigurasi sehingga pengguna dapat mengelola konten mereka sendiri. Fragmen kode berikut menunjukkan cara mengatur izin direktori menggunakan kode terkelola di C#:
public static bool AddDirectorySecurity(string directoryPath, string userAccount, FileSystemRights rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType controlType)
{
try
{
// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo(directoryPath);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(userAccount, rights, inheritanceFlags, propagationFlags, controlType));
// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return true;
}
Fragmen kode berikut menunjukkan cara mengatur kuota disk menggunakan kode terkelola jika kuota disk dibatasi. Untuk menggunakan manajemen kuota disk, Anda harus menambahkan referensi ke komponen manajemen kuota disk Windows®; berada di bawah Windows\system32\dskquota.dll.
public static bool AddUserDiskQuota(string userName, double quota, double quotaThreshold, string diskVolume)
{
try
{
DiskQuotaControlClass diskQuotaCtrl = GetDiskQuotaControl(diskVolume);
diskQuotaCtrl.UserNameResolution = UserNameResolutionConstants.dqResolveNone;
DIDiskQuotaUser diskUser = diskQuotaCtrl.AddUser(userName);
diskUser.QuotaLimit = quota;
diskUser.QuotaThreshold = quotaThreshold;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return true;
}
Membuat Kumpulan Aplikasi
Kumpulan aplikasi menentukan pengaturan untuk proses pekerja yang menghosting satu atau beberapa aplikasi Internet Information Services 7 (IIS 7), yang melakukan pemrosesan permintaan mereka. Kumpulan aplikasi adalah unit isolasi proses, karena semua pemrosesan permintaan untuk aplikasi berjalan dalam proses pekerja kumpulan aplikasinya.
Kumpulan aplikasi juga menyediakan isolasi, yang pada gilirannya memberikan keamanan. Setiap kumpulan aplikasi dapat berjalan dengan identitas unik dan dapat menggunakan daftar kontrol akses (ACL) untuk mencegah aplikasi di kumpulan lain mengakses sumber dayanya. Fragmen kode berikut menunjukkan pembuatan kumpulan aplikasi, mengatur identitas, dan mengatur properti.
public static bool CreateApplicationPool(string applicationPoolName, ProcessModelIdentityType identityType, string applicationPoolIdentity, string password, string managedRuntimeVersion, bool autoStart, bool enable32BitAppOnWin64,ManagedPipelineMode managedPipelineMode, long queueLength, TimeSpan idleTimeout, long periodicRestartPrivateMemory, TimeSpan periodicRestartTime)
{
try
{
if (identityType == ProcessModelIdentityType.SpecificUser)
{
if (string.IsNullOrEmpty(applicationPoolName))
throw new ArgumentNullException("applicationPoolName", "CreateApplicationPool: applicationPoolName is null or empty.");
if (string.IsNullOrEmpty(applicationPoolIdentity))
throw new ArgumentNullException("applicationPoolIdentity", "CreateApplicationPool: applicationPoolIdentity is null or empty.");
if (string.IsNullOrEmpty(password))
throw new ArgumentNullException("password", "CreateApplicationPool: password is null or empty.");
}
using (ServerManager mgr = new ServerManager())
{
ApplicationPool newAppPool = mgr.ApplicationPools.Add(applicationPoolName);
if (identityType == ProcessModelIdentityType.SpecificUser)
{
newAppPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser;
newAppPool.ProcessModel.UserName = applicationPoolIdentity;
newAppPool.ProcessModel.Password = password;
}
else
{
newAppPool.ProcessModel.IdentityType = identityType;
}
if (!string.IsNullOrEmpty(managedRuntimeVersion))
newAppPool.ManagedRuntimeVersion = managedRuntimeVersion;
newAppPool.AutoStart = autoStart;
newAppPool.Enable32BitAppOnWin64 = enable32BitAppOnWin64;
newAppPool.ManagedPipelineMode = managedPipelineMode;
if (queueLength > 0)
newAppPool.QueueLength = queueLength;
if (idleTimeout != TimeSpan.MinValue)
newAppPool.ProcessModel.IdleTimeout = idleTimeout;
if (periodicRestartPrivateMemory > 0)
newAppPool.Recycling.PeriodicRestart.PrivateMemory = periodicRestartPrivateMemory;
if (periodicRestartTime != TimeSpan.MinValue)
newAppPool.Recycling.PeriodicRestart.Time = periodicRestartTime;
mgr.CommitChanges();
}
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return true;
}
Buat Situs
Situs adalah kontainer logis tingkat atas yang menentukan bagaimana permintaan HTTP diterima dan diproses. Situs mendefinisikan sekelompok pengikatan yang menentukan bagaimana situs mendengarkan permintaan masuk, dan situs berisi definisi aplikasi atau direktori virtual yang mempartisi namespace URL situs untuk tujuan penataan konten aplikasi.
Fragmen kode berikut menunjukkan cara membuat situs baru. Namespace Microsoft.Web.Administration diperlukan saat mengimplementasikan objek ServerManager. Perhatikan bahwa kumpulan aplikasi, kumpulan situs, dan objek pengikatan semuanya diakses melalui objek ServerManager.
public static bool CreateWebSite(string siteName)
{
try
{
if (string.IsNullOrEmpty(siteName))
{
throw new ArgumentNullException("siteName", "CreateWebSite: siteName is null or empty.");
}
//get the server manager instance
using (ServerManager mgr = new ServerManager())
{
Site newSite = mgr.Sites.CreateElement();
//get site id
newSite.Id = GenerateNewSiteID(mgr, siteName);
newSite.SetAttributeValue("name", siteName);
mgr.Sites.Add(newSite);
mgr.CommitChanges();
}
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return true;
}
Membuat Pengikatan
Pengikatan adalah kombinasi nama protokol dan informasi pengikatan khusus protokol. Sementara IIS 7 mendukung pengikatan multi-protokol (seperti Windows® Communication Foundation [WCF] SOAP-TCP dan FTP), kode yang mengikuti hanya menggunakan jalur HTTP; pengikatan HTTP secara efektif mendefinisikan titik akhir HTTP yang mendengarkan alamat IP antarmuka tertentu (atau semua antarmuka), nomor port tertentu, atau header host HTTP tertentu (atau semua header host). Dengan cara ini, Anda dapat mengonfigurasi banyak situs di server Anda yang mendengarkan alamat IP yang berbeda, port yang berbeda, atau pada alamat IP atau port yang sama tetapi dengan header host yang berbeda.
public static bool AddSiteBinding(string siteName, string ipAddress, string tcpPort, string hostHeader, string protocol)
{
try
{
if (string.IsNullOrEmpty(siteName))
{
throw new ArgumentNullException("siteName", "AddSiteBinding: siteName is null or empty.");
}
//get the server manager instance
using (ServerManager mgr = new ServerManager())
{
SiteCollection sites = mgr.Sites;
Site site = mgr.Sites[siteName];
if (site != null)
{
string bind = ipAddress + ":" + tcpPort + ":" + hostHeader;
//check the binding exists or not
foreach (Binding b in site.Bindings)
{
if (b.Protocol == protocol && b.BindingInformation == bind)
{
throw new Exception("A binding with the same ip, port and host header already exists.");
}
}
Binding newBinding = site.Bindings.CreateElement();
newBinding.Protocol = protocol;
newBinding.BindingInformation = bind;
site.Bindings.Add(newBinding);
mgr.CommitChanges();
return true;
}
else
throw new Exception("Site: " + siteName + " does not exist.");
}
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
Membuat Aplikasi Root
Aplikasi adalah kontainer logis untuk fungsionalitas situs Web, memungkinkan Anda membagi namespace URL situs menjadi bagian terpisah dan mengontrol perilaku runtime setiap bagian satu per satu.
Misalnya, Anda dapat mengonfigurasi setiap aplikasi untuk berada di kumpulan aplikasi terpisah. Ini mengisolasi aplikasi dari aplikasi lain dengan menempatkannya dalam proses terpisah, dan secara opsional membuat proses tersebut berjalan dengan identitas Windows yang berbeda untuk kotak pasir.
public static bool AddApplication(string siteName, string applicationPath, string applicationPool, string virtualDirectoryPath, string physicalPath, string userName, string password)
{
try
{
if (string.IsNullOrEmpty(siteName))
throw new ArgumentNullException("siteName", "AddApplication: siteName is null or empty.");
if (string.IsNullOrEmpty(applicationPath))
throw new ArgumentNullException("applicationPath", "AddApplication: application path is null or empty.");
if (string.IsNullOrEmpty(physicalPath))
throw new ArgumentNullException("PhysicalPath", "AddApplication: Invalid physical path.");
if (string.IsNullOrEmpty(applicationPool))
throw new ArgumentNullException("ApplicationPool", "AddApplication: application pool namespace is Nullable or empty.");
using (ServerManager mgr = new ServerManager())
{
ApplicationPool appPool = mgr.ApplicationPools[applicationPool];
if (appPool == null)
throw new Exception("Application Pool: " + applicationPool + " does not exist.");
Site site = mgr.Sites[siteName];
if (site != null)
{
Application app = site.Applications[applicationPath];
if (app != null)
throw new Exception("Application: " + applicationPath + " already exists.");
else
{
app = site.Applications.CreateElement();
app.Path = applicationPath;
app.ApplicationPoolName = applicationPool;
VirtualDirectory vDir = app.VirtualDirectories.CreateElement();
vDir.Path = virtualDirectoryPath;
vDir.PhysicalPath = physicalPath;
if (!string.IsNullOrEmpty(userName))
{
if (string.IsNullOrEmpty(password))
throw new Exception("Invalid Virtual Directory User Account Password.");
else
{
vDir.UserName = userName;
vDir.Password = password;
}
}
app.VirtualDirectories.Add(vDir);
}
site.Applications.Add(app);
mgr.CommitChanges();
return true;
}
else
throw new Exception("Site: " + siteName + " does not exist.");
}
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
Membuat Direktori Virtual
Direktori virtual memetakan bagian dari namespace URL aplikasi ke lokasi fisik pada disk. Ketika permintaan dirutekan ke aplikasi, permintaan menggunakan algoritma yang sama untuk menemukan direktori virtual dengan jalur virtual terpanjang yang cocok dengan sisa jalur absolut permintaan setelah jalur aplikasi.
public static bool AddVirtualDirectory(string siteName, string application, string virtualDirectoryPath, string physicalPath, string userName, string password)
{
try
{
if (string.IsNullOrEmpty(siteName))
throw new ArgumentNullException("siteName", "AddVirtualDirectory: siteName is null or empty.");
if (string.IsNullOrEmpty(application))
throw new ArgumentNullException("application", "AddVirtualDirectory: application is null or empty.");
if (string.IsNullOrEmpty(virtualDirectoryPath))
throw new ArgumentNullException("virtualDirectoryPath", "AddVirtualDirectory: virtualDirectoryPath is null or empty.");
if (string.IsNullOrEmpty(physicalPath))
throw new ArgumentNullException("physicalPath", "AddVirtualDirectory: physicalPath is null or empty.");
using (ServerManager mgr = new ServerManager())
{
Site site = mgr.Sites[siteName];
if (site != null)
{
Application app = site.Applications[application];
if (app != null)
{
VirtualDirectory vDir = app.VirtualDirectories[virtualDirectoryPath];
if (vDir != null)
{
throw new Exception("Virtual Directory: " + virtualDirectoryPath + " already exists.");
}
else
{
vDir = app.VirtualDirectories.CreateElement();
vDir.Path = virtualDirectoryPath;
vDir.PhysicalPath = physicalPath;
if (!string.IsNullOrEmpty(userName))
{
if (string.IsNullOrEmpty(password))
throw new Exception("Invalid Virtual Directory User Account Password.");
else
{
vDir.UserName = userName;
vDir.Password = password;
}
}
app.VirtualDirectories.Add(vDir);
}
mgr.CommitChanges();
return true;
}
else
throw new Exception("Application: " + application + " does not exist.");
}
else
throw new Exception("Site: " + siteName + " does not exist.");
}
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
Membuat Situs FTP
Situs FTP memungkinkan pelanggan mengunggah konten ke situs Web mereka dan menyediakan kemampuan untuk memindahkan file di internet. Pelanggan dapat mengelola konten dan akses. Pembuatan situs FTP mirip dengan situs Web: Kumpulan aplikasi dan situs dibuat dengan aplikasi akar dan direktori virtual, lalu pengikatan FTP diterapkan.
public static bool CreateFtpSite(string applicationPoolName,string siteName, string domainName, string userName, string password,string contentPath, string ipAddress, string tcpPort, string hostHeader)
{
try
{
//provision the application pool
using (ServerManager mgr = new ServerManager())
{
ApplicationPool appPool = mgr.ApplicationPools[applicationPoolName];
//per IIS7 team recommendation, we always create a new application pool
//create new application pool
if (appPool == null)
{
appPool = mgr.ApplicationPools.Add(applicationPoolName);
//set the application pool attribute
appPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser;
appPool.ProcessModel.UserName = domainName + "\\" + userName;
appPool.ProcessModel.Password = password;
}
//if the appPool is null, we throw an exception. The appPool should be created or already exists.
if (appPool == null)
throw new Exception("Invalid Application Pool.");
//if the site already exists, throw an exception
if (mgr.Sites[siteName] != null)
throw new Exception("Site already exists.");
//create site
Site newSite = mgr.Sites.CreateElement();
newSite.Id = GenerateNewSiteID(mgr, siteName);
newSite.SetAttributeValue("name", siteName);
newSite.ServerAutoStart = true;
mgr.Sites.Add(newSite);
//create the default application for the site
Application newApp = newSite.Applications.CreateElement();
newApp.SetAttributeValue("path", "/"); //set to default root path
newApp.SetAttributeValue("applicationPool", applicationPoolName);
newSite.Applications.Add(newApp);
//create the default virtual directory
VirtualDirectory newVirtualDirectory = newApp.VirtualDirectories.CreateElement();
newVirtualDirectory.SetAttributeValue("path", "/");
newVirtualDirectory.SetAttributeValue("physicalPath", contentPath);
newApp.VirtualDirectories.Add(newVirtualDirectory);
//add the bindings
Binding binding = newSite.Bindings.CreateElement();
binding.SetAttributeValue("protocol", "ftp");
binding.SetAttributeValue("bindingInformation", ipAddress + ":" + tcpPort + ":" + hostHeader);
newSite.Bindings.Add(binding);
//commit the changes
mgr.CommitChanges();
}
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return true;
}