<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>Adam Tibi</title>
    <description>On ASP.NET, C# &amp; SEO</description>
    <link>http://www.adamtibi.net/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.NET 1.4.5.0</generator>
    <language>en-GB</language>
    <blogChannel:blogRoll>http://www.adamtibi.net/opml.axd</blogChannel:blogRoll>
    <dc:creator>Adam Tibi</dc:creator>
    <dc:title>Adam Tibi</dc:title>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/AdamTibi" type="application/rss+xml" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FAdamTibi" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FAdamTibi" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2FAdamTibi" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/AdamTibi" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FAdamTibi" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FAdamTibi" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FAdamTibi" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>Three C# 2.0/3.0 Syntaxes That You Didn't Know But Were Afraid to Ask</title>
      <description>&lt;p&gt;Working with other colleagues, I found these C# syntaxes are still not well-known and used, so I thought of blogging on them.&lt;/p&gt;

&lt;h2&gt;1 - Properties Without Members&lt;/h2&gt;
&lt;p&gt;In the old days, before C# 3.0, we used to write syntax like:&lt;/p&gt;

&lt;pre class="code"&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Point {
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; _x;
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; _y;
        
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; X {
            get {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; _x;
            }
            set {
                _x = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
            }
        }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Y {
            get {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; _y;
            }
            set {
                _y = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
            }
        }
    }
&lt;/pre&gt;
&lt;p&gt;But if you are not doing any special processing in your property, you can use a shorter syntax introduced in C# 3.0:&lt;/p&gt;
&lt;pre class="code"&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Point {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; X {
            get;
            set;
        }
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Y {
            get;
            set;
        }
    }
&lt;/pre&gt;
&lt;h2&gt;2 - The '&lt;code&gt;??&lt;/code&gt;'&lt;/h2&gt;
&lt;p&gt;While all of use, especially those coming from C/C++ background have used the ternary operator '&lt;code&gt;?:&lt;/code&gt;', such as:&lt;/p&gt;
&lt;pre class="code"&gt;
    Point point1 = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
    &lt;span class="rem"&gt;// some code to initialise the point1...&lt;/span&gt;
    Point point2 = (point1 == &lt;span class="kwrd"&gt;null&lt;/span&gt; ? &lt;span class="kwrd"&gt;new&lt;/span&gt; Point() : point1);
&lt;/pre&gt;
However, C# 2.0 introduced this new syntax:
&lt;pre class="code"&gt;
    Point point1 = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
    &lt;span class="rem"&gt;// some code to initialise the point1...&lt;/span&gt;
    Point point2 = (point1 ?? &lt;span class="kwrd"&gt;new&lt;/span&gt; Point());
&lt;/pre&gt;
&lt;p&gt;Which does exactly the same as the previous syntax.&lt;/p&gt;
&lt;h2&gt;3 - Initialising Properties when Creating an Object&lt;/h2&gt;
&lt;pre class="code"&gt;
    Point point = &lt;span class="kwrd"&gt;new&lt;/span&gt; Point();
    point.X = 1;
    point.Y = 1;
&lt;/pre&gt;
&lt;p&gt;Or you can use the C# 3.0 syntax:&lt;/p&gt;
&lt;pre class="code"&gt;
    Point point = &lt;span class="kwrd"&gt;new&lt;/span&gt; Point() { X = 1, Y = 1};
&lt;/pre&gt;
&lt;p&gt;Probably if you are using LINQ then you have used this code several times.&lt;/p&gt;&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f30%2fThree-C-Sharp-Syntaxes-That-You-Didnt-Know-But-Were-Afraid-to-Ask.aspx&amp;amp;title=Three+C%23+2.0%2f3.0+Syntaxes+That+You+Didn't+Know+But+Were+Afraid+to+Ask" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f30%2fThree-C-Sharp-Syntaxes-That-You-Didnt-Know-But-Were-Afraid-to-Ask.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=mtbjSTxDCIk:rUcEVlUOcBk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=mtbjSTxDCIk:rUcEVlUOcBk:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=mtbjSTxDCIk:rUcEVlUOcBk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=mtbjSTxDCIk:rUcEVlUOcBk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=mtbjSTxDCIk:rUcEVlUOcBk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=mtbjSTxDCIk:rUcEVlUOcBk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=mtbjSTxDCIk:rUcEVlUOcBk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/mtbjSTxDCIk" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/mtbjSTxDCIk/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/09/30/Three-C-Sharp-Syntaxes-That-You-Didnt-Know-But-Were-Afraid-to-Ask.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=5f5ad725-3aea-4062-9db2-71e83333ba69</guid>
      <pubDate>Tue, 30 Sep 2008 10:06:00 +0000</pubDate>
      <category>Tips and Tricks</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=5f5ad725-3aea-4062-9db2-71e83333ba69</pingback:target>
      <slash:comments>67</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=5f5ad725-3aea-4062-9db2-71e83333ba69</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/09/30/Three-C-Sharp-Syntaxes-That-You-Didnt-Know-But-Were-Afraid-to-Ask.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=5f5ad725-3aea-4062-9db2-71e83333ba69</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=5f5ad725-3aea-4062-9db2-71e83333ba69</feedburner:origLink></item>
    <item>
      <title>UK Software Consultant Nightmare: The IT Recruiting Agents</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fsoftware-consultant-uk-recruiting-agent.jpg" alt="UK Software Consultant and Recruiting Agent" width="484" height="214" /&gt;
&lt;p&gt;
Working as a &lt;a href="http://www.adamtibi.net/" title=".NET software consultant in UK" class="light"&gt;.NET software consultant in UK&lt;/a&gt;, I spent ages with the IT recruiting agents on the phone and had suffered their tricks. So, in this post, I thought of educating my &lt;a href="http://www.adamtibi.net/" title="software consultant" class="light"&gt;software consultant&lt;/a&gt; colleagues of the agents&amp;#39; sneaky tricks and dodgy tactics.
&lt;/p&gt;
&lt;p&gt;
Recruiting agents, especially in the current credit crunch, are having less &amp;#39;productive&amp;#39; work to do due to the reduced demands in the market, so they are spending more time wasting our &amp;quot;&lt;a href="http://www.adamtibi.net/" title="software consultant" class="light"&gt;software consultants&lt;/a&gt;&amp;quot; time and resources rather than doing their actual role which is, obviously, recruiting!
&lt;/p&gt;
&lt;p&gt;
Below are some of their tricks, tactics and some commonly used phrases on the phone:
&lt;/p&gt;

&lt;h2&gt;1 - &amp;quot;I need two references from your current and ex employers&amp;quot;&lt;/h2&gt;
&lt;p&gt;
This is the most famous phrase that you will hear and probably if you are a &lt;a href="http://www.adamtibi.net/" title=".NET software consultant in UK" class="light"&gt;software consultant in UK&lt;/a&gt; then you know what I am talking about.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;When&lt;/em&gt;: This happens after the agent does the sale pitch for a non-existing job. The job miraculously matches your skills, highly paid, in a location near you and the client is willing to train you for the skills that you don&amp;#39;t have.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Claimed Reason&lt;/em&gt;: His client, which is mostly a blue chip or a company that he can&amp;#39;t give its name at the moment, requires the references to validate your suitability.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Real Reason&lt;/em&gt;: As you have already left your current job, then there might be a vacancy in the company, so the agent will call the reference and offers him/her some candidates that match the used technology as you have already told the agent everything about the projects and used technology.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Implications&lt;/em&gt;: Your references will get TOO MANY cold calls which will put you in a bad position and in the worst case you will lose your references.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;What Should I Do&lt;/em&gt;: You should only give a reference, if asked, after a successful interview with the company and to the employer, not the agent! So, you could apologise by saying that you cannot do it as your references are getting too much calls from recruiting agents. Don&amp;#39;t go with the &amp;quot;I will give you two references but promise me that you won&amp;#39;t contact them for marketing purposes&amp;quot; route.
&lt;/p&gt;
&lt;p&gt;
Always remember that you are the sale, if he hires you then he gets the commission, otherwise he won&amp;#39;t, so he needs you! If the agent insists on having the references, then ask to end the conversation as the agent is not serious and he doesn&amp;#39;t have any vacancy.
&lt;/p&gt;
&lt;h2&gt;2 - &amp;quot;Are you currently lined up for interviews?&amp;quot;&lt;/h2&gt;
&lt;p&gt;
The idea is that you are a pro and you should have many interviews at the moment so you should be telling the agent &amp;#39;Yes&amp;#39; and that you are in demand (this is what he wants you to say to get to his next question).
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;When&lt;/em&gt;: This question is usually proceeded  by &amp;quot;How do you find the market?&amp;quot; This part of speech usually happens in the beginning of the conversation.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Claimed Reason&lt;/em&gt;: The agent is chit chatting with you and wants to know what you are doing at the moment.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Real Reason&lt;/em&gt;: The agent wants to harvest the current vacancies and offer them his candidates; you are not a sale to him as you went through another agent.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Implication&lt;/em&gt;: The agent might call the interviewer and push his candidates. In the worst cases, he might call the interviewer and claim that you have a bad reputation and the interviewer shouldn&amp;#39;t interview or hire you.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;What Should I Do&lt;/em&gt;: Answer with &amp;quot;No&amp;quot;, if the agent asks why, you could tell him that you have just started searching.
&lt;/p&gt;
&lt;h2&gt;3 - &amp;quot;What employers did you submit your CV to&amp;quot;&lt;/h2&gt;
&lt;p&gt;
&lt;em&gt;When&lt;/em&gt;: This is proceeded  by that &amp;quot;We have a lot of vacancies and we will be sending your CV to [put big number here] of employers and we want to make sure that your CV haven&amp;#39;t been submitted to that employer.&amp;quot;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Claimed Reason&lt;/em&gt;: You don&amp;#39;t want the employer to get a duplicate submission of your CV as this will give an unprofessional image about you.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Real Reason&lt;/em&gt;: Yes, You guessed it!
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Implication&lt;/em&gt;: Same as the previous point.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;What Should I Do&lt;/em&gt;: Don&amp;#39;t go down the route of giving clues about the companies that are of interest to you, note that the agent will be pushing for clues if you refuse to give the company name and details. If you give clues then a colleague of the agent will call you later and offer you the same job that you gave clues about and expects you to say &amp;quot;I have already applied for company X, so please don&amp;#39;t put me forward for this.&amp;quot;
&lt;/p&gt;
&lt;h2&gt;4 - &amp;quot;I have a Vacancy for You [sale pitch goes here], I will tell you the full details this [time goes here]&amp;quot;&lt;/h2&gt;
&lt;p&gt;
This is just for harvesting your details and buy some time to keep you out of the market as long as possible as if you get hired by another agent then this agent lost the sale!
&lt;/p&gt;
&lt;h2&gt;5 - &amp;quot;I will put you on the phone with the employer who wants to keep his details hidden&amp;quot;&lt;/h2&gt;
&lt;p&gt;
Probably, the employer will be a colleague of the agent who will try to extract the reference information from you as now he is the employer which you assumingly trust more!
&lt;/p&gt;
&lt;h2&gt;6 - &amp;quot;Oh you have worked at company X, I know [false name] from the HR department, who do you know there?&amp;quot;&lt;/h2&gt;
&lt;p&gt;
Well, probably you know the reason behind this question by now which is information harvesting. Just refuse to give a name or give a false name.
&lt;/p&gt;
&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fSmiths.jpg" alt="Smiths" width="484" height="214" /&gt;
&lt;h2&gt;7 - &amp;quot;He is on the other line&amp;quot;, &amp;quot;He is out of the office&amp;quot;, &amp;quot;He is in a meeting&amp;quot;&lt;/h2&gt;
&lt;p&gt;
This is what the receptionist will tell you after you call the recruiting agency, giving your name and reason for call when asking for a specific agent.
&lt;/p&gt;
&lt;p&gt;
You probably are calling after you have submitted your CV to discuss this matching vacancy further with the agent. But the agent has posted that FAKE ad to harvest CVs and has no time to waste on the phone with you. Good luck trying to get him on the email as well.
&lt;/p&gt;
&lt;h2&gt;8 - &amp;quot;What is your current rate at your current employment?&amp;quot;&lt;/h2&gt;
&lt;p&gt;
In the case of a software consultant, they want to try to squeeze down your rate to get a higher share themselves.
&lt;/p&gt;
&lt;p&gt;
I believe that this question should only be asked after explaining the job they want to propose to you so you could decide your rate based on the given factors.
&lt;/p&gt;
&lt;p&gt;
If you have been asked for your previous rate, ask what his proposed role is paying and what is it about.
&lt;/p&gt;
&lt;h2&gt;9 - False Job Ads&lt;/h2&gt;
&lt;p&gt;
The majority of posted ads on famous job sites like jobserve.com are fake! Their aim is to harvest CVs:
&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;To be ready when they get a client.&lt;/li&gt;
	&lt;li&gt;Because they don&amp;#39;t want to post information that will lead their competitors to the client, so they will contact you and tell you that this vacancy is taken now and they have these new vacancies.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;10 - Threatening of blacklisting you if you are not going to cooperate&lt;/h2&gt;
&lt;p&gt;
Agents might get very rude when you refuse to give information and will start threatening of blacklisting you and tell other agencies how bad you are.
&lt;/p&gt;
&lt;p&gt;
In this case I would beg the agent to blacklist me as I will be more than happy not to get contacted from agents from the same nature.
&lt;/p&gt;
&lt;h2&gt;11 - The Job is Posted Else Where But With The Real Company Name&lt;/h2&gt;
&lt;p&gt;
Agents might go as far as copying a direct employer&amp;#39;s posted ad from some where, change the employer&amp;#39;s real info into vague ones, then post it as if it is their own without the employer&amp;#39;s consent and even though, in most cases, the employer has mentioned the phrase &amp;quot;strictly no agents.&amp;quot; The reason might be:
&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Using a good targeted ad, written by an experienced employer and use it to harvest CVs for the agent&amp;#39;s own benefit, i.e. to be used for other jobs.&lt;/li&gt;
	&lt;li&gt;Will take the CVs, filter it, then send it to the employer to show him that &amp;quot;we are a good agency&amp;quot; and we can get you good candidates.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;12 - Removing Your Contact Information From the CV&lt;/h2&gt;
&lt;p&gt;
Now the agent called you, agreed with you, and is going to send your CV to his client. The next step is removing any contact information or anything that might lead to you before sending it to the client.
&lt;/p&gt;
&lt;p&gt;
Why? You probably know why! He is an agent and since he is working in an enviroment that is &amp;#39;unsafe&amp;#39; where you can&amp;#39;t trust anyone, he assumes that this also applies to software consultants. What a shame...
&lt;/p&gt;
&lt;h2&gt;13 - Agents Might Push You for an Interview for a Job that Doesn&amp;#39;t Meet Your Skills&lt;/h2&gt;
&lt;ol&gt;
	&lt;li&gt;Maybe to send as much candidates as possible to the employer&lt;/li&gt;
	&lt;li&gt;Who knows? It might work! After all, the agent isn&amp;#39;t the one who is wasting his time, it is the candidate and the employer!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Ask for a phone interview at first if you are not sure of the requirements or if you have any suspicion. This will save both your and the interviewer&amp;#39;s time.
&lt;/p&gt;
&lt;p&gt;
Frankly speaking, it might not be the agent&amp;#39;s fault, it might be that the employer did not supply the agent with the full requirement.
&lt;/p&gt;
&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fagent-smith-laugh.jpg" alt="Agent Smith, of The Matrix, laughing" width="420" height="262" /&gt;
&lt;h2&gt;Honest to God Words to the Recruiting Agents&lt;/h2&gt;
&lt;p&gt;
For the honest recruiting agents, I am sorry that these practices, which are employed by some agencies, have ruined your reputation and please note that this post has no intention of generalisation. For the other types of agents, these are my words to you:
&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Don&amp;#39;t insult our intelligence by using cheap tactics, because if we work as software consultants then that mean we are intelligent enough to perform such a job.&lt;/li&gt;
	&lt;li&gt;Stop wasting our time to harvest information as we really have more important things to do.&lt;/li&gt;
	&lt;li&gt;Stop using these phrases: &amp;#39;brilliant&amp;#39;, &amp;#39;fantastic&amp;#39;, &amp;#39;I&amp;#39;m going to pass your CV to my colleagues&amp;#39;, &amp;#39;we have [employer quantity]&amp;#39;, &amp;#39;leave it with me, I&amp;#39;m going to take it from there&amp;#39; and &amp;#39;you have a fantastic CV&amp;#39;.&lt;/li&gt;
	&lt;li&gt;&amp;quot;Largest TV Group in Europe&amp;quot; means Sky and &amp;quot;Europe&amp;#39;s biggest B2B media company&amp;quot; is RBI. Come on guys, Britain is too small for this, could you make the ad description more vague please? This is so easy and software consultants are not dump, you know.&lt;/li&gt;
	&lt;li&gt;If you are honest and not a time waster then please display your phone number, that shows more consideration to the candidates.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Advice To the Software Consultant&lt;/h2&gt;
&lt;ol&gt;
	&lt;li&gt;Don&amp;#39;t give your real phone number to the agents as they will keep cold calling you every [set amount of time] to harvest information and update their database, use a pay as you go phone if you are job hunting.&lt;/li&gt;
	&lt;li&gt;Same goes for email, use a different email for recruitment as you will get loads of irrelevant emails with apologies in the beginning if this is irrelevant.&lt;/li&gt;
	&lt;li&gt;Educate your colleagues with the tactics mentioned in this post as we should all stand against such tricks and have a better, mature and more professional recruiting environment for software consultants in UK.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Finally, I am happy that I wrote this post and shared my experience, and nightmares, with the rest of UK&amp;#39;s software consultant colleagues. If you are a software consultant in the American market, then let me know if you have a similar experience. Please let me know if I have missed an important trick or if you had a bad experience. If you like it then please Digg It and Kick It.
&lt;/p&gt;
&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f30%2fUK-Software-Consultant-Nightmare-The-IT-Recruiting-Agents.aspx&amp;amp;title=UK+Software+Consultant+Nightmare%3a+The+IT+Recruiting+Agents" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f30%2fUK-Software-Consultant-Nightmare-The-IT-Recruiting-Agents.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=SySOhfU1Ph8:3LDh3yd0kxg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=SySOhfU1Ph8:3LDh3yd0kxg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=SySOhfU1Ph8:3LDh3yd0kxg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=SySOhfU1Ph8:3LDh3yd0kxg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=SySOhfU1Ph8:3LDh3yd0kxg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=SySOhfU1Ph8:3LDh3yd0kxg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=SySOhfU1Ph8:3LDh3yd0kxg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/SySOhfU1Ph8" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/SySOhfU1Ph8/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/09/30/UK-Software-Consultant-Nightmare-The-IT-Recruiting-Agents.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=aa5a9892-6ac5-4666-95f7-065c990f3e2e</guid>
      <pubDate>Tue, 30 Sep 2008 09:03:00 +0000</pubDate>
      <category>Software Consultant</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=aa5a9892-6ac5-4666-95f7-065c990f3e2e</pingback:target>
      <slash:comments>57</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=aa5a9892-6ac5-4666-95f7-065c990f3e2e</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/09/30/UK-Software-Consultant-Nightmare-The-IT-Recruiting-Agents.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=aa5a9892-6ac5-4666-95f7-065c990f3e2e</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=aa5a9892-6ac5-4666-95f7-065c990f3e2e</feedburner:origLink></item>
    <item>
      <title>How Not To Compromise Security Through ASP.NET Validators</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fsecurity-hole.gif" alt="Security Holes in ASP.NET Validator Controls" width="484" height="387" /&gt;
&lt;p&gt;I have explained in &lt;a href="http://www.adamtibi.net/post/2008/09/22/The-Three-Steps-of-Building-an-ASPNET-Validator-Control.aspx"&gt;The Three Steps of Building an ASP.NET Validator Control&lt;/a&gt;, how to build a validator control from the ground up in three easy steps and in a reusable format. I highly recommend reading it before going any further.&lt;/p&gt;
&lt;p&gt;Here I am discussing the common validator control security holes that might compromise your forms security when left untreated.&lt;/p&gt;

&lt;h2&gt;Security Hole 1: Failing to Implement The Server-Side Validation&lt;/h2&gt;
&lt;p&gt;When building a validator control from scratch or using a &lt;code&gt;CustomValidator&lt;/code&gt;, you should always implement server-side validation (i.e. the .NET code), however, the client-side validation (i.e. The javascript) code is optional but nice to have.&lt;/p&gt;
&lt;p&gt;The reason is, a malicious user might disable JavaScript from his browser to bypass your validation or might not even be using a browser but some code to post to your form.&lt;/p&gt;
&lt;p&gt;Always start by building the server-side validation, test it, then start building the client one.&lt;/p&gt;
&lt;h2&gt;Security Hole 2: Failing to check &lt;code&gt;Page.IsValid&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is a major pitfall and failing to avoid it will render your validation next to useless! Before you process any data coming from your form, you need to make sure that it has passed your validators, however, if the client's browser has JavaScript disabled, then the code will reach the server without validation and will require you to check the &lt;code&gt;Page.IsValid&lt;/code&gt; manually. For example:&lt;/p&gt;
&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Submit_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e) {
    &lt;span class="rem"&gt;// Very Important&lt;/span&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!Page.IsValid) {
        &lt;span class="kwrd"&gt;return&lt;/span&gt;;
    }

    &lt;span class="rem"&gt;// Do some processing here...&lt;/span&gt;
}
&lt;/pre&gt;
&lt;h2&gt;Security Hole 3: Client-side and Server-Side Regular Expressions&lt;/h2&gt;
&lt;p&gt;Regular expressions AKA RegEx on the server-side and the client-side may not have the same desired effect, in other words, the same regular expression syntax that works on the server side, might not work on the client side. So make sure you thoroughly test both.&lt;/p&gt;
&lt;h2&gt;Security Hole 4: Relying on the &lt;code&gt;MaxLength&lt;/code&gt; property of a &lt;code&gt;TextBox&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is not directly related to validator controls, however, it belongs to validation and I thought of mentioning it for completion.&lt;/p&gt;
&lt;p&gt;You should not rely only on &lt;code&gt;MaxLength&lt;/code&gt; to restrict the max allowed text for your &lt;code&gt;TextBox&lt;/code&gt; as this property can be easily bypassed on the client, by setting the &lt;code&gt;TextBox&lt;/code&gt; with JavaScript for example, and will never be checked on the server-side. However, set it anyway for usability purpose.&lt;/p&gt;
&lt;p&gt;To force a max length on a &lt;code&gt;TextBox&lt;/code&gt;, you might use a &lt;code&gt;RegularExpressionValidator&lt;/code&gt; with the validation expression &lt;code&gt;^.{0,&lt;em&gt;MaxLength&lt;/em&gt;}$&lt;/code&gt;.&lt;/p&gt;
&lt;p class="summary"&gt;Always test your validators in both modes JavaScript enabled and disabled. To turn off JavaScript in Internet Explorer, you can go to the "Security Settings", however, I recommend using &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=e59c3964-672d-4511-bb3e-2d5e1db91038&amp;displaylang=en" target="_blank"&gt;Internet Explorer Developer Toolbar&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you think that there are more security holes that are worth mentioning then please drop me a comment line.&lt;/p&gt;&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f23%2fHow-Not-To-Compromise-Security-Through-ASPNET-Validators.aspx&amp;amp;title=How+Not+To+Compromise+Security+Through+ASP.NET+Validators" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f23%2fHow-Not-To-Compromise-Security-Through-ASPNET-Validators.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=v5mUY8zX0ZU:S_qbwOP2dug:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=v5mUY8zX0ZU:S_qbwOP2dug:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=v5mUY8zX0ZU:S_qbwOP2dug:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=v5mUY8zX0ZU:S_qbwOP2dug:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=v5mUY8zX0ZU:S_qbwOP2dug:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=v5mUY8zX0ZU:S_qbwOP2dug:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=v5mUY8zX0ZU:S_qbwOP2dug:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/v5mUY8zX0ZU" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/v5mUY8zX0ZU/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/09/23/How-Not-To-Compromise-Security-Through-ASPNET-Validators.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=a257ca1d-dff1-4099-863c-3f625f28da58</guid>
      <pubDate>Tue, 23 Sep 2008 09:45:00 +0000</pubDate>
      <category>ASP.NET Validators</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=a257ca1d-dff1-4099-863c-3f625f28da58</pingback:target>
      <slash:comments>123</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=a257ca1d-dff1-4099-863c-3f625f28da58</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/09/23/How-Not-To-Compromise-Security-Through-ASPNET-Validators.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=a257ca1d-dff1-4099-863c-3f625f28da58</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=a257ca1d-dff1-4099-863c-3f625f28da58</feedburner:origLink></item>
    <item>
      <title>The Three Steps of Building an ASP.NET Validator Control</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fcredit-card-test-ie.gif" alt="Credit Card Number ASP.NET Validator" width="484" height="214" /&gt;
&lt;p&gt;The standard ASP.NET validator controls such as the &lt;code&gt;RequiredFieldValidator&lt;/code&gt; or the &lt;code&gt;RegularExpressionValidator&lt;/code&gt; do not cover all validation requirements, so usually developers tend to create a &lt;code&gt;CustomValidator&lt;/code&gt; for such scenarios.&lt;/p&gt;
&lt;p&gt;A major problem with the &lt;code&gt;CustomValidator&lt;/code&gt; is &lt;strong&gt;reusability&lt;/strong&gt;, as if you wanted to use the validator in another project then there would be some copying and pasting and &lt;strong&gt;code duplication&lt;/strong&gt;, then you have to maintain multiple versions of the same control.&lt;/p&gt;
&lt;p&gt;The solution, as you have guessed from the title, is to build your own validator control when possible to promote reusability.&lt;/p&gt;
&lt;p&gt;In this post I will be showing you in three simple steps how to build an ASP.NET validator control and take credit card number format check to show by example. I will also be building the architecture so that your validator and other validators that you will develop in the future could be as reusable as possible.&lt;/p&gt;
&lt;h2&gt;How to Check a Credit Card Format&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Luhn_algorithm" target="_blank"&gt;Luhn check&lt;/a&gt; is an algorithm that checks if a credit card number is valid (format wise), so in practice, before you even think of doing any further processing on the credit card, this check should be satisfied.&lt;/p&gt;

&lt;h2&gt;Introduction to ASP.NET Validators&lt;/h2&gt;
&lt;p&gt;ASP.NET validators are ASP.NET controls that when associated with a web control will perform client-side (JavaScript) and server-side (C#/VB.NET) validation.&lt;/p&gt;
&lt;p&gt;Using them will dramatically reduce the amount of validation code and will helps in writing more maintainable and clean code. The more specialised controls that you have the more you will finish building a form faster.&lt;/p&gt;
&lt;p&gt;All what you need to do is check for &lt;code&gt;Page.IsValid&lt;/code&gt; in the server-side (in our case that would be the code-behind file) to make sure that the page is valid before you start collecting its values.&lt;/p&gt;
&lt;h2&gt;Step 1: Prepare The Class Library to Include the Validators&lt;/h2&gt;
&lt;p&gt;You will need a class library to host your validator, this class library will be used to add additional validators in the future. The library will contain a JavaScript file that will include the required JavaScript and will be served whenever the validator is used.&lt;/p&gt;
&lt;h3&gt;Add The Class Library&lt;/h3&gt;
&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fcreate-class-library.gif" width="484" height="265" alt="create a class library in Visual Studio 2008" /&gt;
&lt;p&gt;Create a new class library, mine is called &lt;code&gt;AT.Web.UI.Validators&lt;/code&gt; then add a reference to &lt;code&gt;System.Web&lt;/code&gt; and remove the auto generated class &lt;code&gt;class1&lt;/code&gt; from the project&lt;/p&gt;
&lt;p&gt;You will need to add this line to the end of the AssemblyInfo.cs&lt;/p&gt;
&lt;pre class="code"&gt;
[assembly: TagPrefix(&lt;span class="str"&gt;"AT.Web.UI.Validators"&lt;/span&gt;, &lt;span class="str"&gt;"at"&lt;/span&gt;)]
&lt;/pre&gt;
&lt;p&gt;The previous line will append the prefix "at" to the validator control when dropped on a form.&lt;/p&gt;
&lt;h3&gt;Add the JavaScript file&lt;/h3&gt;
&lt;img class="alignright" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fcreate-javascript.gif" alt="Add an embedded JavaScript WebResource in Visual Studio 2008" width="216" height="394" /&gt;
&lt;p&gt;This is the JavaScript file that will be served whenever our validator is used on a page. We will &lt;strong&gt;embed&lt;/strong&gt; this file as a &lt;code&gt;WebResource&lt;/code&gt; in the library to save ourselves adding it manually to every page that uses our validator.&lt;/p&gt;
&lt;p&gt;To know more about &lt;code&gt;WebResources&lt;/code&gt; have a look at &lt;a href="http://www.codeproject.com/KB/aspnet/MyWebResourceProj.aspx" target="_blank"&gt;WebResource ASP.NET 2.0 explained&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now add a JavaScript file and call it JavaScript.js then change its build action to be "Embedded Resource." In the AssemblyInfo.cs file you need to add a line that will make this JavaScript file a &lt;code&gt;WebResource&lt;/code&gt;, first add a reference to the name space &lt;code&gt;using System.Web.UI;&lt;/code&gt; then append this line to the end of the file:&lt;/p&gt;
&lt;pre class="code"&gt;
[assembly: WebResource(
      &lt;span class="str"&gt;"AT.Web.UI.Validators.JavaScript.js"&lt;/span&gt;,
      &lt;span class="str"&gt;"application/x-javascript"&lt;/span&gt;)]
&lt;/pre&gt;
&lt;p&gt;Step 1 will only be done once and the next time you add a new validator you won't need to do it again.&lt;/p&gt;
&lt;h2&gt;Step 2: Write the ASP.NET Validator&lt;/h2&gt;
&lt;p&gt;Add to the project a class file and call it CreditCardValidator.cs. The code that should go in the class looks like the following, I will discuss the code later:&lt;/p&gt;
&lt;pre class="code"&gt;
&lt;span class="rem"&gt;// CreditCardValidator.cs&lt;/span&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.WebControls;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; AT.Web.UI.Validators {

&lt;span class="rem"&gt;// Tells VS that when the control is droped on the form, it should look like this&lt;/span&gt;
[ToolboxData(&lt;span class="str"&gt;@"&amp;lt;{0}:CreditCardValidator runat=server&amp;gt;&amp;lt;/{0}:CreditCardValidator&amp;gt;"&lt;/span&gt;)]

&lt;span class="rem"&gt;// The best way to start your own validator is to inherit BaseValidator&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CreditCardValidator : BaseValidator {

    &lt;span class="rem"&gt;// This method will be executing while the attributes are being rendered&lt;/span&gt;
    &lt;span class="rem"&gt;// and the HTML is being generated. This method should always be overriden&lt;/span&gt;
    &lt;span class="rem"&gt;// to supply the name of the client-side check function.&lt;/span&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AddAttributesToRender(HtmlTextWriter writer) {
        &lt;span class="kwrd"&gt;base&lt;/span&gt;.AddAttributesToRender(writer);

    &lt;span class="rem"&gt;// Checking if the browser supports JavaScript&lt;/span&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (RenderUplevel) {
        &lt;span class="rem"&gt;// This will "attach" an attribute called "evaluationfunction" and gives&lt;/span&gt;
            &lt;span class="rem"&gt;// it a value "CreditCardNumberValidatorEvaluateIsValid" which is the &lt;/span&gt;
            &lt;span class="rem"&gt;// JavaScript function that will be called to validate the TextBox&lt;/span&gt;
            Page.ClientScript.RegisterExpandoAttribute(ClientID, &lt;span class="str"&gt;"evaluationfunction"&lt;/span&gt;, 
                &lt;span class="str"&gt;"CreditCardNumberValidatorEvaluateIsValid"&lt;/span&gt;);
       }
    }

    &lt;span class="rem"&gt;// This method will be called when the server-side checking is triggered&lt;/span&gt;
    &lt;span class="rem"&gt;// and should ALWAYS be implemented to return true or false.&lt;/span&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; EvaluateIsValid() {
        &lt;span class="kwrd"&gt;string&lt;/span&gt; cardNumber = &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetControlValidationValue(ControlToValidate);
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!IsValidCardNumber(cardNumber)) {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
        }
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
    }

    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnPreRender(System.EventArgs e) {
        &lt;span class="rem"&gt;// emit the JS file into the page so you won't need to add it manually&lt;/span&gt;
        Page.ClientScript.RegisterClientScriptResource(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(CreditCardValidator),
                                             &lt;span class="str"&gt;"AT.Web.UI.Validators.JavaScript.js"&lt;/span&gt;);

        &lt;span class="kwrd"&gt;base&lt;/span&gt;.OnPreRender(e);
    }
    
    &lt;span class="rem"&gt;// Luhn check algorithm which will check the validity of the Credit Card #&lt;/span&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsValidCardNumber(&lt;span class="kwrd"&gt;string&lt;/span&gt; cardNumber) {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!System.Text.RegularExpressions.Regex.IsMatch(cardNumber,&lt;span class="str"&gt;"^[0-9]*$"&lt;/span&gt;)) {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
        }
        &lt;span class="kwrd"&gt;int&lt;/span&gt; length = cardNumber.Length;

        &lt;span class="kwrd"&gt;if&lt;/span&gt; (length &amp;lt; 12) {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
        }
        &lt;span class="kwrd"&gt;int&lt;/span&gt; sum = 0;
        &lt;span class="kwrd"&gt;int&lt;/span&gt; offset = length % 2;
        &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] digits = &lt;span class="kwrd"&gt;new&lt;/span&gt; ASCIIEncoding().GetBytes(cardNumber);

        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; length; i++) {
            digits[i] -= 48;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (((i + offset) % 2) == 0)
                digits[i] *= 2;

            sum += (digits[i] &amp;gt; 9) ? digits[i] - 9 : digits[i];
        }
        &lt;span class="kwrd"&gt;return&lt;/span&gt; ((sum % 10) == 0);
    }

}

}
&lt;/pre&gt;
&lt;p&gt;And the JavaScript.js file:&lt;/p&gt;
&lt;pre class="code"&gt;
&lt;span class="rem"&gt;// This function shall be called for client-side validation&lt;/span&gt;
function CreditCardNumberValidatorEvaluateIsValid(val) {
    &lt;span class="kwrd"&gt;var&lt;/span&gt; cardNumber = ValidatorTrim(ValidatorGetValue(val.controltovalidate));
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!IsValidCardNumber(cardNumber)) {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    }
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
}

&lt;span class="rem"&gt;// Luhn check, the JavaScript way&lt;/span&gt;
function IsValidCardNumber(cardNumber) {
    &lt;span class="kwrd"&gt;var&lt;/span&gt; digitsRegex = &lt;span class="kwrd"&gt;new&lt;/span&gt; RegExp(&lt;span class="str"&gt;"^[0-9]*$"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!digitsRegex.test(cardNumber)) {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    }
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cardNumber.length &amp;lt; 12) {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    }
    &lt;span class="kwrd"&gt;var&lt;/span&gt; sum = 0;
    &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;var&lt;/span&gt; i = 0; i &amp;lt; cardNumber.length - 1; i++) {
        &lt;span class="kwrd"&gt;var&lt;/span&gt; weight = cardNumber.substr(cardNumber.length - 
                (i + 2), 1) * (2 - (i % 2));
        sum += ((weight &amp;lt; 10) ? weight : (weight - 9));
    }
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (parseInt(cardNumber.substr(cardNumber.length - 1)) == 
                ((10 - sum % 10) % 10)) {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
    } 
    &lt;span class="kwrd"&gt;else&lt;/span&gt; {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    }
}
&lt;/pre&gt;
&lt;h3&gt;What is this code all about?&lt;/h3&gt;
&lt;p&gt;When implementing ASP.NET validators, your best candidate to inherit from is the &lt;code&gt;BaseValidator&lt;/code&gt;. And you should always, at least, override these three methods: &lt;code&gt;AddAttributesToRender&lt;/code&gt;, &lt;code&gt;EvaluateIsValid&lt;/code&gt; and &lt;code&gt;OnPreRender&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The JavaScript in our case matches the C# code to do the same check on the client. Note that the JavaScript is using &lt;code&gt;ValidatorTrim&lt;/code&gt; and &lt;code&gt;ValidatorGetValue&lt;/code&gt; which are methods that are available to you via the framework.&lt;/p&gt;
&lt;p&gt;The reason behind both server and client sides checking is because:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;The user will have an old browser or JavaScript turned off, so in all cases, the server-side check would still execute. You don't want to be at the mercy of your web users, do you?&lt;/li&gt;
	&lt;li&gt;The JavaScript will help informing the user as soon as he changes focus or clicking submit that his entry is invalid and saves the page to do a round trip to the server.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Step 3: Use the Validator Control&lt;/h2&gt;
&lt;img class="alignright" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fcreate-test-website.gif" alt="Creating a test website with Visual Studio 2008" width="216" height="285" /&gt;
&lt;p&gt;Now that you have created the validator you will need to test it and use it. So, create a web project and then add the class library that you have created in Step 1 to the solution. Add a reference from the web project to the class library project (not to the .dll).&lt;/p&gt;
&lt;p&gt;You will need to add this line to the web.config inside your &lt;code&gt;system.web&lt;/code&gt; section:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;pages&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;controls&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;tagPrefix&lt;/span&gt;&lt;span class="kwrd"&gt;="at"&lt;/span&gt;&lt;br /&gt;        &lt;span class="attr"&gt;namespace&lt;/span&gt;&lt;span class="kwrd"&gt;="AT.Web.UI.Validators"&lt;/span&gt;&lt;br /&gt;        &lt;span class="attr"&gt;assembly&lt;/span&gt;&lt;span class="kwrd"&gt;="AT.Web.UI.Validators"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;controls&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;pages&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This will instruct ASP.NET that whenever there is a tag that is prefixed with "at" then it should be fetched from namespace &lt;code&gt;AT.Web.UI.Validators&lt;/code&gt; that exists in assembly &lt;code&gt;AT.Web.UI.Validators.dll&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Drop it on the page&lt;/h3&gt;
&lt;p&gt;Add the following code to the "default.aspx" page.&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Label&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;AssociatedControlID&lt;/span&gt;&lt;span class="kwrd"&gt;="CreditCardNumber"&lt;/span&gt; &lt;br /&gt;            &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Credit Card Number"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Label&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:TextBox&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="CreditCardNumber"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;at:CreditCardValidator&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;ControlToValidate&lt;/span&gt;&lt;span class="kwrd"&gt;="CreditCardNumber"&lt;/span&gt;&lt;br /&gt;            &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Invalid credit card number. Please recheck."&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Button&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="Submit"&lt;/span&gt; &lt;span class="attr"&gt;onclick&lt;/span&gt;&lt;span class="kwrd"&gt;="Submit_Click"&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Submit"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;For a list of test credit card numbers try this &lt;a href="http://www.rimmkaufman.com/rkgblog/2007/11/09/credit-card-test-numbers/" target="_blank" rel="nofollow"&gt;Credit Card Test Numbers&lt;/a&gt;&lt;/p&gt;
&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fcredit-card-test-ff.gif" alt="ASP.NET Validator Test on FireFox" width="484" height="168" /&gt;
&lt;h2&gt;Download&lt;/h2&gt;
&lt;p&gt;I have added the source code with Visual Studio 2008 solution and the assembly file using .NET Framework 2.0, feel free to download it and use it. However, all copyrights should be reserved.&lt;/p&gt;
&lt;p class="download"&gt;&lt;a href="http://www.adamtibi.net/file.axd?file=credit-card-aspnet-validator.zip"&gt;&amp;lt;&amp;lt; Credit Card ASP.NET Validator (11 kb) &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;I tried to ensure that the information posted here are up to date and accurate, however, I do not hold any responsibility to any damages that might occur from using or misusing the information and the posted code.&lt;/p&gt;
&lt;h2&gt;What is next?&lt;/h2&gt;
&lt;p&gt;In the next post I will be discussing the validators secrity holes... If you liked what you've seen so far, then let me know in a comment so I would discuss it in the next post. And finally, &lt;strong&gt;Kick It&lt;/strong&gt; if you like it!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;a href="http://www.adamtibi.net/post/2008/09/23/How-Not-To-Compromise-Security-Through-ASPNET-Validators.aspx"&gt;How Not To Compromise Security Through ASP.NET Validators&lt;/a&gt;.&lt;/p&gt;&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f22%2fThe-Three-Steps-of-Building-an-ASPNET-Validator-Control.aspx&amp;amp;title=The+Three+Steps+of+Building+an+ASP.NET+Validator+Control" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f22%2fThe-Three-Steps-of-Building-an-ASPNET-Validator-Control.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=XgtIoW7Zyug:rH8ij3rMFdc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=XgtIoW7Zyug:rH8ij3rMFdc:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=XgtIoW7Zyug:rH8ij3rMFdc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=XgtIoW7Zyug:rH8ij3rMFdc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=XgtIoW7Zyug:rH8ij3rMFdc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=XgtIoW7Zyug:rH8ij3rMFdc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=XgtIoW7Zyug:rH8ij3rMFdc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/XgtIoW7Zyug" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/XgtIoW7Zyug/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/09/22/The-Three-Steps-of-Building-an-ASPNET-Validator-Control.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=4aaf48c5-2c19-4332-a41b-7dc9674590ee</guid>
      <pubDate>Mon, 22 Sep 2008 09:40:00 +0000</pubDate>
      <category>ASP.NET Validators</category>
      <category>Web Controls</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=4aaf48c5-2c19-4332-a41b-7dc9674590ee</pingback:target>
      <slash:comments>109</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=4aaf48c5-2c19-4332-a41b-7dc9674590ee</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/09/22/The-Three-Steps-of-Building-an-ASPNET-Validator-Control.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=4aaf48c5-2c19-4332-a41b-7dc9674590ee</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=4aaf48c5-2c19-4332-a41b-7dc9674590ee</feedburner:origLink></item>
    <item>
      <title>Google Sandbox: When? Why? And How to Dump it!</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fGoogle-Sandbox.gif" alt="Google Sandbox, your website here" width="484" height="214" /&gt; 
&lt;p&gt;
I got a question from Anthony Grace in the comments of my previous post &lt;a href="http://www.adamtibi.net/post/2008/09/16/Three-Rules-That-ASPNET-Developers-Should-Know-About-SEO.aspx"&gt;Three Rules That ASP.NET Developers Should Know About SEO&lt;/a&gt; about Google Sandbox and thought of writing this short post to illustrate what is it and how to avoid it. 
&lt;/p&gt;
&lt;p&gt;
Google Sandbox is, in essence, the process of keeping your website outside Google search results for competitive keywords because your website has just been registered or changed owner. 
&lt;/p&gt;
&lt;h2&gt;When Google Sandbox&lt;/h2&gt;
&lt;p&gt;
The sandbox usually starts when you register a new website and lasts from 6 months up to a year depending on factors that are only known to Google. 
&lt;/p&gt;
&lt;p&gt;
Google is also monitoring the domain registration information so this will also happen when the registered owner of the website changes i.e. you&amp;#39;ve bought a second hand domain. 
&lt;/p&gt;
&lt;p&gt;
Put simply, you are sandboxed when your website has valuable content and is SEO optimised and you are no where near the search engine top result pages. 
&lt;/p&gt;
 
&lt;h2&gt;Why Google Sandbox&lt;/h2&gt;
&lt;p&gt;
Even though Google doesn&amp;#39;t admit the concept of Google Sandbox, however, it is crystal clear that it exists. 
&lt;/p&gt;
&lt;p&gt;
The reason behind this is obvious, Google is mimicking real life situation when you just start a business and don&amp;#39;t expect people to come running at you for your services. Also, if old sites and newly registered sites are treated the same, then this is unfair. 
&lt;/p&gt;
&lt;p&gt;
Another reason is to prevent spammers of starting a spammy website to market some products and do some &lt;a href="http://websearch.about.com/od/seononos/a/spamseo.htm" target="_blank"&gt;black hat SEO&lt;/a&gt; methods to get visitors to their site. 
&lt;/p&gt;
&lt;h2&gt;How to Dump It&lt;/h2&gt;
&lt;p&gt;
Now the bad news, you cannot avoid it! But you could follow some practices in reducing its effect: 
&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Register your domain name as soon as you think of a business and even before start implementing the website.&lt;/li&gt;
	&lt;li&gt;Some people claim that going with AdSense or AdWords programs could take you out faster, but I didn&amp;#39;t validate this myself.&lt;/li&gt;
	&lt;li&gt;Get external links to your website, aka backlinks, from a high profile websites such as governmental sites, reputable charities, etc...&lt;/li&gt;
	&lt;li&gt;If you are buying a second hand domain name, try to seek ways to not changing the registered owner so that your domain age is not reset. There is not generic way to do it, every case has its own solution.&lt;/li&gt;
	&lt;li&gt;Buy a domain that has recently expired and still appears in Google results, you might be lucky...&lt;/li&gt;
	&lt;li&gt;Temporarily, use a subdomain of a non-sandboxed site. When your subdomain site is fully indexed then do 301 redirections to your sandboxed site. The rank for every page that has already been indexed shall be preserved.&lt;/li&gt;
	&lt;li&gt;Following the movies popular phrase: &amp;quot;If I go down, I will take you all with me!&amp;quot;. There are some black hat SEO methods, that I won&amp;#39;t even mention as they are unethical, to take your competitors down since you cannot climb up...&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
I have experimented the effect myself on this site &lt;a href="http://www.adamtibi.net"&gt;www.adamtibi.net&lt;/a&gt; and on other sites as well. I have met some friends and businesses who were frustrated by this effect thinking that their website is not attracting visitors. 
&lt;/p&gt;
&lt;p&gt;
If you have encountered this effect, then drop me a comment line and let me know how you escaped it. 
&lt;/p&gt;
&lt;p&gt;
Best sandbox-free wishes. 
&lt;/p&gt;
&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f20%2fGoogle-Sandbox-When-Why-And-How-to-Dump-it.aspx&amp;amp;title=Google+Sandbox%3a+When%3f+Why%3f+And+How+to+Dump+it!" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f20%2fGoogle-Sandbox-When-Why-And-How-to-Dump-it.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=f7DyJlls6iw:-MP962QDois:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=f7DyJlls6iw:-MP962QDois:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=f7DyJlls6iw:-MP962QDois:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=f7DyJlls6iw:-MP962QDois:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=f7DyJlls6iw:-MP962QDois:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=f7DyJlls6iw:-MP962QDois:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=f7DyJlls6iw:-MP962QDois:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/f7DyJlls6iw" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/f7DyJlls6iw/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/09/20/Google-Sandbox-When-Why-And-How-to-Dump-it.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=132335bb-d26d-4b6e-ae7d-5e7d98194b37</guid>
      <pubDate>Sat, 20 Sep 2008 14:52:00 +0000</pubDate>
      <category>SEO</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=132335bb-d26d-4b6e-ae7d-5e7d98194b37</pingback:target>
      <slash:comments>82</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=132335bb-d26d-4b6e-ae7d-5e7d98194b37</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/09/20/Google-Sandbox-When-Why-And-How-to-Dump-it.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=132335bb-d26d-4b6e-ae7d-5e7d98194b37</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=132335bb-d26d-4b6e-ae7d-5e7d98194b37</feedburner:origLink></item>
    <item>
      <title>Three Rules That ASP.NET Developers Should Know About SEO</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2faspnet-seo.gif" alt="ASP.NET &amp;amp; SEO" width="484" height="214" /&gt;
&lt;p&gt;Search engines optimisation, SEO, is an evolving &amp;#39;science&amp;#39; and it keeps changing on purpose. Most articles that I read which involve both SEO and ASP.NET usually focus on how to programatically set the meta keywords tag and they tend to make it look like very important while, as of today, it has minimal effect on optimisation.&lt;/p&gt;
&lt;p&gt;Generally, web developers tend to turn the blind eye when it comes to SEO while a great part of SEO should be done by developers. Here are three rules for .NET developers to follow while building a site:&lt;/p&gt;

&lt;h2&gt;1 - Favour XHTML with DIV and CSS Design Over Tabular Design&lt;/h2&gt;
&lt;p&gt;Thankfully, the era of developing tables-based website is about to end. Today most of the sites are following the DIV and CSS style of design and are table free, except for tobular data. However, some designers and developers did not make the leap yet. The DIV with CSS design will:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Generate less code which will improve your &amp;#39;code to content&amp;#39; ranking which is favoured by search engines.&lt;/li&gt;
	&lt;li&gt;Improve your page load as your pages tend to have smaller size with reduced tags and will be even smaller with the CSS sheet separated. Load time is another factor in SEO.&lt;/li&gt;
	&lt;li&gt;Promote better web semantics by marking your content with the correct XHTML elements. This will enable the spider(the search engine robot which will crawl your pages content) to better understand the structure of your site and your page content.&lt;/li&gt;
&lt;/ol&gt;
&lt;p class="summary"&gt;Always opt-in for XHTML with DIV and CSS type of design and think of rewriting your current tabular based site in a table-free format.&lt;/p&gt;
&lt;h2&gt;2 - Allow For Meta Description and Meta Keywords Tags&lt;/h2&gt;
&lt;p&gt;The meta description tag, from SEO point of view, will suggest to the search engine what to display in the search results page. The meta keywords tags are mostly ignored by search engines as spammers gave them a bad reputation, today they are only used to add misspellings and different culture spellings e.g. 'optimisation' and 'optimization'.&lt;/p&gt;
&lt;p&gt;ASP.NET does not provide an out-of-the-box solution in adding these tags, so you have two options:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Add a ContentPlaceholder in the head of your MasterPage and fill it with the appropriate MetaKeyword and MetaDescription tags from within the page.
		&lt;p&gt;In the MasterPage:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!-- other xhtml code... --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ContentPlaceHolder&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="head"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ContentPlaceHolder&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="rem"&gt;&amp;lt;!-- other xhtml code... --&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;In the ASPX Page:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="Content1"&lt;/span&gt; &lt;span class="attr"&gt;ContentPlaceHolderID&lt;/span&gt;&lt;span class="kwrd"&gt;="head"&lt;/span&gt; &lt;span class="attr"&gt;Runat&lt;/span&gt;&lt;span class="kwrd"&gt;="Server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;meta&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="keywords"&lt;/span&gt; &lt;span class="attr"&gt;content&lt;/span&gt;&lt;span class="kwrd"&gt;="ASPNET, optimisation, optimization"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;meta&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="description"&lt;/span&gt; &lt;span class="attr"&gt;content&lt;/span&gt;&lt;span class="kwrd"&gt;="Three SEO rules for ASP.NET developers&lt;br /&gt;        that will improve your site optimisation"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;
	&lt;/li&gt;
	&lt;li&gt;Use a base page for your ASP.NET pages (Also known as: Page Controller Enterprise Design Pattern) in which you will create a definition for generating the meta tags. This article &lt;a href="http://www.codeproject.com/KB/aspnet/PageTags.aspx" target="_blank" title="Using Meta Tags with Master Pages in ASP.NET"&gt;Using Meta Tags with Master Pages in ASP.NET&lt;/a&gt; is well written and the code is in both C# and VB.NET.&lt;/li&gt;
&lt;/ol&gt;
&lt;p class="summary"&gt;Use a development procedure in adding Meta Description to your site pages where relevant. You could also add a Meta Keywords tag where relevant.&lt;/p&gt;
&lt;h2&gt;3 - Do Permanent 301 HTTP Redirects to Mark Moved Pages&lt;/h2&gt;
&lt;p&gt;Usually, when developers change the structure of a website, say upgraded the site from ASP to ASP.NET, they tend to forget that the old pages accumulated SEO ranking over time and it would be unwise to throw that away!&lt;/p&gt;
&lt;p&gt;To point the search engine from the old page location to the new page location, you will need to issue a 301 HTTP redirect to the new URL when somebody, including the spider, requests your old page.&lt;/p&gt;
&lt;p&gt;301 Redirection in ASP.NET could be done with the following code in the old page's &lt;code&gt;Init&lt;/code&gt; event:&lt;/p&gt;
&lt;pre class="code"&gt;
Response.StatusCode = 301;
Response.RedirectLocation = &lt;span class="str"&gt;"new-url.aspx"&lt;/span&gt;;
Response.End();
&lt;/pre&gt;
&lt;p&gt;However, the old page, most probably, will not exist or the old site might be on ASP and ASP is no longer supported on the new site. There is an easy solution for this, try &lt;a href="http://urlrewriter.net/" target="_blank" title="URL Rewriter for ASP.NET"&gt;URL Rewriter for ASP.NET&lt;/a&gt;. You might also consider implementing your own database driven redirection by using a HttpModule or HttpHandler.&lt;/p&gt;
&lt;p class="summary"&gt;Doing 301 HTTP redirections will maintain the previous ranking that the old URL has accumulated and will update the URL on the search engine result page to the new URL.&lt;/p&gt;&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f16%2fThree-Rules-That-ASPNET-Developers-Should-Know-About-SEO.aspx&amp;amp;title=Three+Rules+That+ASP.NET+Developers+Should+Know+About+SEO" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f16%2fThree-Rules-That-ASPNET-Developers-Should-Know-About-SEO.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=TpVZQkQNlr8:PpjmXWV74hE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=TpVZQkQNlr8:PpjmXWV74hE:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=TpVZQkQNlr8:PpjmXWV74hE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=TpVZQkQNlr8:PpjmXWV74hE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=TpVZQkQNlr8:PpjmXWV74hE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=TpVZQkQNlr8:PpjmXWV74hE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=TpVZQkQNlr8:PpjmXWV74hE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/TpVZQkQNlr8" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/TpVZQkQNlr8/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/09/16/Three-Rules-That-ASPNET-Developers-Should-Know-About-SEO.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=b3e4952d-b488-4d0a-9151-7cab0be5d31f</guid>
      <pubDate>Tue, 16 Sep 2008 18:22:00 +0000</pubDate>
      <category>SEO</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=b3e4952d-b488-4d0a-9151-7cab0be5d31f</pingback:target>
      <slash:comments>104</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=b3e4952d-b488-4d0a-9151-7cab0be5d31f</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/09/16/Three-Rules-That-ASPNET-Developers-Should-Know-About-SEO.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=b3e4952d-b488-4d0a-9151-7cab0be5d31f</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=b3e4952d-b488-4d0a-9151-7cab0be5d31f</feedburner:origLink></item>
    <item>
      <title>Two ASP.NET/VS 2008 Performance Tricks That Even Microsoft Didn't Know About!</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f9%2fvisual-studio-2008-performance.gif" alt="Visual Studio 2008 Perofrmance" width="484" height="214" /&gt; 
&lt;p&gt;
Visual Studio 2008 is a huge resources consumer, it takes long to load then long to open your solution, long to run it and debug it. I have been using it for more than a year now after setting VS 2005 to retirement. I have VS 2008 set on a high perforamce Vista Business laptop with 2GB of memory. 
&lt;/p&gt;
&lt;p&gt;
While working with ASP.NET on VS 2008 my colleagues and myself started to notice some patterns when running or debugging a web project that will improve performance rapidally. Tricks that do really work and we laugh every time they work at how silly they are. 
&lt;/p&gt;
&lt;p&gt;
Here are two interesting tips that we encountered: 
&lt;/p&gt;
 
&lt;h2&gt;1 - The Magical VS 2008/ASP.NET Mouse Moving&lt;/h2&gt;
&lt;p&gt;
When debugging a running ASP.NET application, sometimes, it takes long to step from one code line to the other, usually I run out of patience and I snap my fingers asking Studio to leg it, but obviously that doesn&amp;#39;t work. I started changing my pattern into keep moving the mouse right and left and I have noticed that it takes no time to move from one line to another, tried it again and again and it kept working every time. I even asked my collegues to try it and it worked for them. So, now when I debug I usually click F10 with one hand and move the mouse right and left with the other. 
&lt;/p&gt;
&lt;p class="summary"&gt;
Trick: While debugging ASP.NET with VS 2008 moving the mouse continuously will make debugging faster 
&lt;/p&gt;
&lt;h2&gt;2 - The Miraculous VS 2008/ASP.NET Task Bar Click&lt;/h2&gt;
&lt;p&gt;
When hitting F5 or clicking &amp;quot;Run&amp;quot; to run and debug an ASP.NET Website or Web Application, the project used to compile then takes more than a minute, sometimes, to load the browser while I sit patiently looking arround waiting for it to load. 
&lt;/p&gt;
&lt;p&gt;
My colleague, Liz Ridley, which happens to have similar laptop specs, was less patient, she used to click randomly on the screen waiting the project browser to run. Suddenly, she clicked the task bar and the browser run at once! Is it a coincidence? She tried it again and again and it worked! Then I tried it and it worked for me, even if I waited for some time before clicking it. 
&lt;/p&gt;
&lt;p class="summary"&gt;
Trick: Clicking on the task bar after the project completes compilation and preparing to launch the browser in debug mode will reduce the browser's launch time. 
&lt;/p&gt;
&lt;p&gt;
Do you think that Microsoft knows about this? Is there a logical explanation for this? No, but it works so enjoy it while you can. If it works for you then please drop me a line of comment to let me know. And if you happen to know similar tricks, then please hit me with it. 
&lt;/p&gt;
&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f14%2fTwo-ASPNET-VS-2008-Performance-Tricks-That-Even-Microsoft-Didnt-Know-About.aspx&amp;amp;title=Two+ASP.NET%2fVS+2008+Performance+Tricks+That+Even+Microsoft+Didn't+Know+About!" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f09%2f14%2fTwo-ASPNET-VS-2008-Performance-Tricks-That-Even-Microsoft-Didnt-Know-About.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=6i2_7v-UXiE:viiy7ivZC2Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=6i2_7v-UXiE:viiy7ivZC2Y:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=6i2_7v-UXiE:viiy7ivZC2Y:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=6i2_7v-UXiE:viiy7ivZC2Y:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=6i2_7v-UXiE:viiy7ivZC2Y:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=6i2_7v-UXiE:viiy7ivZC2Y:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=6i2_7v-UXiE:viiy7ivZC2Y:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/6i2_7v-UXiE" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/6i2_7v-UXiE/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/09/14/Two-ASPNET-VS-2008-Performance-Tricks-That-Even-Microsoft-Didnt-Know-About.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=eb9020e7-dbd3-4fee-b282-4b58d99575e1</guid>
      <pubDate>Sun, 14 Sep 2008 18:35:00 +0000</pubDate>
      <category>Tips and Tricks</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=eb9020e7-dbd3-4fee-b282-4b58d99575e1</pingback:target>
      <slash:comments>83</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=eb9020e7-dbd3-4fee-b282-4b58d99575e1</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/09/14/Two-ASPNET-VS-2008-Performance-Tricks-That-Even-Microsoft-Didnt-Know-About.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=eb9020e7-dbd3-4fee-b282-4b58d99575e1</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=eb9020e7-dbd3-4fee-b282-4b58d99575e1</feedburner:origLink></item>
    <item>
      <title>LINQ to SQL: The Data Access Layer (DAL) Shrinker</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f8%2fthe-linq-effect.gif" alt="UI, BLL and DAL new architecture with LINQ to SQL" width="470" height="270" /&gt; 

&lt;p&gt;In the pre-LINQ days, I used to use the classical 3-tiers architecture for designing ASP.NET web projects, the user interface (UI), the business logic layer (BLL) and the data access layer (DAL).&lt;/p&gt;

&lt;p&gt;My DAL layer used to rely on Microsoft's Data Access Application Block (DAAB) which abstracted the repetitive and boring ADO.NET implementations. There are some 3rd party tools such as &lt;a href="http://subsonicproject.com/" target="_blank"&gt;SubSonic&lt;/a&gt;, which has some common features with LINQ, or &lt;a href="http://www.hibernate.org/343.html" target="_blank"&gt;NHibernate&lt;/a&gt;, however, I would rather use the enterprise library.&lt;/p&gt;

&lt;p&gt;Let me quickly illustrate the way to solve a problem with the classical architecture. This is a simple business problem, a website that has many brands and each brand has an advertising campaign. To access the campaign stats, which are supplied by the campaign agency, we need to access the agency's webservice by providing our brand credentials. We simply store these login credentials in our database -&gt; retrieve login info of a brand -&gt; call the webservice -&gt; display the stats on a web page.&lt;/p&gt;

&lt;img class="alignright" src="http://www.adamtibi.net/image.axd?picture=2008%2f8%2fcampaign-table.gif" alt="Campaign database table" width="286" height="140" /&gt; 

&lt;p&gt;I did not choose a trivial problem like the Company-Employee one as I wanted a real-life problem which I had experimented myself.&lt;/p&gt;

&lt;p&gt;A stored procedure that fetches a campiagn credential for a brand from the campaign table could look like this:&lt;/p&gt;
      &lt;div class="clear"&gt;&lt;/div&gt;
&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;PROCEDURE&lt;/span&gt; dbo.GetCampaignPerBrand

@BrandID TINYINT,
@AdwordsEmail &lt;span class="kwrd"&gt;VARCHAR&lt;/span&gt;(50) &lt;span class="kwrd"&gt;OUTPUT&lt;/span&gt;,
@AdwordsPassword &lt;span class="kwrd"&gt;VARCHAR&lt;/span&gt;(50) &lt;span class="kwrd"&gt;OUTPUT&lt;/span&gt;,
@AdwordsDeveloperToken &lt;span class="kwrd"&gt;VARCHAR&lt;/span&gt;(50) &lt;span class="kwrd"&gt;OUTPUT&lt;/span&gt;,
@AdwordsApplicationToken &lt;span class="kwrd"&gt;VARCHAR&lt;/span&gt;(50) &lt;span class="kwrd"&gt;OUTPUT&lt;/span&gt;,
@AdwordsClientEmail &lt;span class="kwrd"&gt;VARCHAR&lt;/span&gt;(50) &lt;span class="kwrd"&gt;OUTPUT&lt;/span&gt;

&lt;span class="kwrd"&gt;AS&lt;/span&gt;
&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;

&lt;span class="kwrd"&gt;SELECT&lt;/span&gt;    @AdwordsEmail = AdwordsEmail, 
    @AdwordsPassword = AdwordsPassword, 
    @AdwordsDeveloperToken = AdwordsDeveloperToken,
    @AdwordsApplicationToken = AdwordsApplicationToken, 
    @AdwordsClientEmail = AdwordsClientEmail
    &lt;span class="kwrd"&gt;FROM&lt;/span&gt; Campaign
    &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; BrandID = @BrandID
&lt;span class="kwrd"&gt;END&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;And a class, in the DAL layer, that would consume this method would look like:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CampaignDAL {

&lt;span class="rem"&gt;// More code ...&lt;/span&gt;
        
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; GetCampaignPerBrand(&lt;span class="kwrd"&gt;byte&lt;/span&gt; brandID, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; adwordsEmail,
    &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; adwordsPassword, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; adwordsDeveloperToken, 
    &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; adwordsApplicationToken, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; adwordsClientEmail) {

    &lt;span class="rem"&gt;// Using Microsoft's DAAB from the Microsoft Enterprise Library&lt;/span&gt;
    Database db = DatabaseFactory.CreateDatabase();
    DbCommand command = db.GetStoredProcCommand(&lt;span class="str"&gt;"GetCampaignPerBrand"&lt;/span&gt;);

    db.AddInParameter(command, &lt;span class="str"&gt;"BrandID"&lt;/span&gt;, DbType.Byte, brandID);

    db.AddOutParameter(command, &lt;span class="str"&gt;"AdwordsEmail"&lt;/span&gt;, DbType.AnsiString, 50);
    db.AddOutParameter(command, &lt;span class="str"&gt;"AdwordsPassword"&lt;/span&gt;, DbType.AnsiString, 50);
    db.AddOutParameter(command, &lt;span class="str"&gt;"AdwordsDeveloperToken"&lt;/span&gt;, DbType.AnsiString, 50);
    db.AddOutParameter(command, &lt;span class="str"&gt;"AdwordsApplicationToken"&lt;/span&gt;, DbType.AnsiString, 50);
    db.AddOutParameter(command, &lt;span class="str"&gt;"AdwordsClientEmail"&lt;/span&gt;, DbType.AnsiString, 50);

    db.ExecuteNonQuery(command);

    &lt;span class="kwrd"&gt;object&lt;/span&gt; adwordsEmailObj           = db.GetParameterValue(command, &lt;span class="str"&gt;"AdwordsEmail"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;object&lt;/span&gt; adwordsPasswordObj        = db.GetParameterValue(command, &lt;span class="str"&gt;"AdwordsPassword"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;object&lt;/span&gt; adwordsDeveloperTokenObj  = db.GetParameterValue(command, &lt;span class="str"&gt;"AdwordsDeveloperToken"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;object&lt;/span&gt; adwordsApplicationTokenObj= db.GetParameterValue(command, &lt;span class="str"&gt;"AdwordsApplicationToken"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;object&lt;/span&gt; adwordsClientEmailObj     = db.GetParameterValue(command, &lt;span class="str"&gt;"AdwordsClientEmail"&lt;/span&gt;);

    adwordsEmail             = adwordsEmailObj == DBNull.Value ? &lt;span class="kwrd"&gt;null&lt;/span&gt; : (&lt;span class="kwrd"&gt;string&lt;/span&gt;) adwordsEmailObj;
    adwordsPassword          = adwordsPasswordObj == DBNull.Value ? &lt;span class="kwrd"&gt;null&lt;/span&gt; : (&lt;span class="kwrd"&gt;string&lt;/span&gt;)adwordsPasswordObj;
    adwordsDeveloperToken    = adwordsDeveloperTokenObj == DBNull.Value ? &lt;span class="kwrd"&gt;null&lt;/span&gt; : (&lt;span class="kwrd"&gt;string&lt;/span&gt;)adwordsDeveloperTokenObj;
    adwordsApplicationToken  = adwordsApplicationTokenObj == DBNull.Value ? &lt;span class="kwrd"&gt;null&lt;/span&gt; : (&lt;span class="kwrd"&gt;string&lt;/span&gt;)adwordsApplicationTokenObj;
    adwordsClientEmail       = adwordsClientEmailObj == DBNull.Value ? &lt;span class="kwrd"&gt;null&lt;/span&gt; : (&lt;span class="kwrd"&gt;string&lt;/span&gt;)adwordsClientEmailObj;
}

&lt;span class="rem"&gt;// More code ...&lt;/span&gt;
}
&lt;/pre&gt;

&lt;p&gt;The purists among us might argue that I should be using a Data Container (DC) to carry the data from the BLL to the DAL, yes, it is a good solution, but I am trying a simpler solution here. Now a method in the associated business logic layer might look like this:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CampaignBLL {

&lt;span class="rem"&gt;// More code..&lt;/span&gt;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Stats[] GetStats() {
        &lt;span class="kwrd"&gt;byte&lt;/span&gt; brandID = Brand.CurrentBrand.BrandID;
        &lt;span class="kwrd"&gt;string&lt;/span&gt; adwordsEmail, adwordsPassword, adwordsDeveloperToken, 
                adwordsApplicationToken, adwordsClientEmail;

        GetCampaignPerBrand(brandID, &lt;span class="kwrd"&gt;out&lt;/span&gt; adwordsEmail, 
            &lt;span class="kwrd"&gt;out&lt;/span&gt; adwordsPassword, &lt;span class="kwrd"&gt;out&lt;/span&gt; adwordsDeveloperToken, 
            &lt;span class="kwrd"&gt;out&lt;/span&gt; adwordsApplicationToken, &lt;span class="kwrd"&gt;out&lt;/span&gt; adwordsClientEmail);

        Stats[] stats = &lt;span class="kwrd"&gt;new&lt;/span&gt; Stats();
        &lt;span class="rem"&gt;// Use the retrieved values in calling a&lt;/span&gt;
        &lt;span class="rem"&gt;// webservice and do other stuff to fill the stats array&lt;/span&gt;

        &lt;span class="kwrd"&gt;return&lt;/span&gt; stats;
    }

&lt;span class="rem"&gt;// More code..&lt;/span&gt;
    
}
&lt;/pre&gt;

&lt;p&gt;The advantages of this approach is that I was pushing my SQL into stored procs which, as I was convincing myself, is giving me an extra performance in addition to semi-portability (as the T-SQL will need to be rewritten when taken to another &lt;acronym title="Relational Database Management System"&gt;RDBMS&lt;/acronym&gt;). I had created a &lt;a href="http://www.codesmithtools.com" target="_blank"&gt;CodeSmith&lt;/a&gt; template to generate code which saved me writing it as writing such code with more complex stored procedures is error-prone and most probably the errors will be run-time errors.&lt;/p&gt;

&lt;p&gt;Disadvantages are too much code to achieve a simple task, no intellisense for the column names (there are third party solutions for this which cost money), no compile-time checking for mispellings of stored proc and column names, semi-portable Transact SQL and the code is splitted into multiple locations/projects.&lt;/p&gt;

&lt;p&gt;When I started designing an architecture based on .NET 3.5 of a mid-sized project, I was struggling with the DAL layer. I had tried to force the use of the DAL layer with LINQ to find that I am complicating the architecture rather than simplifying it. If LINQ is dealing with the database transparently and returning my data containers (DC) directly in strongly-typed format then I don't need to use code such as the one used above.&lt;/p&gt;

&lt;h2&gt;To DAL or not to DAL, this is the Question&lt;/h2&gt;

&lt;p&gt;Some evil thoughts started to go arround my head, why do I need to have the DAL layer with LINQ? I went back to the basics for the need of the DAL layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DAL Fact&lt;/strong&gt;: DAL will hide the DB provider such as SQL Server or Oracle make transitions to another DB much simpler and theoratically you will only need to change the implementations of the DAL layer, or you might not even need to change it if you have your own abstraction design or using a library such as EntLib DAAB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LINQ Fact&lt;/strong&gt;: Same fact goes for LINQ. Additional LINQ implementations, other than the SQL Server one, are currently available or in development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DAL Fact&lt;/strong&gt;: DAL will abstract the DB layer for the BLL and transform the db data types into .NET ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LINQ Fact&lt;/strong&gt;: LINQ takes this a step further and returns strongly-typed data containers rather than dummy &lt;code&gt;DataSets&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;First I was afraid, I was Petrified&lt;/h2&gt;

&lt;p&gt;Shrinking the DAL layer or removing it completely? Merging the DAL and the BLL, very bold indeed, but I did it! My architecture turned to be much simpler and easier to change, this is a code snippet from the new LINQ-based model:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CampaignBLL {

&lt;span class="rem"&gt;// More code..&lt;/span&gt;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Stats[] GetStats() {
        &lt;span class="kwrd"&gt;byte&lt;/span&gt; brandID = Brand.CurrentBrand.BrandID;
        
        DataClassesDataContext db = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataClassesDataContext();

        &lt;span class="rem"&gt;// using lambda expressions to make my life even easier.&lt;/span&gt;
        Campaign campaign = db.Campaigns.Single(c =&gt; c.BrandID == brandID);

        Stats[] stats = &lt;span class="kwrd"&gt;new&lt;/span&gt; Stats();
        &lt;span class="rem"&gt;// Use the retrieved object in calling a&lt;/span&gt;
        &lt;span class="rem"&gt;// webservice and do other stuff to fill the stats array&lt;/span&gt;

        &lt;span class="kwrd"&gt;return&lt;/span&gt; stats;
    }
    
&lt;span class="rem"&gt;// More code...&lt;/span&gt;

}
&lt;/pre&gt;

&lt;h2&gt;Where Did The Code Go?!&lt;/h2&gt;
&lt;p&gt;Let us go back to one of the most famous physics laws, yes, phyiscs, I didn't mistype:&lt;/p&gt;
&lt;quote&gt;&lt;strong&gt;Conservation of Energy Law&lt;/strong&gt;: Energy cannot be created or destroyed, but can change its form.&lt;/quote&gt;
&lt;p&gt;Same applies to code. Code cannot suddenly disapear without changing to another form. The generated code by LINQ to SQL has reduced the amount of code to be written. With LINQ, usually developers tend to write less stored procedures as the performance benefit is negligible when compared to that of cleaner code and better architecture (you guessed it, I am a "better architecture" against "higher performance" type of developers).&lt;/p&gt;

&lt;p&gt;Someone might argue that the DAL still exists in the LINQ generated code. Well, yes, but what is important to me that I didn't have to do it and I can hardly see it. My discussion is what I have to do to get the project going and now I have no concern in "outsourcing" my DAL layer.&lt;/p&gt;

&lt;p&gt;Some developers try to keep their DAL layer by having their LINQ statements inside DAL with methods that has 2 or 3 lines. I believe they have the fear of change! Some fanatic developers took this further step by returning &lt;code&gt;IQueriable&lt;/code&gt; objects. I wouldn't have taken such approach as I know that other developers will be working on the project and it is not just me.&lt;/p&gt;

&lt;h2&gt;DAL Shrinking Advantages&lt;/h2&gt;

&lt;p&gt;In the classical DAL architecture, each change in the database structure requires searching the associated stored procedure then changing the related DAL method(s) then changing the related business method(s). I am assuming with all the mentioned steps that you didn't mis a change.&lt;/p&gt;

&lt;p&gt;With LINQ you automatically shift to less stored procedures. Now changing in the db will require a LINQ recompilation and changing in the business layer only. If you've missed anything, you will get a compile-time error.&lt;/p&gt;

&lt;p&gt;The code is easier to read, shorter and still portable as LINQ is having more and more RDBMS providers added every day.&lt;/p&gt;

&lt;h2&gt;Finally&lt;/h2&gt;

&lt;p&gt;Even though the project that I have applied these principles to is a mid-size and the database operations are mostly reading. I am still wondering if this approach is going to work in enterprise projects or projects with intensive write and update operations.&lt;/p&gt;
&lt;p&gt;In the next post I am going to illustrate how I used Codesmith's &lt;a href="http://code.google.com/p/codesmith/wiki/PLINQO" target="_blank"&gt;PLINQO&lt;/a&gt; template and created a simple architecture that made using LINQ a breeze. The results of this architecture was a scalable project which took less development time than it usually takes. It is an end to end architecture with fully functional commercial project. I will keep you posted, you might need to revisit in the next few days or subscribe to my RSS feeds.&lt;/p&gt;
&lt;p&gt;Leave me a comment if you have any suggestion and if you agree or disagree on my approach. Kick It if you like it!&lt;/p&gt;&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f08%2f23%2fLINQ-to-SQL-The-Data-Access-Layer-DAL-Shrinker.aspx&amp;amp;title=LINQ+to+SQL%3a+The+Data+Access+Layer+(DAL)+Shrinker" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f08%2f23%2fLINQ-to-SQL-The-Data-Access-Layer-DAL-Shrinker.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=0dKmG-KOBG0:iKt3WqbWJu0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=0dKmG-KOBG0:iKt3WqbWJu0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=0dKmG-KOBG0:iKt3WqbWJu0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=0dKmG-KOBG0:iKt3WqbWJu0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=0dKmG-KOBG0:iKt3WqbWJu0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=0dKmG-KOBG0:iKt3WqbWJu0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=0dKmG-KOBG0:iKt3WqbWJu0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/0dKmG-KOBG0" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/0dKmG-KOBG0/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/08/23/LINQ-to-SQL-The-Data-Access-Layer-DAL-Shrinker.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=835c05cd-b424-44ff-bfc5-24d3baa66f8f</guid>
      <pubDate>Sat, 23 Aug 2008 10:57:00 +0000</pubDate>
      <category>Architecture</category>
      <category>LINQ to SQL</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=835c05cd-b424-44ff-bfc5-24d3baa66f8f</pingback:target>
      <slash:comments>69</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=835c05cd-b424-44ff-bfc5-24d3baa66f8f</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/08/23/LINQ-to-SQL-The-Data-Access-Layer-DAL-Shrinker.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=835c05cd-b424-44ff-bfc5-24d3baa66f8f</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=835c05cd-b424-44ff-bfc5-24d3baa66f8f</feedburner:origLink></item>
    <item>
      <title>IE6 ? It's alive, IT'S ALIVE!</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f8%2fie-ff-visitors-stats.gif" alt="Internet Explorer &amp;amp; Firefox visitors stats on adamtibi.net" width="470" height="255" /&gt; 
&lt;p&gt;
I redesigned my website, adhered to the XHTML standards, validated on the W3C validator and everything went alright, now the last step, cross-browsers compatibility tests. 
&lt;/p&gt;
&lt;p&gt;
First step, I need to look at the previous stats to learn what browsers are support-worthy. And? Surprise, surprise! IE6 is still alive with quarter of the IE users! But why?! My blog is targeted at the IT pros which are expected to be on modern browsers. 
&lt;/p&gt;
 
&lt;p&gt;
Back in the first half of this decade, Microsoft knocked out the real last competitor, Netscape Navigator (which is now, funnily enough, uses the IE engine) and IE6 became the dominant browser on the internet. Then Microsoft thought, should we upgrade this uncompliant, bugy browser which has no competitors? And probably you know the answer. IE6 was born on August 2001 and IE7 was released on late 2006, that is 5 long years for such a critical software. I would think MS would had left it to live longer if not for Firefox. Even more, Microsoft is rushing into IE8 which is claimed to have &lt;a href="http://blogs.msdn.com/ie/archive/2007/12/19/internet-explorer-8-and-acid2-a-milestone.aspx" target="_blank"&gt;standards better compatibility by passing the ACID2 test&lt;/a&gt;. 
&lt;/p&gt;
&lt;img class="alignright" src="http://www.adamtibi.net/image.axd?picture=2008%2f8%2fall-browser-stats-2008.gif" alt="browser visitor stats from 21 July to 17 August 2008 on adamtibi.net" width="238" height="284" /&gt; 
&lt;p&gt;
IE6 was preventing the web from moving forward with lots and lots of CSS and XHTML bugs. All the important XHTML and CSS updates that have been released years ago are not implemented, therefore as a developer or a designer you can&amp;#39;t use them and you are stuck with what IE6 states. 
&lt;/p&gt;
&lt;p&gt;
I expected to find much less IE6 user and I even promised in a previous post that &lt;a href="http://www.adamtibi.net/post/2008/07/28/Reskinning-My-Blog.aspx"&gt;I won&amp;#39;t test for it&lt;/a&gt;, however, I am very flexible :) So while feeling disgusted, once again, I had to comply with IE6 and do some CSS hacks to make IE6 happy. I have also posted these pie charts which are collected by Google Analytics on adamtibi.net for the public benefit. 
&lt;/p&gt;
&lt;p&gt;
Final word, I am not a Firefox fan, but thank you Mozilla, you saved the web. 
&lt;/p&gt;
&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f08%2f19%2fIE6-Its-alive-ITS-ALIVE.aspx&amp;amp;title=IE6+%3f+It's+alive%2c+IT'S+ALIVE!" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f08%2f19%2fIE6-Its-alive-ITS-ALIVE.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=S_ceHSqgA18:pjmOTdkgeeI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=S_ceHSqgA18:pjmOTdkgeeI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=S_ceHSqgA18:pjmOTdkgeeI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=S_ceHSqgA18:pjmOTdkgeeI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=S_ceHSqgA18:pjmOTdkgeeI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=S_ceHSqgA18:pjmOTdkgeeI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=S_ceHSqgA18:pjmOTdkgeeI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/S_ceHSqgA18" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/S_ceHSqgA18/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/08/19/IE6-Its-alive-ITS-ALIVE.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=67e16347-1f9b-4ff3-86cf-eec9b9ac505b</guid>
      <pubDate>Tue, 19 Aug 2008 20:25:00 +0000</pubDate>
      <category>Miscellaneous</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=67e16347-1f9b-4ff3-86cf-eec9b9ac505b</pingback:target>
      <slash:comments>11</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=67e16347-1f9b-4ff3-86cf-eec9b9ac505b</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/08/19/IE6-Its-alive-ITS-ALIVE.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=67e16347-1f9b-4ff3-86cf-eec9b9ac505b</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=67e16347-1f9b-4ff3-86cf-eec9b9ac505b</feedburner:origLink></item>
    <item>
      <title>Ye Mighty .NET Developers, I Have Betrayed Thy Oath</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f8%2fknight.jpg" alt="knight on horse" width="470" height="200" /&gt; 
&lt;p&gt;
The story began when my wife asked me &amp;quot;Oh my lord, I want a blog.&amp;quot; I was extremely happy to fulfil her request as now she can post her thoughts and save me listening :) . I answered, &amp;quot;My dear queen, I shall grant thee a weblog.&amp;quot; 
&lt;/p&gt;
&lt;p&gt;
.NET blog engines for non-techies anyone? I found only two, &lt;a href="http://www.dotnetblogengine.net" target="_blank"&gt;BlogEngine.NET&lt;/a&gt; and &lt;a href="http://www.dasblog.info" target="_blank"&gt;dasBlog&lt;/a&gt; and they both don&amp;#39;t suit her royal needs. What do the majority of bloggers use? WordPress? But that is PHP?! I&amp;#39;m not touching PHP, I wouldn&amp;#39;t be happy if a mate of mine told me &amp;quot;So, Adam, you are using PHP.&amp;quot; I, who spent hours arguing with the open source blokes, from university professors to collegues to online forums to developers in meetings. 
&lt;/p&gt;
&lt;p&gt;
I thought, what is more important? Turning down her highness&amp;#39; request or betray my oath to Microsoft and .NET community? And the answer, as you have already guessed, the second option. 
&lt;/p&gt;
&lt;p&gt;
And the moral of the story is? Check my wife&amp;#39;s blog&amp;nbsp;&lt;a href="http://aboutxena.com" target="_blank"&gt;AboutXena.com&lt;/a&gt;&amp;nbsp;with WordPress engine, let me know your thoughts and forgive me if you feel that I have betrayed you as a .NET Developer. 
&lt;/p&gt;
&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f08%2f10%2fye-mighty-net-developers-i-have-betrayed-thy-oath.aspx&amp;amp;title=Ye+Mighty+.NET+Developers%2c+I+Have+Betrayed+Thy+Oath" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f08%2f10%2fye-mighty-net-developers-i-have-betrayed-thy-oath.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=9XhT6DNlcow:zxvSLtXL4k4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=9XhT6DNlcow:zxvSLtXL4k4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=9XhT6DNlcow:zxvSLtXL4k4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=9XhT6DNlcow:zxvSLtXL4k4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=9XhT6DNlcow:zxvSLtXL4k4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=9XhT6DNlcow:zxvSLtXL4k4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=9XhT6DNlcow:zxvSLtXL4k4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/9XhT6DNlcow" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/9XhT6DNlcow/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/08/10/ye-mighty-net-developers-i-have-betrayed-thy-oath.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=746788cd-f4b1-4f16-8fa1-5e1a3e083357</guid>
      <pubDate>Sun, 10 Aug 2008 19:24:00 +0000</pubDate>
      <category>Miscellaneous</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=746788cd-f4b1-4f16-8fa1-5e1a3e083357</pingback:target>
      <slash:comments>48</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=746788cd-f4b1-4f16-8fa1-5e1a3e083357</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/08/10/ye-mighty-net-developers-i-have-betrayed-thy-oath.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=746788cd-f4b1-4f16-8fa1-5e1a3e083357</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=746788cd-f4b1-4f16-8fa1-5e1a3e083357</feedburner:origLink></item>
    <item>
      <title>Reskinning My Blog</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=2008%2f8%2freskin.jpg" alt="Amy Winehouse, before and after" width="250" height="276" /&gt; 
&lt;p&gt;
Finally, I redesigned my blog, I did it from scratch, I made it the way I want it to be, bespoked to my own wild desires and following my own specifications (you could count the number of &amp;quot;I&amp;quot; and &amp;quot;my&amp;quot; in the previous sentence and see how proud I am). 
&lt;/p&gt;
&lt;p&gt;
I could have gone to a web designer or to a web agency for the redesign and even though they would have surely done a better art work but I would have lost the pleasure of the DIY (for Americans: DIY = Do It Yourself), not to mention the cost. I read tutorials on how to make Web 2.0 thingies with Photoshop, sharpened my humble graphic design skills, reviewed the list of favourite technology blogs that I have stumbled upon in the past, then started. When designing, I abandoned the 800 pixel width standard and went for the 1024 pixels one, I also haven&amp;#39;t tested for IE6 (and never will!) as I have used unsupported CSS because I know thay my blog readers are technology experts that are using modern browsers. 
&lt;/p&gt;

&lt;h2&gt;Old Design&lt;/h2&gt;
&lt;p&gt;
My original design was based on the Leaves theme of BlogEngine.NET 
&lt;/p&gt;
&lt;img class="alignnone" src="http://www.adamtibi.net/image.axd?picture=2008%2f8%2fold-skin.jpg" alt="Old skin" width="470" height="365" /&gt; 
&lt;p&gt;
There aren&amp;#39;t many choices when it comes to .NET blog engines, there are only two AFAIK, &lt;a href="http://www.dasblog.info/" target="_blank"&gt;dasBlog&lt;/a&gt; and &lt;a href="http://www.dotnetblogengine.net/" target="_blank"&gt;BlogEngine.NET&lt;/a&gt;. After a quick test on both, I went for BlogEngine.NET as I felt it had more features, more updates, better object-oriented architecture and is easier to install. What I didn&amp;#39;t like about BlogEngine.NET is the embedded html inside the code and in-line CSS which prevents the blog from being XHTML strict compatible, however, I am not complaining and would like to thank the BlogEngine.NET guys for the great efforts. 
&lt;/p&gt;
&lt;p&gt;
I cannot deny that I had the desire of building my own LINQ+MVC+AJAX blogging engine, but I reviewed the intial goal of reskinning and concluded that designing and creating an engine from scratch doesn&amp;#39;t fit with the requirements. 
&lt;/p&gt;
&lt;p&gt;
Let me know any feedback and if you want to critique my humble web design skills, then you need to do it on the basis that I am a web design hobbiest. 
&lt;/p&gt;
&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f07%2f28%2fReskinning-My-Blog.aspx&amp;amp;title=Reskinning+My+Blog" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f07%2f28%2fReskinning-My-Blog.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=B7pvmuMxXeI:Ru-lo0sl3X8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=B7pvmuMxXeI:Ru-lo0sl3X8:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=B7pvmuMxXeI:Ru-lo0sl3X8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=B7pvmuMxXeI:Ru-lo0sl3X8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=B7pvmuMxXeI:Ru-lo0sl3X8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=B7pvmuMxXeI:Ru-lo0sl3X8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=B7pvmuMxXeI:Ru-lo0sl3X8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/B7pvmuMxXeI" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/B7pvmuMxXeI/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/07/28/Reskinning-My-Blog.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=838017cb-8dca-44a5-b1e3-5b9ca4b14e7b</guid>
      <pubDate>Mon, 28 Jul 2008 00:07:00 +0000</pubDate>
      <category>Miscellaneous</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=838017cb-8dca-44a5-b1e3-5b9ca4b14e7b</pingback:target>
      <slash:comments>9</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=838017cb-8dca-44a5-b1e3-5b9ca4b14e7b</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/07/28/Reskinning-My-Blog.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=838017cb-8dca-44a5-b1e3-5b9ca4b14e7b</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=838017cb-8dca-44a5-b1e3-5b9ca4b14e7b</feedburner:origLink></item>
    <item>
      <title>Response.Redirect and Server.Transfer Demystified</title>
      <description>&lt;p&gt;
I still remember the old days when I first learned ASP.NET 1.0, I used to search, like other newcomers, for the differences between Response.Redirect and the Server.Transfer. I found answers such as Server.Transfer had been kept in ASP.NET for backward compatibility with ASP so the recommendation was to use Response.Redirect or that I should be using the Server.Transfer for better performance! 
&lt;/p&gt;
&lt;p&gt;
The truth is every method has a completely different and important use. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Response.Redirect&lt;/strong&gt; : When you call this method, ASP.NET will issue HTTP headers that will instruct the browser for the new page tonavigate to and will stop processing any further ASP.NET instruction. The following code: 
&lt;/p&gt;

&lt;pre class="code"&gt; 
Response.Redirect(&amp;quot;default2.aspx&amp;quot;);
&lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&amp;quot;This exception will not be executed!&amp;quot;);
&lt;/pre&gt; 
&lt;p&gt;
will redirect to default2.aspx and will not execute the next line. It will issue an HTTP header instruction to the browser as follows: 
&lt;/p&gt;
&lt;pre class="code"&gt; &lt;br /&gt;Location: /default2.aspx&lt;br /&gt;&lt;/pre&gt; 
&lt;p&gt;
Then the browser will request the new page &amp;quot;default2.aspx&amp;quot;. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Server.Transfer&lt;/strong&gt; : This method will transfer execution ON THE SERVER from the current executing page to the new page &amp;quot;default2.aspx&amp;quot; without notifying the client (the browser) of this change. Also, will stop executing any further instruction on the current page. 
&lt;/p&gt;
&lt;pre class="code"&gt; 
Server.Transfer(&amp;quot;default2.aspx&amp;quot;);
&lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&amp;quot;This exception will not be executed!&amp;quot;);
&lt;/pre&gt; 
&lt;h2&gt;Comparison&lt;/h2&gt;
&lt;table border="0"&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;th&gt;&amp;nbsp;&lt;/th&gt;&lt;th&gt;Redirect&lt;/th&gt;&lt;th&gt;Transfer&lt;/th&gt;&lt;th&gt;Commets&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Better performance&lt;/td&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;&lt;th&gt;X&lt;/th&gt;
			&lt;td&gt;Redirect involves the extra overhead of going back and forth between the server and the client while Transfer is done completely on the server&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Change the URL in the browser&amp;rsquo;s address bar&lt;/td&gt;&lt;th&gt;X&lt;/th&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;
			&lt;td&gt;Transfer will not notify the browser with the change of pages&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;AJAX and JavaScript Friendly&lt;/td&gt;&lt;th&gt;X&lt;/th&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;
			&lt;td&gt;Since Transfer will not notify the browser with the change of page, some Ajax operations might fail as well as some JavaScript operations&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Can carry simple information &lt;strong&gt;securely&lt;/strong&gt; from one page to another&lt;/td&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;&lt;th&gt;X&lt;/th&gt;
			&lt;td&gt;Both methods can transfer simple data from one page to another via query strings, however, with Redirect the client will be able to read the information from the query string. Encrypting the query string is another topic&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Can carry complex objects from one page to another&lt;/td&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;&lt;th&gt;X&lt;/th&gt;
			&lt;td&gt;Doing Transfer (&amp;quot;default2.aspx&amp;quot;, true), you can still access the objects of default.aspx from default2.aspx when default2.aspx first loads&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Errors can easily be traced&lt;/td&gt;&lt;th&gt;X&lt;/th&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;
			&lt;td&gt;Using Transfer, errors might appear in your error log as if they are coming from default.aspx when they might be coming from default2.aspx&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
So what does all this mean? Simply, use the Redirect method by default unless you need to transfer complex data from one page to another, pass the data securely or hide the new page from the client. 
&lt;/p&gt;
&lt;p&gt;
Please let me know if you have additional differences or similarities that haven&amp;#39;t been mentioned. 
&lt;/p&gt;
&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f04%2f23%2fResponseRedirect-and-ServerTransfer-Demystified.aspx&amp;amp;title=Response.Redirect+and+Server.Transfer+Demystified" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f04%2f23%2fResponseRedirect-and-ServerTransfer-Demystified.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=FWU6uedkpZo:LkNgFf-cVPc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=FWU6uedkpZo:LkNgFf-cVPc:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=FWU6uedkpZo:LkNgFf-cVPc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=FWU6uedkpZo:LkNgFf-cVPc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=FWU6uedkpZo:LkNgFf-cVPc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=FWU6uedkpZo:LkNgFf-cVPc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=FWU6uedkpZo:LkNgFf-cVPc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/FWU6uedkpZo" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/FWU6uedkpZo/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/04/23/ResponseRedirect-and-ServerTransfer-Demystified.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=32fa0ed4-cf66-4455-9e28-3b2912fa8835</guid>
      <pubDate>Wed, 23 Apr 2008 11:52:00 +0000</pubDate>
      <category>Code Snippets</category>
      <category>FAQ</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=32fa0ed4-cf66-4455-9e28-3b2912fa8835</pingback:target>
      <slash:comments>71</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=32fa0ed4-cf66-4455-9e28-3b2912fa8835</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/04/23/ResponseRedirect-and-ServerTransfer-Demystified.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=32fa0ed4-cf66-4455-9e28-3b2912fa8835</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=32fa0ed4-cf66-4455-9e28-3b2912fa8835</feedburner:origLink></item>
    <item>
      <title>How to HTTP Post in .NET and handle the 500 errors</title>
      <description>&lt;p&gt;If you google you will find a lot of posts that will tell you how to HTTP post (some call it HTML post) in .NET. However, they all fail, or at least the ones I found, to tell you how to handle the returned 500 errors and retrieve the message behind it.&lt;/p&gt;
&lt;p&gt;I have been posting to a service and getting the "500 Internal Server Error" which doesn't tell much! I had done some research to get the real error behind it. Here is my code snippet in C#:&lt;/p&gt;

&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Post(&lt;span class="kwrd"&gt;string&lt;/span&gt; url, &lt;span class="kwrd"&gt;string&lt;/span&gt; postData) {

    &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer = Encoding.UTF8.GetBytes(postData);
    &lt;span class="kwrd"&gt;int&lt;/span&gt; bufferLength = buffer.Length;
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
    request.Method = &lt;span class="str"&gt;"POST"&lt;/span&gt;;
    request.ContentLength = bufferLength;

    &lt;span class="kwrd"&gt;string&lt;/span&gt; result;

    &lt;span class="kwrd"&gt;using&lt;/span&gt; (Stream requestStream = request.GetRequestStream()) {
        requestStream.Write(buffer, 0, bufferLength);

        &lt;span class="kwrd"&gt;try&lt;/span&gt; {
            &lt;span class="kwrd"&gt;using&lt;/span&gt; (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
                &lt;span class="kwrd"&gt;using&lt;/span&gt; (Stream responseStream = response.GetResponseStream()) {
                    &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader readStream = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(responseStream, Encoding.UTF8)) {
                        result = readStream.ReadToEnd();
                    }
                }
            }
        }
        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (WebException wEx) {
            &lt;span class="kwrd"&gt;using&lt;/span&gt; (Stream errorResponseStream = wEx.Response.GetResponseStream()) {
                &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader errorReadStream = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(errorResponseStream, Encoding.UTF8)) {
                    result = errorReadStream.ReadToEnd();
                }

            }
        }
    }

    &lt;span class="kwrd"&gt;return&lt;/span&gt; result;
}
&lt;/pre&gt;
&lt;p&gt;I have tested the code and it is working, please let me know what do you think or if you have a better approach.&lt;/p&gt;&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f03%2f22%2fHow-to-HTTP-Post-in-NET-and-handle-the-500-errors.aspx&amp;amp;title=How+to+HTTP+Post+in+.NET+and+handle+the+500+errors" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f03%2f22%2fHow-to-HTTP-Post-in-NET-and-handle-the-500-errors.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=NF6-V0BJ7YY:6QsMWEYV4tw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=NF6-V0BJ7YY:6QsMWEYV4tw:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=NF6-V0BJ7YY:6QsMWEYV4tw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=NF6-V0BJ7YY:6QsMWEYV4tw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=NF6-V0BJ7YY:6QsMWEYV4tw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=NF6-V0BJ7YY:6QsMWEYV4tw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=NF6-V0BJ7YY:6QsMWEYV4tw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/NF6-V0BJ7YY" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/NF6-V0BJ7YY/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/03/22/How-to-HTTP-Post-in-NET-and-handle-the-500-errors.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=12ac6be5-47fd-4698-9bf1-b94fc2c96ee0</guid>
      <pubDate>Sat, 22 Mar 2008 18:57:00 +0000</pubDate>
      <category>Code Snippets</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=12ac6be5-47fd-4698-9bf1-b94fc2c96ee0</pingback:target>
      <slash:comments>67</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=12ac6be5-47fd-4698-9bf1-b94fc2c96ee0</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/03/22/How-to-HTTP-Post-in-NET-and-handle-the-500-errors.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=12ac6be5-47fd-4698-9bf1-b94fc2c96ee0</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=12ac6be5-47fd-4698-9bf1-b94fc2c96ee0</feedburner:origLink></item>
    <item>
      <title>Check Validator - An ASP.NET Validator Control</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=CheckValidator.jpg" alt="Check Validator used with checkbox"
        width="264" height="74" /&gt;
  
    &lt;p&gt;While some developers assume that the classical ASP.NET validators support check boxes and radio buttons, this isn't the case! There is a logical explanation for this; there is nothing much to check, the checkbox can only be checked or unchecked so what do you want to validate?&lt;/p&gt;
    &lt;p&gt;In some cases you might want to display an error if a check box or a radio button is unchecked, e.g. terms and conditions check box, if so, then this is the right validator for you. Read on if you are interested in the bits and pieces of how the control works or skip to the "Using The Validator" section if you are just interested in using it.&lt;/p&gt;
    
    &lt;h2&gt;Background&lt;/h2&gt;
    &lt;p&gt;Usually control classes that supports validation are decorated with the &lt;code&gt;ValidationProperty&lt;/code&gt; attribute, for example, the &lt;code&gt;TextBox&lt;/code&gt; control looks like this:&lt;/p&gt;
&lt;pre class="code"&gt;
&lt;span class="rem"&gt;// more attributes...&lt;/span&gt;
[ValidationProperty(&lt;span class="str"&gt;"Text"&lt;/span&gt;)]
&lt;span class="rem"&gt;// more attributes...&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TextBox : WebControl, IPostBackDataHandler, 
                        IEditableTextControl, ITextControl {
    ...
}
&lt;/pre&gt;
    &lt;p&gt;The &lt;code&gt;ValidationProperty&lt;/code&gt; will point the validator at the property to validate against.&lt;/p&gt;
    &lt;p&gt;The CheckBox, RadioButton, HtmlInputCheckBox and HtmlInputRadioButton lack this attribute, accordingly, any standard validation control will throw an exception &lt;code&gt;Control 'ControlID' referenced by the ControlToValidate property of 'ValidatorID' cannot be validated&lt;/code&gt; when set against one of these controls.&lt;/p&gt;
    &lt;h2&gt;Architecture&lt;/h2&gt;
    &lt;p&gt;This validator inherits, as in most validators, from &lt;code&gt;BaseValidator&lt;/code&gt; and overrides method &lt;code&gt;ControlPropertiesValid&lt;/code&gt; that issues this exception.&lt;/p&gt;
&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; ControlPropertiesValid() {
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (ControlToValidate.Trim().Length == 0) {
        &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpException(
            &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;@"The ControlToValidate property of 
                {0} cannot be blank."&lt;/span&gt;, ID));
    }

    Control control = FindControl(ControlToValidate);

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (control == &lt;span class="kwrd"&gt;null&lt;/span&gt;) {
        &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpException(
            &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Could not locate control with ID {0}"&lt;/span&gt;, ID));
    }

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!(control &lt;span class="kwrd"&gt;is&lt;/span&gt; CheckBox) &amp;&amp;
                !(control &lt;span class="kwrd"&gt;is&lt;/span&gt; RadioButton) &amp;&amp; 
                !(control &lt;span class="kwrd"&gt;is&lt;/span&gt; HtmlInputCheckBox) &amp;&amp;
                !(control &lt;span class="kwrd"&gt;is&lt;/span&gt; HtmlInputRadioButton)) {
        &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpException(
            &lt;span class="str"&gt;@"ControlToValidate can only be 
                System.Web.UI.WebControls.CheckBox, 
                System.Web.UI.WebControls.RadioButton, 
                System.Web.UI.HtmlControls.HtmlInputCheckBox, 
                System.Web.UI.HtmlControls.HtmlInputRadioButton"&lt;/span&gt;);
    }

    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
}
&lt;/pre&gt;
    &lt;p&gt;The rest of the server side code is classical. The validator has a property called &lt;code&gt;WarnIf&lt;/code&gt; which will reverse checking (when set to false, the validator will warn if the box is checked).&lt;/p&gt;
    &lt;p&gt;This is the client-side validation code:&lt;/p&gt;
&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;function&lt;/span&gt; CheckValidatorEvaluateIsValid(val) {
    &lt;span class="kwrd"&gt;var&lt;/span&gt; control = document.getElementById(val.controltovalidate);
    &lt;span class="kwrd"&gt;var&lt;/span&gt; warnif = val.warnif == 1 ? &lt;span class="kwrd"&gt;true&lt;/span&gt; : &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; control.&lt;span class="kwrd"&gt;checked&lt;/span&gt; ^ warnif;
}
&lt;/pre&gt;
    &lt;h2&gt;Using the Validator&lt;/h2&gt;
    &lt;p&gt;
        To use this validator from your Visual Studio IDE, you need to add the provided .&lt;em&gt;dll&lt;/em&gt; to the toolbox. For more information on this, check the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms165355.aspx"
            target="_blank"&gt;MSDN documentation&lt;/a&gt;.&lt;/p&gt;

        &lt;p&gt;Drop the control on the form and assign it to the CheckBox/RadioButton that you want to check:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:checkbox&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="_termsAndConditions"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;br /&gt;      &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="I have read the terms and conditions"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;at:CheckValidator&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="_checkValidator"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;br /&gt;  &lt;span class="attr"&gt;ControlToValidate&lt;/span&gt;&lt;span class="kwrd"&gt;="_termsAndConditions"&lt;/span&gt; &lt;br /&gt;  &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Please read and accept our terms and conditions before proceeding"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;at:CheckValidator&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;h2&gt;Licence&lt;/h2&gt;
&lt;p&gt;
This software is disributed under &lt;a href="http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx" target="_blank"&gt;&lt;acronym title="Microsoft Public License"&gt;Ms-PL&lt;/acronym&gt;&lt;/a&gt;. Which simply means, you can freely use it and distribute it but you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 
&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;
Finally, if you like the article and find the control useful, then please Kick It (using the button below) and it would be kind of you to leave a comment. All suggestions and bug reports are welcome. I have also created the &lt;a href="http://www.codeproject.com/KB/validation/MultipleFieldsValidator.aspx" target="_blank"&gt;MultipleFieldsValidator&lt;/a&gt; validator control to tackle the problem of validating multiple controls.
&lt;/p&gt;
&lt;p class="download"&gt;&lt;a href="http://www.adamtibi.net/file.axd?file=CheckValidator.zip" rel="enclosure"&gt;&amp;lt;&amp;lt;Download CheckValidator.zip (16.97 kb))&amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f02%2f15%2fcheck-validator-asp-dot-net.aspx&amp;amp;title=Check+Validator+-+An+ASP.NET+Validator+Control" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f02%2f15%2fcheck-validator-asp-dot-net.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=h2-uoBVi55o:O2JEiGeiZEY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=h2-uoBVi55o:O2JEiGeiZEY:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=h2-uoBVi55o:O2JEiGeiZEY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=h2-uoBVi55o:O2JEiGeiZEY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=h2-uoBVi55o:O2JEiGeiZEY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=h2-uoBVi55o:O2JEiGeiZEY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=h2-uoBVi55o:O2JEiGeiZEY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/h2-uoBVi55o" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/h2-uoBVi55o/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/02/15/check-validator-asp-dot-net.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=91b459a6-2759-447c-93b3-65d05a742358</guid>
      <pubDate>Fri, 15 Feb 2008 21:00:00 +0000</pubDate>
      <category>ASP.NET Validators</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=91b459a6-2759-447c-93b3-65d05a742358</pingback:target>
      <slash:comments>73</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=91b459a6-2759-447c-93b3-65d05a742358</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/02/15/check-validator-asp-dot-net.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=91b459a6-2759-447c-93b3-65d05a742358</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=91b459a6-2759-447c-93b3-65d05a742358</feedburner:origLink></item>
    <item>
      <title>Session Keep-Alive Web Control</title>
      <description>&lt;img class="aligncenter" src="http://www.adamtibi.net/image.axd?picture=session-keep-alive.jpg" alt="Visual Studio project structure overview" width="250" height="201" /&gt; 
    &lt;p&gt;
        Session expiration in ASP.NET is a nasty problem. Imagine yourself filling a long
        form, hitting submit then boom you get the login page! That happened to me before
        and probably happened to you.
    &lt;/p&gt;
    &lt;p&gt;
        This problem doesn&amp;#39;t have an out-of-box solution in ASP.NET and there are different
        appraoches to solve it.
    &lt;/p&gt;
    &lt;ol&gt;
        &lt;li&gt;Increasing the session time out. Probably you are aware of the cons of this problem
            which are mainly consuming more server resources.&lt;/li&gt;
        &lt;li&gt;Having an image or an iframe that refreshes regularly and requests the server. This
            approach is a per page approach and you can select the pages to implement it on.&lt;/li&gt;
    &lt;/ol&gt;
    &lt;p&gt;
        Personally, I&amp;#39;ve been using the second approach for a long time and didn&amp;#39;t
        have any problem with it. However, I made it more reusable, not to mention &amp;quot;cleaner&amp;quot;,
        by making it a web control.
    &lt;/p&gt;
    &lt;p&gt;
        If you are just interested in using the control then you can skip to the last section
        &amp;quot;Using the Control.&amp;quot;
    &lt;/p&gt;
    
    &lt;h2&gt;
        Architecture&lt;/h2&gt;
    &lt;p&gt;
        The architecture here is simple and consists of both server-side and client-side
        solutions.
    &lt;/p&gt;
    &lt;h3&gt;
        Server-Side&lt;/h3&gt;
    &lt;p&gt;
        An &lt;code&gt;AS&lt;strong&gt;H&lt;/strong&gt;X&lt;/code&gt; handler file hosted on the root of the site
        which when requested will renew the session and return a 1-pixel image. In my control,
        I called the &lt;code&gt;ASXH&lt;/code&gt; file as &lt;code&gt;session-keep-alive.ashx&lt;/code&gt; and
        this is the code:
    &lt;/p&gt;
&lt;pre class="code"&gt;
&amp;lt;%@ WebHandler Language=&lt;span class="str"&gt;"C#"&lt;/span&gt; Class=&lt;span class="str"&gt;"session_keep_alive"&lt;/span&gt; %&amp;gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.SessionState;

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; session_keep_alive : IHttpHandler, IRequiresSessionState {
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] gif = {
            0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0x91,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x09,0x00,
            0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x08,0x04,
            0x00,0x01,0x04,0x04,0x00,0x3b,0x00};
    
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ProcessRequest (HttpContext context) {
        context.Response.ContentType = &lt;span class="str"&gt;"image/gif"&lt;/span&gt;;
        context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.Response.BinaryWrite(gif);
        context.Response.End();
    }
 
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsReusable {
        get {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        }
    }
}
&lt;/pre&gt;
    &lt;h3&gt;
        Client-Side&lt;/h3&gt;
    &lt;p&gt;
        On the client, my web control will render a 1-pixel image and some JavaScript code
        that will refresh the image every set amount of time from the &lt;code&gt;ASXH&lt;/code&gt;
        file on the server. This is the control&amp;#39;s code:
    &lt;/p&gt;
&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.HtmlControls;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.ComponentModel;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; AT.Web.UI.Controls {

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Web control to keep the session alive by refreshing every set amount of time&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [ToolboxData(&lt;span class="str"&gt;"&lt;{0}:SessionKeepAlive runat=server /&gt;"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SessionKeepAlive : WebControl {

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Set, in minutes, the duration to trigger the session.&lt;/span&gt;
        &lt;span class="rem"&gt;/// The default value is one minute&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        [Category(&lt;span class="str"&gt;"Behavior"&lt;/span&gt;)]
        [DefaultValue(1)]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Duration {
            get {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt;)(ViewState[&lt;span class="str"&gt;"Duration"&lt;/span&gt;] ??  1);
            }
            set {
                ViewState[&lt;span class="str"&gt;"Duration"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
            }
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// The path of the image's URL that will be requested from the server,&lt;/span&gt;
        &lt;span class="rem"&gt;/// the default is ~/session-keep-alive.ashx&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        [Category(&lt;span class="str"&gt;"Behavior"&lt;/span&gt;)]
        [DefaultValue(&lt;span class="str"&gt;"~/session-keep-alive.ashx"&lt;/span&gt;)]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; PageUrl {
            get {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)(ViewState[&lt;span class="str"&gt;"PageUrl"&lt;/span&gt;] ?? &lt;span class="str"&gt;"~/session-keep-alive.ashx"&lt;/span&gt;);
            }
            set {
                ViewState[&lt;span class="str"&gt;"PageUrl"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
            }
        }

        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="rem"&gt;/// Applies in-line CSS style to hide the generated image. The default is true.&lt;/span&gt;
        &lt;span class="rem"&gt;/// Alternatively, you can set this to false and hide the image using your own&lt;/span&gt;
        &lt;span class="rem"&gt;/// CSS to keep your page XHTML Strict compatible.&lt;/span&gt;
        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        [Category(&lt;span class="str"&gt;"Behavior"&lt;/span&gt;)]
        [DefaultValue(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; AutoHide {
            get {
                &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;bool&lt;/span&gt;)(ViewState[&lt;span class="str"&gt;"AutoHide"&lt;/span&gt;] ?? &lt;span class="kwrd"&gt;true&lt;/span&gt;);
            }
            set {
                ViewState[&lt;span class="str"&gt;"AutoHide"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
            }
        }

        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnPreRender(EventArgs e) {
            &lt;span class="kwrd"&gt;base&lt;/span&gt;.OnPreRender(e);

            &lt;span class="kwrd"&gt;if&lt;/span&gt; (AutoHide) {
                &lt;span class="kwrd"&gt;this&lt;/span&gt;.Style.Add(HtmlTextWriterStyle.Display, &lt;span class="str"&gt;"none"&lt;/span&gt;);
            }

            Page.ClientScript.RegisterClientScriptResource(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(SessionKeepAlive),
                &lt;span class="str"&gt;"AT.Web.UI.Controls.JavaScript.js"&lt;/span&gt;);

            Page.ClientScript.RegisterStartupScript(
                &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(SessionKeepAlive), &lt;span class="str"&gt;"SessionKeepAlive"&lt;/span&gt;,
                &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(
                   &lt;span class="str"&gt;@"window.setInterval('SessionKeepAlive(\'{0}\', \'{1}\');', {2});"&lt;/span&gt;, 
                ClientID, ResolveClientUrl(PageUrl), Duration * 60000), &lt;span class="kwrd"&gt;true&lt;/span&gt;);
        }


        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Render(HtmlTextWriter writer) {
            writer.AddAttribute(HtmlTextWriterAttribute.Src, ResolveClientUrl(PageUrl));
            writer.AddAttribute(HtmlTextWriterAttribute.Alt, &lt;span class="str"&gt;" "&lt;/span&gt;);
            &lt;span class="kwrd"&gt;base&lt;/span&gt;.RenderBeginTag(writer);
            &lt;span class="kwrd"&gt;base&lt;/span&gt;.RenderEndTag(writer);
        }

    }
}
&lt;/pre&gt;
    &lt;p&gt;
        And here is the used JavaScript, note that I am setting the Src of the image to
        the same location (the ASHX file), but changing the query string to prevent the
        browser from caching the request.
    &lt;/p&gt;
&lt;pre class="code"&gt;
&lt;span class="kwrd"&gt;function&lt;/span&gt; SessionKeepAlive(imageID, pageUrl) {
    &lt;span class="kwrd"&gt;var&lt;/span&gt; imageObj = document.getElementById(imageID);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (imageObj == &lt;span class="kwrd"&gt;null&lt;/span&gt; || imageObj == undefined) {
        &lt;span class="kwrd"&gt;return&lt;/span&gt;;
    }
    imageObj.src = pageUrl + &lt;span class="str"&gt;"?par="&lt;/span&gt; + escape((&lt;span class="kwrd"&gt;new&lt;/span&gt; Date()).toString());
}
&lt;/pre&gt;
    &lt;h3&gt;
        Using the JavaScript as an embedded resource&lt;/h3&gt;
    &lt;p&gt;
        I have made the JavaScript file an embedded resource to make it easier for deployment.
        To do that I had to do the following:
    &lt;/p&gt;
    &lt;ol&gt;
        &lt;li&gt;Added a javascript file to the project library and called it JavaScript.js&lt;/li&gt;
        &lt;li&gt;I made this file an embedded resource by selecting it and setting Build Action to
            Embedded Resource&lt;/li&gt;
        &lt;li&gt;I have added the following line to the AssemblyInfo.cs : &lt;code&gt;[assembly: WebResource(&amp;quot;AT.Web.UI.Controls.JavaScript.js&amp;quot;,
            &amp;quot;application/x-javascript&amp;quot;)]&lt;/code&gt;&lt;/li&gt;
    &lt;/ol&gt;
    &lt;h2&gt;Using the Control&lt;/h2&gt;
    &lt;ol&gt;
        &lt;li&gt;Copy &lt;code&gt;session-keep-alive.ashx&lt;/code&gt; to your website.&lt;/li&gt;
        &lt;li&gt;Reference &lt;code&gt;AT.Web.UI.Controls.dll&lt;/code&gt; in your website.&lt;/li&gt;
        &lt;li&gt;You can &lt;a href="http://msdn2.microsoft.com/en-us/library/ms165355.aspx" target="_blank"&gt;
            add this control to the VS.NET toolbox&lt;/a&gt; and drop anywhere on the page OR you
            could add it manually by adding &lt;code&gt;&amp;lt;%@ Register TagPrefix=&amp;quot;at&amp;quot; Namespace=&amp;quot;AT.Web.UI.Controls&amp;quot;
                Assembly=&amp;quot;AT.Web.UI.Controls&amp;quot; %&amp;gt;&lt;/code&gt; to the top of the page
            and adding &lt;code&gt;&amp;lt;at:SessionKeepAlive runat=&amp;quot;server&amp;quot; /&amp;gt;&lt;/code&gt; anywhere
            in the html body. You might need to set the refresh &lt;code&gt;Duration&lt;/code&gt;, &lt;code&gt;AutoHide&lt;/code&gt;
            or &lt;code&gt;PageUrl&lt;/code&gt; &lt;/li&gt;
    &lt;/ol&gt;
    &lt;p&gt;
        Check the sample file for more information.
    &lt;/p&gt;
    &lt;h2&gt;Credits&lt;/h2&gt;
    &lt;p&gt;
        The initial code that I used two years ago was based on an article, &lt;a rel="nofollow"
            href="http://www.codeproject.com/KB/aspnet/SessionForever.aspx" target="_blank"&gt;
            Make session last forever&lt;/a&gt;, written by Gevorg on Code Project.
    &lt;/p&gt;
    &lt;h2&gt;Licence&lt;/h2&gt;
    &lt;p&gt;
        This software is disributed under &lt;a href="http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx"
            target="_blank"&gt;&lt;acronym title="Microsoft Public License"&gt;Ms-PL&lt;/acronym&gt;&lt;/a&gt;.
        Which simply means, you can freely use it and distribute it but you must retain
        all copyright, patent, trademark, and attribution notices that are present in the
        software.
    &lt;/p&gt;
    &lt;p&gt;
        Finally, if you like the article and find the control useful, then please Kick It
        (using the button below) and it would be kind of you to leave a comment. All suggestions
        and bug reports are welcome.
    &lt;/p&gt;
&lt;p class="download"&gt;
&lt;a rel="enclosure" href="http://www.adamtibi.net/file.axd?file=SessionKeepAlive.zip"&gt;&amp;lt;&amp;lt;Download SessionKeepAlive.zip (19.55 kb)&amp;gt;&amp;gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;a class="kickit" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f02%2f11%2fsession-keep-alive-web-control.aspx&amp;amp;title=Session+Keep-Alive+Web+Control" target="_blank" title="Kick It on DotNetKicks.com" rel="nofollow"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.adamtibi.net%2fpost%2f2008%2f02%2f11%2fsession-keep-alive-web-control.aspx" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=VKiFNB93dqc:EDhbqiYp6WY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=VKiFNB93dqc:EDhbqiYp6WY:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=VKiFNB93dqc:EDhbqiYp6WY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=VKiFNB93dqc:EDhbqiYp6WY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=VKiFNB93dqc:EDhbqiYp6WY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/AdamTibi?a=VKiFNB93dqc:EDhbqiYp6WY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/AdamTibi?i=VKiFNB93dqc:EDhbqiYp6WY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/AdamTibi/~4/VKiFNB93dqc" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/AdamTibi/~3/VKiFNB93dqc/post.aspx</link>
      <author>adam.nospam@nospam.adamtibi.net (Adam Tibi)</author>
      <comments>http://www.adamtibi.net/post/2008/02/11/session-keep-alive-web-control.aspx#comment</comments>
      <guid isPermaLink="false">http://www.adamtibi.net/post.aspx?id=81867dd9-ba89-447b-928d-124c6df4a957</guid>
      <pubDate>Mon, 11 Feb 2008 23:32:00 +0000</pubDate>
      <category>Web Controls</category>
      <dc:publisher>Adam Tibi</dc:publisher>
      <pingback:server>http://www.adamtibi.net/pingback.axd</pingback:server>
      <pingback:target>http://www.adamtibi.net/post.aspx?id=81867dd9-ba89-447b-928d-124c6df4a957</pingback:target>
      <slash:comments>84</slash:comments>
      <trackback:ping>http://www.adamtibi.net/trackback.axd?id=81867dd9-ba89-447b-928d-124c6df4a957</trackback:ping>
      <wfw:comment>http://www.adamtibi.net/post/2008/02/11/session-keep-alive-web-control.aspx#comment</wfw:comment>
      <wfw:commentRss>http://www.adamtibi.net/syndication.axd?post=81867dd9-ba89-447b-928d-124c6df4a957</wfw:commentRss>
    <feedburner:origLink>http://www.adamtibi.net/post.aspx?id=81867dd9-ba89-447b-928d-124c6df4a957</feedburner:origLink></item>
  </channel>
</rss>
