مطالب
PersianDatePicker یک DatePicker شمسی به زبان JavaScript که از تاریخ سرور استفاده می‌کند
PersianDatePicker  یک DatePicker شمسی برای نمایش تاریخ شمسی در صفحات وب است.

مهمترین ویژگیها :
  • از تاریخ سرور برای نمایش روز جاری استفاده می‌کند.
  • به زبان جاوااسکریپت است و نیازی به سایر فریمورک‌ها مانند jQuery ندارد.
  • سبک و کم حجم است (3.5 کیلوبایت)
  • روزها به صورت عمودی لیست شده‌اند مانند برنامه هفتگی مدرسه که کاربران فارسی‌زبان با آن راحت‌ترند.

طرز استفاده :

PersianDatePicker.Show(textBox, today)
textBox : کنترلی است که DatePicker برای آن نمایش داده می‌شود.
today : تاریخ روز جاری است.

برای مثال :
<html>
<head>
    <script type="text/javascript" src="Scripts/PersianDatePicker.min.js"></script>
    <link type="text/css" rel="stylesheet" href="Content/PersianDatePicker.min.css" />
</head>
<body>
    <input type="text" onclick="PersianDatePicker.Show(this, '1392/03/22');" />
</body>
</html>

در ASP.NET Web Forms :
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication4.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/PersianDatePicker.min.js"></script>
    <link href="Content/PersianDatePicker.min.css" rel="stylesheet" />
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Label runat="server" Text="Label" AssociatedControlID="TextBox1">تاریخ : </asp:Label>
            <asp:TextBox  runat="server" ID="TextBox1"></asp:TextBox>
        </div>
    </form>
</body>
</html>

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        var now = PersianDateTime.Now;
        var today = now.ToString(PersianDateTimeFormat.Date);

        TextBox1.Attributes["onclick"] = "PersianDatePicker.Show(this,'" + today + "');";
    }
}

در مثال بالا برای گرفتن تاریخ روز جاری از PersianDateTime استفاده شده است. 

در ASP.NET MVC یا PHP یا هر زبان دیگری کافیست onclick کنترل متنی مورد نظر در سمت سرور مانند مثال بالا مقدار داده شود. یا می‌توان image کوچکی کنار textbox مورد نظر قرار داد و onclick آن تنظیم شود.

برای استفاده از PersianDatePicker می‌توانید آنرا از NuGet دریافت کنید :
PM> Install-Package PersianDatePicker

همچنین یک مثال کامل ASP.NET MVC آن‌را می‌توانید از اینجا دریافت کنید:
MvcAppPersianDatePicker.zip   
نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 2 - بررسی ساختار جدید Solution
از قسمت «یک مثال: فایل جدیدی را به نام bower.json به پروژه‌ی جاری با این محتوا اضافه کنید» شروع کنید به بررسی مجدد. فایل یاد شده را با محتوای JSON ایی که ذکر شده، اضافه کنید. بعد روی گره dependencies کلیک راست کرده و گزینه‌ی restore packages را انتخاب کنید (با فرض اتصال به اینترنت). حتی اضافه شدن این فایل و یا ذخیره شدن مجدد آن هم (Ctrl+S) سبب آغاز کار restore می‌شود.

نظرات اشتراک‌ها
دریافت کتاب Pro ASP.NET MVC 5 Platform
«... سالهاست ASP.NET MVC دیگر وابستگی به ASP.NET ندارد ...»
سورس ASP.NET MVC از اینجا قابل دریافت است. حاصل جستجوی «;using System.Web» در فایل‌های آن به صورت زیر است:
Matching lines: 72    Matching files: 72    Total files searched: 4488
 از VirtualPathUtility ، HttpRequestBase تا HttpUtility ، HttpCookie ، HttpSessionStateBase و HttpPostedFileBase ، PreApplicationStartMethod  و ... خیلی موارد دیگر زیر ساخت آن، در System.Web تعریف شده‌اند.
نظرات مطالب
بررسی روش ارتقاء به NET Core 1.1.
بله به این مورد برخورد کردم اما قبل از اینکه publish صورت گیرد خطای نسخه 1.0 رو دریافت خواهید کرد و باید اصطلاحی که شما فرمودید را اعمال و سپس توزیع کرد.
اما پس از اعمال این مورد هم مشکل برطرف نمیشه.
توزیع بدون فایل Microsoft.AspNetCore.Hosting.dll انجام میشود.
در نسخه قبلی 1.0 هم همینطور بوده که با کپی کردن فایل از مسیر هایی (که در نظر قبلی مشخص کردم ) به مسیر فایل‌های توزیع شده مشکل رفع میشد.
برای مثال فایل هایی مانند :
 Microsoft.AspNetCore.Hosting.Server.Abstractions.dll
Microsoft.AspNetCore.Server.IISIntegration.dll
هم نیاز به کپی در مسیر توزیع فایل‌های پروژه داشتند.
مطالب
WF:Windows Workflow #۶
در این قسمت به تکمیل مثالی که در قسمت قبل زده شد پرداخته می‌شود و همچنین کنترل‌های Foreach , Try Catch نیز بررسی خواهند شد.
در ابتدا دو کلاس به نام‌های ItemInfo و OutOfStockException  را به برنامه اضافه می‌کنیم. کلاس اول برای ذخیره سازی مشخصات هر سفارش و کلاس دیگر برای مدیریت خطا‌ها می‌باشد.
public class ItemInfo
    {
        public string ItemCode { get; set; } 
        public string Description { get; set; } 
        public decimal Price { get; set; }
    }

public class OutOfStockException : Exception
    {
        public OutOfStockException() 
            : base() 
        { 

        }

        public OutOfStockException(string message) 
            : base(message) 
        { 

        }
    }
در Workflow مورد نظر که به نام OrderWF.xaml می‌باشد٬ پس از کنترل Assign که برای صفر کردن مقدار متغیر TotalAmount از آن استفاده می‌شود٬ یک کنترل ForEach را به Flow جاری اضافه می‌کنیم. این کنترل دارای دو خاصیت به نام‌های Type Arguments و Values می‌باشد. اولین خاصیت که مقدار پیش فرض آن، مقدار عددی Int32 است٬ برای مشخص کردن نوع متغییر حلقه و دیگری برای مشخص کردن نوع منبع داده حلقه تعریف شده‌اند.

همانطور که در شکل بالا مشخص می‌باشد٬ Type Arguments حلقه برابر با کلاس OrderItem می‌باشد. Values هم برابر با OrderInfo.Items است. از این جهت نوع حلقه  را از جنس کلاس OrderItem مشخص کرد‌‌ه‌ایم تا کنترل بر روی مقادیر Items اجرا شود (لیستی از کلاس مورد نظر).
حال همانند شکل بالا، در قسمت Body کنترل ForEach، یک کنترل Sequence را ایجاد کرده و سپس برای اینکه کنترل LookupItem را ایجاد کنیم٬ ابتدا باید یک Code Activity را به پروژه اضافه کنیم. به همین منظور پروژه جاری را انتخاب کرده و یک Code Activity به آن اضافه و نام آن را LookupItem  می‌گذاریم. سپس کد زیر را به آن اضافه می‌کنیم:
 public sealed class LookupItem : CodeActivity
    {
        // Define an activity input argument of type string
        public InArgument<string> ItemCode { get; set; }         
        public OutArgument<ItemInfo> Item { get; set; }

        // If your activity returns a value, derive from CodeActivity<TResult>
        // and return the value from the Execute method.
        protected override void Execute(CodeActivityContext context)
        {
            // Obtain the runtime value of the Text input argument
            ItemInfo i = new ItemInfo();             
            i.ItemCode = context.GetValue<string>(ItemCode);
            switch (i.ItemCode)
            {

                case "12345": 
                    i.Description = "Widget"; 
                    i.Price = (decimal)10.0; 
                    break;
                case "12346": 
                    i.Description = "Gadget"; 
                    i.Price = (decimal)15.0; 
                    break;
                case "12347": 
                    i.Description = "Super Gadget"; 
                    i.Price = (decimal)25.0; break;
            }
     
            context.SetValue(this.Item, i);
            
        }
    }
در این کد، دو متغییر تعریف شده‌اند؛ یکی از نوع رشته بوده و از طریق آن، دستور Switch تصمیم می‌گیرد که کلاس ItemInfo را با چه مقادیری پرکند. متغییر دیگر از نوع کلاس  ItemInfo می‌باشد و برای گرفتن مقدار کلاس از دستور Switch تعریف شده است.
حال برای اینکه بتوانیم از Code Activity مورد نظر استفاده کنیم٬ ابتدا باید پروژه را یکبار Build کنیم. اکنون در قسمت Toolbox یک٬ Tab ایی به نام پروژه ایجاد شده است و در آن یک کنترل به نام  LookupItem  موجود می‌باشد. آن را گرفته و به درون Sequence انتقال می‌دهیم.
سپس برای مقدار دادن به متغیر‌های تعریف شده در Code Activity، کنترل LookupItem را انتخاب کرده و در قسمت Properties به خصوصیت ItemCode، کد زیر را اضافه می‌کنیم:
item.ItemCode

نکته
: از کلاس Code Activity برای ارسال و دریافت مقادیر به درون Workflow استفاده می‌شود.

 Try Catch 
از این کنترل برای مدیریت خطا‌ها استفاده می‌شود.
ابتدا یک کنترل Try Catch را به Workflow اضافه کرده، مانند شکل زیر:

در بدنه Try می‌توان از کنترل‌های مورد نظر استفاده کنیم و همانطور که در شکل بالا مشخص است٬ از کنترل Throw برای ایجاد خطا استفاده شده‌است. کنترل جاری را انتخاب کرده و از قسمت Properties در خاصیت Exception کد زیر را اضافه می‌کنیم:
new OutOfStockException("Item Code"+item.ItemCode)
این  دستور باعث ایجاد یک خطا از نوع کلاس OutOfStockException می‌شود. برای کنترل خطای مورد نظر در قسمت Catches مانند شکل زیر عمل می‌کنیم.

بازخوردهای دوره
نگاهی به SignalR Hubs
نصب کنید خوبه؛ ولی ضروری نیست. با نصب از طریق NuGet فقط اسمبلی‌های لازم و فایل‌های لازم اضافه می‌شوند؛ نه قالب‌های VS.NET مرتبط. این قالب‌ها هم ضروری نیستند. مثلا یک کلاس Hub چیزی نیست جز یک کلاس ساده (نمونه‌اش در متن مطلب جاری هست) که از کلاس پایه Hub مشتق می‌شود (این کلاس رو دستی خودتون ایجاد کنید؛ الزامی نیست که ابزار اینکار را برای شما انجام دهد)
مطالب
اعتبارسنجی سرویس های WCF
حالتی را در نظر بگیرید که سرویس‌های یک برنامه در آدرسی مشخص هاست شده اند. اگر اعتبار سنجی برای این سرویس‌ها در نظر گرفته نشود به راحتی می‌توان با در اختیار داشتن آدرس مورد نظر تمام سرویس های  برنامه را فراخوانی کرد و اگر رمزگذاری اطلاعات بر روی سرویس‌ها فعال نشده باشد می‌توان تمام اطلاعات این سرویس‌ها را به راحتی به دست آورد. کمترین تلاش در این مرحله برای پیاده سازی امنیت این است که برای فراخوانی هر سرویس حداقل یک شناسه و رمز عبور چک شود و فقط در صورتی که فراخوانی سرویس همراه با شناسه و رمز عبور درست بود اطلاعات در اختیار کلاینت قرار گیرد. قصد داریم طی یک مثال این مورد را بررسی کنیم:
ابتدا یک پروژه با دو Console Application  با نام های  Service و Client ایجاد کنید. سپس در پروژه Service یک سرویس به نام BookService ایجاد کنید و کد‌های زیر را در آن کپی نمایید:
Contract مربوطه به صورت زیر است:
[ServiceContract]
public interface IBookService
    {
        [OperationContract]
        int GetCountOfBook();
    }
کد‌های مربوط به سرویس:
 [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class BookService : IBookService
    {
        public int GetCountOfBook()
        {
            return 10;
        }
    }
فایل Program در پروژه Service را باز نمایید و کد‌های زیر را که مربوط به hosting سرویس مورد نظر است در آن کپی کنید:
 class Program
    {
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(BookService));

            var binding = new BasicHttpBinding();
            
            host.AddServiceEndpoint(typeof(IBookService), binding, "http://localhost/BookService");
            host.Open();

            Console.Write("BookService host");

            Console.ReadKey();
        }
    }
بر اساس کد‌های بالا، سرویس BookService در آدرس http://localhost/BookService هاست می‌شود.  نوع Binding نیز BasicHttpBinding انتخاب شده است.
حال نوبت به پیاده سازی سمت کلاینت می‌رسد. فایل Program سمت کلاینت را باز کرده و کد‌های زیر را نیز در آن کپی نمایید:
        static void Main(string[] args)
        {
            Thread.Sleep(2000);
            BasicHttpBinding binding = new BasicHttpBinding();

            ChannelFactory<IBookService> channel = new ChannelFactory<IBookService>(binding, new EndpointAddress("http://localhost/BookService"));

            Console.WriteLine("Count of book: {0}", channel.CreateChannel().GetCountOfBook());

            Console.ReadKey();
        }
در کد‌های عملیات ساخت ChannelFactory برای برقراری اطلاعات با سرویس مورد نظر انجام شده است. پروژه را Build نمایید و سپس آن را اجرا کنید.
 خروجی زیر مشاهده می‌شود:

تا اینجا هیچ گونه اعتبار سنجی انجام نشد. برای پیاده سازی اعتبار سنجی باید یک سری تنظیمات بر روی Binding و Hosting  سمت سرور و البته کلاینت بر قرار شود. فایل Program پروزه Service را باز نمایید و محتویات آن را به صورت زیر تغییر دهید:

 static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(BookService));

            var binding = new BasicHttpBinding();
            binding.Security = new BasicHttpSecurity();
            binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

            host.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;

            host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNamePasswordValidator();               

            host.AddServiceEndpoint(typeof(IBookService), binding, "http://localhost/BookService");
            host.Open();


            Console.Write("BookService host");

            Console.ReadKey();
        }
تغییرات اعمال شده:
ابتدا نوع Security در Binding را به حالت TransportCredentialOnly تنظیم کردیم. در یک جمله هیچ گونه تضمینی برای صحت اطلاعات انتقالی در این حالت وجود ندارد و فقط یک اعتبار سنجی اولیه انجام خواهد شد. در نتیجه هنگام استفاده از این حالت باید با دقت عمل نمود و نباید فقط به پیاده سازی این حالت اکتفا کرد.( Encryption اطلاعات سرویس‌ها مورد بحث این پست نیست)
ClientCredentialType نیز باید به حالت Basic تنظیم شود. در WCF اعتبار سنجی به صورت پیش فرض در حالت Windows است (بعنی UserNamePasswordValidationMode برابر مقدار Windows است و اعتبار سنجی بر اساس کاربر انجام می‌شود) . این مورد باید به مقدار Custom تغییر یابد. در انتها نیز باید مدل اعتبار سنجی دلخواه خود را به صورت زیر پیاده سازی کنیم:
در پروژه سرویس یک کلاس به نام CustomUserNamePasswordValidator بسازید و کد‌های زیر را در آن کپی کنید:
 public class CustomUserNamePasswordValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (userName != "Masoud" || password != "Pakdel")
                throw new SecurityException("Incorrect userName or password");
        }
    }
Validator مورد نظر از کلاسی abstract به نام UserNamePasswordValidator  ارث می‌برد، در نتیجه باید متد abstract به نام Validate را override نماید. در بدنه این متد شناسه و رمز عبور با یک مقدار پیش فرض چک می‌شوند و در صورت عدم درستی این پارارمترها یک استثنا پرتاب خواهد شد.

تغییرات مورد نیاز سمت کلاینت:
اگر در این حالت پروژه را اجرا نمایید از آن جا که از این به بعد، درخواست‌ها سمت سرور اعتبار سنجی می‌شوند در نتیجه با خطای زیر روبرو خواهید شد:

این خطا از آن جا ناشی می‌شود که تنظیمات کلاینت و سرور از نظر امنیتی با هم تناسب ندارد. در نتیجه باید تنظیمات Binding کلاینت و سرور یکی شود. برای این کار کد زیر را به فایل Program سمت کلاینت اضافه می‌کنیم:


static void Main(string[] args)
        {
            Thread.Sleep(2000);
            BasicHttpBinding binding = new BasicHttpBinding();

            binding.Security = new BasicHttpSecurity();
            binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;            

            ChannelFactory<IBookService> channel = new ChannelFactory<IBookService>(binding, new EndpointAddress("http://localhost/BookService"));

            channel.Credentials.UserName.UserName = "WrongUserName";
            channel.Credentials.UserName.Password = "WrongPassword";

 Console.WriteLine("Count of book: {0}", channel.CreateChannel().GetCountOfBook()); Console.ReadKey(); }
توسط دستور زیر، مقدار شناسه و رمز عبور به درخواست اضافه می‌شود.
channel.Credentials.UserName.UserName = "WrongUserName";
channel.Credentials.UserName.Password = "WrongPassword";
 در اینجا UserName و Password اشتباه مقدار دهی شده اند تا روش کار Validator مورد بررسی قرار گیرد. حال اگر پروژه را اجرا نمایید خواهید دید که در Validator مورد نظر، عملیات اعتبار سنجی به درستی انجام می‌شود:


دریافت سورس مثال بالا
اشتراک‌ها
نمایش Bread Crumbs در ASP.NET MVC

MvcBreadCrumbs is a NuGet package that allows you to specify custom bread crumb definitions at the controller and route level.  

نمایش Bread Crumbs در ASP.NET MVC