<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://www.dotnetzone.gr:443/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Nikos Makris' Blog</title><link>https://www.dotnetzone.gr:443/cs/blogs/nikosm/default.aspx</link><description>Blog για Microsoft .NET τεχνολογίες (και όχι μόνο)...</description><dc:language>el</dc:language><generator>CommunityServer 2.1 SP3 (Build: 20423.1)</generator><item><title>Singleton Patterns in C#</title><link>https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/2008/01/05/singleton-patterns-in-c.aspx</link><pubDate>Sat, 05 Jan 2008 17:48:24 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:38814</guid><dc:creator>Nick Makris</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/blogs/nikosm/comments/38814.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/blogs/nikosm/commentrss.aspx?PostID=38814</wfw:commentRss><wfw:comment>https://www.dotnetzone.gr:443/cs/blogs/nikosm/rsscomments.aspx?PostID=38814</wfw:comment><description>&lt;p&gt;Πολύ ενδιαφέρον posting για Singleton Patterns σε C# (και με κάποιες αναφορές στην αντίστοιχη υλοποίηση σε Java). &lt;/p&gt; &lt;p&gt;&lt;a title="http://www.yoda.arachsys.com/csharp/singleton.html" href="http://www.yoda.arachsys.com/csharp/singleton.html"&gt;http://www.yoda.arachsys.com/csharp/singleton.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;... το πέμπτο pattern είναι και το πιο ενδιαφέρον (κατά την άποψή μου), χρησιμοποιεί μια nested κλάσση (για τους Java developers inner κλάσση) χωρίς να χρειάζεται lock. &lt;/p&gt;&lt;img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=38814" width="1" height="1"&gt;</description></item><item><title>Finalization και Dispose</title><link>https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/2007/12/30/finalization-dispose.aspx</link><pubDate>Sun, 30 Dec 2007 21:26:01 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:38703</guid><dc:creator>Nick Makris</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/blogs/nikosm/comments/38703.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/blogs/nikosm/commentrss.aspx?PostID=38703</wfw:commentRss><wfw:comment>https://www.dotnetzone.gr:443/cs/blogs/nikosm/rsscomments.aspx?PostID=38703</wfw:comment><description>&lt;p&gt;Μια από τις πιο χρήσιμες&amp;nbsp;υπηρεσίες του CLR&amp;nbsp;είναι το Garbage Collection. Δηλαδή&amp;nbsp;ο περιοδικός καθαρισμός του Heap από&amp;nbsp;objects που πλέον δεν χρησιμοποιούνται. Θαυμάσια, τώρα πια μπορούμε να δημιουργούμε όποιο αντικείμενο θέλουμε να το χρησιμοποιούμε για όσο θέλουμε και μετά.... να μή μας ενδιαφέρει ούτε να το "κλείσουμε" ούτε να το "καθαρίσουμε" ούτε τίποτα. Μετά από λίγη ώρα ο Garbage Collector θα καθαρίσει το Heap από τα αχρησιμοποίητα αντικείμενα. &lt;/p&gt; &lt;p&gt;&amp;nbsp;Αυτό ισχύει για τις περισσότερες των περιπτώσεων, όταν όμως ένας τύπος μας διαχειρίζεται unmanaged resources (για παράδειγμα database connections, queue ή file handlers), τότε πρέπει να "κλείνουμε" μόνοι μας αυτά τα resources. Στις ακόλουθες παραγράφους παραθέτω ένα πολύ γνωστό pattern για finalization και disposing τύπων που διαχειρίζονται unmanaged resources. Πρώτα όμως λίγη θεωρία.&lt;/p&gt; &lt;h3&gt;Finalizers&lt;/h3&gt; &lt;p&gt;Πρόκειται για μεθόδους που το όνομά τους ξεκινά με το "~" και έχουν το ίδιο όνομα με τον τύπο. Αν για παράδειγμα ο τύπος μας λέγεται MyClass ο finalizer του τύπου έχει το ακόλουθο signature:&lt;/p&gt;&lt;pre class="code"&gt; &lt;span&gt;class&lt;/span&gt; &lt;span&gt;MyClass
&lt;/span&gt; {
        ~MyClass()
        {&lt;/pre&gt;&lt;pre class="code"&gt;//Your code here...
        }
 }&lt;/pre&gt;
&lt;p&gt;Ούτε void ούτε παράμετροι. Δεν είναι υποχρεωτικό να έχουμε finalizers για κάθε τύπο. Σε περίπτωση όμως που έχουμε τότε κατά τη διαδικασία του Garbage Collection του αντικειμένου μας γίνονται τα ακόλουθα &lt;strong&gt;δύο&lt;/strong&gt; πράγματα:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Το αντικείμενο "καθαρίζεται" από το heap (στην πραγματικότητα η μνήμη που καταλαμβάνει είναι και πάλι διαθέσιμη) 
&lt;li&gt;Το αντικείμενο&amp;nbsp;μπαίνει σε μια ουρά (queue) finalization. ΧΧΧμμμμμ τι είναι αυτή η finalization ουρά?, Πρόκειται για μιά κλασσική FIFO ουρά στην οποία κάθε αντικείμενο (πριν βγει από εκεί), υπόκειται σε finalization, δηλαδή απλά καλείται η finalize μεθοδός του. &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Συνεπώς μπορείτε να φανταστείται το κώδικα του Garbage collector κάπως έτσι: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font face="Courier New" size="2"&gt;List&amp;lt;object&amp;gt; objectsToBeCGed = GetAllObjectsFromHeapToBeCGed();&lt;br&gt;List&amp;lt;object&amp;gt; objectsWithFinalizersToBeCGed = GetAllObjectsFromHeapToBeCGedWithFinalizers();&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New" size="2"&gt;CleanHeapFromObjects(objectsToBeCGed );&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New" size="2"&gt;FinalizationQueue.AddRange(objectsWithFinalizersToBeCGed.ToArray());&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Προφανώς ο παραπάνω είναι&lt;strong&gt; ψευδω-κώδικας&lt;/strong&gt; (και η λίστα &lt;font face="Courier New" size="2"&gt;objectsToBeCGed&lt;/font&gt;&amp;nbsp;είναι υπερσύνολο του &lt;font face="Courier New" size="2"&gt;objectsWithFinalizersToBeCGed&lt;/font&gt;).&lt;/p&gt;
&lt;p&gt;To&amp;nbsp;CLR εποπτεύει την ουρά και κάθε φορά που βγάζει ένα αντικείμενο από αυτή καλεί τον Finalizer της. &lt;/p&gt;
&lt;h3&gt;Γιατί&amp;nbsp;χρειαζόματε τους Finalizers?&lt;/h3&gt;
&lt;p&gt;Ας υποθέσουμε ότι φτιάχνουμε ένα τύπο (μιά κλάση) η οποία χειρίζεται unmanaged resources (π.χ. ένα database connection). Κάνουμε την κλάση να υλοποιεί το IDisposable Interface και στη Dispose μέθοδο έχουμε τον κώδικα που κλείνει το database connection:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;class&lt;/span&gt; &lt;span&gt;MyClassThatHandlesDBConnection&lt;/span&gt; : &lt;span&gt;IDisposable&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Dispose()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;this&lt;/span&gt;.DBConnection.Close();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Ολα φαίνονται εντάξει, αν κάποιος χρησιμοποιήσει την κλάσση με using ή καλέσει την Dispose πράγματι δεν θα έχουμε προβλήματα. Αν όμως ο χρήστης της κλάσης δεν τη χρησιμοποιήσει σωστά τότε θα έχουμε απρόσμενα αποτελέσματα και μάλλον δυσάρεστες εκπλήξεις οι οποίες ΔΕΝ φαίνονται στο UNIT TEST. &lt;strong&gt;Είναι ευθύνη του developer που υλοποιεί&lt;/strong&gt; την &lt;span&gt;MyClassThatHandlesDBConnection&lt;/span&gt;&amp;nbsp;να τη φτιάξει όσο το δυνατό πιο bullet proof. Σε ένα τέτοιο σενάριο&amp;nbsp;χρησιμοποίούμε τον Finalizer με το ακόλοθο&amp;nbsp;pattern:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;class&lt;/span&gt; &lt;span&gt;MyClassThatHandlesDBConnection&lt;/span&gt; : &lt;span&gt;IDisposable&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Dispose()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;this&lt;/span&gt;.Dispose(&lt;span&gt;true&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;GC&lt;/span&gt;.SuppressFinalize(&lt;span&gt;this&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ~MyClassThatHandlesDBConnection()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;//Clean up unmanaged resources only&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;this&lt;/span&gt;.Dispose(&lt;span&gt;false&lt;/span&gt;);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;protected&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Dispose(&lt;span&gt;bool&lt;/span&gt; disposing)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;if&lt;/span&gt; (disposing)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;//Clean up all managed resources if disposing is true&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;//Always clean up unmanaged resources regardless of disposing parameter&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;this&lt;/span&gt;.DBConnection.Close();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Από το παραπάνω snippet κώδικα παρατηρούμε τα ακόλουθα:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Αν χρησιμοποιήσουμε σωστά την κλάσση (με using ή καλώντας την Dispose() explicitly),&amp;nbsp;τότε καθαρίζονται τα managed&amp;nbsp;και unmanaged resources&amp;nbsp;ΚΑΙ ΕΠΙΠΛΕΟΝ&amp;nbsp;με τη δήλωση&amp;nbsp;&lt;font size="2"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;GC&lt;/span&gt;.SuppressFinalize(&lt;span&gt;this&lt;/span&gt;);&lt;/font&gt;&lt;/font&gt; λέμε στον&amp;nbsp;Garbage Collector να ΜΗ&amp;nbsp;βάλει το αντικείμενο στην&amp;nbsp;finalization ουρά όταν&amp;nbsp;το κάνει collect από το heap,&amp;nbsp;μιας και έχουμε φροντίσει να κάνουμε "finalize" το αντικείμενο εμείς (δηλαδή να καθαρίσουμε και τα unmanaged resources). 
&lt;li&gt;Στην περίπτωση που δεν χρησιμοποιηθεί η κλάσση σωστά (δηλαδή δεν γίνει dispose από τον developer που την χρησιμοποίησε), τότε και πάλι&amp;nbsp;δεν θα έχουμε&amp;nbsp;κακή συμπεριφορά -τουλάχιστο από την κλάσση μας- &lt;strong&gt;διότι έστω και αργά&lt;/strong&gt; (αφού γίνει GCed και αφου βγεί από την Finalization ουρά) τα unmanaged resources θα "καθαριστούν" διότι θα κληθεί η ~MyClassThatHandlesDBConnection()&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Αρα έχουμε φτιάξει μια κλάσση που ακόμα και αν δεν χρησιμοποιηθεί με το σωστό τρόπο, παρέχει τους μηχανισμούς για να μη μένουν unmanaged resources ανοιχτά. Προφανώς το καλύτερο σενάριο είναι να χρησιμοποιηθεί η κλάσση μας σωστά και να μην χρειαστεί να βασιστούμε στο finalization του CLR. Γιαυτό και πάντα πρέπει να χρησιμοποιούμε το using block ή να καλούμε το Dispose σε οποιοδήποτε Τύπο υλοποιεί το IDisposable. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Μπορούμε λοιπόν να&amp;nbsp;διατυπώσουμε τον κανόνα ότι όταν φτιάχνουμε κλάσσεις που χειρίζονται unmanaged resources, καλό είναι να κάνουμε finalization και disposing με το παραπάνω pattern&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Ελπίζω να σας φανεί χρήσιμο.....&lt;/p&gt;
&lt;p&gt;&lt;font color="#008000"&gt;&lt;strong&gt;Με την ευκαιρία εύχομαι&amp;nbsp;ΚΑΛΗ ΧΡΟΝΙΑ&amp;nbsp;ΜΕ ΥΓΕΙΑ ΚΑΙ ΕΥΤΥΧΙΑ ΣΕ ΟΛΟΥΣ.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=38703" width="1" height="1"&gt;</description><category domain="https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Βάλτε λίγο "αλάτι" στη ζωή σας και στο hashing...</title><link>https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/2007/06/17/quot-quot-hashing.aspx</link><pubDate>Sun, 17 Jun 2007 20:30:00 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:32986</guid><dc:creator>Nick Makris</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/blogs/nikosm/comments/32986.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/blogs/nikosm/commentrss.aspx?PostID=32986</wfw:commentRss><wfw:comment>https://www.dotnetzone.gr:443/cs/blogs/nikosm/rsscomments.aspx?PostID=32986</wfw:comment><description>&lt;P&gt;&lt;STRONG&gt;Γενικά&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Hashing&lt;/STRONG&gt; είναι η διαδικασία στην οποία&amp;nbsp;από ένα αλφαριθμητικό (γενικά ένα byte stream) παράγουμε ένα&amp;nbsp;άλλα αλφαριθμητικό που ονομάζεται &lt;STRONG&gt;hash value&lt;/STRONG&gt; του αρχικού μυνήματος. Η δημιουργία του hash value γίνεται με ειδικούς μαθηματικούς αλγορίθμους που έχουν (εκτός των άλλων) τις ακόλουθες δύο βασικές ιδιότητες:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Είναι "πρακτικά αδύνατο" να&amp;nbsp;αναπαραχθεί το αρχικό αλφαριθμητικό από το &lt;STRONG&gt;hash value&lt;/STRONG&gt; 
&lt;LI&gt;Δύο διαφορετικά αλφαριθμητικά είναι "πρακτικά αδύνατο" να δώσουν το ίδιο &lt;STRONG&gt;hash value&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Με τον όρο "πρακτικά αδύνατο" εννοούμε ότι απαιτείται πολύ χρόνος και μεγάλη υπολογιστική ισχύ για να πετύχουμε τα παραπάνω. Ετσι για παράδειγμα αν έχουμε μια hash value και θέλουμε να μάθουμε το αλφαριθμητικό από το οποίο προήλθε, το μόνο που μπορούμε να κάνουμε είναι να παράγουμε hash values από όλα τα πιθανά αλφαριθμητικά (&lt;STRONG&gt;brute force attack&lt;/STRONG&gt;) και να ελέγχουμε αν το παραγόμενο hash value ταιριάζει με αυτό που ψάχνουμε. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Αλγόριθμοι για Hashing&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Υπάρχουν αρκετοί τέτοιοι αλγόριθμοι, οι πιο γνωστοί είναι οι:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;SHA1 (Secure Hash Algorithm)&amp;nbsp;και οι παραλλαγές του SHA256, SHA384, SHA512 κτλ. 
&lt;LI&gt;MD5 (Message Digest)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Καθένας από αυτούς παράγει hash values συγκεκριμένου μεγέθους, για παράδειγμα ο MD5 παράγει 128 bit hashes, o SHA1 160 bit hashes, o SHA1 256 bit hashes κτλ.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Που είναι χρήσιμο το&amp;nbsp;Hashing?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Σε πολλές περιπτώσεις, εδώ θα σχολιάσουμε αυτές που έχουν να κάνουν με αποθήκευση &lt;STRONG&gt;ευαίσθητων δεδομένων&lt;/STRONG&gt;.&amp;nbsp;Ισως το πιο αντιπροσωπευτικό παράδειγμα είναι&amp;nbsp;η &lt;STRONG&gt;αποθήκευση&amp;nbsp;passwords&lt;/STRONG&gt;. Πράγματι φανταστείται ένα σύστημα στο οποίο θέλουμε να αποθηκεύουμε τα&amp;nbsp;password των χρηστών σε μια βάση δεδομένων&amp;nbsp;και &lt;STRONG&gt;ΔΕΝ θέλουμε&lt;/STRONG&gt; να&amp;nbsp;έχουμε την υπηρεσία "&lt;STRONG&gt;I forgot my&amp;nbsp;password&lt;/STRONG&gt;". Δηλαδή &lt;STRONG&gt;ΔΕΝ&lt;/STRONG&gt;&amp;nbsp;χρειάζετε να έχουμε διαθέσιμο το password κανενός χρήστη σαν clear text. Σε αυτή την περίπτωση δεν πρέπει να&amp;nbsp;σώζουμε τα password με τρόπο που να μπορούν να &lt;STRONG&gt;ΑΝΑΚΤΗΘΟΥΝ&lt;/STRONG&gt;. Μια καλή ιδέα λοιπόν&amp;nbsp;είναι να αώζουμε &lt;STRONG&gt;hash values των passwords&lt;/STRONG&gt;. &lt;/P&gt;
&lt;P&gt;Ετσι αφενώς&amp;nbsp;μπορούμε να κάνουμε έλεγχο αν ένας χρήστης έδωσε σωστό password (ελέγχοντας αν το hash του&amp;nbsp;password που έδωσε&amp;nbsp;είναι ίδιο με το hash που έχουμε αποθηκεύσει) και αφετέρου κανένας (ούτε ο DBA) δεν έχει πρόσβαση στο password κανενός χρήστη (πράγματι ο DBA μπορεί να δεί το hash ενός&amp;nbsp;password αλλά ΔΕΝ μπορεί να ανακτήσει το clear text password).&lt;/P&gt;
&lt;P&gt;Το μόνο που μπορεί να κάνεις κάποιος για να ανακτήσει το clear text password ξέροντας ένα hash, είναι το brute force attack που αναφέραμε παραπάνω. Αυτό όμως εν'γένει είναι μια πάρα πολύ χρονοβόρα (και resource consuming) διαδικασία. Πρέπει για κάθε πιθανό αλφαριθμητικό (πάααααρα πολλά σε πλήθος) να υπολογίζουμε το hash και να το συγκρίνουμε με το&amp;nbsp;hash που θέλουμε&amp;nbsp;να κάνουμε attack.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Salted Hash. Τί είναι?&amp;nbsp;Γιατί είναι απαραίτητο σε κάποιες περιπτώσεις?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Τώρα που ανέφερα τη φράση "ευαίσθητα δεδομένα" ήρθαν στο μυαλό μου οι πιστωτικές μου κάρτες (ναι έχω και εγώ πολλές...) και οι cash κάρτες -πολλές πάλι αλλά με λίγο υπόλοιπο :(((. &lt;/P&gt;
&lt;P&gt;Κάθε μια από αυτές έχει ένα τετραψήφιο PIN το οποίο, λογικά, φυλάσεται σε κάποια βάση κάποιου τραπεζικού συστήματτος. Προφανώς δεν αποθηκεύεται σαν clear text αλλά σαν hash value.&amp;nbsp;Ωραία, μπορώ να κοιμάμαι&amp;nbsp;ήσυχος, ο DBA ΔΕΝ&amp;nbsp;μπορεί να ξέρει το PIN&amp;nbsp;κάποια κάρτας μου.&amp;nbsp;Χχχχχχχχχχχμμμμμμμμμμ, για μισό λεπτό, το PIN είναι ένα 4ψήφιο νούμερο, που σημαίνει ότι αν θέλω να κάνω brute force attack για να βρώ πιο νούμερο έχει το ίδιο hashed value ενός 4ψήφιου, αρκεί να δοκιμάσω 10000 νούμερα (από το 0000 μέχρι το 9999).&amp;nbsp;Ο source πιθανόχωρος του brute force attack είναι πολύ περιορισμένος (ακόμα και ο Spectrum +2 που είχα κάποτε, θα μπορούσε σε μερικά δευτερόλεπτα να κάνει το attack!!!).&lt;/P&gt;
&lt;P&gt;Σε αυτές τις περιπτώσεις (όπου ο πιθανόχωρος των ευαίσθητων δεδομένων είναι από τη φύση του περιορισμένος), χρησιμοποιούμε το λεγόμενο &lt;STRONG&gt;salted hash&lt;/STRONG&gt;. Χρησιμοποιούμε ένα επιπλέον αλφαριθμητικό (το salt) και το προσθέτουμε είτε αριστερά είτε δεξιά του "ευαίσθητου δεδομένου" πριν δημιουργήσουμε το hash. Ετσι για παράδειγμα αν το PIN μιας κάρτας είναι το 1234 και το salt είναι το CARDNo τότε θα γινόταν hashed to CARDNo1234 (ή το 1234CARDNo). Ετσι ο πιθανόχωρος για το brute force attack θα ήταν πολύ μεγαλύτερος από τα 10000 νούμερα που αναφέραμε στην προηγούμενη παράγραφο. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Πως παράγω το salt? Πώς το αποθηκεύω?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Το salt παράγεται&amp;nbsp;κατά κανόνα&amp;nbsp;με ευριστικό τρόπο. Συνήθως είναι εξάρτηση άλλων πεδίων του record που περιέχει το "ευαίσθητο δεδομένο" που θέλουμε να&amp;nbsp;αποθηκεύσουμε&amp;nbsp;σαν hash. Για παράδειγμα&amp;nbsp;μπορούμε να χρησιμοποιήσουμε&amp;nbsp;το όνομα του χρήστη (username)&amp;nbsp;σαν salt στο password.&amp;nbsp;Αλλες φορές είναι πάντοτε το ίδιο για όλες τις εγγραφες και είναι αποθηκευμένο&amp;nbsp;κάπου στον κώδικα σαν&amp;nbsp;hardcoded τιμή, ενώ αλλές φορές παράγεται τυχαία από κάποιον random generator.&lt;/P&gt;
&lt;P&gt;Οπως και να το έχουμε δημιουργήσει πρέπει να το αποθηκεύουμε (ή να το παράγουμε) με ασφαλή τρόπο ώστε να μην μπορεί να το βρεί κανείς εύκολα. Αν το salt γίνει compromised τότε μπορεί να έχουμε τα προβλήματα που αναφέραμε στην παραπάνω παράγραφο. &lt;/P&gt;
&lt;P&gt;Στην ακόλουθη παράγραφο παραθέτω τον κώδικά για hashing και salted hashing. Το πού θα αποθηκεύσεται το salt.... δικό σας πρόβλημα :)))&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Κώδικας για hashing και salted hashing (έτσι για να μην ξεχνιώμαστε...)&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;&lt;BR&gt;using&lt;/SPAN&gt; System;&lt;BR&gt;&lt;SPAN&gt;using&lt;/SPAN&gt; System.Security.Cryptography;&lt;BR&gt;&lt;SPAN&gt;using&lt;/SPAN&gt; System.Text;&lt;BR&gt;&lt;BR&gt;&lt;SPAN&gt;namespace&lt;/SPAN&gt; Hashing&lt;BR&gt;{&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;public&lt;/SPAN&gt; &lt;SPAN&gt;enum&lt;/SPAN&gt; &lt;SPAN&gt;HashAlgorithms&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SHA1,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SHA256,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SHA384,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SHA512,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MD5&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;public&lt;/SPAN&gt; &lt;SPAN&gt;class&lt;/SPAN&gt; &lt;SPAN&gt;HashingUtils&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;public&lt;/SPAN&gt; &lt;SPAN&gt;static&lt;/SPAN&gt; &lt;SPAN&gt;string&lt;/SPAN&gt; ComputeHash(&lt;SPAN&gt;string&lt;/SPAN&gt; plainText, &lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt; hashAlgorithm, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;string&lt;/SPAN&gt; salt)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;byte&lt;/SPAN&gt;[] plainTextBytes = &lt;SPAN&gt;Encoding&lt;/SPAN&gt;.UTF8.GetBytes(plainText);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;byte&lt;/SPAN&gt;[] saltBytes = &lt;SPAN&gt;Encoding&lt;/SPAN&gt;.UTF8.GetBytes(salt);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;byte&lt;/SPAN&gt;[] plainTextWithSaltBytes = &lt;SPAN&gt;new&lt;/SPAN&gt; &lt;SPAN&gt;byte&lt;/SPAN&gt;[plainTextBytes.Length + saltBytes.Length];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;for&lt;/SPAN&gt; (&lt;SPAN&gt;int&lt;/SPAN&gt;&amp;nbsp;j = 0;&amp;nbsp;j &amp;lt; plainTextBytes.Length; j++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; plainTextWithSaltBytes[j] = plainTextBytes[j];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;for&lt;/SPAN&gt; ( &lt;SPAN&gt;int&lt;/SPAN&gt; j = 0;&amp;nbsp;j &amp;lt; saltBytes.Length; j++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; plainTextWithSaltBytes[plainTextBytes.Length + j] = saltBytes[j];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;HashAlgorithm&lt;/SPAN&gt; hash = &lt;SPAN&gt;null&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;switch&lt;/SPAN&gt; ( hashAlgorithm )&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;case&lt;/SPAN&gt; &lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt;.SHA1 : &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hash = &lt;SPAN&gt;new&lt;/SPAN&gt; &lt;SPAN&gt;SHA1Managed&lt;/SPAN&gt;();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;case&lt;/SPAN&gt; &lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt;.SHA256&amp;nbsp; : &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hash = &lt;SPAN&gt;new&lt;/SPAN&gt; &lt;SPAN&gt;SHA256Managed&lt;/SPAN&gt;();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;case&lt;/SPAN&gt; &lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt;.SHA384 : &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hash = &lt;SPAN&gt;new&lt;/SPAN&gt; &lt;SPAN&gt;SHA384Managed&lt;/SPAN&gt;();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;case&lt;/SPAN&gt; &lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt;.SHA512 : &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hash = &lt;SPAN&gt;new&lt;/SPAN&gt; &lt;SPAN&gt;SHA512Managed&lt;/SPAN&gt;();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;case&lt;/SPAN&gt; &lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt;.MD5 : &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hash = &lt;SPAN&gt;new&lt;/SPAN&gt; &lt;SPAN&gt;MD5CryptoServiceProvider&lt;/SPAN&gt;();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;byte&lt;/SPAN&gt;[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;return&lt;/SPAN&gt; &lt;SPAN&gt;Convert&lt;/SPAN&gt;.ToBase64String(hashBytes);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;public&lt;/SPAN&gt; &lt;SPAN&gt;static&lt;/SPAN&gt; &lt;SPAN&gt;bool&lt;/SPAN&gt; VerifyHash(&lt;SPAN&gt;string&lt;/SPAN&gt; plainText, &lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt; hashAlgorithm, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;string&lt;/SPAN&gt; hashValue, &lt;SPAN&gt;string&lt;/SPAN&gt; salt)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;byte&lt;/SPAN&gt;[] hashBytes = &lt;SPAN&gt;Convert&lt;/SPAN&gt;.FromBase64String(hashValue);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;byte&lt;/SPAN&gt;[] saltBytes = &lt;SPAN&gt;Encoding&lt;/SPAN&gt;.UTF8.GetBytes(salt);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;string&lt;/SPAN&gt; expectedHashString = ComputeHash(plainText, hashAlgorithm, salt);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN&gt;return&lt;/SPAN&gt; (hashValue == expectedHashString);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;/P&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Χρησιμοποιούμε την κλάση κάπως έτσι:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN&gt;static&lt;/SPAN&gt; &lt;SPAN&gt;void&lt;/SPAN&gt; Main(&lt;SPAN&gt;string&lt;/SPAN&gt;[] args)
        {
            &lt;SPAN&gt;string&lt;/SPAN&gt; plainText = &lt;SPAN&gt;"myPIN"&lt;/SPAN&gt; ;
            &lt;SPAN&gt;string&lt;/SPAN&gt; salt = &lt;SPAN&gt;"mySalt"&lt;/SPAN&gt;;

            &lt;SPAN&gt;string&lt;/SPAN&gt; hashValueInBase64Encoding = Hashing.&lt;SPAN&gt;HashingUtils&lt;/SPAN&gt;.ComputeHash(plainText,
                Hashing.&lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt;.SHA512, salt);

            &lt;SPAN&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN&gt;"This is the hashed value: "&lt;/SPAN&gt; + hashValueInBase64Encoding);
          
            &lt;SPAN&gt;bool&lt;/SPAN&gt; verified = Hashing.&lt;SPAN&gt;HashingUtils&lt;/SPAN&gt;.VerifyHash(plainText,
                Hashing.&lt;SPAN&gt;HashAlgorithms&lt;/SPAN&gt;.SHA512, hashValueInBase64Encoding, salt);

            &lt;SPAN&gt;Console&lt;/SPAN&gt;.WriteLine(verified);
            &lt;SPAN&gt;Console&lt;/SPAN&gt;.ReadLine(); 
        }&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=32986" width="1" height="1"&gt;</description><category domain="https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/tags/.NET/default.aspx">.NET</category><category domain="https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/tags/Security/default.aspx">Security</category></item><item><title>Query για Indexes σε Foreign Keys</title><link>https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/2007/05/23/query-indexes-foreign-keys.aspx</link><pubDate>Thu, 24 May 2007 00:34:00 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:32159</guid><dc:creator>Nick Makris</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/blogs/nikosm/comments/32159.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/blogs/nikosm/commentrss.aspx?PostID=32159</wfw:commentRss><wfw:comment>https://www.dotnetzone.gr:443/cs/blogs/nikosm/rsscomments.aspx?PostID=32159</wfw:comment><description>&lt;P&gt;Σε πολλές (αν όχι σε όλες) τις περιπτώσεις είναι απαραίτητο να έχουμε secondary indexes σε columns που κάνουν reference σε ξένα κλειδιά. Αν για&amp;nbsp;παράδειγμα έχουμε δύο πίνακες&amp;nbsp;(&lt;STRONG&gt;Employees&lt;/STRONG&gt; και &lt;STRONG&gt;Departments&lt;/STRONG&gt;) και ο πίνακας &lt;STRONG&gt;Employees&lt;/STRONG&gt;&amp;nbsp;έχει ένα&amp;nbsp;Foreign Key constraint στο &lt;STRONG&gt;DepartmentID&lt;/STRONG&gt; (δηλαδή η κάθε εγγραφή του πίνακα &lt;STRONG&gt;Employees&lt;/STRONG&gt; έχει&amp;nbsp;ένα&amp;nbsp;reference στο ID του department που ανήκει),&amp;nbsp;τότε κατά πάσα πιθανότητα θα&amp;nbsp;υπάρχουν &lt;STRONG&gt;queries&lt;/STRONG&gt; στα οποία&amp;nbsp;οι δύο αυτοί&amp;nbsp;πίνακες κάνουν JOIN (πιθανότατα INNER JOIN) στο πεδίο αυτό. &lt;/P&gt;
&lt;P&gt;Θα ήταν λοιπόν&amp;nbsp;καλό (για να μην πώ απαραίτητο) να έχουμε&amp;nbsp;μια λίστα με τα ξένα κλειδιά&amp;nbsp;που &lt;STRONG&gt;ΔΕΝ&amp;nbsp;ΕΙΝΑΙ INDEXED&lt;/STRONG&gt;.&amp;nbsp;&lt;BR&gt;&lt;BR&gt;Τρέξτε αυτό το query (μόνο σε SQL 2005)&amp;nbsp;και θα πάρετε αυτή τη λίστα...&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;-- Check that ALL FK columns are indeed indexed in the child table&lt;BR&gt;&lt;BR&gt;select ' FK without Index : Create Secondary index on table&amp;nbsp; ' + o.name + ' for column ' + c.name as IndexesNeeded, &lt;BR&gt;&amp;nbsp;&amp;nbsp;fc.referenced_object_id, fc.referenced_column_id, f.name, f.type, f.type_desc, f.parent_object_id, fc.parent_column_id&lt;BR&gt;from sys.foreign_keys as f, sys.foreign_key_columns as fc, sys.objects as o, sys.columns as c&lt;BR&gt;where c.object_id = o.object_id and c.column_id = fc.parent_column_id and o.object_id = fc.parent_object_id and&lt;BR&gt;&amp;nbsp; fc.constraint_object_id = f.object_id and fc.parent_object_id = f.parent_object_id&lt;BR&gt;and &lt;BR&gt;(&lt;BR&gt;&amp;nbsp;Select count(*) --Parent_object_id, Parent_column_id&amp;nbsp; &lt;BR&gt;&amp;nbsp;from sys.foreign_key_columns&amp;nbsp; fkc, &lt;BR&gt;&amp;nbsp;&amp;nbsp;sys.index_columns ic&lt;BR&gt;&amp;nbsp;where fc.parent_object_id = fkc.Parent_object_id and&lt;BR&gt;&amp;nbsp;&amp;nbsp;fkc.Parent_object_id = ic.object_id and&lt;BR&gt;&amp;nbsp;&amp;nbsp;fkc.Parent_column_id = ic.column_id and &lt;BR&gt;&amp;nbsp;&amp;nbsp;fkc.Parent_column_id = fc.parent_column_id ) = 0&lt;BR&gt;Order by o.Name&lt;/FONT&gt;&lt;/P&gt;&lt;img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=32159" width="1" height="1"&gt;</description><category domain="https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/tags/SQL+2005/default.aspx">SQL 2005</category></item><item><title>Δημιουργήστε Web Test σε AJAX sites με το Visual Studio Team Suite 2005 και τον Fiddler 2</title><link>https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/2007/05/19/web-test-ajax-sites-visual-studio-team-suite-2005.aspx</link><pubDate>Sat, 19 May 2007 17:16:12 GMT</pubDate><guid isPermaLink="false">2622095e-976c-431a-859e-16783ec7ecd7:31956</guid><dc:creator>Nick Makris</dc:creator><slash:comments>0</slash:comments><comments>https://www.dotnetzone.gr:443/cs/blogs/nikosm/comments/31956.aspx</comments><wfw:commentRss>https://www.dotnetzone.gr:443/cs/blogs/nikosm/commentrss.aspx?PostID=31956</wfw:commentRss><wfw:comment>https://www.dotnetzone.gr:443/cs/blogs/nikosm/rsscomments.aspx?PostID=31956</wfw:comment><description>&lt;p&gt;Εάν έχετε δουλέψει με το &lt;strong&gt;Visual Studio Team Suite 2005&lt;/strong&gt; (εάν &lt;strong&gt;δεν έχετε&lt;/strong&gt; αυτή τη version του &lt;strong&gt;visual studio&lt;/strong&gt; μπορείτε να κατεβάσετε την &lt;strong&gt;trial&lt;/strong&gt; από το &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=5677DDC4-5035-401F-95C3-CC6F46F6D8F7&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=5677DDC4-5035-401F-95C3-CC6F46F6D8F7&amp;amp;displaylang=en&lt;/a&gt;), σίγουρα έχετε δεί και&amp;nbsp;το &lt;strong&gt;Test Project Template&lt;/strong&gt;.&lt;br&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image01.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="174" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image0.png" width="240" border="0"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Σε projects αυτού του&amp;nbsp;είδους μπορείτε να δημιουργήσετε&amp;nbsp;διαφόρων ειδών tests όπως &lt;strong&gt;Unit Tests&lt;/strong&gt;, &lt;strong&gt;Web Tests&lt;/strong&gt;, &lt;strong&gt;Load Test&lt;/strong&gt;, &lt;strong&gt;Ordered Tests &lt;/strong&gt;ή &lt;strong&gt;Manual Tests&lt;/strong&gt;.&amp;nbsp;Σε αυτή τη δημοσίευση θα ασχοληθούμε με&amp;nbsp;τη δημιουργία &lt;strong&gt;Web Tests&lt;/strong&gt;&amp;nbsp;σε &lt;strong&gt;AJAX Enabled Web Sites&lt;/strong&gt;. &lt;/p&gt; &lt;h3&gt;Τι είναι ένα Web Test?&lt;/h3&gt; &lt;p&gt;Είναι ένα functional test&amp;nbsp;(λειτουργικός έλεγχος) σε Web οθόνες,&amp;nbsp;δηλαδή έλεγχος της σωστής λειτουργίας&amp;nbsp;των σελίδων μιας Web&amp;nbsp;εφαρμογής. Αν για παράδειγμα&amp;nbsp;θέλουμε να ελέγξουμε αν η λειτουργία login δουλεύει σωστά σε ένα&amp;nbsp;Web Application, τότε στην απλούστερη περίπτωση, πρέπει να&amp;nbsp;κάνουμε δοκιμαστικά login με πολλά usernames και passwords (άλλοτε σωστά και άλλοτε λανθασμένα) και να δούμε πώς&amp;nbsp;αποκρίνεται&amp;nbsp;το σύστημα.&lt;/p&gt; &lt;h3&gt;Δημιουργία&amp;nbsp;του "προς δοκιμή"&amp;nbsp;AJAX Enabled Web Site&lt;/h3&gt; &lt;p&gt;Θα υλοποιήσουμε ένα πολύ απλό AJAX web&amp;nbsp;site&amp;nbsp;με μία μόνο σελίδα που θα&amp;nbsp;επιτελεί τη λειτουργία Login. Η σελίδα Login.aspx θα έχει την ακόλουθη φόρμα:&lt;br&gt;&lt;span&gt;&lt;br&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;form&lt;/span&gt; &lt;span&gt;id&lt;/span&gt;&lt;span&gt;="_mainForm"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&amp;gt;&lt;br&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;ScriptManager&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_scriptManager"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ονομα: &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;TextBox&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_userNameTextBox"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;TextBox&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Κωδικός: &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;TextBox&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_passwordTextBox"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;TextBox&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;br&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_loginButton"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&lt;/span&gt; &lt;span&gt;Text&lt;/span&gt;&lt;span&gt;="Εγγραφή"&lt;/span&gt; &lt;span&gt;OnClick&lt;/span&gt;&lt;span&gt;="_loginButton_Click"&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_loginSuccess"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&lt;/span&gt; &lt;span&gt;Visible&lt;/span&gt;&lt;span&gt;="false"&amp;gt;&lt;/span&gt;Καλωσόρισες &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Label&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_userNameLabel"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="Server"&lt;/span&gt; &lt;span&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_loginFailedPanel"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&lt;/span&gt; &lt;span&gt;Visible&lt;/span&gt;&lt;span&gt;="false"&amp;gt;&lt;/span&gt;Λάθος στοιχεία, παρακαλώ ξαναδοκιμάστε&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;br&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;br&gt;&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;Ενώ ο server side κώδικας θα είναι κάπως έτσι:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span&gt;protected&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Page_Load(&lt;span&gt;object&lt;/span&gt; sender, &lt;span&gt;EventArgs&lt;/span&gt; e)
    {
        &lt;span&gt;this&lt;/span&gt;._loginSuccess.Visible = &lt;span&gt;false&lt;/span&gt;;
        &lt;span&gt;this&lt;/span&gt;._loginFailedPanel.Visible = &lt;span&gt;false&lt;/span&gt;;

    }
    &lt;span&gt;protected&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; _loginButton_Click(&lt;span&gt;object&lt;/span&gt; sender, &lt;span&gt;EventArgs&lt;/span&gt; e)
    {
        &lt;span&gt;if&lt;/span&gt; ((&lt;span&gt;this&lt;/span&gt;._userNameTextBox.Text == &lt;span&gt;"nikos"&lt;/span&gt;) &amp;amp;&amp;amp;
             (&lt;span&gt;this&lt;/span&gt;._passwordTextBox.Text == &lt;span&gt;"makris"&lt;/span&gt;))
        {
            &lt;span&gt;this&lt;/span&gt;._userNameLabel.Text = &lt;span&gt;"nikos"&lt;/span&gt;;
            &lt;span&gt;this&lt;/span&gt;._loginSuccess.Visible = &lt;span&gt;true&lt;/span&gt;;
        }
        &lt;span&gt;else
&lt;/span&gt;        {
            &lt;span&gt;this&lt;/span&gt;._loginFailedPanel.Visible = &lt;span&gt;true&lt;/span&gt;;
        }
    }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Οπως&amp;nbsp;βλέπετε δεν χρησιμοποιούμε (ακόμα) τίποτε από το AJAX -πέρα από το _scriptManager control,&amp;nbsp;ενώ ο κώδικας είναι πάρα πολύ απλός,&amp;nbsp;παρατηρήστε ότι έχουμε (χάρη ευκολίας) ένα μόνο hardcoded&amp;nbsp;όνομα και κωδικό χρήστη που θεωρούμε valid -τυχαία επιλεγμένο... &lt;/p&gt;
&lt;p&gt;Προσθέστε στο solution με αυτό το web site ένα&lt;strong&gt; Test Project&lt;/strong&gt; και στη συνέχει κάντε δεξί κλίκ και επιλέξτε "&lt;strong&gt;Add-&amp;gt;Web Test&lt;/strong&gt;". &lt;br&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image04.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="240" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image0_thumb2.png" width="181" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;&lt;br&gt;Δημιουργείται έτσι ένα web test (με όνομα WebΤest1) και ανοίγει ο Internet Explorer. Παρατηρήστε to "&lt;strong&gt;Web Test Recorder&lt;/strong&gt;" pane στα αριστερά. Κάνωντας κλήση της σελίδας που μόλις φτιάξαμε (&lt;a href="http://localhost/AJAXEnabledWebSite/Login.aspx"&gt;http://localhost/AJAXEnabledWebSite/Login.aspx&lt;/a&gt;),&amp;nbsp;βλέπουμε ότι καταγράφετε η&amp;nbsp;κλήση (αριστερά).&lt;br&gt;&amp;nbsp;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image08.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="200" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image07.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Δώστε το σωστό όνομα και κωδικό και πατήστε το πλήκτρο "Είσοδος". Παρατηρούμε ότι καταγράφονται και το "Form port parameters". &lt;br&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image010.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="200" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image09.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Τώρα μπορείτε να σταματήσετε την καταγραφή (πατήστε το κουμπί Stop Recording πάνω από το Web Test Recorder). Μόλις δημιουργήσαμε ένα απλό web test. Θα το εμπλουτίσουμε με ένα απλό &lt;strong&gt;Validation Rule&lt;/strong&gt; για να δούμε ότι η εφαρμογή μας συμπεριφέρετσι σωστά. Κάντε δεξί κλίκ στο δεύτερο βήμα του Web Test και επιλέξτε "&lt;strong&gt;Add Validation Rule...&lt;/strong&gt;"&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image048.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="197" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image047.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Στο παράθυρο που εμφανίζεται επιλέξτε "&lt;strong&gt;Find Text&lt;/strong&gt;" και στο αντίσοιχο πεδίο (&lt;strong&gt;Find Text στα δεξιά&lt;/strong&gt;) βάλτε τη λέξη "Καλωσόρισες"&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image044.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="187" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image043.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Αυτός ο απλός έλεγχος θα μας δείξει αν το σύστημα συμπεριφέρετε σωστά όταν κάνουμε login με σωστό όνομα και κωδικό. Μπορείτε να τρέξετε το test για να διαπιστώσετε ότι "περνάει" επιτυχώς (παρατηρήστε το &lt;strong&gt;"Test Results" toolbox&lt;/strong&gt; κάτω αριστερά. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image050.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="196" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image049.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Μέχρι εδώ όλα φαίνονται καλά. Αν όμως χρησιμοποιήσουμε το &lt;strong&gt;UpdatePanel&lt;/strong&gt; του AJAX στην aspx σελίδα:&lt;/p&gt;&lt;pre class="code"&gt; &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;form&lt;/span&gt; &lt;span&gt;id&lt;/span&gt;&lt;span&gt;="_mainForm"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&amp;gt;
&lt;/span&gt;        &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;ScriptManager&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_scriptManager"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&lt;/span&gt; &lt;span&gt;/&amp;gt;
&lt;/span&gt;       &lt;strong&gt; &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;UpdatePanel&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_updatePanel"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span&gt;="server"&amp;gt;
&lt;/span&gt;            &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;ContentTemplate&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;
&lt;/span&gt;                &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;
&lt;/span&gt;                    Ονομα: &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;TextBox&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_userNameTextBox"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;TextBox&lt;/span&gt;&lt;span&gt;&amp;gt;
&lt;/span&gt;                    Κωδικός: &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;TextBox&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_passwordTextBox"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;TextBox&lt;/span&gt;&lt;span&gt;&amp;gt;
&lt;/span&gt;                    &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;br&lt;/span&gt; &lt;span&gt;/&amp;gt;
&lt;/span&gt;                    &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Button&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_loginButton"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&lt;/span&gt; &lt;span&gt;Text&lt;/span&gt;&lt;span&gt;="Εγγραφή"&lt;/span&gt; &lt;span&gt;OnClick&lt;/span&gt;&lt;span&gt;="_loginButton_Click"&lt;/span&gt; &lt;span&gt;/&amp;gt;
&lt;/span&gt;                    &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_loginSuccess"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&lt;/span&gt; &lt;span&gt;Visible&lt;/span&gt;&lt;span&gt;="false&amp;gt;&lt;/span&gt;Καλωσόρισες &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Label&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_userNameLabel"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="Server"&lt;/span&gt; &lt;span&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt;&lt;span&gt;&amp;gt;
&lt;/span&gt;                    &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt; &lt;span&gt;ID&lt;/span&gt;&lt;span&gt;="_loginFailedPanel"&lt;/span&gt; &lt;span&gt;runat&lt;/span&gt;&lt;span&gt;="server"&lt;/span&gt; &lt;span&gt;Visible&lt;/span&gt;&lt;span&gt;="false"&amp;gt;Λάθος στοιχεία, παρακαλώ ξαναδοκιμάστε&lt;/span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;Panel&lt;/span&gt;&lt;span&gt;&amp;gt;
&lt;/span&gt;                &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;div&lt;/span&gt;&lt;span&gt;&amp;gt;
&lt;/span&gt;            &lt;strong&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;ContentTemplate&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span&gt;&amp;gt;
&lt;/span&gt;        &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;asp&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;UpdatePanel&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;
&lt;/span&gt;    &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;ώστε να έχουμε partial page update, τότε άν επαναλάβουμε τη διαδικάσία εγγραφής του Web Test θα δούμε ότι &lt;strong&gt;ΔΕΝ ΚΑΤΑΓΡΑΦΕΤΕ το postback&lt;/strong&gt; του _submitButton. &lt;br&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image012.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="193" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image011.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Αααααα.... &lt;strong&gt;να μια αδυναμία του recorder&lt;/strong&gt;, τι κάνουμε τώρα? &lt;strong&gt;Πώς θα καταγράψουμε&amp;nbsp;ένα Web Test σε&amp;nbsp;AJAX&amp;nbsp;sites?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Δύο λύσεις:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Καταγράφουμε το web test με το &lt;strong&gt;νέο&amp;nbsp;Visual Studio "Orcas"&lt;/strong&gt; (μπορείτε να κατεβάσετε τη &lt;strong&gt;Beta 1 version&lt;/strong&gt; από το &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=F10FB5DF-E369-4DB4-B9A7-845DBF793368&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=F10FB5DF-E369-4DB4-B9A7-845DBF793368&amp;amp;displaylang=en&lt;/a&gt; 
&lt;li&gt;ή μπορείτε να χρησιμoποιήσετε για την καταγραφή &lt;strong&gt;το εργαλέιο FIDDLER2&lt;/strong&gt;, (ένα free tool που μπορείτε να κατεβάσετε από το &lt;a href="http://www.fiddler2.com/"&gt;http://www.fiddler2.com/&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Προφανώς πιο άμεση και πιο απλή λύση είναι η &lt;strong&gt;δεύτερη&lt;/strong&gt;, και αυτή θα παρουσιάσουμε στις επόμενες παραγράφους.&lt;/p&gt;
&lt;h3&gt;Χρήση του Fiddler2 για την καταγραφή ενός Web Test&lt;/h3&gt;
&lt;p&gt;Πριν προσωρήσουμε πρέπει να τονίσω ότι το εργαλέιο Fiddler είναι ένας &lt;strong&gt;HTTP Debugging Proxy&lt;/strong&gt;. Κάνει πάρα πολλά και ενδιαφέροντα πράγματα, ένα από αυτά είναι και η&lt;strong&gt; καταγραφή&amp;nbsp;Web κλήσεων&lt;/strong&gt; και η&amp;nbsp;αποθήκευσή τους σαν &lt;strong&gt;Web Test&lt;/strong&gt; του&amp;nbsp;&lt;strong&gt;Visual Studio 2005&lt;/strong&gt;.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Αφού κατεβάσετε και εγκαταστήσετε το Fiddler2, κάντε κλίκ στο εικόνίδιο "Fiddler 2" (τυπικά βρίσκετε στο "All Programs"). &lt;br&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image014.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="187" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image013.png" width="240" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;Στα αριστερά (το κίτρινο Pane) είναι αυτό στο οποίο&amp;nbsp;καταγράφονται&amp;nbsp;οι&amp;nbsp;Web κλήσεις. Αν ανοίξετε έναν &lt;strong&gt;Internet Explorer&lt;/strong&gt;&amp;nbsp;στο "&lt;strong&gt;Tools-&amp;gt;Internet Options-Connections-LAN Settings"&lt;/strong&gt;&amp;nbsp;και πατήσετε το&amp;nbsp;πλήκτρο &lt;strong&gt;Advanced&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image016.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="240" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image015.png" width="221" border="0"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;θα δείτε ότι ότι έχει ορισθεί ένα &lt;strong&gt;Proxy&lt;/strong&gt; στο Port 8888, αυτός έιναι ο &lt;strong&gt;Fiddler&lt;/strong&gt;.&amp;nbsp;&amp;nbsp;&lt;br&gt;&lt;br&gt;&lt;font color="#8080ff"&gt;&lt;strong&gt;Tip&lt;/strong&gt;:&amp;nbsp;Εαν χρησιμοποιείτε&lt;strong&gt;&amp;nbsp;Internet Explorer 7&lt;/strong&gt; και θέλετε να καταγράφετε τις Web κλήσεις προς τον &lt;strong&gt;localhost&lt;/strong&gt; με το &lt;strong&gt;Fiddler&lt;/strong&gt;, τότε θα πρέπει να &lt;strong&gt;ΜΗΝ ΧΡΗΣΙΜΟΠΟΙΕΙΤΕ&lt;/strong&gt; το "&lt;strong&gt;localhost&lt;/strong&gt;" στις http κλήσεις σας. Αντί αυτού χρησιμοποιείστε το &lt;strong&gt;όνομα&lt;/strong&gt; του υπολογιστή σας. Ετσι &lt;strong&gt;αντί για &lt;/strong&gt;&lt;/font&gt;&lt;a href="http://localhost/"&gt;&lt;font color="#8080ff"&gt;&lt;strong&gt;http://localhost/&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#8080ff"&gt;&lt;strong&gt;...&lt;/strong&gt; πρέπει&amp;nbsp;να γράψετε&amp;nbsp;&lt;/font&gt;&lt;a href="http://&amp;lt;COMPUTER_NAME&amp;gt;/"&gt;&lt;font color="#8080ff"&gt;&lt;strong&gt;http://&amp;lt;COMPUTER_NAME&amp;gt;/&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#8080ff"&gt;...&amp;nbsp;Τούτο διότι ο&amp;nbsp;&lt;strong&gt;Internet Explorer 7&lt;/strong&gt; κάνει πάντα "&lt;strong&gt;Bypass proxy settings for local addresses&lt;/strong&gt;"&amp;nbsp;ακόμα και αν&amp;nbsp;στο παρακάτω παράθυρο επιλογών (&lt;strong&gt;Tools-&amp;gt;Internet Options-&amp;gt;Connections-&amp;gt;Lan Settings&lt;/strong&gt;)&amp;nbsp;έχουμε &lt;strong&gt;unchecked&lt;/strong&gt; αυτή την επιλογή. &lt;br&gt;&lt;/font&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image018.png"&gt;&lt;font color="#8080ff"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="211" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image017.png" width="240" border="0"&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&lt;br&gt;&lt;/font&gt;&lt;br&gt;Οπως μπορείτε να δείτε by default ο fiddler κάνει κλήση στο &lt;a href="http://www.fiddler2.com"&gt;www.fiddler2.com&lt;/a&gt;. Επιλέξτε αυτή το entry στα αριστερά και πατήστε &lt;strong&gt;Delete&lt;/strong&gt;. Εν συνεχεία ανοίξτε έναν Internet Explorer και καλέστε το AJAX enabled web site που&amp;nbsp;δημιουργήσαμε&amp;nbsp;&lt;a href="http://&amp;lt;COMPUTER_NAME&amp;gt;/AJAXEnabledWebSite/Login.aspx"&gt;http://&amp;lt;COMPUTER_NAME&amp;gt;/AJAXEnabledWebSite/Login.aspx&lt;/a&gt;.&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image028.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="153" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image027.png" width="240" border="0"&gt;&lt;/a&gt;&amp;nbsp; &lt;br&gt;Στο παράθυρο του fiddler θα εμφανιστούν τα ακόλουθα:&lt;br&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image022.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="146" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image021.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;(ο υπολογιστής μου ονομάζεται &lt;em&gt;Informatics&lt;/em&gt; και χρησιμοποιώ &lt;strong&gt;Internet Explorer 7&lt;/strong&gt;, για αυτό και τα καταγραφόμενα URLs έχουν αυτό το όνομα και όχι Localhost). &lt;/p&gt;
&lt;p&gt;Τώρα ήρθε η ώρα να δούμε ότι ο Fiddler &lt;strong&gt;πράγματι καταγράφει AJAX Web κλήσεις&lt;/strong&gt;. Συμπληρώστε τη login φόρμα (όπως πρίν) και πατήστε το κουμπί "&lt;strong&gt;Είσοδος&lt;/strong&gt;", μπορείτε να δείτε ότι ο Fiddler κατέγραψε αυτή την κλήση (η τελευταία στην επόμενη εικόνα). &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image032.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="146" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image031.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Ωραία λοιπόν, καταγράψαμε στο Fiddler τις web κλήσεις που θέλαμε, τώρα πώς θα τις σώσουμε σαν ένα &lt;strong&gt;Visual Studio Team Suite 2005 Web Test&lt;/strong&gt;? Πολύ απλά, επιλέξτε τις κλήσεις από το αριστερό κίτρινο pane, και στη συνέχεια "&lt;strong&gt;File-&amp;gt;Save-Session(s)-&amp;gt;as Visual Studio Web Test...&lt;/strong&gt;"&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image038.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="145" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image037.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Δώστε όποιο όνομα θέλετε και πατήστε "&lt;strong&gt;Save&lt;/strong&gt;", στο επόμενο παράθυρο για την επιλογή "&lt;strong&gt;Plugins&lt;/strong&gt;" &lt;strong&gt;μην επιλεγετε τίποτε&lt;/strong&gt; (περισσότερα για τα plugins σε επόμενη δημοσίευση) και πατήστε "&lt;strong&gt;ΟΚ&lt;/strong&gt;"&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image042.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="137" src="http://www.dotnetzone.gr/cs/blogs/nikosm/WindowsLiveWriter/WebTestAJAXsitesVisualStudioTeamSuite200_90AA/image041.png" width="240" border="0"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Τώρα στο Visual Studio, μπορείτε να εισάγετε αυτό το Web Test με την επιλογή "Add-&amp;gt;Existing Item". Βάλτε το Validation Rule, Find Text που χρησιμοποιήσαμε και στο παραπάνω παράδειγμα και τρέξτε το test. &lt;strong&gt;Αυτό ήταν&lt;/strong&gt;, δημιουργήσαμε ένα &lt;strong&gt;Web Test&lt;/strong&gt; για το &lt;strong&gt;Visual Studio Team Suite 2005&lt;/strong&gt; σε ένα &lt;strong&gt;AJAX Enabled Web Site&lt;/strong&gt; με τη βοήθεια του &lt;strong&gt;Fiddler 2&lt;/strong&gt;. &lt;/p&gt;
&lt;h3&gt;Συμπεράσματα - Επεκτάσεις&lt;/h3&gt;
&lt;p&gt;Αυτό ήταν ένα απλό demo σχετικά με τα Web Tests, την αδυναμία του Built in recorder του VS 2005 να καταγράψει AJAX Partial Page Updates και ένα work around για αυτό με τη βοήθεια του Fiddler 2. Αυτά που είδαμε δεν ήταν παρά μια &lt;strong&gt;σταγόνα στο ωκεανό των όσων πρέπει να γνωρίζουμε για να κάνουμε ένα σωστό και ρεαλιστικό Web Test&lt;/strong&gt;. Το &lt;strong&gt;ViewState&lt;/strong&gt; και &lt;strong&gt;EvenτValidation&lt;/strong&gt; &lt;strong&gt;correlation&lt;/strong&gt;, τα &lt;strong&gt;custom Validation Rules&lt;/strong&gt;&amp;nbsp;καθώς και η χρήση μίας ή περισσότερων &lt;strong&gt;Datasource&lt;/strong&gt; για τα δεδομένα που κάνουμε post, είναι πράγματα που θα δούμε σε &lt;strong&gt;επόμενη δημοσίευση&lt;/strong&gt; (ελπίζω πολύ σύντομα).&amp;nbsp;Stay&amp;nbsp;tuned...&amp;nbsp;&lt;/p&gt;&lt;img src="https://www.dotnetzone.gr:443/cs/aggbug.aspx?PostID=31956" width="1" height="1"&gt;</description><category domain="https://www.dotnetzone.gr:443/cs/blogs/nikosm/archive/tags/.NET/default.aspx">.NET</category></item></channel></rss>