- سپس باید از فضای نام مرتبط استفاده کنید (و نه از فضاهای نام مشابه)
enum MyEnum { [System.ComponentModel.Description("Blah")] MyValue }
EF Code First #12
using System.Runtime.Serialization; namespace AOP03.DataContracts { [DataContract] public class User { [DataMember] public int Id { set; get; } [DataMember] public string Name { set; get; } } }
تهیه DataContractAspect جهت اعمال خودکار ویژگیهای DataContract و DataMember
using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.Serialization; using PostSharp.Aspects; using PostSharp.Extensibility; using PostSharp.Reflection; namespace AOP03 { [Serializable] //این ویژگی تنها نیاز است به کلاسها اعمال شود [MulticastAttributeUsage(MulticastTargets.Class)] public class DataContractAspect : TypeLevelAspect, IAspectProvider { public IEnumerable<AspectInstance> ProvideAspects(object targetElement) { var targetType = (Type)targetElement; //همان نوعی است که ویژگی جاری به آن اعمال خواهد شد //این سطر معادل است با درخواست تولید ویژگی دیتاکانترکت var introduceDataContractAspect = new CustomAttributeIntroductionAspect( new ObjectConstruction(typeof(DataContractAttribute).GetConstructor(Type.EmptyTypes))); //این سطر معادل است با درخواست تولید ویژگی دیتاممبر var introduceDataMemberAspect = new CustomAttributeIntroductionAspect( new ObjectConstruction(typeof(DataMemberAttribute).GetConstructor(Type.EmptyTypes))); //در اینجا کار اعمال ویژگی دیتاکانترکت به کلاسی که به عنوان پارامتر متد جاری //دریافت شده انجام خواهد شد yield return new AspectInstance(targetType, introduceDataContractAspect); //مرحله بعد کار اعمال ویژگی دیتاممبر به خواص کلاس است foreach (var property in targetType.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance)) { if (property.CanWrite) yield return new AspectInstance(property, introduceDataMemberAspect); } } } }
برای اعمال آن به سراسر برنامه تنها کافی است به فایل AssemblyInfo.cs پروژه مراجعه و سپس سطر زیر را به آن اضافه کنیم:
[assembly: DataContractAspect(AttributeTargetTypes = "AOP03.DataContracts.*")]
در این حالت اگر کلیه ویژگیهای کلاس User فوق را حذف و برنامه را کامپایل کنیم، با مراجعه به برنامه ILSpy میتوان صحت اعمال ویژگیها را به کمک PostSharp بررسی کرد:
غنی سازی کامپایلر C# 9.0 با افزونهها
Roslyn analyzers به همراه پیشنهادهایی در مورد code styles هم هستند؛ برای مثال توصیهی به استفادهی از var و یا عکس آن. میتوان این توصیهها را تبدیل به اجبار هم کرد تا در یک تیم، code styles یکدستی ارائه شود و روش آن، وارد کردن این توصیهها به پروسهی build است. برای اینکار میتوان فایل csproj را به نحو زیر ویرایش کرد:
<PropertyGroup> <TargetFramework>net6.0</TargetFramework> <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> </PropertyGroup>
[*.cs] # Default severity for analyzer diagnostics with category 'Style' (escalated to build warnings) dotnet_analyzer_diagnostic.category-Style.severity = warning
بدیهی است در این صورت، روش لغو توصیهی خاصی به صورت زیر است:
dotnet_diagnostic.IDE0008.severity = none
این تصویر را پیشتر در مطلب «ارتقاء به ASP.NET Core 1.0 - قسمت 6 - سرویسها و تزریق وابستگیها» مشاهده کردهاید. در اینجا لیست سرویسهایی را مشاهده میکنید که به صورت پیش فرض، ثبت شدهاند و فعال هستند و ILogger و ILoggerFactory نیز جزئی از آنها هستند. بنابراین نیازی به فعال سازی آنها نیست؛ اما برای استفادهی از آنها نیاز به انجام یک سری تنظیمات است.
پیاده سازی ثبت وقایع در ASP.NET Core
اولین قدم کار با فریم ورک ثبت وقایع ASP.NET Core، معرفی ILoggerFactory به متد Configure کلاس آغازین برنامه است:
public void Configure(ILoggerFactory loggerFactory, IApplicationBuilder app, IHostingEnvironment env) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug();
سطر اول متد، تنظیمات ثبت وقایع را از خاصیت Logging فایل appsettings.json برنامه میخواند (در مورد خاصیت Configuration، در مطلب «ارتقاء به ASP.NET Core 1.0 - قسمت 7 - کار با فایلهای config» بیشتر بحث شد) و لاگ کردن ویژهی در کنسول NET Core. را فعال میکند:
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information" } } }
و سطر دوم سبب نمایش اطلاعات لاگ شده در کنسول دیباگ ویژوال استودیو میشود.
متد AddDebug برای شناسایی، نیاز به افزودن وابستگیهای ذیل در فایل project.json برنامه را دارد:
{ "dependencies": { //same as before "Microsoft.Extensions.Logging": "1.0.0", "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.Extensions.Logging.Debug": "1.0.0" } }
در اینجا میتوانید ریز وقایعی را که توسط ASP.NET Core لاگ شدهاست، مشاهده کنید. برای مثال چه درخواستی صورت گرفتهاست و چقدر اجرای آن زمانبردهاست.
این فعال سازی مرتبط است به متد AddDebug که اضافه شد. اگر میخواهید خروجی AddConsole را هم مشاهده کنید، از طریق خط فرمان، به پوشهی اصلی پروژه وارد شده و سپس دستور dotnet run را اجرا کنید:
دستور dotnet run سبب راه اندازی وب سرور برنامه بر روی پورت 5000 شدهاست که در تصویر نیز مشخص است.
بنابراین اینبار برای دسترسی به برنامه باید مسیر http://localhost:5000 را در مرورگر خود طی کنید. در اینجا نیز میتوان حالتهای مختلف اطلاعات لاگ شده را مشاهده کرد و تمام اینها مرتبط هستند به ذکر متد AddConsole .
کار با سرویس ثبت وقایع ASP.NET Core از طریق تزریق وابستگیها
برای کار با سرویس ثبت وقایع توکار ASP.NET Core در قسمتهای مختلف برنامه، میتوان از ترزیق وابستگی ILogger آن استفاده کرد:
[Route("[controller]")] public class AboutController : Controller { private readonly ILogger<AboutController> _logger; public AboutController(ILogger<AboutController> logger) { _logger = logger; } [Route("")] public ActionResult Hello() { _logger.LogInformation("Running Hello"); return Content("Hello from DNT!"); }
سپس با توجه به اینکه این سرویس جزو سرویسهای از پیش ثبت شدهی ASP.NET Core است، امکانات آن بدون نیاز به تنظیمات بیشتری در دسترس است. برای مثال از متد LogInformation آن در اکشن متد Hello استفاده شدهاست و خروجی عبارت لاگ شدهی آنرا در اینجا میتوانید مشاهده کنید:
سطوح مختلف ثبت وقایع
اینترفیس ILogger به همراه متدهای مختلفی است؛ مانند LogError، LogDebug و غیره. معانی آنها به شرح زیر هستند:
Debug (1): ثبت واقعهای است با بیشترین حد جزئیات ممکن که عموما شامل اطلاعات حساسی نیز میباشد. بنابراین نباید در حالت ارائهی نهایی برنامه فعال شود.
(2) Verbose: ثبت وقایعی مفصل، جهت بررسی مشکلات در حین توسعهی برنامه. تنها باید حاوی اطلاعاتی برای دیباگ برنامه باشند.
(3) Information: عموما برای ردیابی قسمتهای مختلف برنامه مورد استفاده قرار میگیرند.
(4) Warning: جهت ثبت واقعهای نامطلوب در سیستم بکار میرود و سبب قطع اجرای برنامه نمیشود.
(5) Errors: مشکلات برنامه را که سبب قطع سرویس دهی آن شدهاند را ثبت میکند. هدف آن ثبت مشکلات واحد جاری است و نه کل برنامه.
Critical (6): هدف آن ثبت مشکلات بحرانی کل سیستم است که سبب از کار افتادن آن شدهاند.
برای مثال در حین تنظیم متد AddDebug که سبب نمایش اطلاعات لاگ شده در کنسول دیباگ ویژوال استودیو میشود، میتوان حداقل سطح ثبت وقایع را نیز ذکر کرد:
loggerFactory.AddDebug(minLevel: LogLevel.Information);
البته ترتیب واقعی این سطوح را در enum مرتبط با آنها بهتر میتوان مشاهده کرد:
public enum LogLevel { Trace, Debug, Information, Warning, Error, Critical, None, }
یک نکته: زمانیکه متد AddDebug را بدون پارامتر فراخوانی میکنید، حداقل سطح ثبت وقایع آن به Information تنظیم شدهاست. یعنی در این لاگ، خبری از اطلاعات Debug نخواهد بود (چون سطح دیباگ پایینتر است از Information). بنابراین اگر میخواهید این اطلاعات را هم مشاهده کنید باید پارامتر minLevel آنرا به LogLevel.Debug تنظیم نمائید.
امکان استفادهی از پروایدرهای ثبت وقایع ثالث
تا اینجا، دو نمونه از پروایدرهای توکار ثبت وقایع ASP.NET Core را بررسی کردیم. اگر نیاز به ثبت این اطلاعات با فرمتهای مختلف و یا در بانک اطلاعاتی وجود دارد، میتوان به تامین کنندههای ثالثی که قابلیت کار با ILoggerFactory را دارند نیز مراجعه کرد. برای مثال:
- elmah.io - provider for the elmah.io service
- Loggr - provider for the Loggr service
- NLog - provider for the NLog library
- Serilog - provider for the Serilog library
یکی از مواردی که ممکن است در محیط کاری با آن برخورد داشت، تقاضای تولید فایل word یک گزارش با فرمتی مشخص از یک برنامه ASP.Net است. برای مثال یک قالب درست کردهاند که header و footer و کلا یک فرمت رسمی دارد. الان برنامه شما باید این فایل word رسمی را با گزارشی که تولید میکند پر کند. حالا اینجاست که گرفتاری برنامه نویس شروع میشود! روی سرور باید word نصب باشد تا توسط اشیاء COM آن بتوان یک چنین کارهایی را آنهم با ASP.Net که به صورت پیش فرض کمترین سطح دسترسی را روی سیستم دارد انجام داد. یا اینکه باید به سراغ کامپوننتهای تجاری رفت و حالا اینجا با این وضع تحریم و غیره چگونه بتوان آنها را خریداری کرد یا شاید احتمالا در سایتهای وارز بتوان نسخه تکه پاره شده آنها را یافت. مشکلی هم که این نوع کامپوننتها دارند این است که ممکن است سال دیگر اصلا ساپورت نشوند. محصولات مایکروسافت هم که مرتبا در حال به روز رسانی هستند. در این حالت برنامه متکی به این نوع کامپوننتهای تجاری سورس بسته در همان نگارش قبلی خود مجبور است باقی بماند.
خوشبختانه با ارائه آفیس 2007 و فرمت OpenXML فایلهای آن، این مشکل تقریبا مرتفع شده است. مایکروسافت نیز برای سهولت تولید این نوع اسناد، OpenXML SDK را ارائه داده است که از آدرس زیر قابل دریافت است:
Open XML Format SDK 1.0
البته پیش نمایش نگارش دو SDK آن نیز موجود است که در مطلب جاری به آن پرداخته نخواهد شد.
فایلهای office 2007 از یک فایلzip تشکیل شده از چند فایل xml داخل آن، ایجاد شدهاند. برای مثال یک فایل docx را با winrar یا امثال آن باز کنید (تصویر زیر):
برای کار با اینگونه اسناد باید با اصطلاحات زیر آشنا شد:
Package : فایل zip شما (همان فایل برای مثال docx) اینجا یک بسته نام دارد.
Parts : اجزای این بسته که همان فایلهای آن هستند، parts نامیده شده اند.
Relations : اگر به فایلهای موجود در یک بسته دقت کنید، فایلهایی با پسوند rels را خواهید دید که بیانگر نحوه ارتباط Parts با یکدیگر هستند.
Relations Ids: هر ارتباط با یک ID منحصربفرد تعریف میگردد.
اگر علاقمند باشید که پوستری را در این رابطه مشاهده نمائید میتوان به آدرس زیر مراجعه نمود.
Open XML Developer Map
نحوه استفاده از OpenXML SDK در دات نت:
ابتدا باید ارجاعی را به فایل DocumentFormat.OpenXml.dll که پس از نصب در مسیر OpenXMLSDK\1.0.1825\lib قرار گرفته است به پروژه افزود. سپس نیاز است تا ارجاعی به کتابخانه WindowsBase نیز به برنامه افزوده شود (تصویر زیر). افزودن ارجاعی به این کتابخانه جهت کامپایل برنامه ضروری است (شکل زیر).
تا اینجا ارجاعات برنامه به صورت زیر خواهند بود:
یک مثال ساده:
قصد داریم یک فایل docx ساده را با استفاده از OpenXML SDK ایجاد کنیم. در مثال زیر فرمت متغیر docXml را میتوان با ایجاد یک فایل docx ساده در word و سپس باز کردن بسته فشرده شده آن و مشاهده محتوای فایل word\document.xml بدست آورد.
using System.IO;
using System.Text;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
namespace OpenXMLTestApp
{
class CWord
{
public static void CreateDocument(string documentFileName, string text)
{
using (WordprocessingDocument wordDoc =
WordprocessingDocument.Create(documentFileName, WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = wordDoc.AddMainDocumentPart();
string docXml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
<w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"">
<w:body><w:p><w:r><w:t>#REPLACE#</w:t></w:r></w:p></w:body>
</w:document>";
docXml = docXml.Replace("#REPLACE#", text);
using (Stream stream = mainPart.GetStream())
{
byte[] buf = (new UTF8Encoding()).GetBytes(docXml);
stream.Write(buf, 0, buf.Length);
}
}
}
}
}
CWord.CreateDocument("test.docx", "سلام دنیا");
برای مطالعه بیشتر میتوان به منابع زیر مراجعه نمود:
یک ویدیوی آموزشی رایگان از مایکروسافت
دریافت
سؤالات متداول در MSDN
http://msdn.microsoft.com/en-us/library/bb491088.aspx
البته اگر پس از نصب SDK به پوشه doc آن مراجعه نمائید، این سؤال و جوابها را در فایل راهنمای chm آن نیز میتوان پیدا کرد.
مثال دیگری در مورد ایجاد یک گزارش از بانک اطلاعاتی و گرفتن خروجی docx از آن
http://openxmldeveloper.org/articles/GenerateWordTable.aspx
البته این مثال خیلی قدیمی است و قسمتهای کار با پکیج را با SDK ارائه شده میتوان به صورت خودکار انجام داد. اما حداقل نحوه تولید جداول استاندارد OpenXML را میتوان از آن ایده گرفت.
مثالی در مورد نحوه قرار دادن عکس در فایل docx تولیدی
همچنین مثالهای بیشتری را در وبلاگهای مربوطه میتوان یافت:
http://blogs.msdn.com/brian_jones/
http://blogs.msdn.com/ericwhite/default.aspx
- مسیرها را بررسی کنید.
- کل solution را build کنید.
- روی پروژه اصلی کلیک راست کنید و گزینهی project dependencies را انتخاب کنید. در اینجا میشود مشخص کرد، زمانیکه این پروژه build میشود، چه پروژههایی حتما باید build شوند (در قسمت depends on آن، تیک همهی موارد را قرار دهید).
جهت اینکار یک پروژه از نوع class library ایجاد کنید. فایل class1.cs را که به طور پیش فرض ایجاد میشود، حذف کنید و رفرنسهای Microsoft.Web.Management.dll و Microsoft.Web.Administration.dll را از مسیر زیر اضافه کنید:
\Windows\system32\inetsrv
در مرحله بعدی در تب 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
ساخت یک 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 دارید که میتوانید عملیات جست و جو، گروه بندی و نحوهی نمایش لیست را روی آن اعمال کنید. |
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; } }
mgr.CommitChanges();
%vs110comntools%\vsvars32.bat
GACUTIL /l ClassLibrary1
<add name="imageCopyrightUI" type="ClassLibrary1.imageCopyrightUIProvider, ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d0b3b3b2aa8ea14b"/>
%windir%\system32\inetsrv\config\administration.config
از آنجا که این مقاله طولانی شده است، باقی موارد ویرایشی روی این UI را در مقاله بعدی بررسی خواهیم کرد.