مطالب
معرفی پلاگین Agent Johnson !

چقدر خوب می‌شد اگر IDE ویژوال استودیو دات نت اشیایی از نوع disposable را برای ما مشخص می‌کرد و در ادامه پیشنهاد استفاده از عبارت using را برای آن‌ها می‌داد؟
سؤال: این مساله چه اهمیتی دارد؟
به مثال متداول زیر دقت بفرمائید:

string connString = "...";
SqlConnection conn = new SqlConnection(connString);
string cmdString = "select * from author where name=N'test'";
SqlCommand cmd = new SqlCommand(cmdString, conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
...
}
conn.Close();

این مثالی است که در اکثر سایت‌های آموزشی می‌توان یافت. باز کردن کانکشن به دیتابیس، اجرای کوئری و دریافت اطلاعات حاصل و در آخر بستن کانکشن. بسیار هم خوب! در این مثال اگر name مساوی test وجود نداشته باشد، روند اجرای برنامه در اولین reader.Read با یک exception متوقف خواهد شد. یعنی عملا ممکن است به بستن کانکشن نرسیم (هیچ الزامی وجود ندارد که کدهای ما سطر به سطر اجرا شوند). این مورد چه مشکلی را ایجاد خواهد کرد؟ فقط کافی است سایت ما 100 نفر بازدید کننده داشته باشد. در مدت زمان کوتاهی کل سایت با خطای زیر از کار می‌افتد و پیغامی که از کاربران دریافت خواهید کرد این است: "باز هم برنامه کند شد، "بازهم" سایت کار نمی‌کنه ..."
Exception Details: System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.

روش صحیح برای مقابله با این نوع خطاها قرار دادن قسمت بستن کانکشن در قسمت finally یک try/finally است تا مطمئن باشیم که حتما این قسمت اجرا خواهد شد. روش زیباتر این‌کار استفاده از عبارت using است. عبارت using نیز در نهایت به یک try/finally توسط کامپایلر بسط داده خواهد شد اما کد حاصل در این حالت خواناتر است. بنابراین در این حالت حتی اگر خطایی نیز رخ دهد، شیء مورد نظر حتما dispose خواهد شد. (از دات نت 2 به بعد عبارت using به VB.Net نیز افزوده شده است)

 using (SqlConnection connection =
new SqlConnection(connectionString))
{
...

عبارت using را تنها در مورد اشیایی از نوع IDisposable می‌توان بکار برد. یکی از توانایی‌های پلاگین Agent Johnson تشخیص این مورد و گوشزد کردن آن است (شکل زیر):



Agent Johnson در حقیقت پلاگینی است برای پلاگین دیگری به نام Resharper . این پلاگین را از آدرس زیر می‌توان دریافت کرد (احتمالا به یک پروکسی نیاز خواهد بود ...):
http://code.google.com/p/agentjohnsonplugin/
البته بحث تشخیص اشیاء disposable یکی از توانایی‌های آن است. سایر موارد را در آدرس فوق می‌توانید مشاهده نمائید.

اشتراک‌ها
یک MessageBox بهتر
شاید شما هم مثل من از MessageBox پیش فرض سی شارپ خسته شده باشید و بدنبال جایگزین بهتری برای آن باشید. من در جستجوهای خود به این مطلب برخوردم که یک MessageBox با تقریباً همان ویژگیهای MessagBox پیش فرض اما قدرتمند‌تر را پیاده سازی کرده است بطوریکه به شما امکان تعیین آیکون دلخواه برای MessageBox، تعیین قسمت‌های Main Instruction و Footer و گنجاندن لینک در این قسمت‌ها و ... را می‌دهد. البته این MessageBox به زبان ویژوال بیسیک دات نت نوشته شده، اما در قسمت نظرات مقاله لینک سورس C#.NET پروژه نیز قرار داده شده است.

موفق باشید!
یک MessageBox بهتر
نظرات مطالب
یکی کردن اسمبلی‌های یک پروژه‌ی WPF
یک نکته‌ی تکمیلی
اگر به دنبال یک راه حل پخته‌تر هستید که با انواع و اقسام اسمبلی‌ها بتواند کار کند (از mixed mode گرفته تا pcl و غیره)، افزونه‌ی  Fody / Costura توصیه می‌شود. کار با آن نیز بسیار ساده‌است. فقط کافی است دستور زیر را در کنسول پاور شل نیوگت VS.NET اجرا کنید:
PM> Install-Package Costura.Fody
بعد از نصب، تنها یکبار برنامه را مجددا build کنید.
اکنون اگر اسمبلی آن‌را بررسی کنید موارد ذیل را مشاهده خواهید کرد:

الف) اسمبلی‌های مدفون شده را zip کرده‌است.
ب) فایل pdb هم لحاظ شده.
ج) راه انداز خودکار و کدهای AssemblyResolver را تحت فضای نام  Costura به فایل EXE نهایی افزوده‌است.
 
Fody یکی از ابزارهای AOP سورس باز دات نت است.
نظرات مطالب
الگوی استراتژی - Strategy Pattern
- اگر پروژه خودتون هست، از اینترفیس استفاده کنید. تغییرات آن و نگارش‌های بعدی آن تحت کنترل خودتان است و build دیگران را تحت تاثیر قرار نمی‌دهد.
- در پروژه‌های سورس باز دات نت، عموما از ترکیب این دو استفاده می‌شود. مواردی که قرار است در اختیار عموم باشند حتی دو لایه هم می‌شوند. مثلا در MVC یک اینترفیس IController هست و بعد یک کلاس Abstract به نام Controller، که این اینترفیس را پیاده سازی کرده برای ورژن پذیری بعدی و کنترلرهای پروژه‌های عمومی MVC از این کلاس Abstract مشتق می‌شوند یا در پروژه RavenDB از کلاس‌های Abstract زیاد استفاده شده، مانند AbstractIndexCreationTask و AbstractMultiMapIndexCreationTask و غیره.
نظرات مطالب
آشنایی با Refactoring - قسمت 10
- در مورد طراحی آن اگر نظری دارید لطفا به تیم BCL اطلاع دهید: http://blogs.msdn.com/b/bclteam/
- بحث code contacts در اینجا فراتر است از validation متداول. این نوع اعتبارسنجی‌های متداول عموما و در اکثر موارد جهت بررسی preconditions هستند؛ در حالیکه اینجا post-conditions را هم شامل می‌شوند.
- در مورد کتابخانه‌های Validation هر کسی راه و روش خاص خودش را دارد. یکی ممکن است از DataAnnotations خود دات نت استفاده کند (و http://xval.codeplex.com/)، یکی از http://validationframework.codeplex.com/ یا از http://code.google.com/p/kosher/ و یا http://tnvalidate.codeplex.com/ و یا حتی NHibernate هم کتابخانه اعتبارسنجی خاص خودش را دارد.
در کل هدف این است که این کار بهتر است انجام شود. حالا با هر کدام که راحت هستید. مانند وجود انواع فریم‌ورک‌های Unit test یا  انواع مختلف سورس کنترل‌ها. مهم این است که از یکی استفاده کنید.
نظرات مطالب
بررسی تغییرات ASP.NET MVC 5 beta1
با سلام
با توجه به تغییرات سیستم امنیتی mvc  در نگارش 4 که از وب ماتریکس استفاده می‌کرد و در دات نت که بحث owin و غیره مطرح هست، یه مشکلی که وجود داره ، ساخت یه سری کلاس زیربنایی هست که اصطلاحا به فریم ورک تعبیر میشه. اگر بخوایم مثلا برای قسمت زیربنایی نام کاربری رو داشته باشیم، چه روشی رو پیشنهاد می‌کنید؟
مثلا در mvc 4 من از وب ماتریکس WebMatrix.WebData.WebSecurity.CurrentUserName  استفاده میکردم، ولی الان با mvc 5 نال میشه و مقدار نداره.
مطالب
پنج دلیل برای توسعه‌ی وب با ASP.NET Core

یک:  ASP.NET Core مستقل از Platform است

آینده‌ی محتوم نرم‌افزار، توسعه به شیوه‌های مستقل از Platform است. شاید این دلیل به تنهایی برای مهاجرت به ASP.NET Core کافی باشد. امروزه نرم‌افزارهایی که مبتنی بر یک Platform خاص نیستند، نسبت به سایر نرم‌افزارها مزیت رقابتی‌تری دارند. نرم‌افزارهای Cross Platform یا مستقل از Platform، بر روی هر سیستم عاملی اجرا می‌شوند. برای اجرای آنها در کامپیوترهای شخصی یا Server کافیست معماری پردازنده‌ی مرکزی x86 باشد و سیستم عامل نیز یکی از انواع ویندوز، لینوکس یا مک.
دلیل مستقل بودن ASP.NET Core از Platform، مبتنی بودن آن بر NET Core. است. این نسخه از دات‌نت را می‌توان برای سیستم‌‌عامل‌های مختلف از http://dot.net دانلود و نصب کرد.
برای اجرای نرم‌افزارهایی که مبتنی بر NET Core. هستند نیاز به بازنویسی کدها یا استفاده از زبان‌های برنامه‌نویسی جداگانه‌ای نیست. این خاصیت همچنین برای libraryهای استانداردی که از این نسخه از دات‌نت استفاده می‌کنند نیز صادق است.

دو:  Open Source است

یکی از انتقادهایی که سال‌ها به مایکروسافت می‌شد، ناشناخته بودن سورس نرم‌افزارهای این شرکت و انحصار طلبی‌هایش بود. اما در سال‌های اخیر مایکروسافت نشان داده‌است که این جنبه از کاراکترش را به تدریج اصلاح کرده‌است. به طوری که اسکات هانسلمن، یکی از کارمندان این شرکت و وبلاگ‌نویس مشهور در این مورد گفته است:
دلیل آمدن من به مایکروسافت این بود که می‌خواستیم هر چقدر می‌توانیم کارها را Open Source کنیم و یک جامعه‌ی کاربری برای دات‌نت و اوپن سورس بسازیم و حالا به NET Core 1.0. رسیده‌ایم.
زمانی شایعه‌ی لو رفتن بخشی از سورس کد ویندوز ۹۵، در صدر اخبار تکنولوژی بود و این یک شکست برای مایکروسافت محسوب می‌شد. اما امروزه ASP.NET Core با لایسنس MIT عرضه شده است که یکی از آزادترین مجوزهای اوپن سورس است. نرم‌افزارهایی که با این مجوز عرضه می‌شوند، آزادی تغییر کد، ادغام با مجوزهای دیگر، عرضه به عنوان محصول دیگر، استفاده تجاری و ... را به همه‌ی توسعه‌دهندگان می‌دهد.

سه: جدا بودن از Web Server

این نسخه‌ی از APS.NET، کاملاً از وب‌سرور که نرم‌افزارها را هاست می‌کند، جدا (decouple) شده است. اگرچه همچنان استفاده از IIS بر روی ویندوز منطقی به نظر می‌رسد اما مایکروسافت یک پروژه‌ی اوپن سورس دیگری را به نام Kestrel نیز منتشر کرده است.
وب‌سرور Kestrel مبتنی بر پروژه libuv است و libuv در اصل برای هاست کردن Node.js تولید شده بود و تأکید آن بر روی انجام عملیات I/O به صورت asynchronous است.
نکته جالب این است که یک برنامه‌ی مبتنی بر ASP.NET Core، در واقع یک Console Application است که در متد Main آن وب‌سرور فراخوانی می‌شود:
using System;
using Microsoft.AspNetCore.Hosting;
namespace aspnetcoreapp
{
public class Program
{
  public static void Main(string[] args)
  {
   var host = new WebHostBuilder()
                  .UseKestrel()
                  .UseStartup<Startup>()
                  .Build();
   host.Run();
  }
}
}

چهار: تزریق وابستگی (Dependency Injection) تو کار

تزریق وابستگی‌ها برای ایجاد وابستگی سست (loosely coupling) بین اشیاء مرتبط و وابسته به یکدیگر است. به جای نمونه‌سازی مستقیم اشیاء مرتبط، یا استفاده از ارجاع‌های ایستا به آن اشیاء، زمانی که یک کلاس به آنها احتیاج داشته باشد، با روش‌های خاصی از طریق DI به اشیاء مورد نیاز دسترسی پیدا می‌کند. در این استراتژی، ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند، بلکه هر دو باید به abstraction (معمولا Interface ها) وابسته باشند.
وقتی یک سیستم برای استفاده‌ی از DI طراحی شده‌است و کلاس‌های زیادی دارد که وابستگی‌هایش را از طریق constructor یا property‌ها درخواست می‌کند، بهتر است یک کلاس مخصوص ایجاد آن کلاس‌ها و وابستگی‌هایشان داشته باشد. به این کلاس‌ها container، یا Inversion of Control (IoC) container یا Dependency Injection (DI) container گفته می‌شود.
با این روش، بدون نیاز به hard code کردن instance سازی از کلاس‌ها، می‌توان گراف‌های پیچیده وابستگی را در اختیار یک کلاس قرار داد.
طراحی ASP.NET Core از پایه طوری است که حداکثر استفاده را از Dependency Injection می‌کند. یک container ساده توکار با نام IServiceProvider وجود دارد که به صورت پیش‌فرض constructor injection را پشتیبانی می‌کند.
در ASP.NET Core با مفهومی به نام service سر و کار خواهید داشت که در واقع به type هایی گفته می‌شود که از طریق DI در اختیار شما قرار می‌گیرند. سرویس‌ها در متد ConfigureServices کلاس Startup برنامه شما تعریف می‌شوند. این service‌ها می‌توانند Entity Framework Core یا ASP.NET Core MVC باشند یا سرویس‌هایی که توسط شما تعریف شده‌اند. مثال:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices (IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
  options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
  .AddEntityFrameworkStores<ApplicationDbContext>()
  .AddDefaultTokenProviders();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}


پنج: یکپارچگی با framework‌های مدرن سمت کلاینت

فرآیند build در برنامه‌های تحت وب مدرن معمولاً این وظایف را انجام می‌دهد:
  • bundle و minify کردن فایل‌های جاوا اسکریپت و همینطور CSS
  • اجرای ابزارهایی برای bundle و minify کردن قبل از هر build
  • کامپایل کردن فایل‌های LESS و SASS در CSS
  • کامپیال کردن فایل‌های CoffeeScript و TypeScript در JavaScript
برای اجرای چنین فرآیندهایی از ابزاری به نام task runner استفاده می‌شود که Visual Studio از دو ابزار task runner مبتنی برا جاوا اسکریپت به نام‌های Gulp و Grunt بهره می‌برد. از این ابزارها با استفاده از ASP.NET Core Web Application template می‌توان در ASP.NET Core استفاده کرد.
همچنین امکان استفاده از Bower که یک package manager (مانند NuGet) برای وب است، وجود دارد. معمولاً از Bower برای نصب فایل‌های CSS ، فونت‌ها، framework‌های سمت کلاینت و کتابخانه‌های جاوا اسکریپت استفاده می‌شود. اگرچه بسیاری از package‌ها در NuGet هم وجود دارند، اما تمرکز بیشتر NuGet بر روی کتابخانه‌های دات‌نتی است.
نصب و استفاده‌ی سایر library‌های سمت کلاینت مانند Bootstrap ، Knockout.js ، Angular JS  و زبان TypeScript نیز در Visual Studio و هماهنگی آن با ASP.NET Core نیز بسیار ساده است.
پس همین حالا دست به کار شوید و با نصب -حداقل - Microsoft Visual Studio 2015 Update 3 بر روی ویندوز یا Visual Studio Code  بر روی هر سیستم عاملی از برنامه‌نویسی با ASP.NET Core لذت ببرید!
منابع :
نظرات مطالب
شروع به کار با بوت استرپ 4
یک نکته‌ی تکمیلی: بررسی نگارش‌های ثالث راست به چپ بوت استرپ 4


1) MahdiMajidzadeh/bootstrap-v4-rtl
متاسفانه اصلا برای یک کار رسمی مناسب نیست و منوهای آن به هم ریخته‌است. list-group آن در حالت flush، کل عرض یک card را پر نمی‌کند و جداول آن نیز به همین صورت است. کامپوننت bread-crumb آن محل قرارگیری /‌های نامناسبی دارد. همچنین با آخرین نگارش بوت استرپ 4.1.3 سازگار نیست و از آن کمی عقب است و برای کار با آن، باید دقیقا همین بسته‌ی ثالث را دریافت و اضافه کنید و مستقل از خود بوت استرپ اصلی نیست. اما به همراه یک بسته‌ی npm مخصوص به خود است که یک مزیت به شمار می‌رود. مجوز آن، در مخزن کد Github آن ذکر نشده، اما در صفحه‌ی npm آن MIT ذکر شده‌است.
یک نمونه خروجی آن:


2) DediData/Bootstrap-RTL
به نظر یک پروژه‌ی خاتمه یافته‌است. با نگارش بوت استرپ 4.1.3 سازگار نیست و برای نگارش بتای آن تهیه شده‌است.


3) GhalamborM/bootstrap4-rtl
این پروژه، روش بهتری را نسبت به بسته‌های راست به چپ موجود، انتخاب کرده‌است. در اینجا شما بوت استرپ اصلی را با آخرین نگارش آن به صورت مستقل دریافت، نصب و تنظیم می‌کنید. سپس ذیل آن کلاس‌های راست به چپ این بسته‌ی ثالث را اضافه می‌کنید.
مجوز GPL، برای اینکار انتخاب شده‌است. متاسفانه یک چنین مجوزی در تضاد با مجوز MIT بوت استرپ اصلی است. مجوز GPL یعنی کار مشتق شده‌ی از آن نیز باید سورس باز شود و قابل استفاده‌ی در پروژه‌های تجاری غیر سورس باز نیست.
همچنین متاسفانه به صورت یک بسته‌ی npm نیز ارائه نشده‌است و باید آخرین نگارش آن‌را از GitHub به صورت مستقیم دریافت کنید.

با تمام این اوصاف، مشکلات ذکر شده‌ی مورد اولی که بررسی شد، در این نگارش وجود ندارند و بهترین خروجی را دریافت خواهید کرد:

 



4) PerseusTheGreat/bootstrap-4-rtl
روش راست به چپ سازی این نگارش نیز مانند حالت اولی است که بررسی شد و باید بسته‌ی مستقل آن‌را دریافت و استفاده کنید و به عنوان یک مکمل مطرح نیست. همچنین به همراه بسته‌ی npm نیز ارائه نشده‌است و تا این تاریخ، باید آخرین به روز رسانی‌های آن‌را از همان آدرس GitHub آن مستقیما دریافت کنید. البته مزیت آن، به روز رسانی هفتگی آن است. همچنین مجوز MIT این بسته را نیز تغییر نداده‌است.
خروجی آن با خروجی بسته‌ی سومی که معرفی شد، تقریبا یکی و مناسب است:



در کل اگر از مجوز GPL مورد سوم صرف نظر کنیم، به علت استقلال فایل CSS راست به چپ کننده‌ی آن از بسته‌ی اصلی بوت استرپ، انتخاب مناسب‌تری به نظر می‌رسد و خروجی قابل قبولی را نیز به همراه دارد. فقط ایکاش بسته‌ی npm ای نیز به پروژه‌ی آن اضافه شود.
به روز رسانی: تغییر مجوز به MIT و همچنین افزوده شدن بسته‌ی npm به مورد سوم صورت گرفته‌است:
npm install @ghalamborm/bootstrap4-rtl


پ.ن.
این روزها ارائه‌ی یک کتابخانه‌ی جاوا اسکریپتی و یا CSS ای بدون بسته‌ی npm متناظر با آن، ناقص به شمار می‌رود.
مطالب
آشنایی با ساختار IIS قسمت نهم
در قسمت قبلی  ما یک هندلر ایجاد کردیم و درخواست‌هایی را که برای فایل jpg و به صورت GET ارسال میشد، هندل می‌کردیم و تگی را در گوشه‌ی تصویر درج و آن را در خروجی نمایش میدادیم. در این مقاله قصد داریم که کمی هندلر مورد نظر را توسعه دهیم و برای آن یک UI یا یک رابط کاربری ایجاد نماییم. برای توسعه دادن ماژولها و هندلر‌ها ما یک dll نوشته و باید آن را در GAC که مخفف عبارت Global Assembly Cache ریجستر کنیم.


جهت اینکار یک پروژه از نوع class library ایجاد کنید. فایل class1.cs را که به طور پیش فرض ایجاد می‌شود، حذف کنید و رفرنس‌های Microsoft.Web.Management.dll و Microsoft.Web.Administration.dll را از مسیر زیر اضافه کنید:
\Windows\system32\inetsrv
اولین رفرنس شامل کلاس‌هایی است که جهت ساخت ماژول‌ها برای کنسول IIS مورد نیاز است و دومی هم برای خواندن پیکربندی‌های نوشته شده مورد استفاده قرار می‌گیرد.
برای طراحی UI  بر پایه winform باید رفرنس‌های System.Windows.Forms.dll و System.Web.dll را از سری اسمبلی‌های دات نت نیز اضافه کنیم و در مرحله‌ی بعدی جهت ایجاد امضاء یا strong name (^  و  ^  ) به خاطر ثبت در GAC پروژه را انتخاب و وارد Properties پروژه شوید. در تب signing گزینه sign the assembly را تیک زده و در لیست باز شده گزینه new را انتخاب نمایید و نام  imageCopyrightUI را به آن نسبت داده و گزینه تعیین کلمه عبور را غیرفعال کنید و تایید و تمام. الان باید یک فایل snk مخفف strong name key ایجاد شده باشد تا بعدا با استفاده از این کلید dll ایجاد شده را در GAC ریجستر کنیم.

در مرحله بعدی در تب Build Events کد زیر را در بخش Post-build event command line اضافه کنید. این کد باعث می‌شود بعد از هر بار کامپایل پروژه، به طور خودکار در GAC ثبت شود:

call "%VS80COMNTOOLS%\vsvars32.bat" > NULL 
gacutil.exe /if "$(TargetPath)"

نکته:در صورتی که از VS2005 استفاده می‌کنید در تب Debug در قسمت Start External Program مسیر زیر را قرار بدهید. اینکار برای تست و دیباگینگ پروژه به شما کمک خواهد کرد. این تنظیم شامل نسخه‌های اکسپرس نمی‌شود.
 \windows\system32\inetsrv\inetmgr.exe

بعد از پایان اینکار پروژه را Rebuild کنید. با اینکار dll در GAC ثبت می‌شود. استفاده از سوییچ‌های if به طور همزمان در درستور gacutil به معنی این هست که اگر اولین بار است نصب می‌شود، پس با سوییچ i نصب کن. ولی اگر قبلا نصب شده است نسخه جدید را به هر صورتی هست جایگزین قبلی کن یا همان reinstall کن.
 
ساخت یک Module Provider
رابط‌های کاربری IIS همانند هسته و کل سیستمش، ماژولار و قابل خصوصی سازی است. رابط کاربری، مجموعه‌ای از ماژول هایی است که میتوان آن‌ها را حذف یا جایگزین کرد. تگ ورودی یا معرفی برای هر UI یک module provider است. خیلی خودمانی، تگ ماژول پروایدر به معرفی یک UI در IIS می‌پردازد. لیستی از module provider‌ها را می‌توان در فایل زیر در تگ بخش <modules> پیدا کرد.
%windir%\system32\inetsrv\Administration.config

در اولین گام یک کلاس را به اسم imageCopyrightUIModuleProvider.cs ایجاد کرده و سپس آن‌را به کد زیر، تغییر می‌دهیم. کد زیر با استفاده از ModuleDefinition  یک نام به تگ Module Provider داده و کلاس imageCopyrightUI را که بعدا تعریف می‌کنیم، به عنوان مدخل entry رابط کاربری معرفی کرده:

using System;
using System.Security;
using Microsoft.Web.Management.Server;
    
namespace IIS7Demos           
{
    class imageCopyrightUIProvider : ModuleProvider
    {
        public override Type ServiceType              
        {
            get { return null; }
        }

        public override ModuleDefinition GetModuleDefinition(IManagementContext context)
        {
            return new ModuleDefinition(Name, typeof(imageCopyrightUI).AssemblyQualifiedName);
        }

        public override bool SupportsScope(ManagementScope scope)
        {
            return true;
        }
    }            
}

با ارث بری از کلاس module provider، سه متد بازنویسی می‌شوند که یکی از آن ها SupportsScope هست که میدان عمل پروایدر را مشخص می‌کند، مانند اینکه این پرواید در چه میدانی باید کار کند که می‌تواند سه گزینه‌ی server,site,application باشد. در کد زیر مثلا میدان عمل application انتخاب شده است ولی در کد بالا با برگشت مستقیم true، همه‌ی میدان را جهت پشتیبانی از این پروایدر اعلام کردیم.

 public override bool SupportsScope(ManagementScope scope)
        {
            return (scope == ManagementScope.Application) ;
        }

حالا که پروایدر (معرف رابط کاربری به IIS) تامین شده، نیاز است قلب کار یعنی ماژول معرفی گردد. اصلی‌ترین متدی که باید از اینترفیس ماژول پیاده سازی شود متد initialize است. این متد جایی است که تمام عملیات در آن رخ می‌دهد. در کلاس زیر imageCopyrightUI ما به معرفی مدخل entry رابط کاربری می‌پردازیم. در سازنده‌های این متد، پارامترهای نام، صفحه رابط کاربری وتوضیحی در مورد آن است. تصویر کوچک و بزرگ جهت آیکن سازی (در صورت عدم تعریف آیکن، چرخ دنده نمایش داده می‌شود) و توصیف‌های بلندتر را نیز شامل می‌شود.

 internal class imageCopyrightUI : Module
    {
        protected override void Initialize(IServiceProvider serviceProvider, ModuleInfo moduleInfo)
        {            
            base.Initialize(serviceProvider, moduleInfo);
            IControlPanel controlPanel = (IControlPanel)GetService(typeof(IControlPanel));
            ModulePageInfo modulePageInfo = new ModulePageInfo(this, typeof(imageCopyrightUIPage), "Image Copyright", "Image Copyright",Resource1.Visual_Studio_2012,Resource1.Visual_Studio_2012);
            controlPanel.RegisterPage(modulePageInfo);
        }
    }

شیء ControlPanel مکانی است که قرار است آیکن ماژول نمایش داده شود. شکل زیر به خوبی نام همه قسمت‌ها را بر اساس نام کلاس و اینترفیس آن‌ها دسته بندی کرده است:

پس با تعریف این کلاس جدید ما روی صفحه‌ی کنترل پنل IIS، یک آیکن ساخته و صفحه‌ی رابط کاربری را به نام imageCopyrightUIPage، در آن ریجستر می‌کنیم. این کلاس را پایینتر شرح داده‌ایم. ولی قبل از آن اجازه بدهید تا انواع کلاس هایی را که برای ساخت صفحه کاربرد دارند، بررسی نماییم. در این مثال ما با استفاده از پایه‌ای‌ترین کلاس، ساده‌ترین نوع صفحه ممکن را خواهیم ساخت. 4 کلاس برای ساخت یک صفحه وجود دارند که بسته به سناریوی کاری، شما یکی را انتخاب می‌کنید.

 ModulePage   شامل اساسی‌ترین متدها و سورس‌ها شده و هیچگونه رابط کاری ویژه‌ای را در اختیار شما قرار نمی‌دهد. تنها یک صفحه‌ی خام به شما می‌دهد که می‌توانید از آن استفاده کرده یا حتی با ارث بری از آن، کلاس‌های جدیدتری را برای ساخت صفحات مختلف و ویژه‌تر بسازید. در حال حاضر که هیچ کدام از ویژگی‌های IIS فعلی از این کلاس برای ساخت رابط کاربری استفاده نکرده‌اند.
 ModuleDialogPage   یک صفحه شبیه به دیالوگ را ایجاد می‌کند و شامل دکمه‌های Apply و Cancel میشود به همراه یک سری متدهای اضافی‌تر که اجازه‌ی override کردن آنها را دارید. همچنین یک سری از کارهایی چون refresh  و از این دست عملیات خودکار را نیز انجام میدهد. از نمونه رابط‌هایی که از این صفحات استفاده می‌کنند میتوان  machine key و management service را اسم برد.
 ModulePropertiesPage   این صفحه یک رابط کاربری را شبیه پنجره property که در ویژوال استادیو وجود دارد، در دسترس شما قرار میدهد. تمام عناصر آن در یک حالت گرید grid لیست می‌شوند. از نمونه‌های موجود میتوان به CGI,ASP.Net Compilation اشاره کرد.
 ModuleListPage   این کلاس برای مواقعی کاربرد دارد که شما قرار است لیستی از آیتم‌ها را نشان دهید. در این صفحه شما یک ListView دارید که میتوانید عملیات جست و جو، گروه بندی و نحوه‌ی نمایش لیست را روی آن اعمال کنید.
در این مثال ما از اولین کلاس نامبرده که پایه‌ی همه کلاس هاست استفاده می‌کنیم. کد زیر را در کلاسی به اسم imageCopyrightUIPage  می‌نویسیم:
    public sealed class imageCopyrightUIPage : ModulePage
    {
        public string message;
        public bool featureenabled;
        public string color;

        ComboBox _colCombo = new ComboBox();
        TextBox _msgTB = new TextBox();
        CheckBox _enabledCB = new CheckBox();

        public imageCopyrightUIPage()
        {
            this.Initialize();
        }


        void Initialize()
        {
            Label crlabel = new Label();
            crlabel.Left = 50;
            crlabel.Top = 100;
            crlabel.AutoSize = true;
            crlabel.Text = "Enable Image Copyright:";
            _enabledCB.Text = "";
            _enabledCB.Left = 200;
            _enabledCB.Top = 100;
            _enabledCB.AutoSize = true;

            Label msglabel = new Label();
            msglabel.Left = 150;
            msglabel.Top = 130;
            msglabel.AutoSize = true;
            msglabel.Text = "Message:";
            _msgTB.Left = 200;
            _msgTB.Top = 130;
            _msgTB.Width = 200;
            _msgTB.Height = 50;

            Label collabel = new Label();
            collabel.Left = 160;
            collabel.Top = 160;
            collabel.AutoSize = true;
            collabel.Text = "Color:";
            _colCombo.Left = 200;
            _colCombo.Top = 160;
            _colCombo.Width = 50;
            _colCombo.Height = 90;
            _colCombo.Items.Add((object)"Yellow");
            _colCombo.Items.Add((object)"Blue");
            _colCombo.Items.Add((object)"Red");
            _colCombo.Items.Add((object)"White");

            Button apply = new Button();
            apply.Text = "Apply";
            apply.Click += new EventHandler(this.applyClick);
            apply.Left = 200;
            apply.AutoSize = true;
            apply.Top = 250;

            Controls.Add(crlabel);
            Controls.Add(_enabledCB);
            Controls.Add(collabel);
            Controls.Add(_colCombo);
            Controls.Add(msglabel);
            Controls.Add(_msgTB);
            Controls.Add(apply);
        }

        public void ReadConfig()
        {
            try
            {
                ServerManager mgr;
                ConfigurationSection section;
                mgr = new ServerManager();
                Configuration config =
                mgr.GetWebConfiguration(
                       Connection.ConfigurationPath.SiteName,
                       Connection.ConfigurationPath.ApplicationPath +
                       Connection.ConfigurationPath.FolderPath);

                section = config.GetSection("system.webServer/imageCopyright");
                color = (string)section.GetAttribute("color").Value;
                message = (string)section.GetAttribute("message").Value;
                featureenabled = (bool)section.GetAttribute("enabled").Value;

            }

            catch
            { }

        }
      
        void UpdateUI()
        {
            _enabledCB.Checked = featureenabled;
            int n = _colCombo.FindString(color, 0);
            _colCombo.SelectedIndex = n;
            _msgTB.Text = message;
        }


        protected override void OnActivated(bool initialActivation)
        {
            base.OnActivated(initialActivation);
            if (initialActivation)
            {
                ReadConfig();
                UpdateUI();
            }
        }



        private void applyClick(Object sender, EventArgs e)
        {
            try
            {
                UpdateVariables();
                ServerManager mgr;
                ConfigurationSection section;
                mgr = new ServerManager();
                Configuration config =
                mgr.GetWebConfiguration
                (
                       Connection.ConfigurationPath.SiteName,
                       Connection.ConfigurationPath.ApplicationPath +
                       Connection.ConfigurationPath.FolderPath
                );

                section = config.GetSection("system.webServer/imageCopyright");
                section.GetAttribute("color").Value = (object)color;
                section.GetAttribute("message").Value = (object)message;
                section.GetAttribute("enabled").Value = (object)featureenabled;

                mgr.CommitChanges();

            }

            catch
            { }

        }

        public void UpdateVariables()
        {
            featureenabled = _enabledCB.Checked;
            color = _colCombo.Text;
            message = _msgTB.Text;
        }
    }
اولین چیزی که در کلاس بالا صدا زده می‌شود، سازنده‌ی کلاس هست که ما در آن یک تابع تعریف کردیم به اسم initialize که به آماده سازی اینترفیس یا رابط کاربری می‌پردازد و کنترل‌ها را روی صفحه می‌چیند. این سه کنترل، یکی Combox برای تعیین رنگ، یک Checkbox برای فعال بودن ماژول و دیگری هم یک textbox جهت نوشتن متن است. مابقی هم که سه label برای نامگذاری اشیاست. بعد از اینکه کنترل‌ها روی صفحه درج شدند، لازم است که تنظیمات پیش فرض یا قبلی روی کنترل‌ها نمایش یابند که اینکار را به وسیله تابع readConfig انجام می‌دهیم و تنظیمات خوانده شده را در متغیر‌های عمومی قرار داده و با استفاده از تابع UpdateUI این اطلاعات را روی کنترل‌ها ست می‌کنیم و به این ترتیب UI به روز می‌شود. این دو تابع را به ترتیب پشت سر هم در یک متد به اسم OnActivated  که override کرده‌ایم صدا میزنیم. در واقع این متد یک جورایی همانند رویداد Load می‌باشد؛ اگر true برگرداند اولین فعال سازی رابط کاربری بعد از باز شدن IIS است و در غیر این صورت false بر میگرداند.

در صورتی که کاربر مقادیر را تغییر دهد و روی گزینه apply کلیک کند تابع applyClick اجرا شده و ابتدا به تابع UpdateVariables ارجاع داده میشود که در آن مقادیر خوانده شده و در متغیرهای Global قرار می‌گیرند و سپس با استفاده از دو شیء از نوع serverManger و ConfigSection جایگذاری یا ذخیره می‌شوند.
استفاده از دو کلاس Servermanager و Configsection در دو قسمت خواندن و نوشتن مقادیر به کار رفته‌اند. کلاس servermanager به ما اجازه دسترسی به تنظیمات IIS و قابلیت‌های آن را میدهد. در تابع ReadConfig مسیر وب سایتی را که در لیست IIS انتخاب شده است، دریافت کرده و به وب کانفیگ آن وب سایت رجوع نموده و تگ imageCopyright آن را که در تگ system.webserver قرار گرفته است، میخواند (در صورتی که این تگ در آن وب کانفیگ موجود نباشد، خواندن و سپس ذخیره مجدد آن روی تگ داخل فایل applicationHost.config اتفاق میفتد که نتیجتا برای همه‌ی وب سایت هایی که این تگ را ندارند یا مقدارهای پیش فرض آن را تغییر نداده‌اند رخ میدهد) عملیات نوشتن هم مشابه خواندن است. تنها باید خط زیر را در آخر برای اعمال تغییرات نوشت؛ مثل EF با گزینه Context.SaveChanges:
mgr.CommitChanges();
وقت آن است که رابط کاربری را به IIS اضافه کنیم: پروژه را Rebuild کنید. بعد از آن با خطوطی که قبلا در Post-Build Command نوشتیم باید dll ما در GAC ریجستر شود. برای همین آدرس زیر را در cmd تایپ کنید:
%vs110comntools%\vsvars32.bat
عبارت اول که مسیر ویژوال استودیوی  شماست و عدد 110 یعنی نسخه‌ی 11. هر نسخه‌ای را که استفاده میکنید، یک صفر جلویش بگذارید و جایگزین عدد بالا کنید. مثلا نسخه 8 می‌شود 80 و فایل بچ بالا هم دستورات visual studio را برای شما آزاد می‌کند.
سپس دستور زیر را وارد کنید:
GACUTIL /l ClassLibrary1
کلمه classLibrary1 نام پروژه‌ی ما بود که در GAC ریجستر شده است. با سوییچ l تمامی اطلاعات اسمبلی‌هایی که در GAC ریجستر شده‌اند، نمایش می‌یابند. ولی اگر اسم آن اسمبلی را جلویش بنویسید، فقط اطلاعات آن اسمبلی نمایش میابد. با اجرای خط فوق میتوانیم کلید عمومی public key اسمبلی خود را بدانیم که در شکل زیر مشخص شده است:

پس اگر کلید را دریافت کرده‌اید، خط زیر را به فایل administration.config در تگ <ModuleProviders> اضافه کنید:
<add name="imageCopyrightUI" type="ClassLibrary1.imageCopyrightUIProvider,   ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d0b3b3b2aa8ea14b"/>
عبارت ClassLibrary1.imageCopyrightUIProvider به کلاس imageCopyrightUIProvider اشاره می‌کند که در این کلاس UI معرفی می‌شود. مابقی عبارت هم کاملا مشخص است و در لینک‌های بالا در مورد Strong name توضیح داده شده اند. 
فایل administration.config  در مسیر زیر قرار دارد:
%windir%\system32\inetsrv\config\administration.config
حالا تنها کاری که نیاز است، باز کردن IIS است. به بخش وب سایت‌ها رفته و اپلیکیشنی که قبلا با نام mypictures را ایجاد کرده بودیم، انتخاب کنید. در سمت راست، آخر لیست، بخش others باید ماژول ما دیده شود. بازش کنید و تنظمیات آن را تغییر دهید و حالا یک تصویر را از اپلیکیشن mypictures، روی مرورگر درخواست کنید تا تغییرات را روی تگ مشاهده کنید:

 
حالا دیگر باید ماژول نویسی برای IIS را فراگرفته باشیم. این ماژول‌ها می‌توانند از یک مورد ساده تا یک کلاس مهم و امنیتی باشند که روی سرور شما برای همه یا بعضی از وب سایت‌ها در حال اجرا هستند و در صورت لزوم و اجازه شما، برنامه نویس‌ها میتوانند مثل همه‌ی تگ‌های موجود در وب کانفیگ سایتی را که  مینویسند، تگ ماژول شما و  تنظیمات آن را با استفاده از attribute یا خصوصیت‌های تعریف شده، بر اساس سلایق و نیازهایشان تغییر دهند و روی سرور شما آپلود کنند. الان شما یک سرور خصوصی سازی شده دارید.
از آنجا که این مقاله طولانی شده است، باقی موارد ویرایشی روی این UI را در مقاله بعدی بررسی خواهیم کرد.