مطالب
به روز رسانی قالب فایل‌های csproj پروژه‌های قدیمی
اگر شما هم مثل بنده در حال نگه‌داری از یک سیستم قدیمی می‌باشید، به احتمال زیاد همیشه با یک سری مسائل مثل آپدیت پکیج‌ها، اضافه کردن یا حذف کردن فایلی از پروژه، مدیریت وابستگی‌ها، خروجی گرفتن از یک پروژه کنسول و ... درگیر هستید؛ مسائلی که سال‌هاست با روی کار آمدن «دات نت کور» و پس از آن «دات نت ۵» حل شده‌است. این حجم از مشکلات به حدی بود که گاهاً کدنویسی را با مشکل مواجه می‌کرد و امروز تصمیم گرفتم این مشکل را برای پروژه شرکت حل کنم. ابتدا باید بگویم، یک نسخه‌ی پشتیبان از کد خود تهیه کنید؛ چرا که زیاد به آن رجوع خواهید داشت.

انجام این آپدیت از طریق دو نرم‌افزار  upgrade-assistant و try-convert قابل انجام است. بنده به شخصه از upgrade-assistant استفاده کردم چرا که به نظر به بلوغ بیشتری رسیده‌است. ابتدا با دستور زیر این نرم‌افزار را نصب کنید:
dotnet tool install -g upgrade-assistant
اگر پیغامی دریافت میکنید مبتنی بر این که این نرم‌افزار قبلاً نصب شده، با دستور زیر از به‌روز بودن آن اطمینان حاصل کنید:
dotnet tool update -g upgrade-assistant

توجه داشته باشید، نرم‌افزار upgrade-assistant برای ارتقاء پروژه‌ها به دات نت 5 و 6 طراحی شده‌اند. بنابراین ما فقط با سه مرحله‌ی اول سر و کار داریم:
  • Back up project
  • Convert project file to SDK style
  • Clean up NuGet package references 

حال یک terminal را باز کنید و به محل پروژه بروید و دستور زیر را اجرا کنید:
upgrade-assistant upgrade MyProject.csproj
در دستور بالا، کلمه‌ی MyProject را با نام پروژه‌ی خود جایگزین کنید. پس از اجرای این دستور، مراحل ۱ تا ۳ را که پیش‌تر در مورد آن توضیح داده شد، اجرا کنید. توجه داشته باشید که اگر solution شما از بیش از یک پروژه تشکیل شده، برای هر پروژه به‌طور جداگانه‌ای باید این عمل تکرار شود. حال اگر فایل csproj پروژه را ببینید، متوجه آن می‌شوید که پروژه به ساختار جدید درآمده است.
  • اگر پروژه از جنس Library باشد، فایل csproj را به شکل زیر درآورید: 
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net472</TargetFramework>
        <OutputType>Library</OutputType>
    </PropertyGroup>
.
.
.
</Project>

  • اگر پروژه از جنس Console باشد، فایل csproj را به شکل زیر درآورید:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<OutputType>Exe</OutputType>
<ApplicationIcon>logo.ico</ApplicationIcon>
<AppConfig>App.config</AppConfig>
</PropertyGroup>
.
.
.
</Project>

  • اگر پروژه از جنس Web باشد، فایل csproj را به شکل زیر درآورید. احتمالاً پیچیده‌ترین و سخت‌ترین فایل‌ها، متعلق به پروژه‌های وب باشد. اگر دقت کنید نوع SDK از نوع MSBuild.SDK.SystemWeb می‌باشد. نسخه این SDK ممکن است در زمانیکه شما در حال خواندن این مطلب می‌باشد آپدیت شده باشد و بهتر است قبل از استفاده، آخرین نسخه را از نیوگت برداشت کنید. (باید ذکر کنم که این hack کوچک را از یک comment  در issueهای گیت‌هاب پیدا کردم.)
<Project Sdk="MSBuild.SDK.SystemWeb/4.0.54">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net472</TargetFramework>
<AppConfig>Web.config</AppConfig>
</PropertyGroup>
.
.
.
</Project>
مطالب
ایجاد ابزارهای سراسری ویژه NET Core.
از زمان ارائه نگارش net core 2.1.، ابزارهای سراسری (Global tools) نیز معرفی شدند. استفاده از این ابزارها در محیط cli در جهت آسان‌تر شدن و سریعتر شدن وظایف، صورت می‌پذیرد. net core sdk. مربوطه، تمامی امکانات لازم از جهت ایجاد، حذف و به روزرسانی ابزارها را از طریق nuget شامل می‌گردد. تعداد بسیار زیادی از این ابزارها در حال حاضر ایجاد شده‌اند که در لیست زیر، تعدادی از آن‌ها را معرفی میکنیم و سپس به نحوه‌ی ایجاد این نوع ابزارها میپردازیم.
  • dotnet-ignore : این ابزار جهت دریافت فایل‌های gitignore. کاربرد داشته و از یک مخزن عمومی گیت هاب جهت دریافت این فایل‌ها استفاده میکند. این مخزن شامل انواع قالب‌های gitignore در پروژه‌های متفاوت میباشد. با استفاده از این ابزار، ایجاد فایل gitignore راحت‌تر و سریعتر امکانپذیر میباشد.
  • dotnet-serve : میزبانی و نمایش لیست فایل‌های استاتیک محلی و اجرای آن‌ها را در بستر http، فراهم مینماید.
  • dotnet-cleanup : جهت پاکسازی محیط بیلد مانند دایرکتوری‌های bin و obj میباشد. همان کار گزینه clean در منوی بیلد را بازی میکند.
  • dotnet-warp : این ابزار در واقع پروژه Warp است که برای ایجاد یک تک فایل اجرایی جهت انتقال راحت‌تر فایل پروژه صورت میگیرد که همه وابستگی‌های آن در همان تک فایل قرار میگیرد.
  • Amazon.ECS.Tools Amazon.ElasticBeanstalk.Tools  و  Amazon.Lambda.Tools  : این ابزارها که به صورت رسمی از طرف آمازون ارائه شده‌اند که جهت deploy شدن راحت‌تر پروژه به محیط‌های توسعه وب آمازون مورد استفاده قرار میگیرند.
جهت مشاهده لیست کامل این ابزارها، به این مخزن گیت هاب مراجعه نمایید. نام ابزار و همچنین لینک‌ها و توضیحات هر کدام، در این مخزن موجود است. همچنین جهت اضافه شدن ابزاری که در لیست نیست، از طریق ایجاد issue یا pull request لیست را به روزرسانی نمایید.

نحوه‌ی نصب، حذف و به روزرسانی ابزارهای سراسری
جهت نصب یک ابزار، از دستور زیر استفاده میکنیم:
dotnet tool install -g dotnet-ignore
سوییچ g به معنای نصب سراسری ابزار و افزوده شدن آن به متغیرهای محیطی PATH میباشد که به راحتی در هر مسیری از محیط کنسول در دسترس خواهد بود و به مسیر dotnet/tools/. محدود نخواهد بود.
جهت مشاهده لیست تمامی ابزاهای سراسری نصب شده بر روی سیستم میتوانید از کامند زیر استفاده نمایید:
dotnet tool list -g
نحوه به روزرسانی ابزار و ارتقا آن به آخرین نسخه پایدار، با دستور زیر میباشد:
dotnet tool update -g dotnet-ignore
دستور حذف:
dotnet tool uninstall -g dotnet-ignore

ایجاد یک ابزار سراسری
جهت ساخت یک ابزار سراسری نیاز است تا یک پروژه را از نوع کنسول ایجاد نمایید و سپس به فایل csproj، خطوط زیر را اضافه کنید:
<PropertyGroup>
    <PackAsTool>true</PackAsTool>
    <ToolCommandName>dotnet-mytool</ToolCommandName>
    <PackageOutputPath>./nupkg</PackageOutputPath>
</PropertyGroup>
گزینه PackAsTool، امکان تبدیل فایل اجرایی شما را به یک ابزار سراسری فراهم میکند. دو گزینه بعدی که اختیاری است، به ترتیب شامل نام ابزار سراسری است که در صورت ذکر نشدن نام فایل پروژه، بدون پسوند csproj. میباشد و سومین مورد نیز مسیر قرارگیری فایل ابزار سراسری به عنوان یک بسته nuget میباشد.
جهت ساخته شدن فایل، ابتدا یکبار پروژه را بیلد کرده و پس از اجرای دستور dotnet pack، فایل پکیج در مسیر ذکر شده ساخته میشود و آماده انتقال به مخازن nuget میباشد. جهت تست و اجرای ابزار بر روی سیستم خود قبل از عرضه نهایی نیاز است تا با دستور زیر آن را بر روی سیستم خود نصب و آزمایش نمایید:
dotnet tool install --global --add-source ./nupkg globaltools
سوییچ global که در بالاتر نیز توضیح داده شد، باعث نصب سراسری ابزار میگردد و سوییچ add-source که بعد از آن مسیر فایل ابزار، آمده است، به این معنا است که به صورت موقت، این دایرکتوری یا مسیر را به عنوان مخزن nuget  شناسایی کرده تا امکان یافتن بسته در آن مسیر مهیا گردد و سپس نام پروژه در پایان ذکر میگردد. در آخر جهت اطمینان از نصب میتوانید ابزار را صدا بزنید:
dotnet-mytool
با توجه به اینکه اصل مطلب گفته در رابطه با ایجاد یک ابزار سراسری در اینجا به پایان میرسد، ولی ایجاد یک ابزار خط فرمانی نیازمند یک سری کدنویسی‌ها جهت ایجاد کامندها و سوییچ‌ها و راهنمای مربوط به آن نیز میباشد. بدین جهت کتابخانه زیر را نصب نمایید:
https://www.nuget.org/packages/McMaster.Extensions.CommandLineUtils
این کتابخانه شامل کلاس هایی جهت ایجاد یک ابزار خط فرمانی راحت‌تر میباشد.

ایجاد یک ابزار عمومی جهت یادداشت نویسی
برای استفاده از این کتابخانه، یک پروژه از نوع کنسول را با نام globaltools ایجاد نمایید و کتابخانه‌ی بالا را نصب نمایید. سپس به ازای هر کامند، یک کلاس را ایجاد میکنیم. ابتدا جهت ایجاد کامندی با نام NewNote یک کلاس را به همین نام میسازیم:
[Command(Description="Add a new note")]
    public class NewNote
    {
        [Required]
        [Option(Description="title of note")]
        public string Title{ get; set; }

        [Option(Description="content of note")]
        public string Body{ get; set; }
    }
با مزین کردن کلاس به ویژگی command، این کلاس را یک کامند معرفی کرده و شرحی از کاری که این کامند را انجام میدهد، نیز وارد می‌کنیم. این شرح بعدا در ابزار تولید شده به عنوان متن راهنما به کار می‌رود. سپس پراپرتی‌هایی را که با ویژگی option مزین گشته‌اند، به عنوان سوییچ معرفی میکنیم. همچنین میتوان از DataAnotation‌ها نیز جهت اعتبار سنجی نیز استفاده نمود. 
بعد از ایجاد موارد بالا، نیاز است که اکشنی که باید این کامند را اجرا کند، به آن اضافه کرد. جهت افزودن این اکشن، یک متد را با نام OnExecute، به بدنه این کلاس اضافه می‌کنیم:
[Command(Description="Add a new note")]
    public class NewNote:BaseClass
    {
        [Required]
        [Option(Description="title of note")]
        public string Title{ get; set; }

        [Option(Description="content of note")]
        public string Body{ get; set; }

        public void OnExecute(IConsole console)
        {

            var dir = GetBaseDirectory();
            if(!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            var filePath = Path.Combine(dir, Title + ".txt");
            File.WriteAllText(filePath, Body);
            console.WriteLine("the note is saved");
        }
    }
در پارامتر این متد، یک اینترفیس با نام IConsole جهت ارتباط با محیط کنسول دیده میشود که در پایان عملیات، پیام «یادداشت ذخیره شد» توسط آن چاپ میگردد. کار این متد به طور خلاصه این است که مسیر اجرایی ابزار جاری را دریافت کرده و سپس در یک دایرکتوری با نام notes، برای هر یادداشت یک فایل ایجاد شده و محتوای دریافتی از کاربر داخل آن قرار میگرد و نام هر فایل، موضوع یادداشتی است که کاربر وارد کرده‌است. متد GetBaseDirectory که مسیر ذخیره یادداشت‌ها را بر میگرداند، در کلاس BaseClass با محتوای زیر قرار گرفته است:
public class BaseClass
    {
        protected string GetBaseDirectory(){
            var baseDirectory = Environment.CurrentDirectory;
            return (Path.Combine(baseDirectory, "notes"));
        }
    }

کامند بعدی، لیست یادداشت‌های ثبت شده‌است:
public class List:BaseClass
    {
        [Option(Description="search a phrase in notes title")]
        public string Grep{ get; set; }
        public void OnExecute(IConsole console)
        {
            try
            {
                var baseDirectory = GetBaseDirectory();

                var dir = new DirectoryInfo(baseDirectory);
                var files = dir.GetFiles();
                foreach(var file in files)
                {
                    if(!String.IsNullOrEmpty(Grep) && !file.Name.Contains(Grep))
                        continue;

                    console.WriteLine(Path.GetFileNameWithoutExtension(file.Name));
                }
            }
            catch (Exception e)
            {
                console.WriteLine(e.Message);
            }
        }
    }
کار این کلاس، بازگردانی لیستی از یادداشت‌های ثبت شده است که حاوی سوییچ grep برای فیلتر کردن اسامی یادداشت هاست.
کلاس بعدی show نیز جهت نمایش کلاس بر اساس عنوان یادداشت است:
[Command(Description="show contnet of note")]
    public class Show:BaseClass
    {
        [Required]
        [Option(Description="title of note")]
        public string Title{ get; set; }


        public void OnExecute(IConsole console){
            var baseDirectory = GetBaseDirectory();
            var file = Path.Combine(baseDirectory, Title+".txt");

            if(!File.Exists(file))
            {
                console.WriteLine("The Note NotFound...");
                return;
            }
            console.WriteLine(File.ReadAllText(file));

        }
    }
در صورتیکه یادداشت مورد نظر وجود نداشته باشد، با پیام The Note NotFound کار به پایان میرسد.
بعد از اتمام کامندهای مربوطه، به کلاس program رفته و برای آن نیز ویژگی command را اضافه می‌کنیم و همچنین ویژگی subCommand را جهت معرفی کامندهایی که در برنامه در دسترس کاربر قرار میگیرند، اضافه میکنیم:
    [Command(Description="An Immediate Note Saver")]
    [Subcommand(typeof(NewNote),typeof(List),typeof(Show))]
    class Program
    {
        static int Main(string[] args)
        {
            return CommandLineApplication.Execute<Program>(args);
        }

        public int OnExecute(CommandLineApplication app, IConsole console)
        {
            console.WriteLine("You must specify a subcommand.");
            console.WriteLine();
            app.ShowHelp();
            return 1;
        }
    }
از آنجا که کلاس Program نیز به ویژگی command مزین شده‌است، متد OnExecute را اضافه می‌کنیم. تنها تفاوت این متد با متدهای قبلی، در نوع خروجی آن است که هر مقدار غیر از صفر، به منزله خطا میباشد. در این حالت چون کاربر کامندی را صادر نکرده است، ابتدا به کاربر اجباری بودن کامند را گوشزد کرده و سپس از طریق متد ShowHelp، راهنمای کار با ابزار را به او نشان داده و سپس کد یک را به منزله رخ دادن خطا یا اعلام شرایط غیرعادی بازمیگردانیم. نوع خروجی متد OnExecute در صورتی که void باشد، به معنای مقدار 0 میباشد که در کلاس‌های قبلی از آن استفاده کرده‌ایم.
در نهایت متد Main را نیز به شکل زیر تغییر می‌دهیم:
        static int Main(string[] args)
        {
            return CommandLineApplication.Execute<Program>(args);
        }
تکه کد CommandLineApplication.Execute آرگومان‌های ورودی را دریافت کرده و کامند مورد نظر را شناسایی میکند و همچنین مقدار عددی که از آن جهت return شدن استفاده می‌کند، همان عددهای صفر و غیر صفر میباشد که در بالا توضیح داده شده است.

نمونه استفاده از ابزار نهایی
PS D:\projects\Samples\globaltools> dotnet-notes new-note -t "sample1" -b "this is body"
the note is saved
PS D:\projects\Samples\globaltools> dotnet-notes new-note -t "test1" -b "this is body of another note"
the note is saved
PS D:\projects\Samples\globaltools> dotnet-notes list
sample1
test1
PS D:\projects\Samples\globaltools> dotnet-notes list -g sa
sample1
PS D:\projects\Samples\globaltools> dotnet-notes show -t sample1
this is body
در ابزار بالا کامند new-note به صورت جدا از هم با خط تیره مشخص شده‌است. دلیل این امر نیز جداشدن این کلمات در نام کلاس با حروف بزرگ است. در صورتیکه قصد ندارید نام کامندها با خط تیره از هم جدا شوند، باید نام کلاس را از NewNote به Newnote تغییر دهید.
مطالب
پَرباد - آموزش پیاده‌سازی پرداخت آنلاین در دات نت - مقدمه
پَرباد یک کتابخانه رایگان و اوپن سورس است که امکان افزودن قابلیت پرداخت آنلاین را به وب اپلیکیشن‌ها محیا میکند.

با توجه به نسخه قدیمی و درخواست کاربران جهت ارائه نسخه‌ای برای پشتیبانی از NET Core. ، نسخه‌ی کاملا جدیدی از این پروژه آماده گردید.

مزایا و ویژگی‌ها
  • نصب آسان با استفاده از Nuget
  • بدون نیاز به هیچگونه وب سرویس و یا دانش پیاده سازی سیستم‌های پرداخت آنلاین 
  • پشتیبانی از درگاه‌های: ملت، ملی (سداد)، پارسیان، پاسارگاد، ایران کیش و سامان
  • انجام پرداخت، فقط با نوشتن ۳ خط کد
  • طراحی کاملا یکپارچه برای انجام عملیات پرداخت با تمامی بانک‌ها
  • رعایت نکات امنیتی پرداخت آنلاین
  • درگاه مجازی، برای شبیه سازی عملیات پرداخت 
  • امکان استفاده از پروکسی برای سرور‌های خارج از ایران در صورت نیاز
  • استفاده از تکنولوژی‌های مدرن و استاندارد
  • قابل نصب بر روی پروژه‌های: ASP.NET Core, ASP.NET MVC, ASP.NET WebForms

آنچه شما در این سری مقالات یاد خواهید گرفت:

نحوه نصب
  • ASP.NET WebForms
  • ASP.NET MVC
  • ASP.NET CORE

آموزش پایه
  • درخواست پرداخت
  • تایید پرداخت
  • بازگرداندن مبلغ پرداخت شده

تنظیمات
  • درگاه‌ها
  • HttpContext
  • پایگاه داده
  • پیام‌ها

آموزش پیشرفته
  • ایجاد یک صورت‌حساب پرداخت با استفاده از InvoiceBuilder
  • درگاه مجازی پرداخت
  • استفاده از پروکسی
  • توکن پرداخت
  • تزریق وابستگی
  • Logging

نمونه پروژه‌ها
نحوه نصب
مطالب
ایجاد اعتبار سنجی های شرطی با Foolproof
ابتدا کلاس زیر را در نظر بگیرید:
public class UserVM  
 {
        public string Name { get; set; }
        public bool  Gender { get; set; }
        public string Soldier { get; set; }
    }
قصد داریم یک سری اعتبار سنجی را بر روی خصوصیات کلاس فوق ایجاد کنیم. می‌خواهیم اگر کاربر جنسیت مرد را انتخاب کرد، حتما مقداری برای فیلد محل خدمت خود که در این کلاس Soldier می‌باشد، انتخاب کند. شاید انتخاب اول برای انجام چنین کاری، کنترل کردن آن در سمت کاربر با استفاده از جاوا اسکریپت باشد که می‌بایست یک رویداد را برای چک باکس جنسیت تعریف کنیم و بر اساس اینکه مرد انتخاب شده یا زن، ادامه کار را انجام دهیم.

روش اول: نوشتن یک کلاس سفارشی برای اعتبار سنجی کلاس فوق
public class SoldierValidation : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        UserVM app = value as UserVM ;
        if (app.Gender && app.Soldier.Length==0)
        {
            ErrorMessage = "لطفا محل خدمت را وارد نمایید";

            return false;
        }
        return true;
    }
}
و سپس اعمال به کلاس مورد نظر همانند زیر :
[SoldierValidation ]
   public class UserVM
    {
        public string Name { get; set; }
        public bool  Gender { get; set; }       
        public string Soldier { get; set; }
    }
تا اینجای کار، اگر کاربر از DropDown و یا RadioButton، آقا را انتخاب کرده باشد و View مورد نظر را برای Update و یا Insert ارسال کند، با خطای «لطفا محل خدمت را وارد نمایید» مواجه خواهد شد. تا به اینجا به مقصود مورد نظرمان رسیدیم.

روش دوم
لازم نیست چرخ رو دوباره اختراع کنید (البته در بعضی مواقع لازم است)
استفاده از MVC Foolproof:
ّFoolprof یک سری Annotation هایی را در اختیار شما قرار  می‌دهد که با استفاده از آنها می‌توانید اعتبار سنجی‌های شرطی را انجام دهید؛ دقیقا همانند کاری که در بالا برای آن یک Validation سفارشی نوشتیم. البته Foolproof فقط به این مورد ختم نمی‌شود. در ادامه با چند مورد از آنها آشنا خواهیم شد.

ابتدا از طریق NuGet اقدام به نصب Foolproof نمایید:
PM> Install-Package foolproof
سپس اینبار همان مثال خود را با FoolPfoof انجام می‌دهیم:
   public class UserVM
    {
        public string Name { get; set; }
        public bool  Gender { get; set; }
        [RequiredIfTrue("Gender ")]
        public string Soldier { get; set; }
    }
 با استفاده از RequiredIfTrue دقیقا به همان مقصود خواهیم رسید که از ورودی، اسم فیلدی را می‌گیرد که می‌خواهیم آن را چک کنیم.

حال بپردازیم به چندین Annotation دیگر که در Foolproof وجود دارند:
GreatThan: همانطور که از نام آن پیداست، برای موقعیکه می‌خواهیم این فیلد بزرگتر از فیلد مورد نظرمان باشد:
public class EventViewModel
{
    public string Name { get; set; }
    public DateTime Start { get; set; }

    [Required]
    [GreaterThan("Start")]
    public DateTime End { get; set; }
}
جهت آشنایی بیشتر، در ادامه فقط لیست Annotation‌های موجود در این پکیج قرار داده شده است .
[Is]
[EqualTo]
[NotEqualTo]
[GreaterThan]
[LessThan]
[GreaterThanOrEqualTo]
[LessThanOrEqualTo]
و
[RequiredIf]
[RequiredIfNot]
[RequiredIfTrue]
[RequiredIfFalse]
[RequiredIfEmpty]
[RequiredIfNotEmpty]
[RequiredIfRegExMatch]
[RequiredIfNotRegExMatch]
مطالب
به روز رسانی قسمت assemblyBinding فایل‌های config توسط NuGet
زمانیکه پروژه‌ی شما وابستگی‌های متعددی داشته باشد، احتمال برخوردن به یک چنین خطایی بسیار محتمل است:
 Could not load file or assembly Newtonsoft.Json or one of its dependencies. The system cannot find the file specified.
کتابخانه‌ی Newtonsoft.Json جزو پروژه‌هایی است که مدام به روز رسانی و نگهداری می‌شود. در این بین ممکن است وابستگی A از نگارش 4.5 آن استفاده کند و وابستگی B بر اساس نگارش 4.7 آن کامپایل شده باشد و وابستگی جدیدی از نگارش 6 آن استفاده کند. در یک چنین حالتی زمانیکه پروژه‌ی شما آخرین نگارش JSON.NET را به همراه داشته باشد، وابستگی‌های A و B پیام یافت نشدن نگارش‌های خاص کتابخانه‌ی Newtonsoft.Json را صادر خواهند کرد و در این حالت، برنامه در همان ابتدای کار کرش می‌کند. برای رفع این مشکل می‌توان به دات نت گفت که تمام درخواست‌های مرتبط با JSON.NET را به اسمبلی خاصی هدایت و پردازش کن. به این قابلیت assembly redirects گفته می‌شود و به نحو ذیل در فایل‌های کانفیگ برنامه (app.config یا web.config) قابل تعریف است:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- ... -->
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
به این ترتیب تمام اسمبلی‌هایی که بر اساس نگارش قدیمی JSON.NET کامپایل شده‌اند، باور خواهند کرد که نگارش 6 آن، همان نگارشی است که باید با آن کار کنند.


به روز رسانی قسمت assembly redirects توسط NuGet

البته اگر بسته‌ی جدیدی را توسط نیوگت نصب کنیم، این assembly redirects به صورت خودکار توسط آن اضافه خواهند شد اما ... گاهی ممکن است موارد قدیمی را به روز نکند یا موردی فراموش شوند یا حتی اگر اطلاعاتی را پیشتر از وب یافته‌اید، دارای خطای تایپی باشند. برای یک چنین مواردی اگر با خطای Could not load file or assembly ابتدای بحث مواجه شدید، مراحل ذیل را طی کنید تا بتوانید قسمت assembly redirects را بازسازی کنید:
الف) به فایل config برنامه مراجعه کرده و کلا قسمت assemblyBinding آن‌را حذف کنید.
ب) سپس دستور ذیل را در کنسول پاورشل نیوگت اجرا کنید:
 PM> Get-Project -All | Add-BindingRedirect
این دستور به تمام پروژه‌های موجود در solution جاری مراجعه کرده و قسمت assemblyBinding آن‌ها را بر اساس آخرین اطلاعات پروژه‌ها و وابستگی‌های آن‌ها به روز می‌کند.
مطالب
پیاده سازی کنترلرهای Angular با استفاده از Typescript
پیشتر با ویژگی ها  و نحوه کد نویسی این زبان آشنا شدید. از طرفی دیگر، نحوه تعریف کنترلرها در Angular نیز آموزش داده شد. در این پست قصد دارم طی یک مثال ساده با استفاده از زبان Typescript یک کنترلر Angular را ایجاد  و سپس از آن در یک پروژه Asp.Net MVC استفاده نمایم. از آن جا که به صورت پیش فرض در VS.Net امکانات TypeScript نصب نشده است، برای شروع ابتدا TypeScript را از اینجا دانلود نمایید. بعد از نصب یک پروژه Asp.Net MVC ایجاد نمایید و سپس با استفاده از nuget فایل‌های مربوط به AngularJs  را نصب نمایید. در این پست به تفصیل این مورد بررسی شده است (عملیات BundleConfig فایل‌های مورد نیاز به عهده خودتان). در پوشه scripts یک فولدر به نام app ساخته، سپس یک فایل TypeScript به نام ProductController.ts ایجاد کنید. (بعد از نصب TypeScript گزینه TypeScript File مشاهده خواهد شد)
 

در فایل ProductController.ts کد‌های زیر را کپی نمایید: 

module Product {
    export interface Scope {
        message: string;
    }

    export class Controller {
        constructor($scope: Scope) {
            $scope.message = "Hello from Masoud";
        }
    }
}
توضیح کد‌ها بالا :

ابتدا یک ماژول به نام Product ایجاد می‌کنیم. سپس یک اینترفیس برای پیاده سازی آبجکت Scope که جهت مقید سازی عناصر DOM به آبجکت‌های کنترلر مورد استفاده قرار می‌گیرد، ایجاد می‌کنیم. در داخل این اینترفیس متغیری به نام message از نوع string داریم. قصد داریم این متغیر را به یک  عنصر مقید کنیم. حال یک کلاس به نام کنترلر ایجاد می‌کنیم که در تابع سازنده آن تزریق وابستگی برای scope$ از نوع اینترفیس Scope تعیین شده است. در نتیجه در بدنه سازنده می‌توانیم به متغیر message مقدار مورد نظر را نسبت دهیم .

کلمه کلیدی export برای تعریف عمومی کلاس استفاده شده است .
یک View ایجاد و کد‌های زیر را در آن کپی کنید :

<script type="text/javascript" src="~/scripts/app/ProductController.js"></script>
<div ng-app>
    <div ng-controller="Product.Controller">
        <p>{{message}}</p>
    </div>
</div>

اولین نکته در تگ script است که فراخوانی فایل TypeScript باید با پسوند   js. انجام گیرد. به دلیل اینکه فایل‌های TypeScript بعد از کامپایل تبدیل به فایل‌های JavaScript خواهند شد؛ در نتیجه پسوند آن نیز js. است. دومین نکته در فراخوانی کنترلر مورد نظر است که  از ترکیب نام ماژول و نام کلاس است. بعد از اجرای پروژه خروجی به صورت زیر خواهد بود :

 

مطالب
CSS پویا در ASP.NET MVC
سناریو هایی وجود دارد که نیاز است مشتری ، خود شیوه نامه هایی (CSS) را برای قسمت‌های مختلف سایت انتخاب کند. برای مثال تنظیماتی را برای منوی سایت در نظر گرفته ایم که مشتری بتواند رنگ و قلم و ... را متناسب با سلیقه‌ی خود تغییر دهد و یا یک قسمت کلی برای اعمال شیوه نامه‌ها به سایت ایجاد کرده ایم که در همه‌ی قسمت‌های سایت اعمال شود. بدین شکل در صورتی که مشتری، اطلاعات اندکی هم در مورد CSS داشته باشد میتواند ظاهر سایت خود را به آسانی تغییر دهد و تا حدودی بار را از روی دوش پشتیبان سایت بر میدارد.
و برای همه‌ی این‌ها نیاز است تا فیلدی در دیتابیس برای ذخیره‌ی شیوه نامه‌های مشتری ایجاد شود و یا در یک فایل متنی ذخیره شود که بسته به سیاست برنامه نویس دارد.
در این مطلب تصمیم داریم این سناریو را به صورت ساده در یک پروژه ASP.NET MVC پیاده سازی کنیم.
ایتدا یک پروژه از نوع ASP.NET MVC 4 ایجاد میکنیم. سپس قطعه کد زیر را به فایل  Layout.cshtml_ موجود در مسیر Views/Shared به صورت زیر اضافه میکنیم :
<head>
    @*سایر شیوه نامه‌ها و اسکریپت ها*@
    @RenderSection("styles", required: false)
</head>
RenderSection این امکان را میدهد که ما بتوانیم شیوه نامه‌ی دیگری را در صفحات دیگر به MasterPage خود تزریق کنیم.
سپس کنترلری به نام Home ایجاد میکنیم :
namespace DynamicCssExample.Controllers
{
    public class HomeController : Controller
    {

        public ActionResult Index()
        {
            return View();
        }

        public string GetStyle()
        {
            Response.ContentType = "text/css";
            //در این قسمت میتوانیم به دیتابیس متصل شویم و شیوه نامه‌ی مورد نظر را واکشی کنیم و بازگشت دهیم
            return "h2{color:yellow}";
        }

    }
}
در اینجا یک متد به نام GetStyle داریم که وظیفه‌ی بازگشت یک رشته را بر عهده دارد و نوع این مقدار بازگشتی از نوع text/css است و میتواند شیوه نامه هایی که در دیتابیس و یا یک فایل متنی ذخیره کرده ایم را واکشی و به استریم ارسال کند.
در انتها برای استفاده از این متد کافی است در View مربوطه بدین شکل عمل کنیم :
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@section styles
{
    <link rel="stylesheet" href="@Url.Action("GetStyle", "Home")" type="text/css"/>
}

<h2>Index</h2>
در سکشن Style لینک شیوه نامه ای تعریف کرده ایم که ویژگی href آن به اکشن GetStyle در کنترلر Home اشاره میکند و این اکشن نیز محتوای شیوه نامه را برگشت میدهد.
مطالب
TwitterBootstrapMVC

TwitterBootstrapMVC   یا  به اختصار BMVC  یک کتابخانه از Helper  های مفید برای ساده سازی استفاده از Twitter Bootstrap  در MVC می‌باشد .

در این کتابخانه امکانات مختلف Bootstrap از طریق Helper  های نوشته شده برای MVC براحتی قابل استفاده می‌باشد و فرایند کد نویسی را ساده‌تر و در عین حال خوانا‌تر می‌کند ، Helper  های موجود در این کتابخانه به صورت زنجیره ای  (fluent syntax)   نوشته شده که استفاده از آن را سهولت می‌بخشد .

برای استفاده از آن در mvc 4 کافی است بعد از پیکر بندی Bootstrap  ( راهنمایی)  به کتابخانه TwitterBootstrapMvc رفرنسی ایجاد کنید و با استفاده از این راهنما  نحوه استفاده را فرا گیرید . همچنین می‌توانید آن را از طریق NuGet بارگذاری نمایید .

نسخه‌ی MVC4 آن‌را در اینجا برای شما نیز آپلود نمودم 

در زیر نمونه ای از استفاده از آن را می‌بینید 
@Html.Bootstrap().LabelFor(x => x.UserName)
@Html.Bootstrap().TextBoxFor(m => m.UserName)
@Html.Bootstrap().PasswordFor(m => m.Password)
@Html.Bootstrap().FileFor(m => m.File)
@Html.Bootstrap().CheckBoxFor(m => m.IsActivated)
@Html.Bootstrap().RadioButtonFor(m => m.Gender, "male")
@Html.Bootstrap().DropDownListFor(m => m.State, Model.UsaStates)
@Html.Bootstrap().ListBoxFor(m => m.State, Model.UsaStates)
@Html.Bootstrap().TextAreaFor(m => m.Description)
ایجاد یک فرم
@using (Html.Bootstrap().Begin(new Form().Type(FormType.Inline)))
{
    @Html.Bootstrap().TextBoxFor(m => m.Email).Placeholder("Email")
    @Html.Bootstrap().PasswordFor(m => m.Password).Placeholder("Password")
    @Html.Bootstrap().CheckBoxFor(m => m.RememberMe).Label()
    @Html.Bootstrap().SubmitButton().Text("Sign in")
}
یک فرم  Modal
@Html.Bootstrap().Button().Text("Show Modal").IconAppend(Icons.camera) .TriggerModal("MyModal") 



@using(var modal = Html.Bootstrap().Begin(new Modal()   .Id("MyModal")    .HtmlAttributes(new { @class = "custom-class" })    .Fade() )){
    using(modal.BeginHeader())
    {
        <h2>Some header</h2>
    }
    using(modal.BeginBody())
    {
        <p>Some body<p>
    }
    using(modal.BeginFooter())
    {
        <p>Footer here.<p>
        @Html.Bootstrap().Button().Text("Close")
    }
}

مطالب
استفاده از RequireJs در پروژه های Asp.Net MVC
 در پست قبلی با کلیات RequireJs آشنا شدید. در این به بررسی  و پیاده سازی مثال قبل در قالب یک پروژه Asp.Net MVC می‌پردازم:
ابتدا یک پروژه Asp.Net MVC ایجاد کنید. در فولدر scripts تمام فایل‌های جاوااسکریپ پروژه قرار خواهند داشت. اگر قصد داشته باشیم که فایل‌های جاوااسکریپی سایر فریم ورک‌ها را استفاده نماییم (مثل backbone.js و ExtJs و...) برای طبقه بندی بهتر فایل ها، بهتر است که یک فولدر با نامی مشخص بسازیم و فایل‌های مورد نیاز را در آن قرار دهیم. البته اگر از nuget برای نصب این فریم ورک‌ها استفاده نمایید عموما این کار انجام خواهد شد.
حال با استفاده از Package Manager Console و اجرای دستور زیر، اقدام به نصب requireJs کنید
PM> Install-package requireJs
ساختار فولدر scripts به صورت زیر خواهد شد(دو فایل r.js و require.js به این فولدر اضافه می‌شود)  

 

یک فولدر به نام MyFiles در فولدر Scripts بسازید و فایل‌های purchase.js و product.js و credits.js در پروژه قبل را در آن کپی نمایید. کد فایل‌های پروژه قبل به صورت زیر بوده است:
purchase.js
define(["credits","products"], function(credits,products) {
  console.log("Function : purchaseProduct");
  return {
    purchaseProduct: function() {
      var credit = credits.getCredits();
      if(credit > 0){
        products.reserveProduct();
        alert('purchase done');'
        return true;
 } alert('purchase cancel');   return false; } } });
در کد بالا از یک alert برای نمایش موفقیت یا عدم موفقیت عملیات استفاده کردم.
products.js
define(function(products) {
  return {
    reserveProduct: function() {
      console.log("Function : reserveProduct");
      return true;
    }
  }
});
credits.js
define(function() {
  console.log("Function : getCredits");
  return {
    getCredits: function() {
      var credits = "100";
      return credits;
    }
  }
});
در نتیجه فایل‌های زیر به ساختار فولدر scripts اضافه شده است:


برای قدم بعدی، در متد RegisterBundles فایل bundleConfig پروژه دستور زیر را وارد نمایید:
  bundles.Add( new ScriptBundle( "~/bundles/require" ).Include(
                      "~/Scripts/require.js" ) );
کاملا واضح است که نیاز به تغییر در فایل Layout_  پروژه نیز داریم؛ در نتیجه تغییرات زیر را در فایل اعمال نمایید:



همان طور که مشاهده می‌کنید ابتدا با استفاده از دستور Scripts.Render فایل‌های include شده برای requireJs را در صفحه لود می‌کنید. سپس در تگ scripts که نوشته شده است با استفاده از دستور require.config مکان فایل‌های مورد نیاز را به فریم ورک Require معرفی میکنیم. این بدان معنی است که فریم ورک هر زمان که نیاز به لود یک وابستگی برای فایل‌های جاوااسکریپ داشته باشد، این مکان معرفی شده را جستجو خواهد کرد.
حال برای استفاده و لود ماژول purchase در انتهای فایل Index فولدر Home تغییرات زیر را اعمال نمایید:
@section scripts
{
    <script type="text/javascript">
    require(['purchase'], function (purchase)
    {        
        purchase.purchaseProduct();
    });
</script>
}
در دستورات بالا با کمک دستور require(همان طور که در پست قبلی توضیح داده شد) ماژول purchase را لود می‌کنیم و بعد با فراخوانی تابع purchaseProduct به خروجی مورد نظر خواهیم رسید. در این جا من از دستور alert برای نمایش خروجی استفاده کردم! در نتیجه خروجی به صورت زیر خواهد بود:

 
مطالب
آشنایی و بررسی ابزار Glimpse
در مطلب MiniProfiler ابزار مانیتور کارآیی وب سایت‌ها را بررسی کردیم. اما ابزار Glimpse هم جزو ابزار‌های حرفه‌ای است که در مطلبی آقای هانسلمن در سایت خود به آن پرداخته بودند. اما دیدم جای یک مطلب فارسی در این رابطه خالی است.


Glimpse چیست؟
glimpse یک ابزار حرفه‌ای برای نمایش زمان اجرای کدها، پیکربندی سرور، درخواست‌های وب، اشکال زدایی و بررسی کارآیی وب سایت‌های MVC و Web Forms می‌باشد. البنه بدون آنکه در کد‌های پروژه شما تغییری ایجاد نماید.
ابتدا در پنجره Nuget عبارت glimpse را جستجو و آن را نصب نمایید:


کتابخانه‌های زیادی برای این ابزار آماده شده‌اند:

  • کتابخانه Glimpse Core
    که هسته اصلی ابزار است، حتما باید نصب شود.
  • کتابخانه Glimpse ASP.NET
    برای بررسی وب سایت‌های نوشته شده با ASP.NET Web Forms استفاده می‌شود. البته بری Mvc هم لازم است.
  • کتابخانه Glimpse Mvc2, Glimpse Mvc3، Glimpse Mvc4
    برای بررسی وب سایت‌های نوشته شده با ASP.NET Mvc
  • کتابخانه Glimpse Ado
    برای بررسی و نمایش زمان کوئری بر روی پایگاه داده
  • کتاخانه Glimpse EF4.3، Glimpse EF5، Glimpse EF6
    برای زمانیکه از نگارش‌های مختلف Entity Framework استفاده می‌نماییم
پس از نصب کتابخانه‌های مورد نیاز، پروژه را rebuild و سپس اجرا نمایید. برای فعال کردن glimpse آدرس http://{your-site}/Glimpse.axd را اجرا کنید تا صفحه تنظیمات آن فعال شوند و سپس بر روی گزینه Turn Glimpse on، کلیک کنید. همچنین با گزینه Turn Glimpse off می‌توانید آن را غیر فعال نمایید.

علاوه بر این، تنظیمات استاندارد این ابزار قابل تغییر است.
به صفحه اصلی سایت برگشته و صفحه را بروز رسانی کنید. ابزار glimpse در پایین مرورگر نمایش داده می‌شود.


این ابزار شامل سه قسمت است:
  • HTTP
    اطلاعات Request و زمان پاسخ و اطلاعات سرور نمایش داده می‌شود
  • HOST
    اطلاعات صفحه اجرا شده، زمان پاسخ و تعداد کوئری‌های اجرا شده و زمان آن نمایش داده می‌شوند
  • AJAX
    اطلاعات درخواست‌های اجکسی این صفحه و تعداد آن نمایش داده می‌شوند
بر روی هر یک از این قسمت‌ها با حرکت ماوس، جزئیات آن قسمت نمایش داده می‌شود.

اگر بر روی آیکون g ابزار کلیک کنید، همچون developer tools مرورگر‌ها باز شده و دارای زبانه‌های متعددی می‌باشد. مثلا اگر پلاگین ado و ef5 نصب باشند، در زبانه SQL می‌توانید کوئری‌های اجرا شده و زمان مصرف شده آن‌ها را مشاهده نمایید

زبانه دیگر Timeline است که زمان انقیاد اشیاء و رویدادها را بصورت گرافیکی نمایش می‌دهد.

در مطلب بعدی به جزئیات بیشتری از این ابزار می‌پردازم.