مطالب
نگاشت JSON به کلاس‌های معادل آن

یکی از مواردی که عموما در برنامه نویسی با آن سر و کار داریم، parse اطلاعات با فرمت‌های مختلف است. از CSV تا XML تا ... JSON .
در مورد کار با XML در دات نت فریم ورک، فضاهای نام مرتبط زیادی وجود دارند؛ برای مثال System.Xml.Linq و System.Xml . همچنین یک روش دیگر هم برای کار با اطلاعات XML ایی در دات نت وجود دارد. می‌شود کلاس معادل یک فایل XML را تولید و سپس اطلاعات آن‌را به این کلاس نگاشت کرد. اطلاعات بیشتر : (^). این برنامه کار خود مایکروسافت است.
در مورد JSON از دات نت سه و نیم به بعد کارهایی صورت گرفته مانند : (^). اما آنچنان دلچسب نیست. جهت رفع این خلاء کتابخانه‌ی سورس باز و بسیار کاملی در این زمینه به نام JSON.NET تهیه شده که از این آدرس قابل دریافت است: (^)
و خبر خوب اینکه امکان تهیه کلاس‌های معادل اطلاعات JSON ایی هم مدتی‌است توسط برنامه نویس‌های مستقل تهیه شده است. یا می‌توان از امکانات توکار دات نت استفاده کرد یا از کتابخانه‌‌هایی مانند JSON.NET یا از هیچکدام! می‌توان یک راست کل اطلاعات JSON ایی دریافتی را به یک یا چند کلاس معادل آن نگاشت کرد:
  • و یا یک ابزار آنلاین مشابه: json2csharp

مطالب
انجام پی در پی اعمال Async به کمک Iterators - قسمت اول

تقریبا تمام اعمال کار با شبکه در Silverlight از مدل asynchronous programming پیروی می‌کنند؛ از فراخوانی یک متد وب سرویس تا دریافت اطلاعات از وب و غیره. اگر در سایر فناوری‌های موجود در دات نت فریم ورک برای مثال جهت کار با یک وب سرویس هر دو متد همزمان و غیرهمزمان در اختیار برنامه نویس هستند اما اینجا خیر. اینجا فقط روش‌های غیرهمزمان مرسوم هستند و بس. خیلی هم خوب. یک چارچوب کاری خوب باید روش استفاده‌ی صحیح از کتابخانه‌های موجود را نیز ترویج کند و این مورد حداقل در Silverlight اتفاق افتاده است.
برای مثال فراخوانی‌های زیر را در نظر بگیرید:
private int n1, n2;

private void FirstCall()
{
Service.GetRandomNumber(10, SecondCall);
}

private void SecondCall(int number)
{
n1 = number;
Service.GetRandomNumber(n1, ThirdCall);
}

private void ThirdCall(int number)
{
n2 = number;
// etc
}
عموما در اعمال Async پس از پایان عملیات در تردی دیگر، یک متد فراخوانی می‌گردد که به آن callback delegate نیز گفته می‌شود. برای مثال توسط این سه متد قصد داریم اطلاعاتی را از یک وب سرویس دریافت و استفاده کنیم. ابتدا FirstCall فراخوانی می‌شود. پس از پایان کار آن به صورت خودکار متد SecondCall فراخوانی شده و این متد نیز یک عملیات Async دیگر را شروع کرده و الی آخر. در نهایت قصد داریم توسط مقادیر بازگشت داده شده منطق خاصی را پیاده سازی کنیم. همانطور که مشاهده می‌کنید این اعمال زیبا نیستند! چقدر خوب می‌شد مانند دوران synchronous programming (!) فراخوانی‌های این متدها به صورت ذیل انجام می‌شد:
private void FetchNumbers()
{
int n1 = Service.GetRandomNumber(10);
int n2 = Service.GetRandomNumber(n1);
}
در برنامه نویسی متداول همیشه عادت داریم که اعمال به صورت A –> B –> C انجام شوند. اما در Async programming ممکن است ابتدا C انجام شود، سپس A و بعد B یا هر حالت دیگری صرفنظر از تقدم و تاخر آن‌ها در حین معرفی متدهای مرتبط در یک قطعه کد. همچنین میزان خوانایی این نوع کدنویسی نیز مطلوب نیست. مانند مثال اول ذکر شده، یک عملیات به ظاهر ساده به چندین متد منقطع تقسیم شده است. البته به کمک lambda expressions مثال اول را به شکل زیر نیز می‌توان در طی یک متد ارائه داد اما اگر تعداد فراخوانی‌ها بیشتر بود چطور؟ همچنین آیا استفاده از عدد n2 بلافاصله پس از عبارت ذکر شده مجاز است؟ آیا عملیات واقعا به پایان رسیده و مقدار مطلوب به آن انتساب داده شده است؟
private void FetchNumbers()
{
int n1, n2;

Service.GetRandomNumber(10, result =>
{
n1 = result;
Service.GetRandomNumber(n1, secondResult =>
{
n2 = secondResult;
});
});
}

به عبارتی می‌خواهیم کل اعمال انجام شده در متد FetchNumbers هنوز Async باشند (ترد اصلی برنامه را قفل نکنند) اما پی در پی انجام شوند تا مدیریت آن‌ها ساده‌تر شوند (هر لحظه دقیقا بدانیم که کجا هستیم) و همچنین کدهای تولیدی نیز خواناتر باشند.
روش استانداری که توسط الگوهای برنامه نویسی برای حل این مساله پیشنهاد می‌شود، استفاده از الگوی coroutines است. توسط این الگو می‌توان چندین متد Async را در حالت معلق قرار داده و سپس در هر زمانی که نیاز به آن‌ها بود عملیات آن‌ها را از سر گرفت.
دات نت فریم ورک حالت ویژه‌ای از coroutines را توسط Iterators پشتیبانی می‌کند (از C# 2.0 به بعد) که در ابتدا نیاز است از دیدگاه این مساله مروری بر آن‌ها داشته باشیم. مثال بعد یک enumerator را به همراه yield return ارائه داده است:

using System;
using System.Collections.Generic;
using System.Threading;

namespace CoroutinesSample
{
class Program
{
static void printAll()
{
foreach (int x in integerList())
{
Console.WriteLine(x);
}
}

static IEnumerable<int> integerList()
{
yield return 1;
Thread.Sleep(1000);
yield return 2;
yield return 3;
}

static void Main()
{
printAll();
}
}
}

کامپایلر سی شارپ در عمل یک state machine را برای پیاده سازی این عملیات به صورت خودکار تولید خواهد کرد:

private bool MoveNext()
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
this.<>2__current = 1;
this.<>1__state = 1;
return true;

case 1:
this.<>1__state = -1;
Thread.Sleep(0x3e8);
this.<>2__current = 2;
this.<>1__state = 2;
return true;

case 2:
this.<>1__state = -1;
this.<>2__current = 3;
this.<>1__state = 3;
return true;

case 3:
this.<>1__state = -1;
break;
}
return false;
}

در حین استفاده از یک IEnumerator ابتدا در وضعیت شیء Current آن قرار خواهیم داشت و تا زمانیکه متد MoveNext آن فراخوانی نشود هیچ اتفاق دیگری رخ نخواهد داد. هر بار که متد MoveNext این enumerator فرخوانی گردد (برای مثال توسط یک حلقه‌ی foreach) اجرای متد integerList ادامه خواهد یافت تا به yield return بعدی برسیم (سایر اعمال تعریف شده در حالت تعلیق قرار دارند) و همینطور الی آخر.
از همین قابلیت جهت مدیریت اعمال Async پی در پی نیز می‌توان استفاده کرد. State machine فوق تا پایان اولین عملیات تعریف شده صبر می‌کند تا به yield return برسد. سپس با فراخوانی متد MoveNext به عملیات بعدی رهنمون خواهیم شد. به این صورت دیدگاهی پی در پی از یک سلسه عملیات غیرهمزمان حاصل می‌گردد.

خوب ما الان نیاز به یک کلاس داریم که بتواند enumerator ایی از این دست را به صورت خودکار مرحله به مرحله آن هم پس از پایان واقعی عملیات Async قبلی (یا مرحله‌ی قبلی)، اجرا کند. قبل از اختراع چرخ باید متذکر شد که دیگران اینکار را انجام داده‌اند و کتابخانه‌های رایگان و یا سورس بازی برای این منظور موجود است.


ادامه دارد ...

نظرات مطالب
بررسی تغییرات ASP.NET MVC 5 beta1
- نکات مهم Bootstrap رو ما در سایت جاری بررسی کردیم و الزاما برای استفاده از آن نیازی به MVC5 نیست. همین الان در MVC4 هم می‌تونید ازش استفاده کنید. ولی درکل هر وقت مایکروسافت دست روی چیزی می‌گذارد، مزیتش تهیه حداقل 20 جلد کتاب جدید در مورد CSS و Bootstrap و طراحی است که در نهایت برای دنیای وب، از لحاظ بالا رفتن کیفیت کارهای انجام شده، بسیار مفید خواهد بود.
- در کل این به روز رسانی برای مدیریت و دریافت تغییرات انجام شده اخیر بسیار مناسب خواهد بود (تمام اجزای MVC مانند اسکریپت‌های اعتبارسنجی سازگار با نسخه جدید jQuery، فشرده سازهای CSS و JS، قسمت‌های مرتبط با SignalR و Web API همین Owin ایی که نامبردید، مرتبا به روز می‌شوند). حداقل دیگر نیازی به دریافت چند گیگ به روز رسانی VS 2012 نیست و به یکباره می‌شود تمام آن‌ها را در VS 2013 داشت.
- همچنین با توجه به سورس باز بودن MVC، دنبال کردن History سورس کنترل آن‌ها در جهت مشاهده تغییرات انجام شده ضروری است. یعنی صرفا نباید در منوها یا صفحه دیالوگ‌های جدید به دنبال تغییرات بود. اگر تغییرات سورس کنترل را بررسی کنید مواردی مانند MVC Attribute Routing، رفع تعدادی از باگ‌های Razor parser و تغییرات گسترده‌ای در Web API انجام شده (بیشتر موارد مرتبط به Web API است).
مطالب
توسعه برنامه‌های Cross Platform با Xamarin Forms & Bit Framework - قسمت هشتم
تا اینجا می‌دانیم که View که با Xaml نوشته می‌شود؛ مسئولیت ظاهر صفحات را به عهده داشته و View Model که با CSharp نوشته می‌شود نیز منطق هر صفحه را مدیریت می‌کند.
حال اگر بخواهیم در مثال Login، در صورتی که UserName و یا Password خالی بودند، به کاربر هشدار دهیم چه؟ برای این کار شما می‌توانید با توجه به دسترسی کد CSharp به صد در صد امکانات هر سیستم عامل، مثلا در Android از MakeToast استفاده کنید، ولی این کار باعث می‌شود مجبور شوید برای Android - iOS - Windows کدی متفاوت بنویسید که البته همه CSharp ای هستند، ولی به هر حال سه بار نوشتن یک چیز اصلا جالب نیست!
توجه: اگر پروژه XamApp را ندارید، آن را Clone کنید و اگر دارید، آخرین تغییرات را Pull کنید. مواردی که در ادامه گفته شده‌اند، در آخرین سورس‌های پروژه XamApp وجود دارند.
یک کتابخانه که این کار را برای ما ساده سازی می‌کند Acr User Dialogs است که قابلیت نمایش دادن Toast - Alert - Confirm - Action Sheet - Loading و ... را با یک کد و برای هر سه پلتفرم دارد. برای استفاده از این کتابخانه، ابتدا روی پروژه XamApp راست کلیک کرده و در Manage Nuget Packages پکیج Acr User Dialogs را نصب کنید.
برای نصب Package مربوطه، دقت کنید که Package Source در گوشه سمت راست-بالا روی All قرار گرفته باشد:

سپس در پروژه XamApp.Android، در کلاس Main Activity، کد زیر را قرار دهید:
 UserDialogs.Init(this); // Before Forms.Init
ممکن است ویژوال استودیو کلاس UserDialogs را نشناسد و کمکی برای افزودن using مربوطه در بالای کلاس MainActivity نکند. در این صورت ویژوال استودیو را باز و بسته کنید تا روال Restore کردن Nuget Package‌ها این بار به صورت کامل انجام شود و بتوانید این کلاس را ببینید و استفاده کنید.
نکته مهم: در آموزش خیلی از کتابخانه‌های Xamarin Forms، به شما گفته می‌شود که Nuget مربوطه را در پروژه Android-iOS-UWP نیز نصب کنید. در نسخه‌های اخیر Visual Studio نیازی به این کار نیست و بیهوده پروژه را شلوغ نکنید!

بعد از نصب، می‌توانیم از UserDialogs.Instance و متدهای آن برای نمایش هشدار و ... در هر جای پروژه استفاده کنیم؛ چون که اینها  static هستند. اما اگر اهل استفاده از Dependency injection و تست خودکار و سایر موارد ایده آل باشید، می‌دانید که استفاده از هر آنچه که static باشد، در اکثر مواقع ایده خوبی نیست.
کانفیگ کردن Dependency injection برای این کتابخانه کار ساده‌ای است. فقط کافی است کد زیر را در فایل App.xaml.cs در پروژه XamApp، به متد RegisterTypes اضافه کنید:
containerBuilder.RegisterInstance(UserDialogs.Instance);
RegisterInstance یکی از متدهای کتابخانه معروف و محبوب Autofac است که برای Dependency injection ساخته شده است.
در متد Login در LoginViewModel برای هشدار دادن خالی بودن نام کاربری یا رمز عبور، به جای استفاده مستقیم از UserDialogs.Instance می‌توانیم IUserDialogs را به صورت یک Property تعریف نموده و از آن استفاده کنیم. وظیفه پر کردن آن Property به عهده Autofac است و ما کار بیشتری نداریم!
public IUserDialogs UserDialogs { get; set; }

public async Task Login()
{
      if (string.IsNullOrWhiteSpace(UserName) || string.IsNullOrWhiteSpace(Password))
           await UserDialogs.AlertAsync(message: "Please provide UserName and Password!", title: ")-:", okText: "Ok!");
}
به سادگی نصب یک Nuget Package در پروژه XamApp، فراخوانی یک متد Init در پروژه XamApp.Android و یک خط کانفیگ برای Autofac، می‌توانید از IUserDialogs در تمامی View Model‌های خود استفاده کنید.
فرض کنید بعد از این که مطمئن شدید نام کاربری و رمز عبور خالی نیستند، می‌خواهید یک Request به سرور بفرستید و نام کاربری و رمز عبور را اعتبار سنجی کنید. ممکن است به خاطر کندی اینترنت یا سرور یا هر چیز دیگری، این پروسه کمی طول بکشد و نشان دادن یک Loading ایده خوبی است. چون فعلا نمی‌خواهیم درگیر فراخوانی سرور شویم، این طول کشیدن را من با Task.Delay شبیه سازی می‌کنم و Loading مربوطه را نمایش می‌دهم:
using (UserDialogs.Loading("Logging in...", maskType: MaskType.Black))
{
     // Login implementation ...
     await Task.Delay(TimeSpan.FromSeconds(3));
}

بررسی Navigation در Xamarin Forms
اگر در متد OnInitializedAsync در App.xaml.cs کد
await NavigationService.NavigateAsync("/Login", animated: false);
را داشته باشیم، وقتی برنامه اجرا می‌شود، ما به صفحه لاگین می‌رویم؛ این از تکلیف اولین صفحه برنامه! حال اگر در LoginViewModel بخواهیم در صورت موفقیت آمیز بودن فرآیند لاگین، مثلا به صفحه HelloWorld برویم چه؟ در این صورت در متد Login داریم:
await NavigationService.NavigateAsync("/Nav/HelloWorld");
چون کلاس LoginViewModel از BitViewModelBase ارث بری کرده است، به صورت پیش فرض دارای NavigationService هست. در رشته (string) استفاده شده، یعنی "/Nav/HelloWorld" چند نکته وجود دارد:
1- آن / اول اگر وجود داشته باشد، یعنی اینکه بعد از باز کردن صفحه HelloWorld، صفحه یا صفحات قبلی (در این مثال یعنی صفحه Login) از بین برده می‌شوند و امکان برگشت به آنها وجود ندارد. طبیعی است که بعد از لاگین موفق، فرد انتظار ندارد با زدن Back به صفحه لاگین باز گردد! ولی مثالی را فرض کنید که در یک صفحه، لیست محصولات فروشگاه را نمایش داده‌ایم و روی هر محصول که کلیک کنیم، به صفحه نمایش جزئیات آن محصول می‌رویم. در این صورت انتظار داریم با زدن Back، به صفحه لیست محصولات برگردیم، در این مثال از / در ابتدا استفاده نمی‌کنیم.

2- آن Nav/ به معنی این است که ابتدا Navigation Page را ایجاد و HelloWorld را درون Navigation Page باز کن. Navigation Page خود دارای امکانات زیادی است. عموما در برنامه‌ها، Title صفحه و دکمه Back نرم افزاری و Search bar را در Nav Bar مربوط به Navigation Page قرار می‌دهند. در Xamarin Forms حتی می‌توانید با Xaml، کل Nav Bar را خودتان Customize کنید و یا اینکه از امکان Large titles در iOS 11 استفاده کنید! درخواست بودن Nav Bar لازم است فقط یک بار انجام شود. لازم نیست و نباید ابتدای رفتن به هر صفحه از Nav/ استفاده کنید.


3- ممکن است بخواهید هنگام رفتن از صفحه‌ای به صفحه دیگر، پارامتر نیز ارسال کنید. اگر برای مثال صفحه اول لیست محصولات را نمایش می‌دهد و با زدن روی هر محصول قرار است به صفحه‌ای برویم که جزئیات آن محصول را ببینیم، بهتر است Id آن محصول به صورت پارامتر به صفحه دوم ارسال شود. برای این کار داریم:

await NavigationService.NavigateAsync("ProductDetail", new NavigationParameters
{
      { "productId", productId }
});

حال سؤال این است که در صفحه جزئیات یک محصول، چگونه productId را بگیریم؟ فرض کنید دو صفحه ProductsList و ProductDetail را داریم. هر صفحه دارای View و View Model است. در ViewModel مربوط به ProductDetail، یعنی ProductDetailViewModel که از BitViewModelBase ارث بری کرده‌است، می‌توانیم متد OnNavigatedToAsync را override کنیم. در آنجا به پارامترهای ارسال شده دسترسی داریم:

public async override Task OnNavigatedToAsync(INavigationParameters parameters)
{
      await base.OnNavigatedToAsync(parameters);
      Guid productId = parameters.GetValue<Guid>("productId");
}

هر ViewModel علاوه بر OnNavigatedTo می تواند دارای OnNavigatedFrom هم باشد که زمانیکه داریم از صفحه مربوطه خارج می‌شویم، فراخوانی می‌شود.


4- برای نمایش صفحه به صورت Popup کافی است بجای اینکه View ما یک Content Page باشد، یک PopupPage باشد (برای درک بهتر، فایل IntroView.xaml را در فولدر Views باز کنید).

حتی می‌توانید Animation مربوط به باز شدن پاپ آپ را هم کاملا Customize کنید. مثلا زمان باز شدن، از سمت راست صفحه وارد شود و زمان خارج شدن، Fade out شود. باز کردن Popup در Navigation Page معنی نمی‌دهد، پس با Nav/ در اینجا کاری نداریم. در مثال ما، بعد از لاگین می‌خواهیم یک صفحه Intro شامل هشدارها و راهنمایی‌های اولیه را در قالب Popup به کاربر نمایش دهیم. Popup‌ها می‌توانند همچون Content Page‌ها، دارای View Model باشند و مواردی چون OnNavigatedTo، ارسال پارامتر و هر آنچه که گفته شد، در مورد آنها نیز صدق می‌کند.


5- برای Master/Detail کافی است بجای Nav/HelloWorld/ از MasterDetail/Nav/HelloWorld/ استفاده کنید. این عمل باعث می‌شود HelloWorld در داخل Navigation Page و Navigation Page داخل Master Detail باز شود. از این ساده‌تر امکان ندارد!

برای تغییر UI مربوط به Master که از سمت چپ باز می‌شود، فایل XamAppMasterDetailView.xaml را تغییر دهید.


در قسمت بعدی به جزئیات Binding خواهیم پرداخت.

نظرات اشتراک‌ها
پیاده سازی generic repository یک ضد الگو است
خلاصه این مطلب خوب به این نحو است:
الف) اگر از یک Generic Repository داخل کدهای یک مثلا کنترلر مستقیما استفاده می‌کنید، فقط خودتان را گول زده‌اید!  این طراحی نشتی دارد و همچنین حد و مرز مشخصی را نمی‌توان برای آن قائل شد.
نشتی یا وابستگی که اینجا عنوان شده نمونه‌اش یک چنین متدی است:
IEnumerable<T> Find(Expression<Func<T, bool>> query);
در اینجا کار پیاده سازی query به یک لایه بالاتر (مانند یک کنترلر) محول شده که اشتباه است. حد و مرز لایه پیاده سازی کننده منطق تجاری شما باید مشخص باشد و نه باز. یک Expression فقط یک عبارت است که می‌توان با کمک آن انواع و اقسام کوئری‌های وابسته به فناوری دسترسی به داده‌های در حال استفاده را تهیه کرد. به عبارتی اگر تصور می‌کنید که در اینجا کپسوله سازی خوبی را انجام داده‌اید، اینطور نیست. چون دسترسی مستقیم به ORM خود را به لایه‌ای دیگر واگذار کرده‌اید و این دسترسی محصور نشده است.
نمونه خوبی را که مثال زده به صورت زیر است:
public IEnumerable<Customer> FindCustomerByName(string input)
    {
        return internalRepository.FindBy(c => c.Name == input);
    }
در اینجا دقیقا حد و مرز لایه تجاری و امکان دسترسی به آن مشخص است و دارای نشتی (باز بودن برای تغییرات بی حد و حصر در لایه‌های دیگر) نیست.
ب) الزامی به تعریف یک Generic Repository نیست اما اگر آن‌را تعریف کردید، باید این کلاس خاص داخل کدهایی که منطق تجاری برنامه را با حد و مرز مشخصی کپسوله می‌کنند استفاده کنید. نه اینکه آن‌را در خط مقدم کاری (مانند استفاده مستقیم در یک کنترلر) بکار بگیرید. به آن بیشتر به شکل یک سری متد کمکی نگاه کنید و بس. نامگذاری جالبی را هم در این حالت پیشنهاد داده: internalRepository 
نظرات مطالب
فعال سازی عملیات CRUD در Kendo UI Grid
- این چند سطری را هم که نوشتید، به علت استفاده‌ی از الگوی مخزن، کارآیی بسیار پائینی دارد:
 var tags = _blogRepository.GetAllTags(blogID).OrderBy(s => s.Id);
    var currenttags = _mapper.Map<IList<TagsViewModel>>(tags);
            if (currenttags == null)
            {
                return NotFound();

            }
            return Json(currenttags.AsQueryable()
                       .ToDataSourceResult(request.Take, request.Skip, request.Sort,
                                                       request.Filter));
ابتدا تمام اطلاعات یک جدول را دریافت می‌کنید. بعد این لیست درون حافظه‌ای را نگاشت می‌کنید (که اگر از الگوی مخزن استفاده نمی‌کردید، با یک کوئری قابل انجام بود). بعد آن‌ها را تبدیل می‌کنید به Queryable و در آخر متد ToDataSourceResult را بر روی آن فراخوانی می‌کنید. هدف از متد ToDataSourceResult این بوده که مستقیما روی کوئری LINQ to Entities شما فراخوانی شود (پیاده سازی dynamic linq است) و نه به این شکل. کل این عملیات باید یک کوئری شود؛ نه سه کوئری که یک مورد آن بدترین حالت واکشی کل اطلاعات از بانک اطلاعاتی است و سپس فیلتر کردن آن در طی دو کوئری سمت کلاینت. استفاده از dynamic linq (یا ToDataSourceResult در اینجا)، یعنی اضافه کردن where، take و skip به صورت خودکار به کوئری نهایی شما؛ یعنی عدم نیاز به تنظیم دستی هرباره‌ی این‌ها و ساده شدن کوئری نویسی. هدف آن هم اعمال به کوئری اصلی LINQ to Entities است تا در SQL نهایی ظاهر شود. اینجا است که الگوی مخزن شما نه تنها کمکی نکرده، بلکه با مخفی کردن کوئری اصلی LINQ to Entites و بازگشت کل اطلاعات به صورت درون حافظه‌ای، کارآیی برنامه را هم به شدت کاهش داده.
- مثالی که اینجا ارائه شده جهت سهولت کار و توضیح و همچنین کاهش بار ذهنی خواننده، از یک منبع داده‌ی درون حافظه‌ای ساده‌ی بدون نیاز به بانک اطلاعاتی استفاده می‌کند. نه اینکه کدهای نهایی شما باید دقیقا به این شکل باشد.
نظرات مطالب
پیاده سازی JSON Web Token با ASP.NET Web API 2.x
در وب کانفیگ برنامه یک چنین تنظیمی را داریم:
<appJwtConfiguration
    tokenPath="/login"
 />
این مسیر، یک مسیر دلخواه است. اصلا مقدار آن مهم نیست. هرمقداری که قرار داده شود، نهایتا به متد GrantResourceOwnerCredentials کلاس AppOAuthProvider منتهی می‌شود و اینجا است که کار بررسی نام کاربری و کلمه‌ی عبور کاربر انجام خواهد شد. تمام این مراحل هم توسط Owin مدیریت می‌شود. در متد GrantResourceOwnerCredentials هم از سرویس کاربران و متد FindUser آن استفاده شده‌است. بنابراین تنها موردی را که باید بررسی و پیاده سازی کنید، این متد Find در لایه سرویس برنامه است.
«... برای درک عملکرد این کلاس (و تمام کلاس‌های دیگر آن)، در ابتدای متدهای مختلف آن، یک break point قرار دهید. برنامه را اجرا کرده و سپس بر روی دکمه‌ی login کلیک کنید. به این ترتیب جریان کاری این کلاس را بهتر می‌توانید درک کنید ... »
نظرات نظرسنجی‌ها
به عنوان یک برنامه نویس به کدام گزینه بیشتر اهمیت می دهید؟
متاسفانه - برنامه نویس - تبدیل به یک اصطلاح عامیانه شده و به عنوان یک شغل شاید نتوان تعریف مشخصی از آن ارائه داد، چنان که یک نفر که زمینه کاری دیگری دارد و برای پروژه دانش آموزی و دانشجویی مثلا با زبان C برنامه ای ساده مینویسد را شامل می‌شود تا فردی که توسعه دهنده Front End یا Back End است و یا برنامه نویس سیستمی یا توکار است، یا پروژه هایی را مدیریت و یا پشتیبانی می‌کند یا برای پروژه‌های خودش کار می‌کند، یا برای یک کارفرما، یا پروژه ای یا ساعتی، یا تمام وقت و یا پاره وقت و ...
به هر حال هر کسی که کار تمام وقت برای کارفرما انجام می‌دهد باید بیمه باشد و حقوق مناسب هم بگیرد.
مطالب
بازسازی کد: گسترش امکانات کلاس های غریبه
هیچ کلاسی کامل نیست. در مواقع زیادی ممکن است یک کلاس نیاز به متدی داشته باشد که در آن وجود ندارد. در چنین شرایطی اگر سورس کلاس را در دست داشته باشیم به راحتی می‌توان رفتار مورد نظر را به آن اضافه کرد. اما اگر از کلاسهایی استفاده می‌کنیم که سورس آنها در دست نیست، حل این مورد کمی مشکل خواهد بود. برای مدیریت و رفع این مورد، دو بازسازی کد وجود دارند که به جهت همسویی این دو، آنها را در یک نوشتار پوشش می‌دهیم.
نیاز به متد جدید در یک کلاس خاص، نیازی مکرر در توسعه نرم افزار است. معمولا اگر این نیاز فقط در یک مورد بوجود بیاید موضوع خیلی سخت نیست و می‌توان در بدنه متد استفاده کننده، منطق را پیاده سازی کرد. اما زمانیکه تعداد استفاده‌ها از متد مورد نیاز بیشتر از یک بار باشد، کپی کردن روال آن کار درستی نیست و باید متدی برای این روال ایجاد کرد؛ اما کجا؟ 

ایجاد متد بیرونی  

در این روش در کلاس استفاده کننده، متدی برای نیاز جدید ساخته می‌شود. به طور مثال به تکه کد زیر توجه نمایید. در این مثال نیاز داریم در شیء نشان دهنده تاریخ، به روز بعد برسیم. برای این منظور می‌توانیم تکه کدی به صورت زیر داشته باشیم:  
DateTime newStart = new DateTime(previousEnd.Year, previousEnd.Month, previousEnd.Day + 1);
زمانیکه بدست آوردن روز بعدی در جاهای زیادی از کد نیاز باشد، باید این روال را در متدی پیاده سازی کرد. این متد می‌تواند بدنه‌ای به صورت زیر داشته باشد:  
private static DateTime NextDay(DateTime now) 
{ 
      return new DateTime(now.Year, now.Month, now.Day + 1); 
}

ایجاد کلاس توسعه دهنده برای کلاس غریبه 

زمانیکه تعداد متدهای جدید مورد نیاز روی یک کلاس غریبه کم است، روش اول روش قابل قبولی است. اما در مواردی تعداد متدهای جدید مورد نیاز زیاد می‌شوند. در چنین شرایطی بهتر است کلاسی را برای توسعه امکانات کلاس غریبه ایجاد کنیم و متدهای مورد نظر را در آن بنویسیم.
برای ایجاد این کلاس نیز دو روش وجود دارد:
روش اول: ارث بری از کلاس غریبه. این روش در شرایطی که کلاس غریبه به صورت sealed باشد، جواب نخواهد داد. به طور مثال تکه کد زیر را در نظر بگیرید. در این تکه کد با فرض این که کد کلاس Person در دست نیست و نیاز است متدی برای دریافت سن فرد، بر اساس سال تولد او به کلاس اضافه شود.  
public class MyPerson : Person 
{ 
    public int GetAge() 
    { 
        return 0; 
    } 
}
یکی از اشکالات این روش این است که برای استفاده از این کلاس و متد تعریف شده در آن، باید تمامی موارد مورد نیاز متد جدید را از کلاس Person، به نوع کلاس جدید تغییر داد. این تغییر در مقاطعی نیاز به Cast یا ایجاد شیء جدیدی با نوع جدیدی منجر خواهد شد.
روش دوم: ساختن wrapper به دور شیء کلاس غریبه. در این روش کلاسی ایجاد می‌شود و شیء‌ای از کلاس غریبه در آن ساخت شده و تمامی متدهای کلاس غریبه در آن تعریف می‌شوند. این متدها صرفا امر هدایت فرخوانی به متدهای کلاس اصلی را انجام می‌دهند. سپس متدهای جدیدی در این کلاس تعریف و پیاده سازی می‌شوند. برای ایجاد امکان محاسبه سن فرد می‌توان کلاسی را مانند کلاس زیر نوشت:  
public class PersonWrapper 
{ 
    private readonly Person _person; 
    public PersonWrapper(Person person) 
    { 
        _person = person; 
    } 
    public int GetAge() 
    { 
        return 0; 
    } 
}
دقت کنید که در این روش پیاده سازی نیز تمامی خصوصیات و متدهای کلاس اصلی در کلاس wrapper وجود خواهند داشت. استفاده از این کلاس به صورت زیر خواهد بود:  
var person = new Person(); 
var wrapper = new PersonWrapper(person); 
wrapper.GetAge();
در زبان برنامه نویسی سی شارپ امکانی به نام extension method وجود دارد که هدف آن پیاده سازی همین طراحی از طریق امکانات زبان است. برای مطالعه بیشتر این مبحث در زبان سی شارپ می‌توانید به اینجا مراجعه نمایید.  
مطالب
مروری بر چند تجربه‌ی کاری با SQLite




SQLite بانک اطلاعاتی سریع، کم حجم و سورس بازی است که استفاده از آن در دات نت فریم ورک بسیار ساده است. فقط کافی است پروایدر مربوط به آن را دریافت کنید و در کدهای قدیمی خود هر جایی مثلا sqlconnection داشتید آن‌را تبدیل به sqliteconnection کنید و امثال آن (به بیان دیگر، پروایدر تهیه شده از معماری ADO.NET پیروی می‌کند و عملا دانش قبلی شما به سادگی قابل استفاده و ارتقاء است). علاوه بر آن پروایدر ADO.NET‌ تهیه شده برای آن، پشتیبانی از Entity framework را هم ارائه می‌دهد.
این دیتابیس تحت سیستم عامل‌های مختلف مهیا است و مهم‌ترین مزیت آن عدم نیاز به نصب آن می‌باشد.

مزایا:
- سورس باز و رایگان
- مهیا بودن آن در سایر پلتفرم‌ها (ویندوز، لینوکس و ...)
- نیازی به نصب ندارد و فقط یک DLL بومی است. این مورد برای کاربرانی که در مدیریت بانک‌های اطلاعاتی پیچیده مشکل دارند، یک مزیت مهم است.
- امکان تشیکل دیتابیس در حافظه. این نکته و توانایی، در آزمون‌های واحد بسیار جالب توجه است. می‌توانید با سرعت بالا دیتابیسی واقعی را در حافظه تشکیل داده، کلیه آزمون‌های واحد خود را اجرا کرده و پس از پایان کار، اثری از دیتابیس و تغییر داده‌ها و مشکلات بازگردانی اطلاعات به حالت اول وجود نخواهد داشت.


ملاحظات:
الف) مرتب سازی SQLite حساس به حروف کوچک و بزرگ است.
برای برگشت به عادت متداولی که وجود دارد می‌شود به صورت زیر عمل کرد:
select f1 from tbl1 order by f1 COLLATE NOCASE
یک COLLATE NOCASE اضافه شده است.

ب) رعایت نکات مرتبط با سیستم‌های 64 بیتی
در مورد سیستم‌های 64 بیتی و دات نت قبلا مطلبی را نوشته بودم : {+}. این مطلب دقیقا اینجا کاربرد پیدا می‌کند، از این لحاظ که SQLite یک بانک اطلاعاتی Native است. اگر برنامه‌ی دات نت شما برای حالت Any CPU تهیه شده است، در سیستم‌های 32 بیتی نیاز است تا DLL مرتبط SQLite را توزیع کنید و در سیستم‌های 64 بیتی DLL مرتبط 64 بیتی آن نیاز خواهد بود. در غیراینصورت برنامه‌ی شما در بدو امر کرش کرده و اجرا نخواهد شد.

مشکلات:
الف) کلید خارجی بی خاصیت!
SQLite از کلید خارجی پشتیبانی می‌کند اما آن‌را اعمال نمی‌کند! برای اینکه کلید خارجی را اعمال کنید باید خودتان تریگر بنویسید تا این‌کار را انجام دهد.

ب) پشتیبانی در حد صفر از مباحث همزمانی و تردینگ.
اگر برنامه شما مالتی ترد است، در بد مخمصه‌ای گرفتار شده‌اید. مدام با پیغام database is locked مواجه خواهید شد. (چه انتظاری داشتید؟ یک dll کمتر از 2 مگابایت که قرار نیست کار غول‌های دیتابیسی را انجام دهد)
بنابراین اصلا تصورش را هم نکنید که از این دیتابیس به عنوان بانک اطلاعاتی یک سایت (و محیط‌های چند کاربره) بتوان استفاده کرد و کاربران دچار مشکل نشوند.

ج)حجم بالای دیتابیس و عدم کش
از مباحث caching که در دیتابیس‌های معظم دیگر به صورت توکار وجود دارد خبری نیست. برای مثال اگر یک کوئری قرار است تعدادی را شمارش نماید، حاصلی کش نشده و اگر صدبار هم به صورت متوالی آن‌را فراخوانی کنید باز هم از نو محاسبات آن انجام خواهد شد.
این مورد در حجم بالای دیتابیس واقعا مهم است و نمودش را با دیتابیسی با حجم بالای یک گیگ به وضوح مشاهده خواهید. افت کارآیی و همچنین قرچ و قرچ مداوم هارد دیسک سیستم! (چون به کش رجوع نمی‌شود)

د) امنیت
روی بانک‌های اطلاعاتی اکسس حداقل می‌توان یک کلمه‌ی عبور را قرار داد (که در کسری از ثانیه قابل شکستن است!). در SQLite استاندارد هیچ خبری از این مباحث نبوده و امنیت را باید خودتان تامین کنید. (البته یک نسخه‌ی تجاری هم از این بانک اطلاعاتی با پشتیبانی از رمزنگاری اطلاعات موجود است : +)

ه) مرتب سازی فارسی
هر چند SQLite هیچ مشکلی در ثبت اطلاعات یونیکد و خصوصا متون فارسی ندارد، اما با مرتب سازی کلمات یونیکد مشکل داشته و بر اساس کد اسکی آن‌ها عمل می‌کند. هر چند امکان تعریف Collation سفارشی در آن ممکن است : + (البته ممکن بودن با موجود بودن متفاوت است)


نتیجه گیری:
- SQLite برای دیتابیسی تا حدود یک گیگ که فقط یک نفر قرار باشد از آن استفاده کند انتخاب بسیار مناسبی است (برای مثال فایرفاکس از آن برای ذخیره سازی تنظیمات خودش استفاده می‌کند).