مطالب
چرا در سازمان‌ها برنامه‌های وب جایگزین برنامه‌های دسکتاپ شده‌اند (یا می‌شوند)؟

- برنامه‌های وب نیازی به نصب بر روی تک تک کلاینت‌ها و همچنین به روز رسانی مداوم کلاینت‌ها را ندارند. به این صورت مدیریت چند صد کاربر در یک سازمان ساده‌تر از قبل خواهد بود. دیگر نگران این نخواهید بود که آیا فلان کاربر آخرین به روز رسانی‌ها را نصب کرده (دریافت کرده) یا خیر.
- امکان دسترسی از راه دور، برای مثال از طریق اینترنت یا VPN یا RRAS و خطوط دایال آپ (برای مثال دسترسی ساده‌تر دفاتر مختلف یک سازمان به اطلاعات یکدیگر یا امکان داشتن کارکنانی که از راه دور برای شما کار می‌کنند).
- امکان ذخیره سازی داده‌ها در سازمانی دیگر (هاست کردن این برنامه‌ها در محیط‌های ابری(!) (cloud computing) هزینه‌های تهیه و نگهداری سخت افزارهای یک سازمان را نیز کاهش می‌دهند).
- کاهش هزینه‌های سازمان با توجه به اینکه اگر از سرورهای قدرتمندی استفاده شود؛ از یک برنامه‌ی وب چندین هزار یا چند میلیون کاربر می‌توانند استفاده کنند بدون اینکه نگران تامین هزینه مجوز استفاده از برنامه‌ی تهیه شده به ازای هر کاربر باشید.
- امکان دسترسی به برنامه‌ی وب تهیه شده در انواع و اقسام سیستم عامل‌هایی که تنها مجهز به یک مرورگر وب هستند (نتیجه نهایی قابل استفاده مستقل از سکو است). برای مثال این‌ روزها به کمک Adobe AIR ، Silverlight و یا کتابخانه‌های اسکریپتی مانند jQuery و ASP.Net Ajax، بسیاری از توانایی‌های نمایشی برنامه‌های دسکتاپ را در وب نیز می‌توان شاهد بود با این خصوصیت که نتیجه‌ی نهایی مستقل از سکو است.
- در این حالت کلاینت‌ها نیازی به داشتن سخت افزارهای قوی ندارند (که در کاهش هزینه‌های یک سازمان مؤثر است). همچنین این برنامه‌ها مشکلات ناسازگاری با سخت افزارها و نگارش‌های مختلف سیستم عامل‌ها را نیز ندارند. بنابراین یک سازمان می‌تواند بودجه‌ی خود را صرف تهیه‌ی سرورهای بهتری کند.
- کلاینت‌ها با توجه به محدود بودن دسترسی‌های امنیتی اعمالی توسط مرورگرها، امنیت بیشتری خواهند داشت. به همین ترتیب کاربران برای استفاده از این برنامه‌ها نیز نیازی به دسترسی بالا در یک سازمان برای اجرای مرورگر خود نخواهند داشت (کمتر جمله‌ی "من دسترسی ادمین می‌خواهم" را خواهید شنید).
- امکان مونیتور کردن ساده‌تر فعالیت کاربران در برنامه.
- در صورت محافظت از سرور، کدهای شما از خطر دزدیده شدن مصون‌(تر) هستند.
- مدیریت ساده‌تر و مجتمع اطلاعات تولیدی با توجه به اینکه همه چیز باید بر روی سرور ذخیره شود. به این صورت مدیریت نقل مکان کاربران از یک کامپیوتر به کامپیوتری دیگر نیز ساده‌تر می شود؛ زیرا چیزی را قرار نیست جابجا کنند (نه اطلاعات و نه برنامه ‌را). اگر یکی از کامپیوترهای کلاینت‌ها قابل استفاده نباشد، به سادگی می‌تواند از کامپیوتری دیگر در شبکه استفاده کند، بدون اینکه معطل تیم فنی شود تا برنامه‌ای را برای او نصب و راه اندازی کنند. به علاوه تهیه پشتیبان از اطلاعات سرورها نیز همیشه ساده‌تر است از تهیه پشتیبان از 100 ها کامپیوتر موجود در شبکه.
- اگر خروجی برنامه‌ی وب شما تنها از صفحات وب و جاوا اسکریپت تشکیل شده باشد، امکان دسترسی آن در دستگاه‌های موبایل به سادگی میسر است.

نظرات مطالب
آموزش Knockout.Js #2
Knockout.js جایگزین jQuery یا  MooTools نیست. در این کتابخانه animation یا مدیریت عمومی رخدادها، ساده سازی Ajax و مانند آن پیاده سازی نشده‌اند (هرچند Knockout.js امکان parse اطلاعات Ajax ایی دریافتی را دارد). هدف از Knockout.js ارائه مکملی برای سایر فناوری‌های وب جهت تولید برنامه‌های غنی و دسکتاپ مانند وب است. پشتیبانی خوبی از آن توسط مایکروسافت صورت می‌گیره چون نویسنده‌اش عضو تیم ASP.NET MVC است.
مطالب
آموزش (jQuery) جی کوئری 1#
با سلام خدمت دوستان عزیز
تصمیم گرفتم در طی چندین پست در حد توانم به آموزش jQuery بپردازم. (مطالب نوشته شده برداشت ازادی از کتاب jQuery in action است)

جی کوئری (jQuery) چیست؟
jQuery یک کتابخانه بسیار مفید برای جاوا اسکریپت است. بسیار ساده و کارآمد است و مشکل جاوا اسکریپت را برای تطابق با مرورگرهای اینترنتی مختلف برطرف نموده است؛ یادگیریjQuery بسیار آسان است. در جی کوئری کد جاوا اسکریپت از فایل HTML جدا شده و بنابراین کنترل کدھا و بھینه‌سازی آنھا بسیار ساده‌تر خواھد شد. توابعی برای کار با AJAX فراھم نموده و در این زمینه نیز کار را بسیار ساده کرده است. در جی کوئری می‌توان از خصوصیت فراخوانی زنجیره‌ای متدھا استفاده نمود و این باعث می‌شود چندین کد فقط در یک سطر قرار گیرد و در نتیجه کد بسیار مختصر گردد. در مقایسه با سایر ابزارهایی که تاکید عمده‌ای بروی تکنیک‌های هوشمند جاوا اسکریپت دارند، هدف جی کوئری تغییر تفکر سازندگان وب سایت‌ها، به ایجاد صفحه‌هایی با کارکرد بالا می‌باشد. به جای صرف زمان برای مقابله با پیچیدگی‌های جاوا اسکریپت پیشرفته، طراحان می‌توانند با استفاده از زمان و دانش خود در زمینه‌ی CSS، HTML، XHTML و جاوا اسکریپت‌های ساده، عناصر صفحه را مستقیما دستکاری کنند و از همین طریق تغییرهای گشترده و سریعی انجام دهند.

نکته: برای استفاده از جی کوئری باید HTML و CSS و جاوا اسکریپت آشنایی داشته باشید.

چگونه از جی کوئری استفاده کنیم؟
برای استفاده از جی کوئری باید ابتدا فایل آن را از سایت آن دانلود کرده و در پروژه خود استفاده نمایید. البته روش‌های دیگری برای استفاده از این فایل وجود دارد که در آینده بیشتر با آن آشنا خواهیم شد. برای استفاده از این فایل در پروژه باید به شکل زیر آن را به صفحه HTML خود معرفی کنیم.
<html>
   <head>
       <script type="text/javascript" src="jquery-1.9.1.min.js"></script>
   </head>
   <body>
   </body>
</html>
سپس بعد از معرفی خط فوق در قسمت head صفحه باید کد‌های خود را در یک تگ script بنویسیم.

کوتاه کردن کد: هر زمان شما خواسته باشید کارکرد یک صفحه وب را پویا‌تر کنید، در اکثر مواقع به ناچار این کار از طریق عناصری بروی صفحه انجام داده اید که با توجه به انتخاب شدن آنها، صفحه کارکردی خاص خواهد داشت. مثلا در جاوا اسکریپت اگر بخواهیم عنصری را که در یک radioGroup انتخاب شده است را برگردانیم باید کد‌های زیر را بنویسیم:
var checkedValue;
var elements = document.getElementByTagName ('input');
for (var n = 0; n < elements.length; n++) {
       if (elements[n].type == 'radio' && elements[n].name == 'myRadioGroup' && elements[n].checked) {
               checkedValue = elements[n].value;
       }
}
اما اگر بخواهیم همین کد را با جی کوئری بنویسیم:
var checkedValue = $ ('[name="myRadioGroup"]:checked').val();
ممکن است مثال بالا کمی گنگ باشد نگران نباشید در آینده با این دستورات بیشتر آشنا خواهیم شد.
قدرت اصلی جی کوئری برگفته از انتخاب‌کننده‌ها (Selector) هاست، انتخاب‌کننده ، یک عبارت است که دسترسی به عنصری خاص بر روی صفحه را موجب می‌شود؛ انتخاب‌کننده این امکان را فراهم می‌سازد تا به سادگی عنصر مورد نظر را مشخص و به آن دسترسی پیدا کنیم که در مثال فوق، عنصر مورد نظر ما گزینه انتخاب شده از myRadioGroup بود.
Unobtrusive JavaScript: اگر پیش از پیدایش CSS در کار ایجاد صفحه‌های اینترنتی بوده‌اید حتما مشکلات و مشقات آن دوران را به خاطر می‌آورید. در آن زمان برای فرمت‌دهی به اجزای مختلف صفحه ، به ناچار علائم فرمت‌دهی را به همراه دستورات خود اجزا، در صفحه‌های HTML استفاده می‌کردیم. اکنون بسیار بعید به نظر می‌رسد کسی ترجیح دهد فرمت‌دهی اجزا را به همراه دستورهای HTML آن انجام دهد. اگر چه هنوز دستوری مانند زیر بسیار عادی به نظر می‌آید:
<button type="button" onclick="document.getElementById('xyz').style.color='red';">
        Click Me
</button>
نکته ای که در مثال فوق حائز اهمیت است، این است که خصوصیات ظاهری دکمه ایجاد شده از قبیل فونت و عنوان دکمه، از طریق تگ <font> و یا پارامترهای قابل استفاده در خود دستور دکمه تعیین نشده است، بلکه CSS وظیفه تعیین آنها را دارد. اما اگرچه در این مثال فرمت‌دهی و دستور خود دکمه از یکدیگر جدا شده‌اند؛ شاهد ترکیب این دکمه با رفتار آن هستیم. در جی کوئری می‌توانیم رفتار را از اجزا به آسانی جدا کنیم.

مجموعه عناصر در جی کوئری:

زمانی که CSS به عنوان یک تکنولوژی به منظور جداسازی طراحی از ساختار به دنیای صفحه‌های اینترنتی معرفی شد، می‌بایست راهی برای اشاره به اجزای صفحات از طرف فایل CSS نیز معرفی می‌شد. این امر از طریق انتخاب‌کننده‌ها (Selector) صورت پذیرفت.

برای مثال انتخاب‌کننده زیر، به تمام عناصر <a> اشاره دارد که در یک عنصر <p> قرار گرفته‌اند:

p a
جی کوئری نیز از چنین انتخاب‌کننده‌هایی استفاده می‌کند، الته نه تنها از انتخاب‌کننده‌هایی که هم اکنون در CSS موجود می‌باشند، بلکه برخی از انتخاب‌کننده‌هایی که هنوز در تمام مرورگرها پشتیبانی نمی‌شوند.
برای انتخاب مجموعه‌ای از عناصر از یکی از دو Syntax زیر استفاده می‌کنیم.
$(Selector)
یا
jQuery(Selector)
ممکن است در ابتدا ()$ کمی نا معمول به نظر آید، اما اکثر کسانی که با جی کوئری کار می‌کنند از اختصار و کوتاهی این ساختار استفاده می‌کنند.
مثال زیر نمونه‌ای دیگر است که در آن مجموعه‌ای از تمام لینک‌هایی که درون تگ <p> قرار دارند را انتخاب می‌کند:
$("p a")
تابع ()$ که در حقیقت نام خلاصه‌ای برای ()jQuery می‌باشد، نوع خروجی مخصوصی دارد که شامل یک آرایه از اشیایی می‌شود که انتخاب‌کننده آن را برگزیده است. این نوع خروجی این مزیت را دارد که شمار زیادی متد از پیش تعریف شده را داراست که به سادگی قابل اعمال می‌باشند.
در اصطلاح برنامه نویسی به چنین توابعی که گروهی از عناصر را جمع می‌کنند، Wrapper می‌گویند زیرا تمام عناصر مطلوب را تحت یک شی بسته‌بندی می‌کند. در جی‌کوئری به آنها Wrapped Set یا jQuery Wrapper می‌گویند و به متدهایی که قابل اعمال بروی اینها به نام jQuery Wrapper Methodes شناخته می‌شوند.
در مثال زیر می‌خواهیم تمام عناصر <div> در صورتی که دارای کلاس notLongForThisWorldباشند را مخفی (با فید شدن) کنیم.

$("div.notLongForThisWorld").fadeOut();
یکی از مزیت‌های اکثر متدهای قابل اجرا بروی مجموعه عناصر انتخاب شده آن است که خروجی خود آنها مجموعه‌ای دیگر است. به این معنا که خروجی این متد، آماده اعمال یک متد دیگر است.
فرض کنید در مثال بالا بخواهیم پس از مخفی کردن هر <div> بخواهیم یک کلاس به نام removedبه آن بیافزاییم. به این منظور می‌توان کدی مانند زیر نوشت:
$("div.notLongForThisWorld").fadeOut().addClass("removed");
این زنجیره متدها می‌توانند به هرتعداد ادامه پیدا کند.

چند نمونه  انتخاب کننده:

نتیجه
  انتخاب کننده
 تمام <p>‌های زوج را انتخاب می‌کند

$('p:even')
 سطر اول هر جدول را انتخاب می‌کند

$("tr:nth-child(1)");
 <div>هایی که مستقیما در <body> تعریف شده باشند را انتخاب می‌کند.

$("body > div");
 لینک هایی که به یک فایل pdf اشاره دارند را انتخاب می‌کند.

$("a[href$=pdf]");
 تمام <div> هایی که مستقیما در <body> معرفی شده اند و دارای لینک می‌باشند را انتخاب می‌کند.

$("body > div:has(a)")
   

ادامه مطالب در پست‌های بعدی تشریح خواهد شد.


جهت مطالعه بیشتر می‌توانید از این منابع ^  و  ^  و  ^  و  ^  و  ^ استفاده کنید.
موفق و موید باشید
نظرات اشتراک‌ها
آیا یک توسعه دهنده‌ی وب می‌تواند یک طراح وب هم باشد؟
به نظر تعبیر عبارت "طراح وب"  طی سال‌های اخیر دست خوش تغییراتی شده است و امروزه برای بسیاری از ما بخوبی روشن و واضح نیست.
من معتقدم برداشت شما از عبارت طراح وب در مطلب فوق، باید به دو شکل مجزا و متمایز تعریف شود. اول طراح گرافیک و دوم طراحی رابط کاربری. در طراحی گرافیک هنر و شناخت مخاطب در خلق یک اثر هنری حرف اول و آخر را می‌زند. لطفاً توجه داشته باشید که عبارت شناخت به مسائل مختلفی اشاره دارد. دوم، طراح رابط کاربری. طراحی رابط کاربری موضوع بسیار حساسی است. در یک طراحی رابط کاربری کمتر صحبت از خلق یک اثر هنری است. من معتقدم آن دوران که از وب سایت به عنوان ارائه و تبلیغات استفاده می‌شد رو به پایان است. در واقع این نوع نگرش به وب سایت موجب استفاده حداقلی از ظرفیت آن است.
لذا امروزه شاهد این داستان هستیم که ضمن خلاقیت، بیشتر تمرکز طراحان وب (برنامه‌های کاربردی وب و وب سایت ها) بروی کاربرد پذیری و رقم زدن تجربه مناسبی برای کاربر از کار کردن با برنامه است. در این راستا رابط گرافیکی کاربر تنها بخش کوچکی از فاکتورهایی است که تجارب کاربری را شکل می‌دهد.
من منکر بحث خلاقیت و هنر نیستم اما باید پذیرفت که ما تابع قدرت‌های برتر اینترنت هستیم. برای مثال اگر کاربری بطور روزانه ساعت‌های زیادی را در سرویس‌های متعدد سایت گوگل می‌گذراند و یا بخشی از زندگی اجتماعی خود را در توییتر و فیس بوک سپری می‌کند، چیزی را تجربه می‌کند که ما باید تابع آن باشیم. 
زمانی که شما برنامه ای را برای مشتری آماده می‌کنید درخواست‌های حداقلی او مربوط به همین تجارب روزانه اش است.  نقش Framework هایی مانند Bootstrap در اینجا نمایان می‌شود. در حقیقت Framework ی با عنوان Bootstrap سعی دارد تا تجارب کاربری افراد را تکرار کند و بهبود بخشد.
بنابراین اینگونه نتیجه می‌گیریم که یک توسعه دهنده برنامه‌های تحت وب بهتر است تا توانمندی‌های خود را در خلق یک تجربه کاربری مناسب بهبود بخشد. در این راستا Framework هایی مانند Bootstrap کمک می‌کند تا ضمن حفظ استانداردها به یک طراحی منعطف رسید که امکانات حداقلی سایت‌ها و سرویس دهنده‌های مطرح اینترنت را فراهم می‌کند.
حال اگر بحث طراحی یک وب سایت شکیل و سرشار از خلاقیت است باید از یک طراح گرافیست کمک گرفت که در حوزه وب و نرم افزار فعال باشد. برای مثال اگر حمل بر تبلیغ نشود آقای مصطفی مقدم + یکی از طراحان گرافیکی است که ضمن اشراف کامل به خلق یک اثر هنری و تأثیرگذار، به ASP.NET هم اشراف دارند. وجود چنین فردی در تیم توسعه نرم افزار و استفاده هم زمان از Framework Bootstrap به ایجاد یک ادبیات مشترک بین برنامه نویس و طراح منجر خواهد شد که در نهایت برنامه ای منعطف و مطابق با استاندارد‌های جهانی وب را منتج خواهد شد.
خوب است در تمام علوم مطالعه داشته باشیم اما در علومی باید تخصص کسب کرد. مطالعه و تقویت یک توانمندی خوب است اما معنای تخصص را نمی‌دهد. اخیراً شاهد این امر هستیم که دوستانی بدون حتی یک پروژه عملی قابل قبول در جایگاهی قرار دارند که همایش‌های معتبر جهانی را  در این حوزه در ایران برگزار می‌کنند. من مخالف این همایش‌ها نیستم اما بهتر است به تخصص‌ها احترام بگزاریم و صرفاً بدلیل مطالعه 2 کتاب و چند مقاله ادعای تخصص در علومی نکنیم، آن هم تا جایی که ...
امیدوارم مفید واقع شود.

مطالب
Google OpenID Authentication در ASP.NET با استفاده از DotNetOpenAuth
در پست‌های قبلی
در این پست می‌خواهیم با یک مثال ساده نشان دهیم که سایت ما چگونه با استفاده از OpenID Authentication می تواند از اکانت گوگل استفاده کرده و کاربر در وب سایت ما شناسایی شود.
برای اینکار ابتدا
1- کتابخانه DotNetOpenAuth را از طریق NuGet به لیست رفرنس‌های پروژه وب خود اضافه نمایید
2- یک صفحه بنام Login.aspx یا هر نام دلخواهی را به پروژه خود اضافه نمایید. در نهایت کد Html صفحه شما به ید به صورت زیر باشد.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="OAuthWebTest.Login" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div id="loginform">
        <div id="NotLoggedIn" runat="server">
            <asp:ImageButton ID="ButtonLoginWithGoogle" runat="server" ImageUrl="Google.JPG"
                OnCommand="ButtonLoginWithGoogle_Click" CommandArgument="https://www.google.com/accounts/o8/id" />
            <p />
            <asp:Label runat="server" ID="LabelMessage" />
        </div>
    </div>
    </form>
</body>
</html>
در کد Html بالا به خصوصیت CommandArgument از کنترل ImageButton دقت نمایید که دارای مقدار "https://www.google.com/accounts/o8/id" می باشد. در واقع این آدرس باید برای اکانت گوگل جهت احراز هویت توسط OpenID استفاده شود. (آدرس API گوگل برای استفاده از این سرویس)
3- در قسمت کد نویسی صفحه کد‌های زیر را وارد نمایید.

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetOpenAuth.OpenId.RelyingParty;

namespace OAuthWebTest
{
    public partial class Login : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            OpenIdRelyingParty openIdRelyingParty = new OpenIdRelyingParty();
            var response = openIdRelyingParty.GetResponse();
            if (response == null) return;
            switch (response.Status)
            {
                case AuthenticationStatus.Authenticated:
                    NotLoggedIn.Visible = false;
                    Session["GoogleIdentifier"] = response.ClaimedIdentifier.ToString();
                    Response.Redirect("Default.aspx");
                    break;
                case AuthenticationStatus.Canceled:
                    LabelMessage.Text = "Cancelled.";
                    break;
                case AuthenticationStatus.Failed:
                    LabelMessage.Text = "Login Failed.";
                    break;
            }
        }

        protected void ButtonLoginWithGoogle_Click(object src, CommandEventArgs e)
        {
            string discoveryUri = e.CommandArgument.ToString();
            OpenIdRelyingParty openId = new OpenIdRelyingParty();
            var returnToUrl = new UriBuilder(Request.Url) { Query = "" };
            var request = openId.CreateRequest(discoveryUri, returnToUrl.Uri, returnToUrl.Uri);
            request.RedirectToProvider();
        }
    }
}
همانگونه که مشاهده می‌کنید  در رویداد کلیک دکمه لوگین ButtonLoginWithGoogle_Click ابتدا آدرس یکتا گوگل (مقدار CommandArgument اختصاص داده شده به کنترل ImageButton) به همراه آدرس صفحه جاری وب سایت توسط متد CreateRequest از شی openId ترکیب شده و یک درخواست (Request) ساخته شده و در نهایت برای سرویس دهنده گوگل ارسال می‌شود. با اجرای پروژه با تصویر زیر روبرو می‌شوید بروی کلید لوگین کلیک نمایید.

اجرای پروژه

در واقع با کلیک روی دکمه مورد نظر تکه کدی که در بالا شرح داده شد اجرا شده و ما را به صفحه ای شبیه تصویر پایین هدایت می‌کند

رفتن به صفحه گوگل جهت احراز هویت

در صورتی که کلید Sign In انتخاب شود شما به سایت (همین برنامه) اجازه داده اید که از اطلاعات حساب کاربری شما استفاده کند. پس از کلیک به برنامه اصلی (طبق آدرس بازگشت تعیین شده در رویداد ButtonLoginWithGoogle_Click) در رویداد PageLoad صفحه لاگین اطلاعات بازگشتی از سایت سرویس دهنده (در اینجا گوگل) چک می‌شود و با توجه با پاسخ مورد نظر عملیاتی انجام می‌شود، مثلا در صورتی که شما تایید کرده باشید اطلاعات شناسایی شما توسط گوگل در کلیدی به نام GoogleIdentifier در سشن ذهیره شده و شما به صفحه اصلی سایت هدایت می‌شوید.
دموی پروژه در این آدرس قرار داده شده است.
سورس پروژه از این آدرس قابل دسترسی است.
توجه: در این آدرس  شرح داده شده که چگونه دسترسی سایت‌های دیگر به اکانت گوگل خود را قطع کنید
در پست‌های آینده اتصال به تویتر و ف ی س بوک و سایت‌های دیگر توضیح داده خواهد شد.





مطالب
سازگار کردن لینک‌های قدیمی یک سایت با ساختار جدید آن در ASP.NET MVC
اگر پیشتر سایتی را در آدرس مشخصی در اینترنت داشته‌اید و اکنون تنها نرم افزار آن تغییر کرده است، اما نحوه ارائه خدمات آن خیر، لازم است بتوانید شرایط ذیل را مدیریت کنید:
- موتورهای جستجو مدام اطلاعات قبلی خود را به روز می‌کنند. اگر آدرس قبلی مقاله‌ای در سایت شما http://site/year/month/day/title بوده، برای نمونه گوگل هر از چندگاهی مجددا به این آدرس مراجعه می‌کند تا حداقل مطمئن شود وجود خارجی دارد یا خیر (این نکته را از لاگ‌های خطای سایت استخراج کردم).
- سایت‌های زیادی هستند که پیشتر به سایت شما و مطالب آن لینک داده‌اند. نمی‌توانید از آن‌ها درخواست کنید لطفا بانک اطلاعاتی خود را به روز کنید.
- اگر فید قبلی سایت شما http://site/feeds/posts بوده و اکنون چیز دیگری است، باز هم نمی‌توانید از همه درخواست کنید اطلاعات خود را به روز کنند. عده‌ای اینکار را خواهند کرد و تعداد زیادی هم خیر.

برای مدیریت یک چنین مواردی می‌توان از امکانات مسیریابی موجود در ASP.NET MVC استفاده کرد؛ که نمونه‌ای عملی از آن‌را جهت سازگاری سایت جاری با هاست قبلی آن (بلاگر) در ادامه مطالعه خواهید نمود:

الف) سازگار سازی لینک‌های قدیمی برچسب‌های سایت با ساختار جدید آن
در بلاگر آدرس‌های برچسب‌ها، به صورت http://site/search/label/name تعریف شده است. در سایت جاری برچسب‌ها توسط کنترلر Tag مدیریت می‌شوند. برای هدایت آدرس‌های قدیمی (موجود در موتورهای جستجو یا ثبت شده در سایت‌هایی که به ما لینک داده‌اند) می‌توان از تعریف مسیریابی ذیل در فایل global.asax استفاده کرد:
routes.MapRoute(
                "old_bloger_tags_list", // Route name
                "search/label/{name}", // URL with parameters
                new { controller = "Tag", action = "Index", name = UrlParameter.Optional, area = "" } // Parameter defaults
            );
به این ترتیب به صورت خودکار تمامی آدرس‌های شروع شده با http://site/search/label پالایش شده و سپس قسمت name آن‌ها جدا سازی می‌شود. این نام به متدی به نام Index در کنترلر Tag که دارای پارامتری به نام name است ارسال خواهد شد.

ب) از دست ندادن خوانندگان قدیمی فیدهای سایت
دو نوع فید کلی در بلاگر وجود دارد: http://site/feeds/posts/default و http://site/feeds/comments/default؛ اما در سایت جاری فیدها توسط کنترلری به نام Feed ارائه می‌شوند. برای سازگار سازی آدرس‌های قدیمی و هدایت آن‌ها به صورت خودکار به کنترلر فید می‌توان از دو تعریف مسیریابی ذیل استفاده کرد:
routes.MapRoute(
                "old_bloger_posts_feeds_list", // Route name
                "feeds/posts/default", // URL with parameters
                new { controller = "Feed", action = "Posts", name = UrlParameter.Optional, area = "" } // Parameter defaults
            );

routes.MapRoute(
                "old_bloger_comments_feeds_list", // Route name
                "feeds/comments/default", // URL with parameters
                new { controller = "Feed", action = "Comments", name = UrlParameter.Optional, area = "" } // Parameter defaults
            );            
در اینجا دو آدرس ذکر شده به کنترلر Feed و متدهای Posts و Comments آن هدایت خواهند شد و به این نحو کاربران قدیمی سایت هیچگونه تغییری را احساس نکرده و باز هم فیدخوان‌های آن‌ها، بدون مشکل کار خواهند کرد.

ج) پردازش لینک‌های قدیمی مطالب سایت و هدایت آن‌ها به آدرس‌های جدید
این مورد اندکی مشکل‌تر از موارد قبلی است:
routes.MapRoute(
                "old_bloger_post_urls",
                "{yyyy}/{mm}/{title}",
                new { controller = "Post", action = "OldBloggerLinks" },
                new { yyyy = @"\d{4}", mm = @"\d{1,2}" }
            );
برای نمونه آدرس مقاله‌ای مانند http://site/2012/05/ef-code-first-15.html را درنظر بگیرید. سه قسمت سال، ماه و عنوان آن، حائز اهمیت هستند. این‌ها را در اینجا به کنترلر Post و متد OldBloggerLinks آن هدایت خواهیم کرد. همچنین برای سال و ماه آن نیز قید تعریف شده است. سال عددی 4 رقمی است و ماه عددی یک تا دو رقمی.
کدهای متد OldBloggerLinks را در اینجا مشاهده می‌کنید:
        public virtual ActionResult OldBloggerLinks(int yyyy, int mm, string title)
        {
            var oldUrl = string.Format(CultureInfo.InvariantCulture, "https://www.dntips.ir/{0}/{1}/{2}", yyyy, mm.ToString("00"), title);
            var blogPost = _blogPostsService.FindBlogPost(oldUrl);
            if (blogPost != null)
                return RedirectToActionPermanent(actionName: ActionNames.Index, controllerName: MVC.Post.Name,
                                                 routeValues: new { id = blogPost.Id, name = blogPost.Title.GetPostSlug() });
            return this.Redirect("/");
        }
در اینجا چون ساختار لینک‌ها کلا تغییر کرده است، ابتدا بر اساس پارامترهای دریافت شده، لینک قدیمی بازسازی می‌شود. سپس به بانک اطلاعاتی مراجعه شده و لینک قدیمی به همراه شماره مطلب مرتبط با آن یافت می‌شود (یک فیلد oldUrl برای مطالب قدیمی در بانک اطلاعاتی وجود دارد). در آخر هم به کمک متد  RedirectToActionPermanent آدرس رسیده به آدرس جدید مطلب در سایت ترجمه و هدایت خواهد شد. Permanent بودن آن برای به روز رسانی خودکار اطلاعات موتورهای جستجو مفید است.


نتیجه گیری
به کمک امکانات مسیریابی توکار ASP.NET MVC می‌توان ساختار قدیمی یک سایت را به ساختار جدید آن ترجمه کرد. به این ترتیب لینک‌های قدیمی ثبت شده در صدها سایت اینترنتی که به سایت ما اشاره می‌کنند، مجددا بدون مشکل قابل استفاده بوده و همچنین موتورهای جستجو نیز امکان به روز رسانی اطلاعات خود را خواهند یافت.

مطالب
کار با مجموعه‌ها ( الگوی طراحی Composite)
یکی از پیچیدگی‌های معمول در کد، کلاسی است که دارای مجموعه‌ای باشد. مشکل اصلی با چنین طراحی این است که تمام عملیات باید از وضعیت مجموعه آگاه باشند. چرا مجموعه‌ها خیلی پیچیده هستند؟
داشتن مجموعه، خود با بسیاری از سوالات همراه است. آیا مجموعه حاوی اشیایی است یا خالی است؟ برخی از توابع تجمعی را نمی‌توان در مجموعه‌های خالی محاسبه کرد. به عنوان مثال Maximum در یک مجموعه خالی تعریف نشده است. بعضی دیگر از توابع تجمعی به این مشکل اهمیت نمی‌دهند، مانند sum و count که هر دوی آنها مقدار صفر را بر میگردانند.
 وقتی یک کلاس مجموعه‌‌ای را کنترل می‌کند، چیزهای زیادی برای فکر کردن وجود دارد. آیا عملیاتی که فراخوانی می‌کنیم ایمن است؟ آیا باید نتیجه قبل از ادامه به نحوی اصلاح شود؟ آیا آن را باید بر روی کل مجموعه تکرار کند و یا بر روی یک عنصر؟ 

با مجموعه‌های موجود چه کاری را باید انجام دهیم؟
کلاس‌هایی که دارای مجموعه هستند، تمایل به رشد دارند. این رشد‌ها هیچ ارتباطی با مسئولیت‌های کلاس ندارند و تنها هدفشان این است که کلاس کار کند. راه حل طبیعی برای این مشکل این است که کلاس جدیدی را تعریف کنیم تا هدف آن نگهداری از مجموعه باشد. این کلاس مسئول فیلتر کردن عناصر، شمارش و اعمال عملیات بر روی عناصر و جمع آوری نتایج هست. هدف نهایی این refactoring، ساده سازی کلاس اصلی و تمرکز بر روی domain model هست.

الگوی طراحی Composite
در بسیاری از موارد، عملیاتی را که بر روی یک شیء قابل تعریف هستند می‌توان بر روی مجموعه‌ای از اشیاء نیز تعریف کرد؛ مانند یک تابع تجمعی که نتیجه‌ای را بر می‌گرداند. این عمل می‌تواند بر روی یک شیء و یا گروهی از اشیاء فراخوانی شود. اگر بتوانیم یک اینترفیس مشترک را بر روی یک عنصر و مجموعه تعریف کنیم، آنگاه می‌توانیم الگوی Composite را بر روی آن اعمال نمائیم.

یک مثال
فرض کنید می‌خواهیم یک نقاش را برای رنگ آمیزی یک خانه استخدام کنیم. نقاش به تعدادی روز نیاز دارد تا کار را تمام کند. اکنون فرض کنید که ما می‌خواهیم چندین نقاش را برای همکاری با هم استخدام کنیم. درنتیجه زمان لازم برای پایان دادن به کار، کوتاه‌تر می‌شود.
پیاده سازی نقاش به صورت زیر است: 
class Painter
{
    private readonly float daysPerHouse;

    public Painter(float daysPerHouse)
    {
        this.daysPerHouse = daysPerHouse;
    }

    public float EstimateDaysToPaint(int houses)
    {
        return houses * daysPerHouse;
    }
}
نقاش فقط خانه‌ها را رنگ می‌کند. برآورد کار نقاشی به این صورت است که تعداد خانه‌ها را با زمانیکه برای هر خانه صرف می‌کند، بدست می‌آوریم.
ما می‌توانیم یک صاحب زمین را معرفی کنیم که این فرد چندین خانه را دارد:
class LandOwner
{
    private readonly Painter painter;
    private readonly int housesCount;

    public LandOwner(Painter painter, int housesCount)
    {
        this.painter = painter;
        this.housesCount = housesCount;
    }

    public void ManageHouses()
    {
        float daysToPaint = this.painter.EstimateDaysToPaint(this.housesCount);
        Console.WriteLine("Painting houses for {0:0.0} day(s).", daysToPaint);
    }
}
صاحب زمین، اشاره‌ای به یک نقاش دارد. هنگام مدیریت خانه‌ها، مالک به نقاش می‌گوید که چقدر زمان لازم است تا تمام خانه‌ها را رنگ کند و مشکلات زمانی آغاز می‌شوند که نقاش نمی‌تواند تمام کارها را در زمان معقولی انجام دهد.به این صورت مالک زمین، نقاشان بیشتری را استخدام می‌کند:
class LandOwner
{
    private readonly IEnumerable<Painter> painters;
    private readonly int housesCount;

    public LandOwner(IEnumerable<Painter> painters, int housesCount)
    {
        this.painters = new List<Painter>(painters);
        this.housesCount = housesCount;
    }
    ...
}
زمان لازم برای رنگ کردن خانه‌ها در شکل زیر نشان داده شده است: 

اکنون مالک زمین مسئولیت انجام این محاسبه را برعهده گرفته است؛ ولی این پیاده سازی کمی پیچیده‌تر می‌شود: 

class LandOwner
{
    private readonly IEnumerable<Painter> painters;
    private readonly int housesCount;
    public LandOwner(IEnumerable<Painter> painters, int housesCount)
    {
        this.painters = new List<Painter>(painters);
        this.housesCount = housesCount;
    }

    private float GetVelocity(Painter painter)
    {
        return painter.EstimateDaysToPaint(1);
    }

    private float GetTotalVelocity()
    {
        float sum = 0;
        foreach (Painter painter in this.painters)
            sum += 1  this.GetVelocity(painter);
        return   sum;
    }

    public void ManageHouses()
    {
        float daysToPaint = this.GetTotalVelocity() * this.housesCount;
        Console.WriteLine("Painting houses for {0:0.0} day(s).", daysToPaint);
    }
}

این پیاده سازی کمی پیچیده‌است؛ اما کار می‌کند و همچنین دارای مشکلاتی است. فرض کنید یکی از نقاشان صاحب شرکت، نقاشی است که نقاشان دیگر را استخدام می‌کند. حتی بدتر از آن این است که اگر شرکت نقاشی، شرکت دیگری را نیز همراه با نقاشان خود، استخدام کند. مالک زمین با سلسله مراتبی چندسطحی از نقاشان روبرو می‌شود. برآورد زمان لازم برای نقاشی خانه‌ها در چنین شرایطی برای مالک زمین دشوار خواهد شد. 


پیاده سازی  Composite

اگر تنها بتوانیم یک اینترفیس عمومی را از یک نقاش، بیرون بکشیم، سازماندهی نقاش‌ها راحت‌تر می‌شود:

interface IPainter
{
    float EstimateDaysToPaint(int houses);
}

مالک زمین دیگر کاری با مجموعه نقاش‌ها ندارد و در حال حاضر تنها یک نقاش انتزاعی را کنترل می‌کند: 

class LandOwner
{
    private readonly IPainter painter;
    private readonly int housesCount;
    public LandOwner(IPainter painter, int housesCount)
    {
        this.painter = painter;
        this.housesCount = housesCount;
    }

    public void ManageHouses()
    {
        float daysToPaint = this.painter.EstimateDaysToPaint(this.housesCount);
        Console.WriteLine("Painting houses for {0:0.0} day(s).", daysToPaint);
    }
}

اینبار مالک زمین فقط ارجاعی را به یک نقاش انتزاعی دارد. از سوی دیگر، کلاس نقاش دست نخورده باقی می‌ماند و تنها رابط IPainter را پیاده سازی می‌کند: 

class Painter: IPainter
{
    ...
}

حالا می‌توانیم نتیجه آن را ببینیم. ما آماده تعریف یک عنصر Composite هستیم که خود و عناصرش، اینترفیس IPainter را پیاده سازی کرده‌اند. 

class PaintingCompany: IPainter
{
    private readonly IEnumerable<IPainter> painters;

    public PaintingCompany(IEnumerable<IPainter> painters)
    {
        this.painters = new List<IPainter>(painters);
    }

    private float GetVelocity(Painter painter)
    {
        return painter.EstimateDaysToPaint(1);
    }

    private float GetTotalVelocity()
    {
        float sum = 0;
        foreach (Painter painter in this.painters)
            sum += 1  this.GetVelocity(painter);
        return   sum;
    }

    public float EstimateDaysToPaint(int houses)
    {
        return this.GetTotalVelocity() * houses;
    }
}

این پیاده سازی شرکت نقاشی است. کد کلاس LandOwner قبلی که وظیفه آن کنترل نقاش‌ها بود، به این کلاس منتقل شده‌است. تفاوت این است که شرکت نقاشی اکنون تعدادی نقاش انتزاعی را مدیریت می‌کند. از انتزاعات می‌توان دو حالت را در نظر گرفت: به صورت تک و یا به صورت گروه. این مورد قدرت نوع انتزاعی است در برنامه نویسی شیء گرا که در اینجا خودش را به صورت یک نقاش و یا گروهی از افراد که با هم کار می‌کنند، نشان می‌دهد.


نتیجه گیری

در این مقاله ما به یک نمونه از الگوی طراحی Composite پرداختیم. با استفاده از الگوی Composite، شیوه‌ای که کلاس‌ها با مجموعه‌ها برخورد می‌کنند، بسیار ساده‌تر شده‌است. کار با مجموعه‌ها، کد را پیچیده‌تر کرده و باعث می‌شود کلاس، کاری بیشتر از مسئولیت‌های خود را انجام دهد که ربطی به آن ندارد.

مطالب
پَرباد - راهنمای اتصال و پیاده‌سازی درگاه‌های پرداخت اینترنتی (شبکه شتاب)

پَرباد چیست؟

همانطور که همه ما میدانیم، اتصال و راه اندازی درگاه‌های پرداخت اینترنتی (شبکه شتاب)، از همان ابتدا کاری مشکل و  پر دردسر برای برنامه نویسان بود. هر بانک، سیستم متفاوت و مخصوص به خود را دارد و این بدان معنا است که برنامه نویسان باید کدهای کاملا متفاوت و همچنین پیاده سازی‌های متفاوتی را از روی فایل‌های PDF راهنمای بانکی، که در نهایت منجر به بی نظمی در پروژه‌ها می‌شود، بنویسند و البته مشکل بزرگتر آن است که پس از پیاده سازی هم اطمینان کاملی از صحت کدهای نوشته شده وجود ندارد؛ چه بسا که واحد‌های پشتیبانی درگاه‌های پرداخت هم افراد حرفه‌ای و آشنا با توسعه نرم افزار نیستند و اکثر اوقات نمی‌توان به آنها تکیه کرد.
برای راحتی کار برنامه نویسان حوضه فریم ورک دات نت، سیستمی جامع، اوپن سورس و کاملا رایگان، بدون نیاز به اضافه کردن هیچ گونه وب سرویسی تهیه شده است که به برنامه نویسان اجازه می‌دهد تنها با نوشتن چند خط کد، وب سایت خود را به پرداخت اینترنتی مجهز کنند. لطفا پیشنهادات، بحث‌ها و نظرات خود را در صفحه مخصوص این پروژه ارسال کنید.  
این سیستم در حال حاضر متشکل از درگاه‌های پرداخت اینترنتی بانک‌های ملت، سامان، پارسیان، تجارت و پاسارگاد است.
همچنین این سیستم در قالب یک Nuget Package برای نصب راحت در اپلیکیشن آماده شده است.


آنچه که شما در این مطلب یاد خواهید گرفت:

  • طریقه نصب
  • ایجاد صورتحساب و ارسال کاربر به درگاه پرداخت
  • تایید صورتحساب
  • مردود کردن صورتحساب قبل از انتقال وجه از مشتری به فروشنده
  • برگشت وجه به حساب مشتری پس از تأیید صورتحساب
  • درگاه مجازی پرداخت (برای تست وب اپلیکیشن، بدون داشتن حساب واقعی در درگاه‌های بانکی)
  • تنظیمات
  • ذخیره سازی اطلاعات پرداخت


طریقه نصب

PM> Install-Package Parbad

برای وب سایت‌های بر پایه فریم ورک MVC

PM> Install-Package Parbad.MVC5


ایجاد صورتحساب و ارسال کاربر به درگاه پرداخت

ابتدا یک شیٔ صورتحساب را به صورت زیر ایجاد کنید
var invoice = new Invoice( [Order Number], [Amount], [Verify URL]);

- Order Number شماره صورتحساب است و باید همیشه یک عدد یکتا باشد (تکراری نباشد).
- Amount مبلغ قابل پرداخت به ریال است.
- Verify URL یک آدرس در وب سایت شما، برای بازگشت مشتری پس از پرداخت و تأیید صورتحساب است.
برای مثال:
var invoice = new Invoice(1, 30000, "http://www.mywebsite.com/payment/verify" );
سپس صورتحساب را به درگاه مورد نظر ارسال میکنیم.
var result = Payment.Request(Gateways.Mellat, invoice);

شیٔ result حاوی شماره یکتا رجوع و وضعیت درخواست (موفقیت یا عدم موفقیت درخواست) است.
if (result.Status == RequestResultStatus.Success)
{
    // این متد، کاربر را به سمت وب سایت درگاه پرداخت هدایت میکند
    result.Process(Context);
}
else
{
    // در صورت تمایل می‌توانید پیغام مورد نظر از درگاه پرداخت را نمایش دهید
    var msg = result.Message;
}

در وب سایت‌های MVC می‌توانید به روش زیر عمل کنید

if (result.Status == RequestResultStatus.Success)
{
   // کاربر را به سمت وب سایت درگاه پرداخت هدایت میکند 
   return new RequestActionResult(result);
}
else
{
   return View("Error");
}


تأیید صورتحساب

پس از بازگشت کاربر از وب سایت بانک، باید از پرداخت صورتحساب توسط کاربر اطمینان حاصل کنید. کد زیر را باید در آدرسی که هنگام ساخت صورتحساب ذکر کرده بودید، قرار دهید.
var result = Payment.Verify(System.Web.HttpContext.Current);

شیٔ result در اینجا حاوی اطلاعاتی مانند: درگاه بانکی (که کاربر در آن صورتحساب را پرداخت کرده)، شماره رجوع، شماره تراکنش یکتای بانکی، وضعیت پرداخت و پیام درگاه است.
شما می‌توانید با بررسی این شیٔ، تصمیمات لازم را بگیرید.
if(result.Status == VerifyResultStatus.Success)
{
    // کاربر، صورتحساب را پرداخت کرده است و شما میتوانید ادامه عملیات خرید را انجام دهید
}
else
{
    // کاربر بنا به دلایلی صورتحساب را پرداخت نکرده است
    // شما همچنین میتوانید علت را در قالب یک پیام از پراپرتی پیام مشاهده کنید

    // بنابراین شما میتوانید این صورتحساب را در پایگاه داده خود مردود اعلام کنید
}


مردود کردن صورتحساب قبل از انتقال وجه از مشتری به فروشنده

در بعضی شرایط، پس از پرداخت صورتحساب توسط مشتری، شما متوجه می‌شوید که باید عملیات را لغو کنید.  
سناریو زیر را در نظر بگیرید:
در زمانیکه مشتری در وب سایت بانکی، صورتحساب را پرداخت میکرده است،  موجودی کالای خریداری شده توسط او در فروشگاه شما، به پایان رسیده ! حال باید این وجه پرداخت شده را فورا مردود اعلام کنید.
برای این منظور متد تأیید صورتحساب را به روش زیر بازنویسی کنید



همانطور که در تصویر می‌بینید، در هنگام بازگشت مشتری به وب سایت شما و تأیید کردن صورتحساب، شما می‌توانید اطلاعات تراکنش مورد نظر را که شامل، درگاه پرداخت بانکی، شماره سفارش و شماره رجوع است را دریافت کنید و سپس با استفاده از این اطلاعات، پایگاه داده خود را بررسی کرده و در صورت لزوم، متد Cancel را فراخوانی کنید. به این ترتیب به درگاه بانکی، هیچگونه تأییدیه ای اعلام نمی‌شود و این بدان معناست که اگر وجهی به حساب فروشگاه واریز شده باشد، پس از چند دقیقه (معمولا ۱۵ دقیقه) به حساب مشتری برگشت داده خواهد شد.


برگشت وجه به حساب مشتری پس از تأیید صورتحساب

var refundResult = Payment.Refund(new RefundInvoice([Order Number], [Amount]));
در اینجا، Order Number همان شماره سفارش صورتحساب و Amount مقداری از وجه و یا کل وجه برای برگشت به حساب مشتری است.
پس از آن شما می‌توانید نتیجه این عملیات را در شیٔ refundResult بررسی کنید.


درگاه مجازی پرداخت

درصورتیکه شما نیاز به تست عملکرد اپلیکیشن خود داشته باشید، نیازی به داشتن یک حساب واقعی در بانک‌های اینترنتی ندارید و می‌توانید اپلیکیشن خود را با یک درگاه مجازی بسیار ساده تست کنید. برای انجام این کار در هنگام ارسال صورتحساب، از میان درگاه‌های بانکی، درگاه مجازی پَرباد را انتخاب کنید.
var result = Payment.Request(Gateways.ParbadVirtualGateway, invoice);


در نتیجه در هنگام هدایت کاربر به درگاه پرداخت، کاربر به درگاه مجازی هدایت خواهد شد.

اما قبل از کار با درگاه مجازی باید در فایل web.config وب اپلیکیشن خود، تنظیمات زیر را قرار دهید:
<system.webServer>
  <handlers>
   <add name="ParbadGatewayPage" verb="*" path="Parbad.axd" type="Parbad.Web.Gateway.ParbadVirtualGatewayHandler" />
  </handlers>
</system.webServer>
در اینجا، درگاه مجازی به عنوان یک HttpHandler معرفی شده است. مقداری که در مشخصه path ذکر شده، در واقع آدرس درگاه مجازی است که شما می‌توانید به دلخواه خود آن را وارد کنید. ما در این مثال از آدرس parbad.axd استفاده کرده ایم.
و در نهایت در وب اپلیکیشن خود، مسیر ذکر شده را به صورت زیر معرفی کنید:
ParbadConfiguration.Gateways.ConfigureParbadVirtualGateway(new ParbadVirtualGatewayConfiguration("Parbad.axd"));
در نتیجه در هنگام هدایت کاربر به درگاه مجازی، شما باید در نوار آدرس مرورگر خود، مقداری را که تنظیم کرده اید مشاهده کنید.


نکته مهم: فراموش نکنید، قبل از انتشار نهایی وب سایت بر روی سرور (نمایش عمومی)، تنظیمات HttpHandler مربوط به این درگاه مجازی را از درون فایل web.config حذف کنید. بدین صورت، این درگاه از دسترس عموم خارج خواهد بود.

تنظیمات پَرباد

بهترین مکان برای درج این تنظیمات در اپلیکیشن‌های ASP.NET WebForms فایل Global.asax.cs و در اپلیکیشن‌های ASP.NET MVC فایل Startup.cs است.
ASP.NET Web Forms
public class Global : HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        // configurations
    }
}

ASP.NET MVC
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // configurations
    }
}

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

قبل از ارتباط با درگاه‌های بانکی شبکه شتاب، باید مشخصات درگاه بانکی را که استفاده می‌کنید، تنظیم کنید.
برای مثال: تنظیم درگاه پرداخت بانک ملت


تنظیمات ذخیره سازی اطلاعات پرداخت

پَرباد برای ذخیره و بازیابی اطلاعات پرداخت، نیاز به یک منبع ذخیره سازی دارد.
منبع پیش فرض پَرباد، کلاس TemporaryMemoryStorage است که همانطور که از نام آن پیداست، اطلاعات را به صورت موقت در حافظه رَم سرور ذخیره میکند. اگر شما خودتان اطلاعات پرداخت را در پایگاه داده ذخیره میکنید، این منبع، گزینه مناسبی است به دلیل سرعت بسیار بالای حافظه رَم.
توجه: در نظر داشته باشید که اگر به هر دلیلی سرور و یا وب سایت شما، ری‌استارت شود، کلیه اطلاعات موجود در این منبع هم از بین خواهد رفت.
ذخیره و بازیابی توسط SQL Server
برای این منظور در قسمت تنظیمات، کد زیر را قرار داده و رشته اتصال و نام جدول پرداخت را معرفی کنید.
ParbadConfiguration.Storage = new SqlServerStorage("Connection String", "MyPaymentTableName");

فیلد‌های مورد نیاز در این جدول:

ذخیره و بازیابی اطلاعات توسط روش مورد نظر شما:
در صورتیکه مایلید ذخیره و بازیابی را به روش خود انجام دهید، کلاس Storage را پیاده سازی کنید
public class MyStorage : Storage
{
    // Implement methods here...
}

و کلاس مورد نظر را در تنظیمات به عنوان منبع، معرفی کنید.
ParbadConfiguration.Storage = new MyStorage();

لازم به ذکر است که این کلاس شامل متد‌های synchronous و همچنین asynchronous است. بنابراین در صورتیکه برای مثال در هنگام ارسال درخواست به بانک، از متد‌های async استفاده می‌کنید، نیازی به پیاده سازی کردن متد‌های synchronous نیست.
در صورتیکه هر گونه پیشنهاد یا انتقاد نسبت به کارکرد این سیستم دارید، صمیمانه منتظر شنیدن آن در راستای توسعه این سیستم هستم.
همچنین در صورت تمایل به توسعه آن، می‌توانید آن را در گیت هاب دنبال کنید و یا لطفا پیشنهادات، بحث‌ها و نظرات خود را در صفحه مخصوص این پروژه ارسال کنید. 
با تشکر.
مطالب
تفاوت AngularJS با KnockoutJS
با پیشرفت HTML 5 و پدید آمدن چارچوب‌های مختلف JavaScript توسعه‌ی نرم افزار‌های تک صفحه ای تحت وب (Single Page Applications) محبوب شده است. 
اخیرا مطالب خوبی در رابطه با AngularJS در وبسایت جاری منتشر شده است. KnockoutJS توسط Microsoft معرفی شد و در قالب پیشفرض پروژه‌های SPA قرار گرفت ، بنابراین احتمالا این سوال برای افرادی مطرح شده است که تفاوت بین KnockoutJS و AngularJS چیست ؟ 
می توان پاسخ داد این مقایسه ممکن نیست. 
KnockoutJS : یک پیاده سازی مستقل JavaScript از الگوی MVVM با امکانات Databinding می‌باشد. Knokcout یک کتابخانه‌ی Databinding است نه یک کتاب خانه‌ی SPA
AngularJS : طبق معرفی در این مطلب AngularJS فریم ورکی متن باز و نوشته شده به زبان جاوا اسکریپت است. هدف از به وجود آمدن این فریم ورک، توسعه هر چه ساده‌تر SPA‌ها با الگوی طراحی MVC و تست پذیری هر چه آسان‌تر آن‌ها است. این فریم ورک توسط یکی از محققان Google در سال 2009 به وجود آمد. بعد‌ها این فریم ورک تحت مجوز MIT به صورت متن باز در آمد و اکنون گوگل آن را حمایت می‌کند و توسط هزاران توسعه دهنده در سرتاسر دنیا، توسعه داده می‌شود. 

بنابراین شاید بهتر باشد ذکر شود AngularJS یک Presentation Framework مخصوص برنامه‌های وب تک صفحه ای می‌باشد در حالی که KnockoutJS کتاب خانه ای با تمرکز بر Databinding می‌باشد ، بنابراین مقایسه‌ی این‌ها چندان صحیح نیست.

اگر قصد بر بررسی گزینه‌های دیگر در کنار Angular باشد ، می‌توان از Durandal نام برد. Durandal یک چارچوب SPA می‌باشد ، این چارچوب بر فراز jQuery ، RequireJS و Knockout توسعه پیدا کرده است. (سابقا برای routing از SammyJS استفاده می‌کرد که در نسخه‌های اخیر از موتور خودش استفاده می‌کند.)

Durandal از Knockout جهت Databinding و از RequireJS برای مدیریت وابستگی‌ها استفاده می‌کند.
Angular همه‌ی امکانات بالا را مستقل پیاده سازی کرده و حتی نیازی به jQuery ندارد. اگر jQuery وجود داشته باشد Angular از آن استفاده می‌کند در غیر این صورت از jQuery Lite یا jqLite استفاده می‌کند. jqLite پیاده سازی توابع متداول jQuery برای دستکاری DOM می‌باشد. اطلاعات بیشتر در اینجا

بنابراین با استفاده تنها از KnockoutJS نمی‌توان یک برنامه‌ی کامل SPA توسعه داد ، در کنار آن نیاز به کتابخانه‌های دیگری مثل jQuery برای مدیریت درخواست‌های  AJAX و استفاده از دیگر API‌ها ، Sammy برای routing و RequireJS برای مدیریت وابستگی‌ها می‌باشد.

در Knockout و در نتیجه Durandal عمل Databinding به این صورت است :
// JavaScript
var vm = {
    firstName = ko.observable('John')
};
ko.applyBindings(vm);
<!-- HTML -->
<input data-bind="value:firstName"/>
در Angular :
// JavaScript
// Inside of a personController
this.firstName = 'John';
در Angular همچنین از یک روش Controller As استفاده می‌شود :
<!-- HTML -->
<div ng-controller="personController as vm">
    <input ng-model="vm.firstName"/>
</div>
اگر تنها نیاز به یک کتابخانه‌ی Databinding باشد ، Knockout گزینه‌ی مناسبی است ، به خوبی از عمل مقید سازی داده‌ها پشتیبانی می‌کند و Syntax خوش دستی دارد اما اگر نیاز به چارچوبی برای توسعه‌ی پروژه‌های SPA می‌باشد می‌توان از Angular یا Durandal استفاده کرد. 
مقایسه‌ی Knockout با Angular همانند مقایسه‌ی موتور بنز با ماشین پورشه می‌باشد. 



مطالب
پیش بینی وضعیت دنیای برنامه نویسی در 5 سال آینده

در 5 سال آینده مواردی که در ادمه برشمرده خواهند شد، نقش بسیار مهمی را در دنیای برنامه نویسی و جهت گیری‌های آن ایفا خواهند کرد (برای مثال اگر برای شما این سؤال مطرح است که هدف از WCF ، REST services ، سیلورلایت 3 و غیره چیست، این مقاله‌ی کوتاه را مطالعه نمائید) :

الف) Object Relational Mapping
ORM یکی از بازیگرهای واضح خواهد بود. خصوصا پروژه‌ای مانند Fluent NHibernate با ویژگی‌های زیر:
  • سابقه‌ای 10 ساله (قسمت عمده‌ای از این سابقه به دنیای جاوا بر می‌گردد)
  • امکان استفاده از انواع و اقسام دیتابیس‌ها توسط آن
  • پشتیبانی از Linq
  • و ...

ب) نرم افزار به عنوان سرویس ( Software as a Service یا SaaS )
نرم افزار به عنوان سرویس یک مفهوم تجاری است که در آن مصرف کننده بر اساس نیازهایش هزینه‌ی یک نرم افزار را خواهد پرداخت. بر این اساس برنامه نویسی در زمینه‌های طراحی و مدیریت دست خوش تغییرات عمده‌ای می‌شود. شاید نیازی به ذکر نباشد که حتی مایکروسافت نیز در حال برنامه ریزی برای این نوع از توسعه است.
پرداختن به SaaS نیازمند یک سری از ویژگی‌ها است:
  • سادگی توسعه و دستیابی: در این مدل تجاری، استفاده و دسترسی به نرم افزار مورد نظر باید بسیار ساده باشد. بر این اساس برنامه‌های تحت وب، یا برنامه‌های هاست شده توسط مرورگرها (مانند سیلورلایت) محبوبیت بیش از پیشی را خواهند یافت.
  • قابلیت تنظیم و ماژولار بودن برنامه‌ها: در این مدل نیاز است تا کاربر تنها هزینه‌ی ماژول‌هایی را بپردازد که به آن‌ها نیاز دارد و این امر سبب بازنگری در طراحی و توسعه‌ی برنامه‌های موجود خواهد شد.
  • نیاز به زیر ساخت بهینه و سریعی خواهد بود: از آنجائیکه کاربران بسیار ساده می‌توانند از یک برنامه به برنامه و شرکتی دیگر رجوع کنند، برای بقا باید جنگید! نیاز به زیر ساخت‌هایی وجود خواهد داشت که توسط آن‌ها بتوان نیازهای کاربران را در حداقل زمان ممکن برآورده کرد و این موارد نیاز به آموختن یکی از فریم ورک‌های مطرح موجود را خواهد داشت به همراه آموختن مباحث مدیریت پروژه، آشنایی با آزمون‌های واحد، کنترل کیفیت ، یکپارچگی مداوم و امثال آن.

ج) پردازش ابری
پردازش ابری شبیه به آن‌چیزی که مایکروسافت Azure ارائه می‌دهد، نیز یکی از نتایج مفهوم تجاری SaaS است. تمرکز پردازش ابری بر روی ارائه‌ی وب سرورها، مکان‌های ذخیره داده و امثال آن است. به این صورت شما دیگر درگیر تهیه و پرداخت هزینه جهت راه اندازی دیتاسنتر ویژه‌ی خود نخواهید شد و بسیاری از هزینه‌های شما کاهش خواهند یافت. بهره برداری تجاری گسترده از این روش با توجه به توسعه‌ی فریم ورک‌های ویژه‌ی این نوع پردازش‌ها، آموزش و غیره ، بین سال‌های 2010 و 2015 شروع خواهد شد.

د) اجرای موازی
پردازش ابری اثرات خاص خودش را بر روی دنیای نرم افزار و برنامه نویسی خواهد گذاشت. این طبیعت توزیع شده سبب خواهد شد که در آینده از برنامه نویسی‌های چند ریسمانی و مسایل همزمانی حاصل از آن‌ها بیشتر بشنوید و نهایتا معماری برنامه‌ها به سمت استفاده از روش‌های زیر سوق خواهند یافت:
REST services;
Message-based distributed architectures, i.e.: see NServiceBus, Mass Transit or Rhino Service Bus



ه) برنامه‌های غنی وب یا Rich Internet Applications
Rich Internet Applications یا RIA نقش مهمی را در SaaS بازی خواهند کرد و هدفگیری مایکروسافت در این باره ارائه Silverlight 3.0‌ و Microsoft .NET RIA Services است. هر چند این موارد راه طولانی (یکی دو ساله) را در پیش خواهند داشت تا به حد استانداردهای لازم برسند اما حرکت‌های مهمی در این زمینه به شمار می‌روند.

برداشتی آزاد از Development in 5 Years Would be Affected by