تحديثات جديدة على lightado.net

مازلت أكمل مشواري في تعلم الكثير من المفاهيم حول ORM و احدث مكتبة lightado.net قدر المستطاع , هذا الاسبوع كان بامتياز العمل متواصل على تطوير المكتبة و اضافة الكثير من المميزات و ازالت بعض المشاكل السابقة, في البداية يمكنك الحصول على الـ lightado.net  من خلال Nuget :

image

إن أول ما ستلاحظه بعد التحديث هو حصولك على النسخة 2.0.0 و هذا يعني تغيرات جدرية حدث في هذه المكتبة جعلتني ارقيها من الاصدار 1.0.0 إلى 2.0.0 مرورا ب 1.0.0 و حتى 1.1.11 لان لنتحدث عن التغيرات الجدرية التي قمت بها:

لا مزيد من LightAdoExpcetion

وصلتي أكثر من بريد الكتروني يتحدث أنه يواجه مشكلة في عملية معالجة الاخطاء التي تصدر عن المكتبة حيث كان يجب على المطور أن يعالج الاخطاء يشكل التالي:

   1: try 
   2: {
   3: }
   4: catch(LightAdoException ex)
   5: {
   6: }
   7: catch(Excpetion ex)
   8: {
   9: }

استبدلت الشفرة الأن بـ
   1: try 
   2: {
   3: }
   4: catch(Exception ex)
   5: {
   6: }

و هذا يعني أنه استغنيت كليا على LightAdoException

الأحداث

أيضا قمت بإضافات مجموعة من الاحداث للكائن Query و NonQuery على النحو التالي
  • الحدث BeforeConnectionOpened
و هو حديث يقع قبل فتح الاتصال مع قاعدة البيانات.
  • الحدث AfterConnectionOpened
و يقع بعد فتح الاتصال بقاعدة البيانات .
  • الحدث BeforeConnectionClosed
و يقع قبل اغلاق الاتصال بقاعدة البيانات.
  • الحدث AfterConnectionClosed
و يقع بعد اغلاق الاتصال بقاعدة البيانات.
  • الحديثين BeforQueryEexecutee و BeforeNonQueryExecute
و كلاهما يقع قبل تنفيذ جملة الـ SQL .
  • الحديثين AfterQueryExecute و AfterNonQueryExecute
و كلاهما يقع بعد تنفيذ جملة الـ SQL .
image

الحدث OnError

و يقع عند حدوث خطئ في معالجة DataMapping او عند تنفيذ جملة الاستعلام و بالتالي يمكنك كتابة الشفرة التالية:
   1: try 
   2: {
   3: }
   4: catch(Exception ex)
   5: {
   6: }

بطريقة أفضل بشكل التالي:
   1: static void Main(string[] args)
   2: {
   3:     Query query = new Query();
   4:     query.OnError += OnError;
   5: }
   6:  
   7: private static void OnError(Exception ex)
   8: {
   9:     throw new NotImplementedException();
  10: }

لاحظ الأن أنني قمت بتبسط الأمر اكثر مما تتخيل حيث يمكنك معالجة جميع الاخطاء في مكان واحد عوضا عن استخدام جملة TryCatch مع كل Query او NonQuery

معاجلة القيمة Null

أثناء عملي و استخدامي للمكتبة لفترة الماضية لاحظة تكرار الشفرة التالية بشكل كثير جدا:


   1: User user = new Query().EexecuteToObject<User>("select * from users where ID = 10", System.Data.CommandType.Text);
   2:             if(user != null)
   3:             {
   4:                 // do what I want
   5:             }
   6:             else
   7:             {
   8:                 throw new ArgumentNullException("");
   9:             }

لاحظ الأن أنني اقوم أولا بتحقق من الكائن User موجود و غير فارغ قبل أن أبدأ التعامل معه و هو شيء جدا مزعج بنسبة لي على الاقل , لعلاج هذه المشكلة قمت بإعادة كتابة جميع الطرق بحيث يمكن لهذه الطرق أن تستقبل Exception في حالة كون الكائن Null و تقوم الطريقه نفسها بتحقق من الكائن اذا كان فارغا ترمي الـ Exception واذا لم يكن كذلك تعيد الكائن , الشفرة:

   1: User user = new Query().EexecuteToObject<User>(
   2:             "select * from users where ID = 10",
   3:              new ArgumentNullException(""), 
   4:             System.Data.CommandType.Text);

و بالتالي استغنيت كليا عن التحقق من قيمة الكائن كونه Null أو لا و جعلت هذه المهمة على مكتبة LightAdo.net لتفعل ذلك.

استقلالية التشفير

في السابق كانت المكتبة تفرض عليك استخدام التشفير الموجود بداخلها و ذلك من خلال تعين الـ class أو الـ Property كـ Ecrypted , الشفرة:


   1: [Encrypted]
   2: public class User
   3: {
   4:     public string Password { get; set; }
   5: }

أو

   1: public class User
   2: {
   3:     [Encrypted]
   4:     public string Password { get; set; }
   5: }

ما يحدث خلف الكواليس هو أن المكتبة تقوم باستدعاء الطريقة Ecnrypt من أجل التشفير و الطريقة Decrypt من أجل فك التشفير , و اجهتني مشكلة قبل يومين كنت التعامل مع قاعدة بيانات مشفرة أصلا بطريقة مختلفة عن مكتبة Lightado.net و كان يجب عليا إجاد حل لهذه المعضلة , دون أن احتاج إلى استدعاء تلك الطرق في كل مرة من أجل فكر التشفير و التشفير و استغلال قدرة Lightado.net على العمل بطريقة اتوماتيكية, كان الحل هو أن انشاء Class يحمل العنوان EncryptEngine حيث يحتوي هذا التصنيف على طريقتين abstract هما Ecrypt و Dcrypt حيث تأخذ كلاهما string و تعيد string و بتالي يمكنك اشتقاق هذا الـ class و افعل ما اريد في كلا الطرقتين حيث ستقوم LightADO.net استدعائهما من الـ Class الخاص بك و بالتالي تتحكم أنت بتشفير و طريقته , الشفرة:

   1: public class User
   2: {
   3:     [UserEcryptor]
   4:     public string Password { get; set; }
   5: }
   6:  
   7: public class UserEcryptor : EncryptEngine
   8: {
   9:     public override string Decrypt(string valueToDecrypt)
  10:     {
  11:         throw new NotImplementedException();
  12:     }
  13:  
  14:     public override string Encrypt(string valueToEncrypt)
  15:     {
  16:         throw new NotImplementedException();
  17:     }
  18: }

حماية خدمات WCF ( الجزء الخامس )

تحدث في المقالة السابقة كيف أنه يمكن استخدام الـ WSDL Offline كطريقة و وسيلة أمانه لحماية الخدمة و عدم عرضها على الملاء , و على الرغم من اننا قطعنا شوطا طويلا حتى الان في حماية خدمات الويب من الغرباء إلى أننا فعلا لم نفعل اي شيء لحماية خدمات الويب من الاصدقاء ما اقصده هنا بالأصدقاء هم الاشخاص الذين سيحصلون على Offline WSDL على الرغم من اننا نثق بهم نوعا ما إلى أنه يجب أن يحصل الاصدقاء إلا على ما يحتاجونه فعلا.
لنفكر مثلا بخدمة تقوم لعميلة التسديد لفاتورة ما حيث تحتوي الخدمة على ثلاثة طريقتين الطريقة الأولى من أجل طلب فاتورة جديدة حيث سيستخدم هذه الطريقة التطبيقات المختلفة لرفع فاتورة ما, بينما الطريقة الثانية تقوم بتأكيد عملية الدفع من قبل طرف ثالث حيث أن الطرف الثالث سوف يقوم بعملية التأكيد للفاتورة, و هنا يجب علينا الفصل بين الطرقتين حيث يجب أن يرى المستخدم الأول الطريقة التي تقوم بإنشاء فتورة فقط و الطرف الثالث الطريقة التي تؤكد على عملية الدفع, لنبدأ بعمل.
الخطوة الأولى: الحصول على الـ Offline WSDL , يمكنك استخدام الاداة المرفقة سواء Windows  أو على OSX , الصورة:

Screen Shot 2015-06-15 at 4.00.37 PM
بعد حصولك على ملف الـ WSDL افتح الملف بأي مفكرة ترغب هنا سأستخدم Visual Studio Code  , تتكون الفكرة من ثلاث خطوات الأولى ازالة الطرق غير اللازمة التي يجب على العميل ان لا يراها , ازالة المتغيرات التي تحتجاها هذه الطرق و اذا كانت الطريقة تعيد كائنا يجب ايضا أن يتم ازالتها.
الخطوة الثانية: ازالة الطرق, بعد حصولك على ملف الـ WSDL ابحث فيه عن الطريقة التي ترغب بإزالتها في مثالي هنا سأبحث عن الطريقة Initate payment , الشفرة قبل:
image
و الان للنظر لشفرة بعد ازالة الطريقة المذكورة سابقا:
image

الان سنتحاج إلى مسح جميع الكائنات التي تستخدمها هذه الطريقة, في العادة و اذا كان لا تستخدم Singel WSDL فإن جميع الكائنات تكون الملف XSD2 سأفتح الملف و ابحث عن الكائن PaymentRequest و الكائن , و الكائن PaymentRequestDetails  الشفرة قبل:
image
حيث ستصبح الشفرة بعد التعديل بشكل التالي:
image

سأحفظ الملف الأن و أبدأ باستخدامه مع مشروع تجربة لاحظ الصورة في الأسفل:
image
و بتالي تستطيع عزل المستخدمين بعضهم عن البعض دون الحاجة إلى بناء خدمات WCF جديدة أو بعثرتها بنشرها بين روابط مختلفة , في حين ان كلامها يستخدمان نفس الخدمة إلى أنه كل عميل سيرى ما يجب أن يراه فقط لا غير .

حماية خدمات WCF ( الجزء الرابع )

مرحبا تحدث في المقالات السابقة عن حماية خدمات الـ WCF سواء بواسطة استخدام الـ Ceritifcate  او باستخدام كلمة المرور و اسم المستخدم , في هذه المقالة سأتحدث عن حماية خدمات الويب من خلال عدم توفيرها للعامة , بمعني أخر لا يمكن الوصول للـ WSDL عن طريق المتصفح , حيث يجب على من يرغب التواصل مع الخدمة الحصول على ملف الـ WSDL كاملا أو جزء منه على حسب رغبتك وهو ما سأتحدث عنه في المقالة القادمة. تسمى هذه الطريقة بـ Offline WSDL و تعني الحصول على نسخة من الـ WSDL حيث ترسل هذه النسخة إلى العميل, من جهة العميل يقوم هو بتوليد الشفرة التي يحتاجها من أجل العمل من خلال ذلك الملف, لنبدأ:
الخطوة الأولى: الحصول على ملف الـ WSDL من أجل مشاركته مع العميل, يمكنك تشغيل الأداة Take WSDL Offline لعمل ذلك, افتح الاداة ثم اكتب الرابط الذي ترغب به , لاحظ أن الاداة سوف تقوم بتوليد كافة محتويات الـ WSDL بما في ذلك ملفات الـ XSD ,
Capture
Capture3
Capture4
الخطوة الثانية : الأن و قد حصلت على ملف الـ WSDL يمكنك بكل بسطة تعين الخاصية httpGetEnabled و httpsGetEanbled إلى false هذا سيجبر العميل على استخدام الـ offline WSDL بدل عن استخدام الرابط للوصول إلى الـ WSDL الشفرةم
   1: <behaviors>

   2:       <serviceBehaviors>            

   3:           <behavior name="MyServiceBehavior">

   4:             <serviceMetadata httpGetEnabled="false"  httpsGetEnabled="false"  />

   5:             <serviceDebug includeExceptionDetailInFaults="true"/>

   6:           </behavior>

   7:       </serviceBehaviors>

   8:   </behaviors>

اذا حاول العميل الأن الوصول للخدمة عن طريق الـ HTTP أو اي متصفح سيحصل على رسالة الخطأ Bad Request 400 , في الختام لماذا احتاج إلى عمل هذا الأمر, بكل بساطة لحماية الخدمة من المتطفلين لو كانت الخدمة مثلا مرفوعة على Server متصل بالويب سيكون امكانية الوصول امر غاية في السهولة من خلال استخدام أدوات الاستكشاف المختلف للموقع, لكن مع توفير هذه الطريقة فأنت ستكون متأكد بنسبة كبيرة جدا جدا بأن الشخص الذي يحاول التواصل معك هو الشخص المرخص و الذي حصل عى ملف الـ WSDL منك أنت.

حماية خدمات WCF ( الحزء الثالث )

مرحبا, تحدث في المقالات السابقة عن كيفية حماية خدمات الـ WCF باستخدام الـ Ceritifcate , سأتحدث في هذه المقالة عن حماية خدمات الـ WCF باستخدام كلمة المرور و اسم المستخدم و كيف  تتم عملية الـ Consuming لهذه الخدمة, سأقوم هنا بإنشاء مشروع WCF جديد, سوف يكون عملنا بأكمله تقريبا في ملف الويب Config .
بناء الخدمة
الخطوة الأولى عمل الـ Binding : سوف نحتاج أن نخبر الـ WCF بان هذه الخدمة تستخدم كلمة مرور و اسم مستخدم من أجل التحقق قبل تنفيذ أي اوامر , الشفرة:
   1: <bindings>

   2:   <basicHttpBinding>

   3:     <binding name="basicHttpBinding">

   4:       <security mode="TransportWithMessageCredential">

   5:         <message clientCredentialType="UserName"/>

   6:       </security>

   7:     </binding>

   8:   </basicHttpBinding>

   9: </bindings>

 الخطوة التالية: تحديد الـ Behavior من أجل تسجيل الدخول , يحث يمكنك استخدام الـ Active Dreicotry او Membership Provider أو ان تقوم بعمل شيء خاص بك, أعتقد أن الأول و التالي ابسط من أن نتحدث عنه لذلك سأقوم هنا بالحديث عن النوع الثالث و هو الـ Custom أضف Class جديد إلى المشروع و اسمه UserAuthecation او كما ترغب, الشفرة


   1: <behaviors>

   2:   <serviceBehaviors>

   3:     <behavior name="DefaultBehavior">

   4:       <serviceCredentials>

   5:         <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFDemo.UserAuthcation, WCFDemo"/>

   6:       </serviceCredentials>

   7:       <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>

   8:       <serviceDebug includeExceptionDetailInFaults="false"/>

   9:     </behavior>

  10:   </serviceBehaviors>

  11: </behaviors>

الخطوة الثالثة: علينا ربط كلا من الـ Binding و الـ behavior مع الـ Service و الشفرة:


   1: <services>

   2:   <service  name="WCFDemo.Service1" behaviorConfiguration="DefaultBehavior">

   3:     <endpoint bindingConfiguration="basicHttpBinding" contract="WCFDemo.IService1" binding="basicHttpBinding"/>

   4:   </service>

   5: </services>

الخطوة الرابعة: يجب أن تلاحظ الأن اذا حاولت تشغيل الخدمة ستطلب منك أن تستخدم HTTPS و ليس HTTP , في الـ IIS يجب أن تقوم بتفعيل الـ HTTPS , و لكن نحن حاليا في عملية التطوير حدد المشروع من نافذة Solution Exploere اضغط بزر الفأرة الأيمن  ثم اضغط على Ctrl + W + P ستظهر نافذة Properties في النافذة حدد SSL Enabled و عدلها إلى True .

image

الخطوة الخامسة: الأن أصبح إعدادات الخدمة جاهزة إذا حاولت تشغيل الخدمة ستجد بأنها تخبرك بأن الـ Class WCFDemo.UserAuthcation لم يشتق بعد من التنصيف UserNamePasswordValidator , و هو الخطوة الخامسة من أجل بناء تحقق خاص بنا, اشنق UserAuthcantion من UserNamePasswordValidator الموجود في الـ Reference : System.IdentityModel , هذا التصنيف عبارة عن abstract لذلك ستحتاج إلى وجود الطريقة الـ Validate , الشفرة:


   1: namespace WCFDemo

   2: {

   3:     using System.IdentityModel.Selectors;

   4:     using System.ServiceModel;

   5:  

   6:     public class UserAuthcation : UserNamePasswordValidator

   7:     {

   8:         public override void Validate(string userName, string password)

   9:         {

  10:             if(userName != "ALGHABBAN" && password != "123456")

  11:             {

  12:                 throw new FaultException(new FaultReason("User not Authenticat"), new FaultCode("401"));

  13:             }

  14:         }

  15:     }

  16: }

الشفرة في الأعلى ليست اختراع قنبلة ذرية كل ما في الأمر أنني أتحقق من اسم المستخدم و كلمة المرور في حالة أنهما غير متوافقة لما اريد أقوم برمي Fault Exception موضحا للمستخدم أن المستخدم غير مرخص له استخدم هذه الخدمة , شغل الخدمة الأن و حاول استخدام WSDLER معها.

Test1

test2

test3

test4

test6

test66

لاحظ في الصورة الأخير فقد تم إنشاء Time Stamp لعميل تسجيل الدخول لمدة خمسة دقائق , الأن نأتي لعملية الـ Consuming لهذه الخدمة من قبل الـ .net Application.

الـ Consuming للخدمة

لبدء العمل افتح مشروع جديد كما يحلو لك هنا سأقوم باستخدام الـ Console Application سأضيف Service كالمعتاد عن طريق شاشة Add Reference لأحظ أنه لا يمكنك استخدام Add Web Reference كما هو الحال مع asmx سابقا, المهم , بعد اضافة الخدمة إلى المشروع يمكنك مباشرة كتابة الشفرة التي تريد , لاحظ هنا كيف يتم تمرير كلمة المرور و اسم المستخدم, الشفرة:


   1: Service1Client client = new Service1Client();

   2: client.ClientCredentials.UserName.UserName = "alghabban";

   3: client.ClientCredentials.UserName.Password = "123456";

   4: System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

   5: Console.WriteLine(client.GetData(0));

   6: Console.ReadLine();



test65677

trest623043

test4755

تحميل نسخة من المشروع