نظرات مطالب
EF Code First #12
StructureMap امکان اسکن اسمبلی‌های اضافه شده به سیستم را دارد. باید وقت بگذارید مستندات آن‌را مطالعه کنید: (^)
بازخوردهای پروژه‌ها
نیاز به آزمون‌های واحد بیشتر
سلام؛ من فکر می‌کنم یکی از بهترین مستندات این نوع کتابخانه‌های عمومی می‌تونه تهیه آزمون‌های واحد باشه.
مطالب
ساختار پروژه های Angular
با توجه به پست‌ها منتشر شده قبلی درباره AngularJs به احتمال قوی شما نیز به این نتیجه رسیده اید که این فریم ورک برای انواع پروژه‌ها به ویژه پروژه هایی با مقیاس بزرگ بسیار مناسب است. منظور از ساختار پروژه Angular این است که به چه سبکی فایل‌های پروژه را سازمان دهی کنیم طوری که در هنگام توسعه و تغییرات با مشکل مواجه نشویم. عموما کد‌های مربوط به بخش frontend پروژه دارای ساختار قوی نمی‌باشند در نتیجه developer‌ها بیشتر سلیقه ای کد‌های مربوطه را می‌نویسند که با گذر زمان این مورد باعث بروز مشکل در امر توسعه نرم افزار می‌شود (نمونه بارز آن کدهای نوشته شده Jquery در صفحات است). AngularJs نیز همانند سایر کتابخانه‌ها و فریم ورک‌های جاوااسکریپتی دیگر از این امر مستثنی نیست و فایل‌های آن باید طبق روشی مناسب پیاده سازی و مدیریت شوند. انتخاب ساختار و روش سازمان دهی فایل‌ها وابستگی مستقیم به مقیاس پروژه دارد. ساختار پروژه‌های کوچک می‌تواند کاملا متفاوت با ساختار پروژه‌های بزرگ باشد. در این پست به بررسی چند روش در این زمینه خواهم پرداخت.
پروژه‌های کوچک عموما دارای ساختاری مشابه تصویر ذیل می‌باشند:

این مورد، روش پیشنهادی در Angular Seed است و بدین صورت است که تعاریف ماژول‌ها در فایل app.js انجام می‌گیرد. تعاریف و پیاده سازی تمام کنترلر‌ها در فایل controller.js است. و همچنین دایرکتیوها و فیلترها و سرویس‌ها هر کدام در فایل‌ها جداگانه تعریف و پیاده سازی می‌شوند. این روش راه حلی سریع برای پروژه‌های کوچک با تعداد developer‌های کم است. برای مثال زمانی که یک developer در حال ویرایش فایل controller.js است، از آن جا که فایل مورد نظر checkout خواهد شد در نتیجه سایر developer‌ها امکان تغییر در فایل مورد نظر را نخواهند داشت. سورس فایل‌ها به مرور زیاد خواهد شد و در نتیجه debug آن سخت می‌شود. 

روش دوم

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

دایرکتیو‌ها و فیلتر‌ها عموما در یک فایل قرار داده خواهند شد تا بنابر نیاز در جای مناسب رفرنس داده شوند. این روش ساختار مناسب‌تری نسبه به روش قبلی دارد اما دارای معایبی هم چون موارد زیر است:
»وابستگی بین فایل‌ها مشخص نیست در نتیجه بدون استفاده از کتابخانه هایی نظیر requireJs  با مشکل مواجه خواهید شد.
»refactoring کد‌ها تا حدودی سخت است.

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

همان طور که ملاحظه می‌کنید سرویس ها، کنترلر‌ها و حتی مدل‌های مربوط به هر بخش در یک مسیر جداگانه قرار می‌گیرند. علاوه بر آن فایل هایی که قابلیت اشتراکی دارند در مسیری به نام common وجود دارند تا بتوان در جای مناسب برای استفاده از آن‌ها رفرنس داده شود. حتی اگر در پروژه خود فقط یک ماژول دارید باز سعی کنید از این روش برای مدیریت فایل‌های خود استفاده نمایید. اگر با ngStart آشنایی داشته باشید به احتمال زیاد با این روش بیگانه نیستید.
بررسی چند نکته درباره کد‌های مشترک
در اکثر پروژه‌های بزرگ، فایل‌ها و کد هایی وجود خواهد داشت که حالت اشتراکی بین ماژول‌ها دارند. در این روش این فایل‌ها در مسیری به نام common یا shared ذخیره می‌شوند. علاوه بر آن در Angular تکنیک هایی برای به اشتراک گذاشتن این اطلاعات وجود دارد.
»اگر ماژول‌ها وابستگی شدیدی به فایل‌ها و سورس‌های مشترک دارند باید اطمینان حاصل نمایید که این ماژولها فقط به اطلاعات مورد نیاز دسترسی دارند. این اصل interface segregation principle اصول SOLID است.
»توابعی که کاربرد زیادی دارند و اصطلاحا به عنوان Utility شناخته می‌شوند باید به rootScope$ اضافه شوند تا scope‌های وابسته نیز به آن‌ها دسترسی داشته باشند. این مورد به ویژه باعث کاهش تکرار وابستگی‌های مربوط به هر کنترلر می‌شود.
»برای جداسازی وابستگی‌های بین دو component بهتر از event‌ها استفاده نمایید. AngularJs این امکان را با استفاده از سرویس‌های on$ و emit$ و broadcast$ به راحتی میسر کرده است.
نظرات مطالب
آموزش Prism #3
سلام . دستتون درد نکنه اقای پاکدل . فقط یه چیزی!
یکی اینکه این اموزشتونو اگه میشه یکم سریعتر بدید . اون روش قبلیه که گفتید رو من خوندم خیلی واضح‌تر توضیح داده بودین . اما از این یکی زیاد نمیتونم درکش کنم.
اگه میشه لطفا رو یه ساختار کنین . یعنی مثلا همین Prism رو با همون الگویه MVVM ای که داره تویه WPF بگین که ما هم بتونیم استفاده کنیم . شما یکی شو با یه روش، یکی دیگشو با یه روشه دیگه  و باز اینارو هر کدوم  یکی تو Silver و اون یکی تو WPF . این نظر منه .  اگه شما یه دونشونو انتخاب کنید و همینطوری ادامه بدین  بهتره که ما هم بتونیم برای خودمون یه جمع بندی و یه راه مشخص پیدا کنیم .  سایت واقعا عالی دارین . خیلی چیزا من از این سایت یاد گرفتم . این ماژولار بودن تو این سبک و تا این سطح خیلی برام کاربردی و مهمه . میخوام پایه پروژه‌های شرکتو بر همین روال قرار بدم . اگه میشد شما از همین Prism  و این MEF یه پروژه WPF بسازین  فقط یکی دوتا ماژول ساده براش پیاده سازه کنین  و یه فیلم بگیرین خیلی ممنون میشم . میخوام ا این روش استفاده کنم اما روال کار برام مبهمه . اگه کتاب یا سری آموزشی در این باره هم دارین بزارین ما استفاده کنیم . اموزش هاتونم من هر روز میام میخونم و  چک میکنم اما خیلی دیر دیر مطلب میزارین . حتما این اموزشو ادامه بدین . مخصوصا Prism With MEF In WPF  . خلییی باحالین....

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

چرا یک سخت افزار به تنهایی پاسخگوی همه نیاز‌های ما نیست؟

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

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

راه حل چیست؟

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


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

مشکل سیستمهای Parallel مشخص است. کارآیی این نوع سیستم، کاملا به سخت افزار و نوع پیاده سازی آنها وابسته است. یعنی در صورت نیاز به کارآیی بیشتر، تنها راه ارتقاء سخت افزار و بهینه کردن کدهاست. اما این روال را تا کجا می‌توانیم انجام دهیم؟

برای روشن شدن مشکل بالا بیایید یک Web Application را بر روی یک سخت افزار اجرا کنیم. در یک Web Application یک Thread Pool شامل مجموعه‌ای از Threadها می‌باشد که هر Thread وظیفه اجرای یک درخواست را بر عهده دارد. یعنی با دریافت یک درخواست، یک Thread از این مجموعه کم می‌شود و وظیفه پاسخ دهی به آن در خواست را بر عهده می‌گیرد. تعداد Thread هایی که در یک Thread Pool می‌باشند نیز وابسته به تعداد هسته‌های پردازنده می‌باشد. برای این تعداد بصورت پیشفرض مقداری در نظر گرفته می‌شود که بیشترین کارآیی را در یک هسته داشته باشد؛ مثلا در ASP.NET بصورت پیشفرض به ازای هر هسته‌ی از CPU، تعداد 20 Thread به این مجموعه اضافه می‌شود. یعنی ما در یک پردازنده 2 هسته‌ای تنها می‌توانیم تعداد 40 درخواست را بصورت همزمان دریافت کنیم. در صورتیکه تعداد در خواستها در یک لحظه بیشتر از این تعداد باشد، تمام درخواست‌های اضافی در صف دریافت قرار می‌گیرند تا یکی از این Thread‌ها به درخواست خودش پاسخ دهد و به Thread Pool بازگردد و آماده اجرای درخواست بعدی باشد.

حال با فرض اینکه بصورت میانگین به هر درخواست در مدت 2 ثانیه پاسخ داده شود و در طول هر 2 ثانیه ما تعداد 200 درخواست جدید دریافت کنیم، یعنی در هر 2 ثانیه تعداد 160 درخواست در صف پردازش درخواست باقی می‌مانند. یعنی در مدت 10 ثانیه تعداد 800 درخواست پردازش نشده در این صف وجود دارند. در صورتیکه این روال ادامه پیدا کند، صف پردازش بزرگتر و بزرگتر می‌شود؛ تا جایی که دیگر حافظه‌ای برای دریافت درخواستهای جدید نباشد. اینجاست که سیستم ما از دسترس خارج می‌شود. پس تصمیم می‌گیریم سخت افزار خود را ارتقاء دهیم و کدهای خود را نیز بهینه کنیم. مثلا جاییکه عملیات I/O را انجام می‌دهیم، برای استفاده‌ی بهینه از Thread‌های موجود، کدهای خود را بصورت Async اجرا کنیم.

تا حدودی مشکل ما فعلا حل شده‌است. بعد از مدتی بدلیل اضافه شدن نیازمندی‌های جدید، تعدادکاربران فعال سیستم زیاد می‌شود و دوباره مشکل پوشش دادن تعداد بیشتر درخواست بوجود می‌آید. مجبوریم دوباره عملیات Scale-up یا Vertical scaling را انجام دهیم. بله؛ عملیاتی که ما در این سیستم‌ها برای مقیاس‌پذیری انجام می‌دهیم، اصطلاحا  Vertical scaling یا Scale-up نام دارد. یعنی با افزایش تعداد کاربران یا تعداد درخواست، کدها بهینه‌تر و سخت افزار ارتقاء پیدا می‌کند.

البته مثالی که ذکر شد به هیچ وجه با دنیای واقعی قابل مقایسه نیست. ممکن است شما سرویسی بسیار حیاتی را پیاده سازی کرده باشید که در شرایط خاص، هزاران یا میلیون‌ها کاربر بصورت همزمان بخواهند درخواستهای خود را برای شما ارسال کنند. در این حالت شما دو راه دارید؛ اول اینکه مرتبا سرویس بسیار حیاتی خود را از دسترس خارج کنید و منتظر بمانید تا حجم تعداد درخواست‌های کاربران کاهش یابد و یا مجبورید سخت افزار سرور خود را آنقدر ارتقاء دهید، تا این تعداد درخواست را بصورت همزمان پوشش دهد. واقعا هزینه تهیه کردن این سرور چقدر است؟

فرض کنید از سمت پایگاه داده نیز با مشکل روبرو شده‌ایم. حجم داده‌های ما روبه افزایش است. فضای حافظه‌ی آزاد تنها Server ی که داده‌های ما را ذخیره می‌کند، رو به اتمام است. چاره چیست؟ آن را ارتقا دهیم؟ بله برای مدتی سرور را از دسترس خارج کرده و فضای آزاد را افزایش می‌دهیم. در این بین تمام سرویس‌های ما که وابسته به این سرور هستند، از دسترس خارج می‌شوند. این کار برای داده‌هایی که ذاتا همیشه رو به افزایش هستند، چقدر باید تکرار شوند؟ چقدر باید هزینه کنیم تا این داده‌ها که تمام سرویس‌های ما به آنها وابسته هستند، با مشکل مواجه نشوند، یا کارآیی بازیابی آنها پایین نیاید؟

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

اینجاست که مفهوم سیستمهای توزیع شده به کمک سیستمهای Parallel می‌آید و مفهوم Scale-up یا Vertical scaling  با مفهموم Horizontal Scaling یا Scale-out ادغام می‌شود. در قسمت بعدی، با مفاهیم، خصوصیات و اصطلاحات موجود در این سیستم‌ها آشنا می‌شویم.
نظرات مطالب
سفارشی سازی ASP.NET Core Identity - قسمت اول - موجودیت‌های پایه و DbContext برنامه
- من از ویژوال استودیو استفاده نمی‌کنم (آخرین نگارشی از آن که روی سیستم من نصب است، نگارش 2015 است). تمام کار این برنامه با VSCode انجام شده و با آن مشکلی نیست. برای کنترل کیفیت برنامه و دسترسی به معادل ReSharper هم می‌توانید از Rider استفاده کنید.
- مطابق مستندات رسمی خود مایکروسافت، VS 2017 دیگر از SDKهای جدید پشتیبانی نمی‌کند و از این پس نیاز به نصب نگارش 2019 را خواهید داشت (این مورد اجباری است برای کسانیکه می‌خواهند از VS و NET Core. استفاده کنند):
.NET Core SDK .NET Core Runtime Compatible Visual Studio MSBuild Notes
2.1.5nn 2.1 2017 15 Installed as part of VS 2017 version 15.9
2.1.6nn 2.1 2019 16 Installed as part of VS 2019
2.2.1nn 2.2 2017 15 Installed manually
2.2.2nn 2.2 2019 16 Installed as part of VS 2019
3.0.1nn 3.0 (Preview) 2019 16 Installed manually

Visual Studio 2017 cannot work with .NET Core SDK 2.1.6nn or 2.2.2nn. 

نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت دوازدهم - توزیع برنامه
یک نکته‌ی تکمیلی

به مستندات رسمی AngularJS 2.0، فصل جدیدی به نام «Introduction to Webpack» اضافه شده‌است. در اینجا می‌توان Webpack را جایگزین Gulp کرد و نکته‌ی جالب آن، امکان نوشتن یک چنین کامپوننت‌هایی هستند:
import { Component } from '@angular/core';
import '../../public/css/styles.css';

@Component({
      selector: 'my-app',
      template: require('./app.component.html'),
      styles: [require('./app.component.css')]
})
export class AppComponent { }
در اینجا معرفی template و css جداگانه‌ی تعریف شده‌ی در فایل‌های مجزای خودشان، توسط متد require مربوط به webpack انجام شده‌اند. مزیت آن این است که زمانیکه webpack کار bundling برنامه را انجام می‌دهد، تک فایل js حاصل، حاوی تمام فایل‌های html و css برنامه هم خواهد بود و دیگر نیازی به توزیع جداگانه‌ی آن‌ها نیست. به عبارتی شما در حین تهیه‌ی برنامه، inline کار نمی‌کنید، اما webpack آن‌ها را حین توزیع نهایی، به صورت خودکار تبدیل به قالب‌ها و شیوه‌نامه‌های inline می‌کند.
مطالب
بلاگر و دومین سفارشی

سلام؛ نوروز مبارک!
امیدوارم در این سال جدید برقرار به مانند سیسکو، محبوب مثل گوگل، پایدار همانند اینتل، به دور از گزند مثل ویندوز 7 و موفق همانند مایکروسافت باشید!

یک دامنه‌ی جدید به نام dotnettips.info برای وبلاگ تهیه و تنظیم کردم که شرح انجام آن برای علاقمندان به صورت زیر است:

الف) خرید یک دامنه (برای مثال من از اینجا تهیه کردم)
ب) تنظیمات CNAME و A Records آن دامنه
برای مثال ممکن است کنترل پنل دامنه‌ی شما به صورت زیر باشد. در این حالت به قسمت DNS مراجعه کرده:



و در ادامه تغییرات ذیل را اعمال نمائید:
در قسمت A Records چهار آدرس IP مربوط به گوگل باید وارد شوند:



4 رکورد جدید را باید ایجاد کنید:



سپس CNAME مربوط به بلاگر باید وارد شود:



ج) اکنون به تنظیمات بلاگ خود مراجعه کرده و نام دامنه جدید را وارد نمائید:



اعمال این تغییرات بین 7 ساعت تا 24 ساعت طول خواهد کشید (مدتی طول می‌کشد تا گوگل آدرس شما را فعال کند؛ مدتی هم طول خواهد کشید تا اطلاعات DNS شما در سراسر سرورهای مرتبط در دنیا به روز شود). بنابراین در این بین، انجام این تنظیمات و رها کردن سایت به حال خود کفایت می‌کند.

ماخذ IP ها و همچنین CNAME فوق مستندات رسمی گوگل است: (+)

اگر هم برای سایت خود یک فید از نوع feedburner ثبت کرده باشید، خوانندگان فید وبلاگ شما نیاز به هیچ نوع تغییر و تنظیمی نخواهند داشت.

مطالب
رفع تداخل jQuery با کتابخانه‌های مشابه

قبل از شروع، یک خبر!
VsDoc for jQuery 1.3.1 (جهت فعال سازی intellisense آخرین نگارش جی کوئری در VS.Net)


اگر سعی کنید jQuery را به همراه سایر کتابخانه‌های جاوا اسکریپتی دیگر به صورت همزمان استفاده کنید (مثلا mootools یا ASP.Net Ajax و امثال آن)، احتمالا قسمتی و یا تمامی کدهای جاوا اسکریپتی شما کار نخواهند کرد. برای مثال update panel شما در ASP.Net Ajax از کار می‌افتد، یا کدهای mootools شما دیگر کار نمی‌کنند. علت اینجا است که تمامی این کتابخانه‌ها از نشانه $ به عنوان متغیری عمومی که بیانگر نام مستعار کتابخانه مربوطه است استفاده می‌کنند و در نهایت تمام این‌ها با هم تداخل خواهند کرد.

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

<script type="text/javascript" language="javascript" src="jquery.min.js"></script>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready(function($) {
//tip-1
$("select > option").each(function() {
var obj = $(this);
obj.attr("title", obj.attr("value"));
});
//tip-1
});
</script>

کد مثال فوق، به تمامی آیتم‌های drop down list‌ های شما در یک صفحه، بر اساس value هر آیتم موجود در آن‌ها، یک tooltip اضافه می‌کند. (با IE7 به بعد و فایرفاکس سازگار است)
در اینجا ابتدا jQuery.noConflict فراخوانی شده و سپس document ready متداول هم باید اندکی مطابق کد فوق تغییر کند. مابقی کدهای شما از این پس نیازی به تغییر نخواهند داشت. (روش‌های دیگری هم برای تغییر نام $ وجود دارند که در مستندات مربوطه قابل مشاهده است)

مطالب
Http Batch Processing در Asp.Net Web Api
بعد از معرفی نسخه‌ی 2 از Asp.Net Web Api و  پشتیبانی رسمی آن از OData بسیاری از توسعه دهندگان سیستم نفس راحتی کشیدند؛ زیرا از آن پس می‌توانستند علاوه بر امکانات جالب و مهمی که تحت پروتکل OData میسر بود، از سایر امکانات تعبیه شده در نسخه‌ی دوم web Api نیز استفاده نمایند. یکی از این قابلیت‌ها، مبحث مهم Batching Processing است که در طی این پست با آن آشنا خواهیم شد.
منظور از Batch Request این است که درخواست دهنده بتواند چندین درخواست (Multiple Http Request) را به صورت یک Pack جامع، در قالب فقط یک درخواست (Single Http Request) ارسال نماید و به همین روال تمام پاسخ‌های معادل درخواست ارسال شده را به صورت یک Pack دیگر دریافت کرده و آن را پردازش نماید. نوع درخواست نیز مهم نیست یعنی می‌توان در قالب یک Pack چندین درخواست از نوع Post و Get یا حتی Put و ... نیز داشته باشید.  بدیهی است که پیاده سازی این قابلیت در جای مناسب و در پروژه‌هایی با تعداد کاربران زیاد می‌تواند باعث بهبود چشمگیر کارآیی پروژه شود.

برای شروع همانند سایر مطالب می‌توانید از این پست جهت راه اندازی هاست سرویس‌های Web Api استفاده نمایید. برای فعال سازی قابلیت batching Request نیاز به یک MessageHandler داریم تا بتوانند درخواست‌هایی از این نوع را پردازش نمایند. خوشبختانه به صورت پیش فرض این Handler پیاده سازی شده‌است و ما فقط باید آن را با استفاده از متد MapHttpBatchRoute به بخش مسیر یابی (Route Handler) پروژه معرفی نماییم.
public class Startup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            var config = new HttpConfiguration();           
          
            config.Routes.MapHttpBatchRoute(
                routeName: "Batch",
                routeTemplate: "api/$batch",
                batchHandler: new DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer));

            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "Default",
                routeTemplate: "{controller}/{action}/{name}",
                defaults: new { name = RouteParameter.Optional }
            );

            config.Formatters.Clear();
            config.Formatters.Add(new JsonMediaTypeFormatter());
            config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

            config.EnsureInitialized();          
            appBuilder.UseWebApi(config);
        }
    }

مهم‌ترین نکته‌ی آن استفاده از DefaultHttpBatchHandler و معرفی آن به بخش batchHandler مسیریابی است. کلاس DefaultHttpBatchHandler  برای وهله سازی نیاز به آبجکت سروری که سرویس‌های WebApi در آن هاست شده‌اند دارد که با دستور GlobalConfiguration.DefaultServer به آن دسترسی خواهید داشت. در صورتی که HttpServer خاص خود را دارید به صورت زیر عمل نمایید:
 var config = new HttpConfiguration();
 HttpServer server = new HttpServer(config);
تنظیمات بخش سرور به اتمام رسید. حال نیاز داریم بخش کلاینت را طوری طراحی نماییم که بتواند درخواست را به صورت دسته‌ای ارسال نماید. در زیر یک مثال قرار داده شده است:
using System.Net.Http;
using System.Net.Http.Formatting;

public class Program
    {
        private static void Main(string[] args)
        {
            string baseAddress = "http://localhost:8080";
            var client = new HttpClient();
            var batchRequest = new HttpRequestMessage(HttpMethod.Post, baseAddress + "/api/$batch")
            {
                Content = new MultipartContent("mixed")
                {                   
                    new HttpMessageContent(new HttpRequestMessage(HttpMethod.Post, baseAddress + "/api/Book/Add")
                    {
                        Content = new ObjectContent<string>("myBook", new JsonMediaTypeFormatter())
                    }),                   
                    new HttpMessageContent(new HttpRequestMessage(HttpMethod.Get, baseAddress + "/api/Book/GetAll"))
                }
            };

            var batchResponse = client.SendAsync(batchRequest).Result;

            MultipartStreamProvider streamProvider = batchResponse.Content.ReadAsMultipartAsync().Result;
            foreach (var content in streamProvider.Contents)
            {
                var response = content.ReadAsHttpResponseMessageAsync().Result;                
            }
        }
    }
همان طور که می‌دانیم برای ارسال درخواست به سرویس Web Api باید یک نمونه از کلاس HttpRequestMessage وهله سازی شود سازنده‌ی آن به نوع HttpMethod اکشن نظیر (POST یا GET) و آدرس سرویس مورد نظر نیاز دارد. نکته‌ی مهم آن این است که خاصیت Content این درخواست باید از نوع MultipartContent و subType آن نیز باید mixed باشد. در بدنه‌ی آن نیز می‌توان تمام درخواست‌ها را به ترتیب و با استفاده از وهله سازی از کلاس HttpMessageContent تعریف کرد.
برای دریافت پاسخ این گونه درخواست‌ها نیز از متد الحاقی ReadAsMultipartAsync استفاده می‌شود که امکان پیمایش بر بدنه‌ی پیام دریافتی را می‌دهد.


مدیریت ترتیب درخواست ها

شاید این سوال به ذهن شما نیز خطور کرده باشد که ترتیب پردازش این گونه پیام‌ها چگونه خواهد بود؟ به صورت پیش فرض ترتیب اجرای درخواست‌ها حائز اهمیت است. بعنی تا زمانیکه پردازش درخواست اول به اتمام نرسد، کنترل اجرای برنامه، به درخواست بعدی نخواهد رسید که این مورد بیشتر زمانی رخ می‌دهد که قصد دریافت اطلاعاتی را داشته باشید که قبل از آن باید عمل Persist در پایگاه داده اتفاق بیافتد. اما در حالاتی غیر از این می‌توانید این گزینه را غیر فعال کرده تا تمام درخواست‌ها به صورت موازی پردازش شوند که به طور قطع کارایی آن نسبت به حالت قبلی بهینه‌تر است.
برای غیر فعال کردن گزینه‌ی ترتیب اجرای درخواست‌ها، به صورت زیر عمل نمایید:
 config.Routes.MapHttpBatchRoute(
                routeName: "WebApiBatch",
                routeTemplate: "api/$batch",
                batchHandler: new DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer)
                {
                    ExecutionOrder = BatchExecutionOrder.NonSequential
                });
تفاوت آن فقط در مقدار دهی خاصیت ExecutionOrder به صورت NonSequential است.