تحديث شيفرة المصدر للإصدارة الأولية من ASP.NET MVC

مؤخراً قمنا بافتتاح مشروع جديد على ASP.NET CodePlex والذي سوف يدعم استعمال الإصدارات الأولية مع (شيفرة المصدر Source Code) لعدد من الإضافات والمزايا الجديدة المتعلقة بالـASP.NET. الشهر الماضي استعملنا هذا المشروع لإصدار النقطة الأولى في شيفرة المصدر لـ ASP.NET MVC. هذه النقطة احتوت على شيفرة المصدر للإصدارة الأولية الثانية والتي شحنت خلال حدث MIX بالإضافة إلى ملفات المشاريع الخاصة بالـ Visual Studio والتي تمكنك من إصلاح وبناء هذه النسخة بنفسك.

قبل بضعة ساعات قمنا بإصدار تحديث لكود المصدرلـ ASP.NET MVC على الموقع ، هذا التحديث ليس إصدارة أولية جديدة من الـ ASP.NET MVC ، بل على العكس إنها نقطة مؤقتة تقدم نظرة إلى الوضع الحالي الذي وصلته شجرة المصدر. سوف يتم شحن الإصدار الأولية الثالثة من الـ ASP.NET MVC  خلال عدة أسابيع قادمة بعد أن يتم الانتهاء من بعض الأعمال (مزايا جديدة والتحسين على بعض المزايا الموجودة ، تحسينات على التوافق مع VS ، دعم لـ VS express edition ، التوثيق ... الخ). إذا كنت  تريد تنصيب نسخة ASP.NET MVC  خالية من العيوب مع التوثيق والدعم فعليك أن تنتظر على الأرجح لحين إصدار النسخة الرسمية من هذه الإصدارة الأولية. وأما إذا ممن يحبون أن يحصلوا على فرصة مبكرة للنظر إلى" نسخة أولية من النسخة الأولية"وأن يكون لك الفرصة في أن تبدأ باستعمال وإبداء آرائك بخصوص بعض المزايا مباشرة فالنظر إلى هذا  التحديث لشيفرة المصدر سيكون ممتعاً.

التحسينات على هذا التحديث لشيفرة المصدر لـ ASP.NET MVC

  • إن تحديثات هذا الأسبوع (والتي يمكنك أن تقوم بتحميلها من هنا) تحتوي على عدد من التحسينات على الـ ASP.NET MVC. بعضها يشتمل على:
  • بالإضافة إلى وجود شيفرة المصدر لـهيكل ASP.NET MVC قمنا أيضاً بوضع شيفر المصدر لاختبارات الوحدة unit test التي يمكنك استعمالها، هذه الاختبارات أعدت بواسطة الـ MSTest وهيكل Moq مفتوح المصدر. كما وتم وضع ملف مشروع VS2008 لاختبارات الوحدة لتسهيل بناء وتشغيل الاختبارات من خلال بيئة التطوير المتكاملة VS2008 .
  • بشكل ملحوظ تم دعم اختبارات دوال الـ Controllers . مما يمكنك من اختبار السيناريوهات الشائعة لـ Controllers دون أن يـتوجــب عليك ختبار أية objects (المزيد من التفصيل عن كيفية عمل ذلك تأتي لاحقا )
  • مجموعة من المزايا الإضافية الجميلة وتحسينات على نظام تحويل العناوين URL routing  تساعد على سهولة الاستخدام(التفاضيل في الأسفل).
إنشاء مشروع جديد لـ  ASP.NET MVC:

يمنكن أن تقوم ببناء نسختتك الخاصة من ASP.NET MVC من الملفات التنفيذية assembly بتحميل شيفرة المصدر لـ MVC ومن ثم تجميعها compile على جهازك الخاص. أو بدلاً من ذلك يمكنك أن تقوم بتحميل حزمة القوالب الخاصة بـ VS لتبدأ بنسخة مبنية بشكل مسبق لتسعملها عن طريق الـ VS والذي يمكنك وبشكل سريع بأن تبني مشروع ASP.NET MVC جديداً لتستعمل آخر التحديثات.

بعد أن تقوم بتنصيب تحديث شيفرة المصدر لـ ASP.NET MVC ، ستلاحظ وجود "برنامج ASP.NET MVC" مندرجا تحت جزء "قوالبي الخاصة" في شاشة "مشروع جديد"

هذه النسخة الجديدة من "قوالبي الخاصة" التي تخص قوالب مشروع MVC ستدوم مع وجود النسخة الأولية الثانية من ASP.NET MVC (والتي ستجدها مندرجة تحت قائمة القوالب الأساسية في الشاشة ). هذا يسمح لك ببناء مشاريع جديدة وأيضاً باستعمال آخر إصدارة من من شيفرة المصدر وأيضاً باستعمال آخر إصدارة رسمية من الإصدارات المبدئية على نفس الجهاز.

عندما تقوم بإنشاء مشروع جديد باستخدام النسخة المحدثة من قالب مشروع الـ ASP.NET MVC ، يمكنك بشكل أساسي أن تحصل على مشروع يظهر بهذا الشكل:

هذا المشروع الجديد يحتوي على متحكم Controller واحد ("Home Controller ") تحت مجلد "Controllers" كما ويحتوي على قوالب لشاشاتين views  هما ("Index" و"About") تحت المجلد الفرعي "Views\Home". كلا هذان القالبان يعتمدان على شاشة رئيسية عامة واحدة لهذا الموقع تسمى ("Site.master")، كل ملفات الـ style تعرف في ملف "Site.css" وتندرج تحت مجلد "\Content".

عندما تقوم بتشغيل البرنامج في إن خادم الويب المدمج سوف يقوم وبشكل أتوماتيكي بالبدء وسوف يظهرصفحة البداية home في الموقع.

إذا قمت بالضغط على "About us" سوف تظهر محتوى شاشة "About":

إن دالة المتحكم بصفحة البداية "Home controller" في هذا المشروع هي المسؤولة عن معالجة كلا العنوانين URLs وسوف يحتوي على خوارزميتين كالآتي

إن قالب الصفحة الرئيسية "Site.master" يبحث عن قيمة "Title" في مجموعة  الـ ViewData ويستعملها لعرض عنصر الـ <title> في صفحة الـ HTML. إن قالب شاشة "Index" يبحث أيضاً عن قيمة "Message" ويستعملها لعرض رسالة الترحيب التي تظهر في الصفحة الرئيسية في الموقع. يمكنك وبشكل واضح من أن تخصص هذه الملفات متى شئت.

 

Controller Changes with this ASP.NET MVC Drop نقطة  تغيير المتحكم Controller في الـ ASP.NET MVC:

إذا كنت تقرأ شيفرة المصدر أعلاه فسوف تلاحظ وبشكل قريب التغيير الذي طرأ على الطريقة التي صنعت بها دوال الـ Controller باستعمال القطرة الجديدة لـتحديث شيفرة المصدر لـ ASP.NET MVC. باستعمال الإصدارة الأولية الثانية من ASP.NET MVC سوف تكون خوارزميات المتحكم Home Controller تبدو بهذا الشكل

إن فريق الـ MVC  يتختبرون بعض المزايا الجديدة في قطرة هذا الأسبوع كما ويحاولون في بعض الأفكار الجديدة:

  1. إن خوارزميات العملAction  في دوال المتحكم أصبحت الآن بشكل اساسي ترجع كائن "ActionResult" بدلاً من لا شيء void. إن كائن الـ، Action Result هذا يحدد نتيجة العمل (إظهار شاشة ، توجيه إلى عنوان URL آخر ، أو أي عمل آخر توجيه/تنفيذ ... الخ ).
  2. إن الخوارزميات المساعدة : RenderView، RedirectToAction،Redirect الموجود في الدالة المتحكم Controller الأساسية base أصبحت ترجع كائن ActionResult يمكن معالجته بشكل أوسع أو إرجاعه إلى خوارزميات العمل.
  3. إن خوارزمية RenderView يمكن أن تدعى بدون الحاجة إلى تمرير اسم قالب الشاشة الذي يراد إظهاره بشكل خارجي. عندما تسقط اسم القالب فإن خوارزمية RenderView سوف تستعمل خوارزمية العمل على اساس أنها هي اسم الشاشة التي يراد إظهارها. فقط قم باستدعاء RenderView بدون تمرير parameters  لخوارزمية العمل "About" سوق يقوم بعمل نفس الشيء كما لو استعملت RenderView("About")

أصبح من السهل جداً أن يتم تحديث دوال Controller الموجودة في الإصدارة الابتدائية الثانية لتقوم باستخدام هذا النمط الجديد (فقط قم تبغيير Void إلى ActionResult وقم بإضافة جملة return في بداية مناداة خوارزمية المساعدة RenderView أو RedirectToAction ).

إرجاع كائنات ActionResult من خوارزميات العمل :

إذن لماذ تم تغيير خوارزميات دوال التحكم لتقوم بإرجاع كائنات ActionResults بدلاً من لا شيء void ؟ إن عدداً من هيكليات Web-MVC تستعملطريقة  إرجاع الكائن (مثل Django,Tapestry و هيكليات أخرى) كما وجدنا فوائد أخرى يمكن تحقيقها لـ ASP.NEt MVC مثل:

  1. إنها توفر طريقة أسهل لدعم اختبارات الوحدة على دوال التحكم. لست بحاجة بعد الآن أن تقوم بعمل mock للخوارزميات في كائن الـ response أو كائنات الـ ViewEngine  لتقوم بعمل اختبارات الوحدة على أداء خوارزميات العمل. بدلاً من ذلك يمكنك وبكل بساطة أن تقوم بعمل assert للشروط التي تستخدم كائن الـ ActionResult العائد من مناداة وارزمية الهمل ضمن اختبار الوحدة (سوف يتم شرح ذلك في المقطع القادم).
  2. يمكمك أن تجعل هدف منطق المتحكم Controller أوضح قليلاً وأن يصبح بشكل خارجي أكثر في بعض السيناريوهات عندما يكون هناك احتمال لأن يعود نتيجتين مختلفتين بالاعتماد على بعض الشروط (فمثلاً إعادة التحويل إذا حصل الشرط أ أو إظهارالشاشة إذا لم يحصل هذا الشرط ). هذا يمكنك من قراءة وتتبع خوارزميات عمل معقدة في المتحكم.
  3. إنه يمكنك من تفعيل بعض السيناريوهات المعقة واللطيفة عندما يمكن لـ FilterActionAttribute أن يأخذ نتيجة خوارزمية العمل ويقوم بتعجيل وتحويل هذه النتيجة قبل أن يككل تشغيلها. فمثلاُ أمر"تصفح" في متحكم "ProudcutCatalog" يمكن أن يقوم بإرجاع RenderActionResult التي تحدد أنها يجب أن تقوم بعرضا شاشة قائمة المنتجات. إن FilterActionAttribute يمكنك وبشكل تعريفي Declaratively أن يعرف في دالة المتحكم ومن ثم يمكن أن تكون هناك فرصة لتخصيص قالب شاشة عرض القائمة التي يراد عرضها من أن تكون من نوه html.aspx أو list-xml.aspx بالاعتماد على النوع المفضل من الوسائط المتعددة MIME  لدى المستخدم. إن وجود العديد من FilterActionAttribute  يمكنك وبشكل اختياري أن تسلسلها لتتبع النتائج من واحدة للأخرى.
  4. إنه يوفر ميكانيكة للتوسع extensibility للناس(بما فيهم أنفسنا) ليتمكنوا من إضافة بعض المزايا في المستقبل. إن أنواع ActionResult يمكنها وبكل سهولة أن تخلق بالوراثة من دوال الأساس ActionResult  ويمكن Override خورازمية "ExecuteResult". وسوف يكون من السهل جداً أن تنشئ خورازمية مساعدة "RenderFile()" فمثلاُ إن مطور البرنامج يمكنه أن يكتب أمراً action ليرجع كائنا جديداً من "FileActionResult".
  5. سوف يكون من السعل أن تقوم ببعض السناريوهات التنفيذية الغير متزامنة في المستقبل ، إن خوارزميات العمل سوف تتكمكن من إرجاع كائن AsyncActionResult الذي يدل على أن هذه الخوارزمية تتنظر في عملية شبكة وأنها تريد منح الـ thread الفاعل لـ ASP.NET بحيث يمكنها أن تطبق خوارزميات أخرى حتى تكتمل خوارزمية الشبكة. هذاي يمكن المطورين من أن يتجنبوا توقف الـ threads على الخادم ويقوموا بدعم شيفرة فعالة وقابلة للتطويرو والتوسع.

إن بعضا من اهداف هذه المراحعة المرحلية هو أن تعطي الناس فرصة للعمل على هذا التوجه الجديد وعمل بعض البرامج الحقيقة والتعلم في إطار هذا التوجه.

سوف نقوم بعمل دالة اساسية جديدة للمتحكم مما يجعل من الممكن استعمالها إذا كنت تفضل العمل على توجه أوامر void. إننا تأنينا في عدم إدراج هذا البديل في نقطة المراجعة هذه لأن هذا سوف يثبط بعض الناس عن استعمال توجه "ActionResult" مما يمنعنا من الاستفاة من مراجعاتهم الناتجة عن تطبيقه في برامجهم.

 

كيف تختبر دوال العمل في دوال المتحكم

لقد وضحت آنفاً أن توجه الـ ActionResult الجديد يمكنك من أن تقوم بعمل اختبارات الوحدة على دوال المتحكم بشكل أسهل (ويجنبك الحاجة إلى أن تقوم Mock في بعض السيناريوهات) دعنا نتحدث عن هذا الموضوع من خلال هذا المثال العملي.

لنفترض دالة متحكم بالأرقام بسيطة NumberController:

إن دالة المتحكم هذه تحتوي على خوارزمية عمل "IsEvenNumber" والتي تأخذ رقماً على شكل قيمة للعنوان URL argument. إن خوارزمية العمل IsEvenNumber تفحص أولاً إذا كان الرقم سالباً -في حالة كهذه لتحول المستخدم إلى صفحة خطأ- إذا كان الرقم موجباً فإنها تحدد إذا كان الرقم زوجياً أم فردياً ، وتقوم بعرض شاشة تختوي على الرسالة المناسبة.

لكتابة اختبار الوخد خوارزمية العمل IsEvenNumber فإن هذا سهل جداً ويعود الفضل في ذلك إلى ActionResult. في الأسفل مثال على اختبار الوحدة التي يتحقق من أن حصول عملية http صحيحة لتحويل المستخدم عندما يكون الرقم الذي أدخله المستخدم سالباً فمثلاً (/Number/IsEvenNumber/-1) تنتج:

لاحظ في الأعلى كيف أننا لم نحتج إلى عمل Mock لأي من الكائنات لننجح في اختبار خوارزمية العمل الخاصة بنا. بلاً من ذلك وبكل بساطة قمنا بإنشاء كائن جديد من دالة المتحكم ونادينا خوارزمية العمل مباشرة وقمنا بتمرير الرقم السالب لها وقمنا بإعطاء النتيجة القادم منها إلى تغير باسم "result". ولقد قمت باستعمال نمط "as type" المتوفر الـ C# لتحويل النتيجة إلى دالة HttpRedirectResult.

إن من الجميل في الـ C# أن تستعمل الكلمة المفتاحية "as" لأنها سوف تقوم بتخزين القيمة كـ null في حالة ان التحويل لم يكن صالحاً بدلاً من إحداث تجاوز exception (فمثلاً إذا كانت خوارزمية العمل ترجع RenderViewResult بدلاً من ذلك). هذا يعني أنه من الممكن وبسهولة أن تقوم بإدارج فحص جازم في اختبار الوحدة ليتحقق من أن النتيجة ليست null للتحقق من أنHttp لإعادة تحويل العنوان سوف تحصل. ويمكن إضافة فحص جازم آخر للتحقق من أن هذا هو العنوان URL الصحيح الذي سوف يتم التحويل إليه.

إن سيناريو الاختبار هذا عندما لا يتم تمرير أصفار سوف ينجح بشكل سهل أيضاً. لنحقق هذا وبشكل جيد سوف نقوم بإنشاء خوارزميتين للاختبار واحدة لفحص الأرقام الزوجية وأخرى لفحص الأرقام الفردية. في كلا الفحصين سوف نعمل على الجزم بانRenderViewResult سوف تكون هي النتيجة وأن نتأكد من الرسالة التي سوف يتم تمريرها إلى الـ ViewData المرتبطة بالشاشة.

يمكننا من خلال استعمال أمر الـ "Run Test " الموجود في القائمة التي سوف تظهر عندما ننقر على الزر الأيمن للماوس على ملف الاختبار في بيئة VS2008

هذا الأمر سوف ينفذ خوارزميات الاختبار الثلاثة  التي قمنا بكتابتها وسف تتنفذ في الذاكرة ولن يكون هناك حاجة لوجود خادم ويب وسوف يظهر التقرير الذي يظهر بأن خوارزمية NumberController.IsEvenNumber تنفذ بالشكل الصحيح.

ملاحظة: في قطرة هذا الأسبوع سوف تحتاج إلى استعمال mocking لتنجح في اختبار خاصية TempData في المتحكم. إن خطتنا تقضي بعدم الحاجة إلى عمل mock أثناء الاختبار عندما تصدر الإصدارة الأولية الثالثة من ASP.NET MVC للأسابيع القادمة.

الخوارزمية المساعدة MapRoute

إن قواعد إعادة توجيه العناوين URL في الـ ASP.NET MVC بشكل اساسي توضح في خوارزمية الـ RegisterRoutes في ملف دالة الـ Global.asax

باستعمال النسخ الأولية لـ ASP.NET MVC الأولى والثانية فإن إعادة التحويل routes كانت تضاف إلى مجموع الـ routs عن طريق خلق كائنRoute جديد وربطه مباشرة بدالة MvcRouteHandler ومن ثم بتعريف قيم الخصائص المناسبة فيه ليتم تعريف قواعد إعادة التحويل

إن الشيفرة أعلاه سوف تستمر في العمل في المرات القادمة ، علماً أن سوف يمكنك أيضاً من تستفيد من خوارزمية المساعدة MapHelper الجديدة والتي سوف تقدم طريق أسهل لعمل نفس الشيء. في الأسفل يمكن النظر إلى الطريق الرسمية لعمل إعادة توجيه لـ URL عن طريق الإعداد الأساسي عندما يتم إنشاء مشروع MVC جديد (وهذه الشيفرة تستبدل الشيفرة السابقة أعلاه)

إن خوارزمية العمل MapRoute المساعدة تتوفر بعدة صيغ بعضها يحتاج إلى تمرير متغيرين أو ثلاث أو أربع متغيرات مثل (route name, URL syntax, URL parameter default, and URL parameter regular expression constraints). 

يمكنك مناداة MapRoute قدر ما تشاء من المرات التي تريد أن تسجل فيها أسماء مختلفة من إعادة التحويل route في البرنامج. فمثلاُ بالإضافة إلى القاعدة الأساسية يمكنك أن تضيف قاعدة لإعادة تحويل "Proudcts-Brows" بهذا الاسم مثل الآتي:

عندها يمكن أن نرجع إلى هذه القاعدة "Products-Browse" بشكل خارجي من خلال دوال المتحكم والشاشات views  عندما نريد أن ننشئ عنواناً لها URL. فمثلاً يمكنك أن تستعمل مساعد الشاشة Html.RouteLink لتحدد أنه يمكن أن توصل إلى إعادة التحويل "Products-Browse" وأن تمرر لها متغير لعنوان التصنيف باسم"Food" باستعمال الشيفرة في الشاشة مثلما يظهر في القالب هنا:

إن مساعد الشاشة هذا يسوف يمكنك من أن تتوصل ‘لى نظام إعادة التحويل وأن تظهرعنوان الوصلة التشعبية HTML hyperlink URL الملائم (لاحظ كيف أنه تم اقتاطع متغير اسم الصنف من العنوان بشكل اتوماتيكي باستعمال قاعدة التحويل )

ملاحظة: في قطرة هذا الاسبوع أن تحتاج لأن تمرر المتحكم ومتغيرات الأمر (بالإضافة إلى متغير اسم الصنف) إلى الخوارزمية المساعدة  Hrml.RouteLink ليتمكن من أنتاج العنوان الصحيح. إن الإصدارة الأولية الثالثة لـ ASP.NET MVC في الأسابيع القادمة سوف لن تحتاج إلى هذا وسوف تسمح لك باستعمال Html.RouteLink مثلما فعلت في المثال أعلاه بالضبط لإنتاج إعادة التحويل.

مزايا إعادة تحويل عناوين

قطرة شيفرة الـ MVC لهذا الأسبوع تدعم أيضاً مزايا تحويل عناوين جديدة. يمكنك إضافة هذه الرموز ".",";","," وأية رموز أخرى ترغب أن تكون ضمن قواعد إعادة التوجيه. فمثلاً إن استعمال فاصل "-" يمكنك من أن تترجم قيم اللغةlanguage والخصائص المحلية locale من العنوان URL بشكل منفصل مثل الآتي:

إن هذا سوف يقوم بتمرير متغيرات "اللغة " و"الخصائص المحلية" و"الصنف" إلى دالة المتحكم ProductsController استعرض خوارزميات العمل عندما يتم تشغيلها:

قاعدة إعادة توجيه العنوان URL

مثال على العنوان URL

المتغيرات التم تم تمريرها إلى خوارزمية العمل

{language}-{locale}/products/browse/{category}

 

 

 

/en-us/products/browse/food

 

 

 

language=en, locale=us, category=food

 

 

 

 

 

 

 

/en-uk/products/browse/food

 

 

 

language=en, locale=uk, category=food

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

أو يمكنك استعمال "." لامتداد الملف في نهاية العنوان لتحدد هل يجب أن تظهر النتيجة بشكل ملف xml أو html

هذا سوف يكون بتمرير متغييرات "category" و"format" إلى متحكم المنتجات ProductsController ، استعرض خوارزميات التشغيل عند تشغيلها:

مثال على العنوان URL

مثال على العنوان URL

المتغيرات التم تم تمريرها إلى خوارزمية العمل

products/browse/{category}.{format}

 

 

 

/products/browse/food.xml

 

 

 

category=food, format=xml

 

 

 

 

 

 

 

/products/browse/food.html

 

 

 

category=food, format=html

 

 

 

 
 
 
 
 
 
 
 
 

 

 

 

 

 

 

إن الإصدارة الأولية الثانية من ASP.NET MVC قدمت قواعد إعادة توجيه wildcard فمثلاً يمكنك أن تحدد في إحدى هذه القواعد كل ما تبقى من مكونات URI على أساس أنها متغيرات لخوارزمية عمل:

هذا سوف يمرر متغير "contentUrl" إلى خوارزمية عمل  WikiController.DisplayPage عندما يتم تشغيلها:

مثال على العنوان URL

مثال على العنوان URL

المتغيرات التم تم تمريرها إلى خوارزمية العمل

Wiki/Pages/{*contentUrl}

 

 

 

/Wiki/Pages/People/Scott

 

 

 

contentUrl="People/Scott"

 

 

 

 

 

 

 

/Wiki/Pages/Countries/UK

 

 

 

contentUrl="Countries/UK"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

إن هذه القواعد wildcards سوف تستمر بالعمل بشكل جيد ضمن الإصدارة الأولية لهذا الأسبوع وسوف تكون مفيدة جداً إذا كنت تنوي بناء نظام مدونات، أوموسوعات wiki أو نظام إدارة المحتوى cms أو أي نظام آخر لإدارة المحتوى.

لاحظ أن هذه الإضافة سوف تستعمل في نظام إعادة التوجيه الجديد لـ ASP.NET MVC وإننا نستعمل نفس النظام في ASP.NET Dynamic Data ضمن الـ ASP.NET Windows Forms

الملخص

أتمنى أن هذه المشاركة أعلاه توفر تحديثاً سريعا لبعض المزيا الهامة والجديدة والتغييرات التي سوف تعرض في نقطة التحديث لـ ASP.NET MVC هذا الاسبوع. يمكنك أن تقوم بتحميلها من هنا إذا أردت أن تبدأ العمل مباشرة. بدلاً من ذلك يمكنك أن تنتظر للأسابيع المقبلة حتى يتم إصدار الإصدارة الرسمية من الإصدارة الأولية الثالثة لـ ASP.NET MVC والتي سوف تحوي بعض المزايا إضافية (وسف يتم مراجعات وملاحظات من المستخدمين حول قطرة هذا الأسبوع)، برنامج سهل للتنصيب ، تكامل أفضل مع بيئة التطوير VS وتوثيق محدث.

لأية اسئلة أو مشاكل حول قطرة هذا الأسبوع من ASP.NET MVC تأكد من مراجعة منتدى ASP.NET MVC forum على موقع www.asp.net

أتنمى أن اكون قد أفدتكم

Scott

يمكنكم الإطلاع على  المشاركة الأصلية عن طريق هذه الوصلة على مدونة Scott باللغة الإنجليزية بتاريخ 17-4-2008

Published Sunday, April 27, 2008 8:52 AM by IsToFix
Filed under: , ,

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)