نظرات مطالب
سفارشی سازی ASP.NET Core Identity - قسمت چهارم - User Claims
با سلام. چطور می‌تونم این کد رو طوری تغییر بدم تا پس از اولین بار که claim‌ها رو ایجاد کردیم، سیستم فقط از claim‌ها نقش‌ها بخونه و هیچ کوئری به دیتابیس زده نشه؟ الان به ازای هر نقش کاربر، ما یک سلکت به دیتابیس داریم و این رو بنده می‌خوام فقط و فقط از claim‌ها بخونم.
مطالب
نصب dotnet core framework روی اوبونتو 16.04
مایکروسافت در چند سال اخیر و به خصوص بعد از روی کار آمدن ساتیا نادلا،  رویکرد خاصی را به مباحث Cross Platform پیدا کرد، تا جایی که dotnet core شکل گرفت. این فناوری جدید به شما این امکان را میدهد تا دات نت فریمورک را بر روی سیستم عامل‌های دیگری چون لینوکس و مک نصب کنید. در سایت اختصاصی این فناوری،  نحوه نصب آن بر روی توزیع‌های مختلف سیستم عامل  لینوکس،  توضیحاتی داده شده است و یکی از این آموزش‌ها مربوط به پرچم دار توزیع‌های لینوکس و به خصوص خانواده دبیان یعنی اوبونتو است. در این راهنما، تنها نسخه خاصی از اوبونتو یعنی نسخه 14.04 آن مدنظر می‌باشد ولی آخرین نسخه اوبونتو 16.04 است که در اینباره توضیحی داده نشده است و با نصب آن به مشکل بر می‌خورد. در این مقاله میخواهیم نصب dotnet core را بر روی آخرین نسخه این سیستم عامل، بررسی کنیم.

با توجه به ابتدای آموزش، کدهای زیر را در ترمینال وارد میکنیم:
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'

sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893

sudo apt-get update
اولین خط از لینوکس، مخزنی را که فایل‌های مربوط به دات نت، در آن قرار دارند، در لینوکس ثبت می‌کند. دستور sh وظیفه‌ی اجرای اسکریپت را بر عهده دارد که میتوانید یک فایل اسکریپت را به آن معرفی کنید. ولی اگر با سوپیچ c به کار رود، می‌توانید خود دستور ارسالی را به آن معرفی کنید. اجرای این اسکریپت منجر به معرفی مخازن دات نت می‌شود که میتواند برای نصب و به روزرسانی آن به کار رود. در ساختار فایل‌های خانواده‌ی دبیان، فایلی به نام Sources.list وجود دارد که شامل آدرس مخازن رسمی اوبونتو جهت دریافت نرم افزاری‌ها آن می‌شود. ولی اگر قرار باشد مخازنی جدای از مخازن رسمی معرفی گردند، باید داخل دایرکتوری sources.list.d قرار گیرند و با نامی مشخص و با همان فرمت مشخص، ذخیره گردند.

در خط  دوم،  کلید اختصاصی این پکیج جهت اعتبارسنجی معرفی می‌گردد که در سایت جاری قبلا به آن پرداخته شده است. در خط آخر هم مخازن موجود را به روزرسانی می‌کنیم تا آماده استفاده شود.
در سایت مایکروسافت از شما خواسته می‌شود که کد زیر را وارد کنید:
sudo apt-get install dotnet-dev-1.0.0-preview1-002702
ولی بهتر است به جای آن از جدیدترین بسته استفاده کنید که باگ آن رفع شده است و علت باگ قبلا به آن پرداخته شده است. پس کد زیر را به جای کد بالا وارد می‌کنیم:
sudo apt-get install dotnet-dev-1.0.0-preview2-003096
چه بسته قبلی و چه جدید را نصب کنید، به خطای زیر برخورد خواهید کرد:
The following packages have unmet dependencies:
 dotnet-dev-1.0.0-preview1-002702 : Depends: dotnet-sharedframework-microsoft.netcore.app-1.0.0-rc2-3002702 but it is not going to be installed
E: Unable to correct problems, you have held broken packages.
که برای حل آن، باید ابتدا بسته‌ی وابسته نصب گردد و سپس دستور بالا دوباره اجرا شود. برای دریافت این وابستگی، به این لینک مراجعه کنید و فایل مربوطه را که با پسوند deb است، دریافت کنید. بعد از آن باید فایل دریافتی را نصب نمایید که برای نصب این نوع بسته‌ها از دستور زیر استفاده می‌کنیم:
sudo dpkg -i libicu52_52.1-3ubuntu0.4_amd64.deb
بعد از نصب موفقیت آمیز این بسته، دستورات زیر را اجرا میکنیم تا بسته dotnet core نصب شود:
sudo apt-get install dotnet-sharedframework-microsoft.netcore.app-1.0.0-rc2-3002702
sudo apt-get install dotnet-dev-1.0.0-preview2-003096
بعد از اتمام نصب، دستور زیر را جهت اطمینان از صحت نصب وارد کنید، تا نسخه نصب شده جاری به شما نمایش داده شود:
dotnet --version
خروجی:
1.0.0-preview2-003096
البته ممکن است خروجی دفعه اول به خاطر پیام‌های خوش آمدگویی، خطوط بیشتری را داشته باشد، ولی برای دفعات آینده همین یک خط است.
مطالب
ایجاد زیر گریدهای چند سطحی در jqGrid
همانطور که در مطلب ایجاد زیرگریدها در jqGrid مشاهده کردید، هرچند این قابلیت برای نمایش لیست ساده‌ای از عناصر مفید است اما ... امکانات آنچنانی را به همراه ندارد. برای مثال صفحه بندی، جستجو، سفارشی سازی عناصر و غیره را به همراه ندارد. اگر علاقمند باشید که این امکانات را نیز اضافه کنید، می‌توان این زیرگرید را با یک گرید کامل jqGrid نیز جایگزین کرد. همچنین اگر نیاز بود، این گرید جدید چون یک jqGrid کامل است، باز هم می‌توان یک سطح دیگر را به آن افزود و الی آخر.



جایگزین کردن یک Subgrid با یک jqGrid کامل

خلاصه‌ی عملیات جایگزینی یک Subgrid را توسط یک jqGrid کامل، در ذیل مشاهده می‌کنید:
            $('#list').jqGrid({
                caption: "آزمایش دوازدهم",
                //..........مانند قبل
                subGrid: true,
                subGridRowExpanded: grid1RowExpanded
            });

        function grid1RowExpanded(subGridId, rowId) {
            var subgridTableId = subGridId + "_t";
            var pagerId = "p_" + subgridTableId;
            var container = 'g_' + subGridId;
            $("#" + subGridId).html('<div dir="rtl" id="' + container + '" style="width:100%; height: 100%">' +
                '<table id="' + subgridTableId + '" class="scroll"></table><div id="'
                + pagerId + '" class="scroll"></div>');

            var url = '@Url.Action("GetOrderDetails", "Home", routeValues: new { id = "js-id" })'
                      .replace("js-id", encodeURIComponent(rowId)); // تزریق اطلاعات سمت کاربر به خروجی سمت سرور

            $("#" + subgridTableId).jqGrid({
                caption: "ریز اقلام سفارش " + rowId,
                autoencode: true, //security - anti-XSS
                url: url,
                //..........مانند قبل
            });
        }
همانند نمایش subgridهای معمولی، ابتدا subGrid: true باید اضافه شود تا ستونی با ردیف‌های + دار، ظاهر شود. اینبار توسط روال رویدادگردان subGridRowExpanded، کنترل نمایش subgrid را در دست گرفته و آن‌را با یک jqGrid جایگزین می‌کنیم.
امضای متد grid1RowExpanded، شامل id یک div است که گرید جدید در آن قرار خواهد گرفت، به همراه Id ردیفی که اطلاعات زیرگرید آن نیاز است از سرور واکشی شود.
بر مبنای subGridId، مانند قبل، یک جدول و یک div را برای نمایش jgGrid و pager آن به صفحه به صورت پویا اضافه می‌کنیم.
سپس تعاریف jqGrid آن مانند قبل است و  نکته‌ی خاصی ندارد. بدیهی است گرید جدید نیز می‌تواند در صورت نیاز یک subgrid دیگر داشته باشد.
در اینجا تنها نکته‌ی مهم آن نحوه‌ی ارسال اطلاعات rowId به سرور است. اکشن متدی که قرار است اطلاعات زیر گرید را تامین کند، یک چنین امضایی دارد:
   public ActionResult GetOrderDetails(int id, JqGridRequest request)
بنابراین نیاز است که به نحوی rowId را به آن ارسال کرد. مشکل اینجا است که Url.Action یک کد سمت سرور است و rowId یک متغیر سمت کاربر. نمی‌توان این متغیر را در کدهای Razor مستقیما قرار داد. اما می‌توان یک محل جایگزینی را در کدهای سمت سرور پیش بینی کرد. مثلا js-id. زمانیکه این رشته در صفحه رندر می‌شود، به صورت معمول و به کمک متد replace جاوا اسکریپت، js-id آن‌را با rowId جایگزین می‌کنیم. به این ترتیب امکان تزریق اطلاعات سمت کاربر به خروجی سمت سرور Razor میسر می‌شود.


کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید:
jqGrid12.zip
مطالب
5 قابلیت برتر جدید در ASP.NET Web API 2
ASP.NET Web API 2 بهمراه یک سری قابلیت جدید جالب منتشر شده است. در این پست 5 قابلیت برتر از این قابلیت‌های جدید را بررسی می‌کنیم.


1. Attribute Routing

در کنار سیستم routing فعلی، ASP.NET Web API 2 حالا از Attribute Routing هم پشتیبانی می‌کند. در مورد سیستم routing فعلی، می‌توانیم قالب‌های متعددی برای routing بنویسیم. هنگامی که یک درخواست به سرور میرسد، کنترلر مناسب انتخاب شده و اکشن متد مناسب فراخوانی می‌شود.
در لیست زیر قالب پیش فرض routing در Web API را مشاهده می‌کنید.
Config.Routes.MapHttpRoute(
     name: "DefaultApi",
     routeTemplate: "api/{Controller}/{id}",
     defaults: new { id = RouteParameter.Optional }
);
این رویکرد routing مزایای خود را دارد. از جلمه اینکه تمام مسیرها در یک مکان واحد تعریف می‌شوند، اما تنها برای الگوهایی مشخص. مثلا پشتیبانی از nested routing روی یک کنترلر مشکل می‌شود.
در ASP.NET Web API 2 به سادگی می‌توانیم الگوی URI ذکرد شده را پشتیبانی کنیم. لیست زیر نمونه ای از یک الگوی URI با AttributeRouting را نشان می‌دهد.
URI Pattern --> books/1/authors

[Route("books/{bookId}/authors")]
public IEnumerable<Author> GetAuthorByBook(int bookId) { ..... }

2. CORS - Cross Origin Resource Sharing

بصورت نرمال، مرورگرها اجازه درخواست‌های cross-domain را نمی‌دهند، که بخاطر same-origin policy است. خوب، (CORS (Cross Origin Resource Sharing چیست؟
CORS یک مکانیزم است که به صفحات وب این را اجازه می‌دهد تا یک درخواست آژاکسی (Ajax Request) به دامنه ای دیگر ارسال کنند. دامنه ای به غیر از دامنه ای که صفحه وب را رندر کرده است. CORS با استاندارد‌های W3C سازگار است و حالا ASP.NET Web API در نسخه 2 خود از آن پشتیبانی می‌کند.

3. OWIN (Open Web Interface for .NET) self-hosting

ASP.NET Web API 2 بهمراه یک پکیج عرضه می‌شود، که Microsoft.AspNet.WebApi.OwinSelfHost نام دارد.
طبق گفته وب سایت http://owin.org :
OWIN یک اینترفیس استاندارد بین سرور‌های دات نت و اپلیکیشن‌های وب تعریف می‌کند. هدف این اینترفیس جداسازی (decoupling) سرور و اپلیکیشن است. تشویق به توسعه ماژول‌های ساده برای توسعه اپلیکیشن‌های وب دات نت. و بعنوان یک استاندارد باز (open standard) اکوسیستم نرم افزار‌های متن باز را تحریک کند تا ابزار توسعه اپلیکیشن‌های وب دات نت توسعه یابند.
بنابراین طبق گفته‌های بالا، OWIN گزینه ای ایده آل برای میزبانی اپلیکیشن‌های وب روی پروسس هایی به غیر از پروسس IIS است. پیاده سازی‌های دیگری از OWIN نیز وجود دارند، مانند Giacomo، Kayak,Firefly و غیره. اما Katana گزینه توصیه شده برای سرور‌های مایکروسافت و فریم ورک‌های Web API است.


4. IHttpActionResult

در کنار دو روش موجود فعلی برای ساختن response اکشن متد‌ها در کنترلر ها، ASP.NET Web API 2 حالا از مدل جدیدی هم پشتیبانی می‌کند.
IHttpResponseMessage یک اینترفیس است که بعنوان یک فاکتوری (factory) برای HttpResponseMessage کار می‌کند. این روش بسیار قدرتمند است بدلیل اینکه web api را گسترش می‌دهد. با استفاده از این رویکرد، می‌توانیم response هایی با هر نوع دلخواه بسازیم.
برای اطلاعات بیشتر به how to serve HTML with IHTTPActionResult مراجعه کنید.


5. Web API OData

پروتکل (OData (Open Data Protocol در واقع یک پروتکل وب برای کوئری گرفتن و بروز رسانی داده‌ها است. ASP.NET Web API 2 پشتیبانی از expand, $select$ و value$ را اضافه کرده است. با استفاده از این امکانات، می‌توانیم نحوه معرفی پاسخ سرور را کنترل کنیم، یعنی representation دریافتی از سرور را می‌توانید سفارشی کنید.
  • expand$: بصورت نرمال، هنگام کوئری گرفتن از یک کالکشن OData، پاسخ سرور موجودیت‌های مرتبط (related entities) را شامل نمی‌شود. با استفاده از expand$ می‌توانیم موجودیت‌های مرتبط را بصورت inline در پاسخ سرور دریافت کنیم.
  • select$: از این متد برای انتخاب چند خاصیت بخصوص از پاسخ سرور استفاده می‌شود، بجای آنکه تمام خاصیت‌ها بارگذاری شوند.
  • value$: با این متد مقدار خام (raw) فیلد‌ها را بدست می‌آورید، بجای دریافت آنها در فرمت OData.


چند مقاله خوب دیگر

مطالب
آشنایی با ساختار 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 را در مقاله بعدی بررسی خواهیم کرد. 
مسیرراه‌ها
ASP.NET MVC
              مطالب
              Microsoft Test Manager - قسمت سوم

              در کنار کاربرگ contents کاربرگی با نام  Propertiesوجود دارد که می‌توانید یک سری تنظیمات را برای plan خود انجام دهید. این تنظیمات از قبیل تغییر عنوان plan، تعیین مسیر پروژه، تاریخ شروع و پایان، کاربری که مالک این plan است، وضعیت جاری تست‌های plan و تعیین مرورگر و ویندوز نیز می‌باشد که می‌توانید در تصویر زیر آن را مشاهده کنید. 

              اگر در لیست کشویی مربوط به test settings مقدار <default> قرار داشت می‌توانید با انتخاب آیتم new از لیست settings جدیدی را ایجاد نمایید و یا می‌توانید لیست test settings هایی را که قبلا ایجاد کرده اید انتخاب نمایید و برای ویرایش آن با کلیک بر روی لینک open که کنار لیست قرار دارد، می‌توانید تنظیمات را ویرایش نمایید.

              همانطور که در تصویر بالا مشاهده می‌کنید، در سمت چپ، بخش هایی برای انجام تنظیمات مربوط به تست وجود دارد. در قسمت general تنظیماتی از قبیل عنوان test settings، شرح و نوع اجرای دستی یا اتومات بودن تستتان وجود دارد. در بخش roles می‌توانید نقش هایی را برای این تست انتخاب نمایید و در قسمت data and diagnostics می‌توانید یک سری اطلاعاتی را که می‌خواهید در زمان تست دریافت کنید، انتخاب کنید. برای اطلاعات بیشتر در مورد این بخش می‌توانید در سایت مایکروسافت مطالعه کنید.

              حالا بر می‌گردیم به بخش contents و موارد تست خود را می‌سازیم. همانطور که در تصویر پایین مشاهده می‌کنید در بخش contents و در سمت راست پنجره یک گزینه ای به نام configuration وجود دارد.

              در configuration شما می‌توانید یک سری تنظیمات مربوط به test شما است انجام دهید مثلا نوع مرورگری که می‌خواهید تست خود را اجرا کنید و یا اولویت تست را مشخص نمایید یا حتی نوع سیستم عامل را مشخص کنید. هم چنین می‌توانید چندین configuration تعریف کنید و از هر کدام برای یک test suite استفاده کنید. به صورت پیش فرض test suite از تنظیمات config والد خودش یعنی test plan استفاده می‌کند.

              دوباره برمی گردیم به بخش contents و می‌خواهیم یک test suite با استفاده از add requirements بسازیم. همانطور که در بخش‌های قبل توضیح دادم می‌توانیم به چند روش test suite بسازیم که یکی از آن‌ها همین add requirements بود که می‌توانستید از test suite هایی که قبلا ساخته اید به این پروژه تستتان اضافه کنید.

              با انتخاب گزینه add requirements پنجره ای باز می‌شود که می‌توانید همه test suite‌ها را مشاهده کنید و حتی می‌توانید براساس عنوان و یا وضعیت تست و ... فیلتر کنید.

              بعد از اینکه در قسمت بالا کوئری خود را تنظیم کردید با انتخاب گزینه run می‌توانید کوئری خود را اجرا کرده و لیست test suite‌ها را براساس آن کوئری فیلتر کنید. می‌توانید یک یا چند سطر را انتخاب کرده و با زدن دکمه add requirements to plan آن‌ها را به plan خود اضافه نمایید. حالا ما یک test suite با استفاده از test suite هایی که قبلا ساخته ایم ایجاد کردیم. حالا باید مورد تست‌های مان را به این test suite اضافه کنیم. در سمت راست با کلیک بر روی گزینه add پنجره ای مشابه پنجره بالا باز می‌شود که شما می‌توانید test case‌ها را فیلتر کنید و یک یا چند مورد را انتخاب کرده و با زدن دکمه add test cases آن‌ها را به test suite تان اضافه کنید. برای اضافه کردن مورد تست جدید هم می‌توانید با کلیک بر روی new که در کنار گزینه Add قرار دارد مورد تست جدیدی را بسازید.

              در تصویر زیر می‌توانید بخش‌های مختلف تست را که در بخش‌های قبل هم توضیح دادم ببینید.

              مطالب
              xamarin.android قسمت اول
              در ابتدای کار تشکر و سپاس از استاد دانشمند و پر مایه‌ام جناب مهندس رضا محمد پور که از محضر پر فیض تدریسشان، بهره‌ها برده‌ام.  
              هدف از این سری آشنایی با زامارین اندروید میباشدکه آشنایی با سی شارپ پیش نیاز آن میباشد و ورژن ویژوال استودیو 2017 من در حال حاضر 15.7.4 می‌باشد.
               اولین پروژه را با زامارین شروع میکنیم. طبق معمول بعد از نصب ویژوال استودیو از گزینه File گزینه New Project را انتخاب میکنیم.

              در ورژن‌های قبلی ویژوال استودیو، در زمان بارگذاری پروژه، احتیاجی به اجرای نرم افزار‌های تحریم گذر نبود؛ همانند ورژن 15.6. ولی در این ورژن که من نصب کردم بدلیل نصب خودکار کتابخانه‌های متریال دیزاین، باید از این گونه نرم افزار‌ها نیز استفاده کرد.

              درقسمت بعدی گزینه BlankApp را انتخاب و در قسمت Minimum Android Version که با انتخاب آن میتوانیم ورژن گوشی‌های اندروید برای استفاده از این اپلیکیشن را انتخاب نماییم. به عنوان مثال با انتخاب اندروید 4.4 برنامه ما صرفا برای گوشی‌های اندورید 4.4 به بالا جواب میدهد. بعد از تایید، پروژه باز شده که با این solution روبرو میشویم.

              - قسمت Properties را اگر بازکنیم، با دو گزینه روبرو میشویم که یکی فایل android manifest هست و اگر روی properties آن کلیک و ویژگی‌هایی را انتخاب کنیم، بطور خودکار بر روی manifest تاثیر میگذارند. در قسمت‌های بعد در این رابطه جداگانه بحث خواهیم کرد.

              - در قسمت Asset که به معنای منابع اندروید می‌باشد، به عنوان مثال صفحات Razor، فونت و یا صفحات HTML و یا عکس و یا ... را می‌توانیم قرار دهیم.

              - در قسمت Resource که پوشه‌های آن layout ،mipmap ،values و resource.designer میباشند، در پوشه layout می‌توانیم صفحات استاندارد اندروید را شروع به طراحی کنیم. درقسمت mipmap عکس‌ها و یا فایل‌های xml ایی را که قرار است استفاده کنیم، در پروژه قرار میدهیم. در قسمت value که بیشتر برای انتخاب و تغییر تم یا استفاده از Resource‌ها (همانند Asp.mvc که استفاده میکردیم) است که البته با ساختاری متفاوت در اندروید از آن‌ها استفاده میکنیم، قرار میگیرند.

              - در قسمت Resource.Designer که در مطالب بعد با آن آشنا خواهید شد، تمامی آیتم‌های انتخابی از جمله Layout ها  و عکس‌ها و... با ذخیره کردن در این قسمت دخیره میشوند که بعد با رفرنس دادن از طریق resource پروژه میتوانیم از عکس‌ها و لی‌آوت‌ها در کد نویسی استفاده کنیم.

              - در انتها جهت معرفی به mainactivity می‌رسیم که یک صفحه است شامل المنت‌ها و اجزای مختلف و کاربر میتواند با آن ارتباط برقرار کند. 

                [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
                  public class MainActivity : AppCompatActivity
                  {
                      protected override void OnCreate(Bundle savedInstanceState)
                      {
                          base.OnCreate(savedInstanceState);
                          // Set our view from the "main" layout resource
                          SetContentView(Resource.Layout.activity_main);
                      }
                  }  
                همانطور که مشاهده میکنید اکتیویتی ما از AppCompatactivity ارث بری کرده، همانند ارث بری که در mvc از controller‌ها داشتیم. در قسمت Attribute که به نام اکتیویتی تعریف شده است، برچسب یا همان Lable را که در زمان اجرا به نام اکتیویتی می‌دهد، مشاهده می‌کنید. در قسمت تم، میتوان تمی را که برای آن از قبل نوشته شده‌است و به یک اکتیویتی اختصاص داد، قرار داد. در ضمن این نکته را یاد آوری کنم زمانیکه اکتیویتی ما از Appcompatactivity ارث بری میکند، انتخاب تم اجباری میباشد.

              - در گزینه بعدی Mainluncher را میبینیم که تعیین کننده‌ی نقطه شروع اکتیویتی ما در بین اکتیویتی‌های دیگر می‌باشد.


              بدیهی است درایور‌های مربوطه به گوشی اندروید را باید تهیه کرد که در سایت مربوط به سازنده و یا در سایت‌های دیگر میتوانید دانلود کنید.  اولین برنامه را می‌نویسیم که هدف از آن، اجرای 10 دکمه بصورت داینامیک هست و اینکه با کلیک بر روی هر کدام از دکمه‌ها، رنگ آن آبی شود.

                protected override void OnCreate(Bundle savedInstanceState)
                      {
                          base.OnCreate(savedInstanceState);
                          LinearLayout ln;
                          Button btn;
                          // Set our view from the "main" layout resource
                          SetContentView(Resource.Layout.activity_main);
                          for (int i = 0; i < 5; i++)
                          {
                           btn = new Button(this);
                           btn.Text = i.ToString();
                           ln= FindViewById<LinearLayout>(Resource.Id.linearLayout1);
                           btn.Click += Btn_Click;
                           ln.AddView(btn);
                          }
                      }
                      private void Btn_Click(object sender, System.EventArgs e)
                      {
                          Button btntest = sender as Button; 
                          btntest.SetBackgroundColor(Android.Graphics.Color.Blue);
                      }
                  }
              در قسمت تعریف دکمه منظور از This این می‌باشد که این دکمه برای اکتیویتی جاری است و Findview by id که می‌بینید، من در قسمت لی‌آوت activity main، یک LinearLayout و یک Id را قرار داده ام که البته id باید منحصر بفرد باشد و با findviewbyid آی‌دی linearlayout را که قرار داده‌ام، پیدا و استفاده کردم که کد‌های آن را در زیر میتوانید مشاهده کنید.
              <?xml version="1.0" encoding="utf-8"?>
              <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:app="http://schemas.android.com/apk/res-auto"
                  xmlns:tools="http://schemas.android.com/tools"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:minWidth="25px"
                  android:minHeight="25px">
                  <LinearLayout
                      android:orientation="vertical"
                      android:minWidth="25px"
                      android:minHeight="25px"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:id="@+id/linearLayout1" />
              </RelativeLayout>
              اکنون اولین برنامه را می‌تونید تست و اجرا کنید: AppTrainng-1.zip
              نظرات مطالب
              تبدیل html به pdf با کیفیت بالا
              من می‌خواهم در یک وب سایت که یک اپلیکیشن است یک سری گزارش تهیه بکنم سناریو به این صورت است که ابتدا درون وب سایت گزارش را نمایش می‌دهیم و اگر کاربر خواست می‌تواند اون گزارش رو به فرمت PDF دانلود کند. برای این سناریو به نظر شما از چه چیزی استفاده کنم؟

              ممنونم