مطالب
پلاگین جستجو با jquery و twitter bootstrap
در این مطلب با نحوه استفاده از پلاگین جستجوی سفارشی searchboxmvc.js آشنا خواهید شد. 

قبلاً در اینجا با نحوه ایجاد پلاگین jQuey آشنا شدید. روشی دیگری نیز برای ایجاد این نوع پلاگین‌ها وجود دارد و آن استفاده از widget factory موجود در پلاگین jQuery UI می‌باشد. 
برای استفاده از این پلاگین که کدهای کامل آن در فایل پیوست موجود است، ابتدا باید فایل‌های لازم را به پروژه خود اضافه کنیم:
    <link rel="stylesheet" href="@Url.Content("~/Content/bootstrap-rtl.css")" type="text/css" />
    <script type="text/javascript" src="@Url.Content("~/scripts/jquery-2.0.2.min.js")"></script>
    <script type="text/javascript" src="@Url.Content("~/scripts/jquery-ui-1.10.3.min.js")"></script>
    <script type="text/javascript" src="@Url.Content("~/scripts/bootstrap-rtl.js")"></script>
    <script type="text/javascript" src="@Url.Content("~/scripts/searchboxmvc.js")"></script>
سپس در کنترلر خود یک Action بصورت زیر ایجاد کنید:
 [HttpPost]
        public virtual ActionResult LoadData(string fieldName, string value, string stringFilterMode = "startWith")
        {
            Thread.Sleep(2000);
            var models = MakePersons();
            if (fieldName == "Id")
            {
                models = models.Where(p => p.Id == int.Parse(value)).Take(1).ToList();
            }
            else if (fieldName == "FirstName")
            {
                models = models.Where(p => p.FirstName.StartsWith(value)).ToList();
            }

            return Json(new { Status = "OK", Records = models });
        }
        private List<Person> MakePersons()
        {
            var lst = new List<Person>();
            lst.Add(new Person() { Id = 1, Code = "Uytffs-098", FirstName = "احمدرضا", LastName = "عابدزاده" });
            lst.Add(new Person() { Id = 2, Code = "fTuuuw-652", FirstName = "کریم", LastName = "باقری" });
            lst.Add(new Person() { Id = 3, Code = "Lopapo-123", FirstName = "خداداد", LastName = "عزیزی" });
            lst.Add(new Person() { Id = 4, Code = "Utppq-981", FirstName = "علی", LastName = "دایی" });
            lst.Add(new Person() { Id = 5, Code = "zttsn-471", FirstName = "علی", LastName = "کریمی" });
            lst.Add(new Person() { Id = 6, Code = "poiud-901", FirstName = "مهدی", LastName = "مهدوی کیا" });
            lst.Add(new Person() { Id = 7, Code = "wqrPoP-391", FirstName = "علیرضا", LastName = "منصوریان" });
            return lst;
        }
در ادامه در ویوی مورد نظر خود یک div ایجاد کنید. همین div خام با اعمال پلاگین بر روی آن ، بصورت یک پلاگین جستجو عمل خواهد کرد.
حال کدهای جاوا اسکریپت مورد نظر را برای اعمال پلاگین و تنظیمات موردنیاز آن به div ایجاد شده می‌نویسیم:
...
<div id="div_SearchBoxContainer">
</div>
...
@section scripts{
    <script type="text/javascript">
        $("#div_SearchBoxContainer").searchboxmvc({
            loadUrl: '@Url.Action(actionName: "LoadData", controllerName: "Home")',
            defaultStringFilterMode: "startWith",
            loadDataOnLeave: true,
            displayClass: "",
            displayNoResultClass: "",
            display: function (element, record) {
                $(element).html(record.FirstName + "  " + record.LastName);
            },
            listItemsDisplay: function (element, record, index) {
                return record.LastName + " " + record.FirstName + "(" + record.Code + ")";
            },
            fields: [
                {
                    fieldName: "Id",
                    fieldTitle: "شناسه",
                    width: 100,
                    defaultValueField: true
                },
                {
                    fieldName: "FirstName",
                    fieldTitle: "نام",
                    width: 200,
                    defaultDisplayField: true,
                    filter: true,
                    isStringType: true
                },
                {
                    fieldName: "LastName",
                    fieldTitle: "نام خانوادگی",
                    filter: false,
                    isStringType: true
                }
            ]
        });
    </script>
}

شرح پارامترهای افزونه searchboxmvc.js 
loadUrl : آدرس اکشن متدی است که بصورت ajax ای فراخوانی شده و نتایج حاصل را بازگشت میدهد.
 نتایج حاصله باید با فرمت json بازگشت داده شوند. اگر نتایج موفقیت باشد باید بصورت  ({Json(new { Status = "OK", Records = models بازگشت داده شوند و اگر خطایی در این بین صورت گرفت مقدار Status نباید مقدار OK باشد.
پارامترهای مورد نیاز این اکشن نیز باید به ترتیب با نام های fieldName و value باشند که fieldName نام فیلدی است که جستجو بر اساس آن صورت می‌گیرد و value همان مقدار وارد شده توسط کاربر است. 
defaultStringFilterMode : اگر فیلد مورد جستجو از نوع رشته ای باشد (یعنی isStringType  آن برابر true باشد) آنگاه پارامتر سوم اکشن متد بطور خودکار مقداردهی خواهد شد. مقادیر این خاصیت میتواند startWith  یا contains و یا equal باشد.
loadDataOnLeave : اگر برابر false باشد، هربار که متن input تغییر کرد بلافاصله یک تقاضا برای یافتن مقادیر به سرور فرستاده میشود و نیازی نیست که فوکوس از کنترل خارج شود.
displayClass : نام کلاس css است که به div 3 اعمال خواهد شد.
displayNoResultClass : در صورتیکه جستجو نتیجه ای نداشته باشد این کلاس به div 3 اعمال خواهد شد.
display : یک فانکشن که برای ایجاد خروجی html برای نمایش در div 3 بکار می‌رود.
listItemsDisplay : یک فانکشن که برای ایجاد خروجی html برای آیتم‌ها بکار می‌رود.
fields : یک آرایه از فیلدهای موردنیاز پلاگین .
خاصیت‌های فیلد نیز بصورت زیر است:
fieldName : نام فیلد
fieldTitle : عنوان فیلد
defaultValueField : فیلد پیش فرض که جستجو بر اساس آن صورت می‌گیرد. اگر تعیین نشود فیلد اول آرایه به عنوان فیلد پیش فرض انتخاب خواهد شد.
defaultDisplayField : فیلد پیش فرض که برای نمایش متن div 3 بکار می‌رود(البته اگر پارامتر display تعیین نشود)
filter : اگر برابر true باشد این فیلد در لیست فیلدهای جستجو خواهد آمد و کاربر می‌تواند بر اساس آن جستجو انجام دهد.
isStringType : اگر برابر true باشد ، پارامتر سوم اکشن متد بطور خودکار مقداردهی خواهد شد.
لازم به ذکر است که این پلاگین کامل نیست و فقط برای ارائه مثال اینجا آورده شده است. هر یک از دوستان می‌توانند محتوای پلاگین را به سلیقه خود تغییر داده و پلاگین را کاملتر کنند.
sample_mvc.zip
مطالب
آشنایی با CLR: قسمت بیست و پنجم
یکی از مهمترین خصوصیات CLR این است که نوع‌ها، ایمن هستند و همواره می‌داند که هر شیء از چه نوعی است. برای اثبات این ادعا می‌توانید متد GetType را صدا بزنید تا به شما بگوید این شیء از چه نوعی است. متد GetType قابلیت رونویسی ندارد و به همین علت می‌توانید مطمئن باشید که خروجی برگشتی دستکاری نشده است.
یکی از نیازهای طراحان این است که مرتبا نیاز به تبدیل نوع‌ها را به یکدیگر دارند. CLR به شما اجازه می‌دهد که هر آبجکتی را به نوع مربوط به خودش یا والدینش تبدیل کنید. بسته به زبانی که انتخاب می‌کنید، این تبدیل شکل متفاوتی دارد و در سی شارپ نیاز به سینتکس خاصی نیست.
سی شارپ برای تبدیل یک شیء به نوع‌های والدش، نیازی به ذکر نوع ندارد ولی اگر قرار است از سمت والد به سمت فرزند Cast شود نیاز است که صریحا نوع آن را اعلام کنید. در این روش اگر نوع تبدیلات با شیء ما سازگاری نداشته باشد، در زمان اجرا، با خطای
 InvalidCastExceptio
 روبرو خواهید شد. کد زیر نمونه‌ای از این تبدیلات است:
internal class Employee {
...
}    
public sealed class Program {
     public static void Main() {
        // بدون ذکر نام والد تبدیل صورت میگیرد
        Object o = new Employee();

      // برای تبدیل والد به یکی از مشتقات آن نیاز است
        // نوع آن به طور صریح ذکر گردد
         // در بعضی زبان‌های مثل ویژوال بیسیک نیازی به ذکر آن نیست
        Employee e = (Employee) o;
     }
  }

استفاده از کلمات as و is در تبدیلات
یکی دیگر از روش‌های امن برای cast کردن اشیاء، استفاده از کلمه‌ی کلیدی is هست. این عبارت چک می‌کند که آیا شیء مورد نظر، از نوع تبدیلی ما پشتیبانی می‌کند یا خیر؛ اگر true بازگرداند به این معنی است که پشتیبانی می‌شود و در حین cast کردن با خطایی روبرو نمی‌شویم.
Object o = new Object();
  Boolean b1 = (o is Object);   // b1 is true.
  Boolean b2 = (o is Employee); // b2 is false.
پی نوشت :در این بررسی اگر شیء نال باشد، مقدار برگشتی همیشه false است. چون به هیچ نوعی قابل تبدیل نیست.
نحوه‌ی استفاده‌ی از کلمه کلیدی is در این تبدیل به شکل زیر است:
if (o is Employee) 
{     
         Employee e = (Employee) o;
}
کد بالا با اینکه ایمنی بیشتری دارد، ولی از نظر کارآیی هزینه بر است. دلیل آن هم این است که عمل تاییدیه، در دو مرتبه انجام می‌شود: اولین مرحله‌ی تایید، استفاده از عبارت is است تا بررسی کند آیا این شیء قابل تبدیل به نوع مورد نظر است یا خیر. دومین بررسی هم در حین تبدیل یا Cast کردن اتفاق می‌افتد که خود این تبدیل هم، همانطور که در بالا اشاره کردیم، بررسی‌هایی برای تبدیل دارد.

برای بهبود کد بالا، سی شارپ کلمه‌ی کلیدی as را ارائه می‌کند. کلمه کلیدی as باعث می‌شود اگر شیء به آن نوع قابل تبدیل باشد، ارجاعی صورت بگیرد؛ در غیر این صورت مقدار نال بازگشت داده می‌شود. شاید شما بگویید که در خط بعدی ما نیز دوباره مجددا یک عبارت شرطی داریم و دوباره داریم عمل تاییدیه را انجام می‌دهیم. ولی باید گفت این if به مراتب هزینه‌ی کمتری نسبت به بررسی‌های تبدیل یا Cast به شیوه‌ی بالاست.
Employee e = o as Employee;
  if (e != null) {
     .....
  }

فضاهای نام و اسمبلی ها
همانطور که مطلع هستید، فضاهای نام به ما این اجازه را می‌دهند تا نوع‌ها را به صورت منطقی گروه بندی کنیم تا دسترسی به آنان راحت‌تر باشد. برای مثال مطمئنا با نگاه به اسم فضای نام
System.Text
متوجه می‌شویم که داخل آن، نوع‌های متفاوتی برای کار با رشته‌ها وجود دارد. برای دسترسی به یک نوع، ابتدا باید از فضاهای نام آن شروع کرد و به شیوه‌ی زیر، به نوع‌ها دسترسی پیدا کرد:
public sealed class Program {
     public static void Main() {
        System.IO.FileStream fs = new System.IO.FileStream(...);
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
     }
  }
احتمالا متوجه‌ی شلوغی و طولانی شدن بی جهت کدها شده‌اید. برای رفع این مشکل، هر زبان شیوه‌ای را می‌تواند بکار بگیرد که سی شارپ از کلمه‌ی کلیدی Using و مثلا ویژوال بیسیک از کلمه‌ی کلیدی Import و ... استفاده می‌کنند و حال می‌توانیم کد بالا را خلاصه‌تر و منظم‌تر بنویسیم:
using System.IO;    // Try prepending "System.IO." 
 using System.Text;  // Try prepending "System.Text." 
  
public sealed class Program {
     public static void Main() {
        FileStream fs = new FileStream(...); 
       StringBuilder sb = new StringBuilder();
     }
  }

موقعیکه شما نوعی را در یک فضای نام استفاده می‌کنید، این نوع به ترتیب بررسی می‌کند که نوع، در کدام فضای نام و کدام اسمبلی مورد استفاده قرار گرفته است. این اسمبلی‌ها شامل FCL و اسمبلی‌های خارجی است که به آن لینک کرده‌اید. حال ممکن است این سؤال پیش بیاید که ممکن است نام دو نوع، در دو فضای نام متفاوت، یکی باشد و در یک جا مورد استفاده قرار گرفته‌اند. چگونه می‌توان تشخیص داد که کدام نوع، متعلق به دیگری است؟ نظر مایکروسافت این است که تا می‌توانید سعی کنید از اسامی متفاوت استفاده کنید. ولی در بعضی شرایط این مورد ممکن نیست. به همین علت باید هر دو کلاس یا به طور کامل، به همراه فضای نام نوشته شوند؛ یا اینکه یکی از آن‌ها بدین شکل باشد و فضای نام نوع دیگر، با using صدا زده شود.
در مثال زیر ما دو نوع را با نام Widget داریم که در دو فضای نام Microsoft و Dotnettips وجود دارند:
using Microsoft; 
using Dotnettips ;
public sealed class Program {
     public static void Main() {
        Widget w = new Widget();// An ambiguous reference
     } 
 }
در کد بالا به دلیل اینکه مشخص نیست نوعی که مدنظر شماست، کدام است، با خطای زیر روبرو می‌شوید:
 'Widget' is an ambiguous reference between 'Microsoft.Widget' and 'Dotnettips.Widget
به همین علت کد را به شکل زیر تغییر می‌دهیم:
using Microsoft; 
using Dotnettips;
   
public sealed class Program {
     public static void Main() {
        Dotnettips.Widget w = new Dotnettips.Widget(); // Not ambiguous
     }
  }
یا بدین صورت:
using Microsoft; 
using Dotnettips;
using DotnettipsWidget = Dotnettips.Widget;   

public sealed class Program {
     public static void Main() {
        DotnettipsWidget w = new DotnettipsWidget (); // No error now
     }
  }
حال بیایید تصور کنیم که فضای‌های نام هم یکسان شده‌اند. مثلا شرکتی به اسم Australian Boomerang Company و شرکت دیگری به اسم Alaskan Boat Corporation یک اسمبلی با نام Widget را تولید کرده اند و تحت فضای نام ABC منتشر کرده‌اند.با اینکه مایکروسافت سفارش زیادی کرده است که از نام کامل استفاده شود و مخفف‌ها را مورد استفاده قرار ندهید ولی از اتفاقاتی است که ممکن است رخ بدهد. در این حالت خوشبختانه کمپایلر سی شارپ قابلیتی به نام Extern را معرفی کرده است.
مطالب دوره‌ها
تبدیل روش‌های قدیمی کدنویسی غیرهمزمان به async سی شارپ 5
در قسمت اول این سری، با مدل برنامه نویسی Event based asynchronous pattern ارائه شده از دات نت 2 و همچنین APM یا Asynchronous programming model موجود از نگارش یک دات نت، آشنا شدیم (به آن الگوی IAsyncResult هم گفته می‌شود). نکته‌ی مهم این الگوها، استفاده‌ی گسترده از آن‌ها در کدهای کلاس‌های مختلف دات نت فریم ورک است و برای بسیاری از آن‌ها هنوز async API سازگار با نگارش مبتنی بر Taskهای سی‌شارپ 5 ارائه نشده‌است. هرچند دات نت 4.5 سعی کرده‌است این خلاء را پوشش دهد، برای مثال متد الحاقی DownloadStringTaskAsync را به کلاس WebClient اضافه کرده‌است و امثال آن، اما هنوز بسیاری از کلاس‌های دیگر دات نتی هستند که معادل Task based API ایی برای آن‌ها طراحی نشده‌است. در ادامه قصد داریم بررسی کنیم چگونه می‌توان این الگوهای مختلف قدیمی برنامه نویسی غیرهمزمان را با استفاده از روش‌های جدیدتر ارائه شده بکار برد.



نگاشت APM به یک Task

در قسمت اول، نمونه مثالی را از APM، که در آن کار با BeginGetResponse آغاز شده و سپس در callback نهایی توسط EndGetResponse، نتیجه‌ی عملیات به دست می‌آید، مشاهده کردید. در ادامه می‌خواهیم یک محصور کننده‌ی جدید را برای این نوع API قدیمی تهیه کنیم، تا آن‌را به صورت یک Task ارائه دهد.
    public static class ApmWrapper
    {
        public static Task<int> ReadAsync(this Stream stream, byte[] data, int offset, int count)
        {
            return Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, data, offset, count, null);
        }
    }
همانطور که در این مثال مشاهده می‌کنید، یک چنین سناریوهایی در TPL یا کتابخانه‌ی Task parallel library پیش بینی شده‌اند. در اینجا یک محصور کننده برای متدهای BeginRead و EndRead کلاس Stream دات نت ارائه شده‌است. به عمد نیز به صورت یک متد الحاقی تهیه شده‌است تا در حین استفاده از آن اینطور به نظر برسد که واقعا کلاس Stream دارای یک چنین متد Async ایی است. مابقی کار توسط متد Task.Factory.FromAsync انجام می‌شود. متد FromAsync دارای امضاهای متعددی است تا اکثر حالات APM را پوشش دهد.
در مثال فوق BeginRead و EndRead استفاده شده از نوع delegate هستند. چون خروجی EndRead از نوع int است، خروجی متد نیز از نوع Task of int تعیین شده‌است. همچنین سه پارامتر ابتدایی BeginRead ، دقیقا data، offset و count هستند. دو پارامتر آخر آن callback و state نام دارند. پارامتر callback توسط متد FromAsync فراهم می‌شود و state نیز در اینجا null درنظر گرفته شده‌است.
یک مثال استفاده از آن‌را در ادامه مشاهده می‌کنید:
using System;
using System.IO;
using System.Threading.Tasks;

namespace Async06
{
    public static class ApmWrapper
    {
        public static Task<int> ReadAsync(this Stream stream, byte[] data, int offset, int count)
        {
            return Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, data, offset, count, null);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var stream = File.OpenRead(@"..\..\program.cs"))
            {
                var data = new byte[10000];
                var task = stream.ReadAsync(data, 0, data.Length);
                Console.WriteLine("Read bytes: {0}", task.Result);
            }
        }
    }
}
File.OpenRead، خروجی از نوع استریم دارد. سپس متد الحاقی ReadAsync بر روی آن فراخوانی شده‌است و نهایتا تعداد بایت خوانده شده نمایش داده می‌شود.
البته همانطور که پیشتر نیز عنوان شد، استفاده از خاصیت Result، اجرای کد را بجای غیرهمزمان بودن، به حالت همزمان تبدیل می‌کند.
در اینجا چون خروجی متد ReadAsync یک Task است، می‌توان از متد ContinueWith نیز بر روی آن جهت دریافت نتیجه استفاده کرد:
using (var stream = File.OpenRead(@"..\..\program.cs"))
{
    var data = new byte[10000];
    var task = stream.ReadAsync(data, 0, data.Length);
    task.ContinueWith(t => Console.WriteLine("Read bytes: {0}", t.Result)).Wait();
}


یک نکته
پروژه‌ی سورس بازی به نام Async Generator در GitHub، سعی کرده‌است برای ساده سازی نوشتن محصور کننده‌های مبتنی بر Task روش APM، یک Code generator تولید کند. فایل‌های آن‌را از آدرس ذیل می‌توانید دریافت کنید:

نگاشت EAP به یک Task

نمونه‌ای از Event based asynchronous pattern یا EAP را در قسمت اول، زمانیکه روال رخدادگردان webClient.DownloadStringCompleted را بررسی کردیم، مشاهده نمودید. کار کردن با آن نسبت به APM بسیار ساده‌تر است و نتیجه‌ی نهایی عملیات غیرهمزمان را در یک روال رخدادگران، در اختیار استفاده کننده قرار می‌دهد. همچنین در روش EAP، اطلاعات در همان Synchronization Context ایی که عملیات شروع شده‌است، بازگشت داده می‌شود. به این ترتیب اگر آغاز کار در ترد UI باشد، نتیجه نیز در همان ترد دریافت خواهد شد. به این ترتیب دیگر نگران دسترسی به مقدار آن در کارهای UI نخواهیم بود؛ اما در APM چنین ضمانتی وجود ندارد.
متاسفانه TPL همانند روش FromAsync معرفی شده در ابتدای بحث، راه حل توکاری را برای محصور سازی متدهای روش EAP ارائه نداده‌است. اما با استفاده از امکانات TaskCompletionSource آن می‌توان چنین کاری را انجام داد. در ادامه سعی خواهیم کرد همان متد الحاقی توکار DownloadStringTaskAsync ارائه شده در دات نت 4.5 را از صفر بازنویسی کنیم.
    public static class WebClientExtensions
    {
        public static Task<string> DownloadTextTaskAsync(this WebClient web, string url)
        {
            var tcs = new TaskCompletionSource<string>();

            DownloadStringCompletedEventHandler handler = null;
            handler = (sender, args) =>
            {
                web.DownloadStringCompleted -= handler;

                if (args.Cancelled)
                {
                    tcs.SetCanceled();
                }
                else if(args.Error!=null)
                {
                    tcs.SetException(args.Error);
                }
                else
                {
                    tcs.SetResult(args.Result);
                }
            };

            web.DownloadStringCompleted += handler;
            web.DownloadStringAsync(new Uri(url));

            return tcs.Task;
        }
    }
روش انجام کار را در اینجا ملاحظه می‌کنید. ابتدا باید تعاریف delaget مرتبط با رخدادگردان Completed اضافه شوند. یکبار += را ملاحظه می‌کنید و بار دوم -= را. مورد دوم جهت آزاد سازی منابع و جلوگیری از نشتی حافظه‌ی ‌روال رخدادگردان هنوز متصل، ضروری است.
سپس از TaskCompletionSource برای تبدیل این عملیات به یک Task کمک می‌گیریم. اگر args.Cancelled مساوی true باشد، یعنی عملیات دریافت فایل لغو شده‌است. بنابراین متد SetCanceled منبع Task ایجاد شده را فراخوانی خواهیم کرد. این مورد استثنایی را در کدهای فراخوان سبب می‌شود. به همین دلیل بررسی خطا با یک if else پس از آن انجام شده‌است. برای بازگشت خطای دریافت شده از متد SetException و برای بازگشت نتیجه‌ی واقعی دریافتی، از متد SetResult می‌توان استفاده کرد.
به این ترتیب متد الحاقی غیرهمزمان جدیدی را به نام DownloadTextTaskAsync برای محصور سازی متد EAP ایی به نام DownloadStringAsync و همچنین رخدادگران آن تهیه کردیم.
اشتراک‌ها
نمایش لیست کشورها به همراه پرچم آنها به صورت dropdown با استفاده از select2
بعد از دانلود و افزودن  select2 ، برای پرچم‌ها سراغ semantic-ui  می‌رویم و بعد از دانلود آن، فایل flag.min.css در آدرس Semantic-Ui/components/flag.min.css را به پروژه اضافه می‌کنیم.
<div>
    <div>
        <select ></select>
    </div>
</div>

 $(document).ready(function () {

            $('.js-example-basic-single').select2({
                data: [
                    { id: "al", text: "Albania" },
                    { id: "dz", text: "Algeria" },
                    { id: "as", text: "American Samoa" },
                    { id: "ad", text: "Andorra" },
                    { id: "ao", text: "Angola" },
                    { id: "ai", text: "Anguilla" },
                    { id: "ag", text: "Antigua" },
                    { id: "ar", text: "Argentina" },
                    { id: "am", text: "Armenia" },
                    { id: "aw", text: "Aruba" },
                    { id: "au", text: "Australia" },
                    { id: "at", text: "Austria" },
                    { id: "az", text: "Azerbaijan" },
                    { id: "bs", text: "Bahamas" },
                    { id: "bh", text: "Bahrain" },
                    { id: "bd", text: "Bangladesh" },
                    { id: "bb", text: "Barbados" },
                    { id: "by", text: "Belarus" },
                    { id: "be", text: "Belgium" },
                    { id: "bz", text: "Belize" },
                    { id: "bj", text: "Benin" },
                    { id: "bm", text: "Bermuda" },
                    { id: "bt", text: "Bhutan" },
                    { id: "bo", text: "Bolivia" },
                    { id: "ba", text: "Bosnia" },
                    { id: "bw", text: "Botswana" },
                    { id: "bv", text: "Bouvet Island" },
                    { id: "br", text: "Brazil" },
                    { id: "vg", text: "British Virgin Islands" },
                    { id: "bn", text: "Brunei" },
                    { id: "bg", text: "Bulgaria" },
                    { id: "bf", text: "Burkina Faso" },
                    { id: "mm", text: "Burma" },
                    { id: "bi", text: "Burundi" },
                    { id: "tc", text: "Caicos Islands" },
                    { id: "kh", text: "Cambodia" },
                    { id: "cm", text: "Cameroon" },
                    { id: "ca", text: "Canada" },
                    { id: "cv", text: "Cape Verde" },
                    { id: "ky", text: "Cayman Islands" },
                    { id: "cf", text: "Central African Republic" },
                    { id: "td", text: "Chad" },
                    { id: "cl", text: "Chile" },
                    { id: "cn", text: "China" },
                    { id: "cx", text: "Christmas Island" },
                    { id: "cc", text: "Cocos Islands" },
                    { id: "co", text: "Colombia" },
                    { id: "km", text: "Comoros" },
                    { id: "cg", text: "Congo Brazzaville" },
                    { id: "cd", text: "Congo" },
                    { id: "ck", text: "Cook Islands" },
                    { id: "cr", text: "Costa Rica" },
                    { id: "ci", text: "Cote Divoire" },
                    { id: "hr", text: "Croatia" },
                    { id: "cu", text: "Cuba" },
                    { id: "cy", text: "Cyprus" },
                    { id: "cz", text: "Czech Republic" },
                    { id: "dk", text: "Denmark" },
                    { id: "dj", text: "Djibouti" },
                    { id: "dm", text: "Dominica" },
                    { id: "do", text: "Dominican Republic" },
                    { id: "ec", text: "Ecuador" },
                    { id: "eg", text: "Egypt" },
                    { id: "sv", text: "El Salvador" },
                    { id: "gb", text: "England" },
                    { id: "gq", text: "Equatorial Guinea" },
                    { id: "er", text: "Eritrea" },
                    { id: "ee", text: "Estonia" },
                    { id: "et", text: "Ethiopia" },
                    { id: "eu", text: "European Union" },
                    { id: "fk", text: "Falkland Islands" },
                    { id: "fo", text: "Faroe Islands" },
                    { id: "fj", text: "Fiji" },
                    { id: "fi", text: "Finland" },
                    { id: "fr", text: "France" },
                    { id: "gf", text: "French Guiana" },
                    { id: "pf", text: "French Polynesia" },
                    { id: "tf", text: "French Territories" },
                    { id: "ga", text: "Gabon" },
                    { id: "gm", text: "Gambia" },
                    { id: "ge", text: "Georgia" },
                    { id: "de", text: "Germany" },
                    { id: "gh", text: "Ghana" },
                    { id: "gi", text: "Gibraltar" },
                    { id: "gr", text: "Greece" },
                    { id: "gl", text: "Greenland" },
                    { id: "gd", text: "Grenada" },
                    { id: "gp", text: "Guadeloupe" },
                    { id: "gu", text: "Guam" },
                    { id: "gt", text: "Guatemala" },
                    { id: "gw", text: "Guinea-Bissau" },
                    { id: "gn", text: "Guinea" },
                    { id: "gy", text: "Guyana" },
                    { id: "ht", text: "Haiti" },
                    { id: "hm", text: "Heard Island" },
                    { id: "hn", text: "Honduras" },
                    { id: "hk", text: "Hong Kong" },
                    { id: "hu", text: "Hungary" },
                    { id: "is", text: "Iceland" },
                    { id: "in", text: "India" },
                    { id: "io", text: "Indian Ocean Territory" },
                    { id: "id", text: "Indonesia" },
                    { id: "ir", text: "Iran" },
                    { id: "iq", text: "Iraq" },
                    { id: "ie", text: "Ireland" },
                    { id: "il", text: "Israel" },
                    { id: "it", text: "Italy" },
                    { id: "jm", text: "Jamaica" },
                    { id: "jp", text: "Japan" },
                    { id: "jo", text: "Jordan" },
                    { id: "kz", text: "Kazakhstan" },
                    { id: "ke", text: "Kenya" },
                    { id: "ki", text: "Kiribati" },
                    { id: "kw", text: "Kuwait" },
                    { id: "kg", text: "Kyrgyzstan" },
                    { id: "la", text: "Laos" },
                    { id: "lv", text: "Latvia" },
                    { id: "lb", text: "Lebanon" },
                    { id: "ls", text: "Lesotho" },
                    { id: "lr", text: "Liberia" },
                    { id: "ly", text: "Libya" },
                    { id: "li", text: "Liechtenstein" },
                    { id: "lt", text: "Lithuania" },
                    { id: "lu", text: "Luxembourg" },
                    { id: "mo", text: "Macau" },
                    { id: "mk", text: "Macedonia" },
                    { id: "mg", text: "Madagascar" },
                    { id: "mw", text: "Malawi" },
                    { id: "my", text: "Malaysia" },
                    { id: "mv", text: "Maldives" },
                    { id: "ml", text: "Mali" },
                    { id: "mt", text: "Malta" },
                    { id: "mh", text: "Marshall Islands" },
                    { id: "mq", text: "Martinique" },
                    { id: "mr", text: "Mauritania" },
                    { id: "mu", text: "Mauritius" },
                    { id: "yt", text: "Mayotte" },
                    { id: "mx", text: "Mexico" },
                    { id: "fm", text: "Micronesia" },
                    { id: "md", text: "Moldova" },
                    { id: "mc", text: "Monaco" },
                    { id: "mn", text: "Mongolia" },
                    { id: "me", text: "Montenegro" },
                    { id: "ms", text: "Montserrat" },
                    { id: "ma", text: "Morocco" },
                    { id: "mz", text: "Mozambique" },
                    { id: "na", text: "Namibia" },
                    { id: "nr", text: "Nauru" },
                    { id: "np", text: "Nepal" },
                    { id: "an", text: "Netherlands Antilles" },
                    { id: "nl", text: "Netherlands" },
                    { id: "nc", text: "New Caledonia" },
                    { id: "pg", text: "New Guinea" },
                    { id: "nz", text: "New Zealand" },
                    { id: "ni", text: "Nicaragua" },
                    { id: "ne", text: "Niger" },
                    { id: "ng", text: "Nigeria" },
                    { id: "nu", text: "Niue" },
                    { id: "nf", text: "Norfolk Island" },
                    { id: "kp", text: "North Korea" },
                    { id: "mp", text: "Northern Mariana Islands" },
                    { id: "no", text: "Norway" },
                    { id: "om", text: "Oman" },
                    { id: "pk", text: "Pakistan" },
                    { id: "pw", text: "Palau" },
                    { id: "ps", text: "Palestine" },
                    { id: "pa", text: "Panama" },
                    { id: "py", text: "Paraguay" },
                    { id: "pe", text: "Peru" },
                    { id: "ph", text: "Philippines" },
                    { id: "pn", text: "Pitcairn Islands" },
                    { id: "pl", text: "Poland" },
                    { id: "pt", text: "Portugal" },
                    { id: "pr", text: "Puerto Rico" },
                    { id: "qa", text: "Qatar" },
                    { id: "re", text: "Reunion" },
                    { id: "ro", text: "Romania" },
                    { id: "ru", text: "Russia" },
                    { id: "rw", text: "Rwanda" },
                    { id: "sh", text: "Saint Helena" },
                    { id: "kn", text: "Saint Kitts and Nevis" },
                    { id: "lc", text: "Saint Lucia" },
                    { id: "pm", text: "Saint Pierre" },
                    { id: "vc", text: "Saint Vincent" },
                    { id: "ws", text: "Samoa" },
                    { id: "sm", text: "San Marino" },
                    { id: "gs", text: "Sandwich Islands" },
                    { id: "st", text: "Sao Tome" },
                    { id: "sa", text: "Saudi Arabia" },
                    { id: "sn", text: "Senegal" },
                    { id: "cs", text: "Serbia" },
                    { id: "rs", text: "Serbia" },
                    { id: "sc", text: "Seychelles" },
                    { id: "sl", text: "Sierra Leone" },
                    { id: "sg", text: "Singapore" },
                    { id: "sk", text: "Slovakia" },
                    { id: "si", text: "Slovenia" },
                    { id: "sb", text: "Solomon Islands" },
                    { id: "so", text: "Somalia" },
                    { id: "za", text: "South Africa" },
                    { id: "kr", text: "South Korea" },
                    { id: "es", text: "Spain" },
                    { id: "lk", text: "Sri Lanka" },
                    { id: "sd", text: "Sudan" },
                    { id: "sr", text: "Suriname" },
                    { id: "sj", text: "Svalbard" },
                    { id: "sz", text: "Swaziland" },
                    { id: "se", text: "Sweden" },
                    { id: "ch", text: "Switzerland" },
                    { id: "sy", text: "Syria" },
                    { id: "tw", text: "Taiwan" },
                    { id: "tj", text: "Tajikistan" },
                    { id: "tz", text: "Tanzania" },
                    { id: "th", text: "Thailand" },
                    { id: "tl", text: "Timorleste" },
                    { id: "tg", text: "Togo" },
                    { id: "tk", text: "Tokelau" },
                    { id: "to", text: "Tonga" },
                    { id: "tt", text: "Trinidad" },
                    { id: "tn", text: "Tunisia" },
                    { id: "tr", text: "Turkey" },
                    { id: "tm", text: "Turkmenistan" },
                    { id: "tv", text: "Tuvalu" },
                    { id: "ug", text: "Uganda" },
                    { id: "ua", text: "Ukraine" },
                    { id: "ae", text: "United Arab Emirates" },
                    { id: "us", text: "United States" },
                    { id: "uy", text: "Uruguay" },
                    { id: "um", text: "Us Minor Islands" },
                    { id: "vi", text: "Us Virgin Islands" },
                    { id: "uz", text: "Uzbekistan" },
                    { id: "vu", text: "Vanuatu" },
                    { id: "va", text: "Vatican City" },
                    { id: "ve", text: "Venezuela" },
                    { id: "vn", text: "Vietnam" },
                    { id: "wf", text: "Wallis and Futuna" },
                    { id: "eh", text: "Western Sahara" },
                    { id: "ye", text: "Yemen" },
                    { id: "zm", text: "Zambia" },
                    { id: "zw", text: "Zimbabwe" }
                ],
                placeholder: "کشور مورد نظرتان را انتخاب نمایید",
                language: "fa",
                theme: "bootstrap",
                dir: "rtl",
                tokenSeparators: [',', ' '],
                multiple: false,
                templateResult:format,
                templateSelection: format,
                escapeMarkup: function (m) { return m; }
            });

        });
    </script>
در اینجا ما اطلاعات را به صورت دستی وارد کرده ایم. شما می‌توانید این اطلاعات را از سمت سرور دریافت نمایید.
در templateResult و templateSelection شما می‌توانید ساختار مورد نظرتان را پیاده سازی کنید. اولی در لیستی از dropdown به عنوان یک option و دومی وقتی که انتخاب می‌شود.
تابع fotmat به صورت زیر می‌باشد.
 function format(state) {
            var $state = $(
                '<span>' + state.text + ' <i class="' + state.id + ' flag"> ' +
                '</i></span>'
            );
            return $state;
        };

لازم به ذکر است کلاس لازم برای ایجاد  پرچم کشوری مثل ایران با استفاده از Semantic-Ui به صورت زیر می‌باشد.
<i class="ir flag"></i>
و در نهایت خروجی آن به شکل زیر می‌باشد

نمایش لیست کشورها به همراه پرچم آنها به صورت dropdown با استفاده از select2
مطالب
ایجاد سرویس چندلایه‎ی WCF با Entity Framework در قالب پروژه - 1

در این نوشتار که به صورت آموزش تصویری ارائه می‌‏شود؛ یک سرویس WCF در Visual Studio 2013 ایجاد می‌کنم، سپس روش استفاده از آن‏را در یک برنامه ویندوزی آموزش خواهم داد. در اینجا در نظرگرفته شده است که شما افزونه‎ی Resharper را روی ویژوال استودیوی خود نصب دارید. پس در صورتیکه هنوز به سراغ آن نرفته اید درنگ نکنید و واپسین نگارش آن را دانلود کنید.

در این پروژه‌ی ساده در نظر می‎گیریم که دو جدول یکی برای اخبار، شامل عنوان، متن خبر و تاریخ ثبت و دسته بندی و دیگری برای نگهداری دسته‎ها در پایگاه داده داریم و می‏خواهیم سرویس‏های مناسب با این دو جدول را بسازیم. با کد زیر، پایگاه داده‌‏ی dbTest و جدول‌های tblNews و tblCategory در SQL Server 2012 ساخته می‌شود:

USE [master]
GO
/****** Object:  Database [dbMyNews]    Script Date: 2014/01/14 09:46:04 ب.ظ ******/
CREATE DATABASE [dbMyNews]
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'dbMyNews', FILENAME = N'D:\dbMyNews.mdf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'dbMyNews_log', FILENAME = N'D:\dbMyNews_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
USE [dbMyNews]
GO
/****** Object:  Table [dbo].[tblCategory]    Script Date: 2014/01/14 09:46:04 ب.ظ ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tblCategory](
[tblCategoryId] [int] IDENTITY(1,1) NOT NULL,
[CatName] [nvarchar](50) NOT NULL,
[IsDeleted] [bit] NOT NULL,
 CONSTRAINT [PK_tblCategory] PRIMARY KEY CLUSTERED 
(
[tblCategoryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
/****** Object:  Table [dbo].[tblNews]    Script Date: 2014/01/14 09:46:04 ب.ظ ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tblNews](
[tblNewsId] [int] IDENTITY(1,1) NOT NULL,
[tblCategoryId] [int] NOT NULL,
[Title] [nvarchar](50) NOT NULL,
[Description] [nvarchar](max) NOT NULL,
[RegDate] [datetime] NOT NULL,
[IsDeleted] [bit] NULL,
 CONSTRAINT [PK_tblNews] PRIMARY KEY CLUSTERED 
(
[tblNewsId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO
ALTER TABLE [dbo].[tblNews]  WITH CHECK ADD  CONSTRAINT [FK_tblNews_tblCategory] FOREIGN KEY([tblCategoryId])
REFERENCES [dbo].[tblCategory] ([tblCategoryId])
GO
ALTER TABLE [dbo].[tblNews] CHECK CONSTRAINT [FK_tblNews_tblCategory]
GO
USE [master]
GO
ALTER DATABASE [dbMyNews] SET  READ_WRITE 
GO

اکنون Visual Studio 2013 را بازکنید سپس روی گزینه New Project کلیک کنید و برابر با نگاره‌ی زیر عمل کنید:

پروژه MyNewsWCFLibrary در راه حل MyNews ساخته می‌شود. این پروژه به صورت پیش‌گزیده دارای یک کلاس به نام Service و یک interface به نام IService است. هر دو را حذف کنید و سپس روی نام پروژه راست‌کلیک کرده، از منوی بازشده گزینه‌ی Add -> New Item را انتخاب کنید. سپس برابر با نگاره‌ی زیر عمل کنید:

در لایه‎‌ی Service Interface کلیه‎ی روال‌های مورد نیاز برای ارتباط با پایگاه داده را می‎سازیم. پیش از آن باید یک Model برای ارتباط با پایگاه داده ساخته باشیم. برای این کار از پنجره Add New Item و از زیرمجموعه Data، گزینه ADO.NET Entity Data Model را انتخاب کنید و به‌سان زیر پیش روید:

در گام پسین روی دکمه New Connection کلیک کنید و رشته‌ی اتصال به پایگاه داده‌ی dbMyNews را بسازید. سپس همانند تنظیمات نگاره‌ی زیر ادامه دهید:

در گام پسین گزینه‌‎ی Entity Framework 6.0 را برگزینید و روی دکمه‎ی Next کلیک کنید.

در پنجره نشان‎ داده شده، جدول‎های مورد نیاز را همانند نگاره‌ی زیر انتخاب کرده و روی دکمه Finish کلیک کنید:

در پایان مدل ما همانند نگاره‌ی زیر خواهد بود.

در بخش پسین درباره‏ی شیوه‏‌ی دست‎کاری کلاس‎های Entity خواهم نوشت.

نظرات مطالب
کار با Docker بر روی ویندوز - قسمت دوم - نصب Docker
بله. فعال سازی Hyper-V سبب از کار افتادن VirtualBox می‌شود و این دو با هم سازگار نیستند (البته با VMWare مشکلی نیست؛ شخصا این مورد را آزمایش کردم). یک نگارش قدیمی‌تر از Docker برای ویندوز، به نام docker toolbox هم وجود دارد که برای اجرای Linux Containers از خود VirtualBox استفاده می‌کند. این روش مشکلات زیر را به همراه دارد:
- docker toolbox یک پروژه‌ی خاتمه یافته و منسوخ شده‌است و مطلقا ویژگی‌های جدید docker را به همراه ندارد.
- فقط و فقط قابلیت اجرای Linux Containers را دارد. برای اجرای Windows Containers تنها راه حل موجود، روشی است که در مطلب جاری بحث شده‌است؛ یعنی استفاده از برنامه‌های Docker For Windows به همراه Hyper-V.
بنابراین اگر نیاز به کار با Docker For Windows و همچنین Virtual Box را دارید، باید به صورت زیر عمل کنید:
الف) نیاز به اجرای Virtual Box است؛ Hyper-V را توسط اجرای دستور زیر با دسترسی ادمین، غیرفعال کنید:
bcdedit /set hypervisorlaunchtype off
ب) نیاز به اجرای Docker for Windows است؛ Hyper-V را توسط اجرای دستور زیر با دسترسی ادمین، فعال کنید:
bcdedit /set hypervisorlaunchtype auto
هر دو دستور، نیاز به ری‌استارت کردن سیستم را هم دارند؛ چون Hyper-V پیش از فعال شدن کرنل ویندوز شروع به کار می‌کند. Hyper-V ویندوز اصطلاحا  Type 1 hyper-visor است و بر روی سخت افزار هاست اجرا می‌شود. اما Virtual Box یا VMWare متفاوت بوده و Type 2 hosted hyper-visor هستند که بر روی OS اجرا می‌شوند.
نظرات مطالب
مخفی کردن کوئری استرینگ‌ها در ASP.NET MVC توسط امکانات Routing
- بحث مطلب جاری در مورد ASP.NET MVC است و ساز و کار استاندارد آن؛ نه در مورد وب فرم‌ها یا روش‌های سفارشی دیگر. هنگام تعریف مسیر اسکریپت‌ها در MVC اگر از Url.Content و ~ برای ذکر ریشه سایت، استفاده شده باشد، موتور توکار MVC مسیرها را به صورت خودکار اصلاح می‌کند. مثلا:
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
- پیشتر در مورد دیباگ اسکریپت‌های یک سایت مطلبی تهیه شده بود: (^)

الان مرورگر، مسیر اسکریپت‌های شما را از انتهای مسیر یک مطلب دریافت می‌کند نه از ریشه سایت. برای وب فرم‌ها هم روش ذیل وجود دارد:
<script language="javascript" src='<%=ResolveUrl("~/App_Themes/MainTheme/jquery.js")%>' type='text/javascript'></script>
البته در این حالت هدر صفحه باید runat server داشته باشد:
<head runat="server">
و یا از اسکریپت منیجر استفاده کنید:
<asp:ScriptManager ID="ScriptManager1" runat="server">
        <Scripts>
            <asp:ScriptReference Path="~/js/somefile.js" />
        </Scripts>
</asp:ScriptManager>