<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" 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:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Code Snippets</title>
        <link>http://www.kowitz.net/category/11.aspx</link>
        <description>Code Snippets</description>
        <language>en-AU</language>
        <copyright>Brendan Kowitz</copyright>
        <managingEditor>brendan@kowitz.net</managingEditor>
        <generator>Subtext Version 2.0.0.43</generator>
        <item>
            <title>What would NHibernate ICriteria look like in .net 3.5?</title>
            <link>http://kowitz.net/archive/2008/08/17/what-would-nhibernate-icriteria-look-like-in-.net-3.5.aspx</link>
            <description>&lt;p&gt;If NHibernate decided to ditch compatibility with plain old .net 2.0 and focus on 3.5 how would the ICriteria interface change? &lt;a href="http://www.kowitz.net/archive/2008/07/22/nhibernate-type-safety-using-lamba-expressions.aspx"&gt;Previously&lt;/a&gt; I was throwing around an idea of using a simple lambda expression to resolve the property name. Well, I couldn't help but build on this a little more. The following idea is not supposed to be LINQ, that would be far more complicated and LINQ is essentially its own interface, which is not the point. The point is, if ICriteria was written today in .net 3.5, what could it look like? How could it change?&lt;/p&gt;
&lt;p&gt;So just to recap, the original code sample looked like:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateCriteria(typeof(Person));
c.Add(Restrictions.Eq(Property.GetFor(() =&amp;gt; new Person().FirstName), "John"));&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://www.paulstovell.com/"&gt;Paul&lt;/a&gt; later come back and suggested I try using a slightly different signature so that the "Person" object doesn't need to be instantiated for no reason, this means the we can do this:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateCriteria(typeof(Person));
c.Add(Restrictions.Eq(Property.For&amp;lt;Person&amp;gt;(p =&amp;gt; p.FirstName), "John"));
&lt;/pre&gt;
&lt;p&gt;I like this a lot more. So this is the point where I started playing around and wanted to try and implement a neater way of integrating this to add Criterion. First off I tried implementing ICriteria.Add(Restrictions.Eq()) as an expression which looked like:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateCriteria(typeof(Person));
c.Add(RestrictBy.Eq&amp;lt;Person&amp;gt;(p =&amp;gt; p.FirstName == "John" ));
&lt;/pre&gt;
&lt;p&gt;That is where I got up to in the previous post. So after this I started implementing some of the other functions found on the 'Restrictions' class such as:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;.NotNull() &lt;/li&gt;
    &lt;li&gt;.IsNotNull() &lt;/li&gt;
    &lt;li&gt;.Not() &lt;/li&gt;
    &lt;li&gt;.Between() &lt;/li&gt;
    &lt;li&gt;.Gt() (Greater than) &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then I realized all of the above functions are able to be figured out using the syntax I already had: 'p.FirstName == "John"', so how about p.FirstName != "John", or p.ID &amp;gt; 0 or p.FirstName != null, you get the idea. This being the case, now there is no need for the Restrictions class at all, nearly everything can be figured out by using Add(). The other problem I wanted to solve was not having to keep passing the generic &amp;lt;Person&amp;gt; class in all the time. So I created a class which wraps ICriteria and keeps track of these few things, so now it looks like:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateExpression&amp;lt;Person&amp;gt;()
     .Add(p =&amp;gt; p.FirstName == "John")
     .Criteria;
&lt;/pre&gt;
&lt;p&gt;Most of the other functions on the Restrictions class can be added the same way:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateExpression&amp;lt;person&amp;gt;()
      .Add(p =&amp;gt; p.FirstName == "John") //Restriction.Eq()
      .Add(p =&amp;gt; p.LastName != null)    //Restriction.IsNotNull() 
      .Add(p =&amp;gt; p.ID &amp;gt; 0 &amp;amp;&amp;amp; p.ID &amp;lt; 1000) //Restriction.Between()
      .Criteria;&lt;/pre&gt;
&lt;p&gt;There are also other more complex things that the ICriteria interface does such as adding Projections and Joins. So how would the old AddAlias() function work? Like this perhaps:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateExpression&amp;lt;Person&amp;gt;()
      .Alias&amp;lt;Address&amp;gt;(p =&amp;gt; p.Addresses, "addr")
            .Add(a =&amp;gt; a.Postcode != null)
            .AddAndReturn(a =&amp;gt; a.Address2 == null)
      .Criteria;&lt;/pre&gt;
&lt;p&gt;Bringing it all together, here's a comparison between the old interface and the expressions version.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Current ICriteria:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria o = session.CreateCriteria(typeof(Person))
    .Add(Restrictions.Eq("FirstName", "John"))
    .CreateAlias("Addresses", "addr")
        .Add(Restrictions.IsNotNull("addr.Postcode"))
        .Add(Restrictions.IsNull("addr.Address2"))
    .AddOrder(Order.Asc("ID"));
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Same query using Expressions:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateExpression&amp;lt;Person&amp;gt;()
    .Add(p =&amp;gt; p.FirstName == "John")
    .Alias&amp;lt;Address&amp;gt;(p =&amp;gt; p.Addresses, "addr")
        .Add(a =&amp;gt; a.Postcode != null)
        .AddAndReturn(a =&amp;gt; a.Address2 == null)
    .OrderAsc(p =&amp;gt; p.ID)
    .Criteria;
&lt;/pre&gt;
&lt;p&gt;In conclusion, this is probably not going to revolutionize the global economy, but on some levels I think it feels a little more intuitive and a little more modern. In other respects, it's probably not much less typing then the original. Also with the up and coming linq provider, is this a waste of time? or does it complement it?&lt;/p&gt;
&lt;p&gt;Feel free to have a poke around the &lt;a href="http://code.google.com/p/systembusinessobjects/source/browse/trunk#trunk/System.BusinessObjects.Framework/Expressions"&gt;source&lt;/a&gt;, and corresponding &lt;a href="http://code.google.com/p/systembusinessobjects/source/browse/trunk/BusinessObject.Framework.Tests/RestrictionHelperTests.cs"&gt;tests&lt;/a&gt;&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/90.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2008/08/17/what-would-nhibernate-icriteria-look-like-in-.net-3.5.aspx</guid>
            <pubDate>Sun, 17 Aug 2008 05:12:29 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/90.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2008/08/17/what-would-nhibernate-icriteria-look-like-in-.net-3.5.aspx#feedback</comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/90.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/90.aspx</trackback:ping>
        </item>
        <item>
            <title>NHibernate Type Safety using Lambda Expressions</title>
            <link>http://kowitz.net/archive/2008/07/22/nhibernate-type-safety-using-lamba-expressions.aspx</link>
            <description>&lt;p&gt;I can't remember if this has been around before, I do vaguely remember seeing something like it. &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;However, I just wanted to apply a snippet of code I found on &lt;a href="http://www.paulstovell.com/blog/strongly-typed-property-names"&gt;Paul's blog&lt;/a&gt; the other day to NHibernate. Of course we will definitely have type safety in queries when Linq-to-NHibernate is completed. But surely linq-to-nhibernate is not going to be the _only_ way of writing queries.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Using the original code snippet 'as is' would look something like this:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateCriteria(typeof(Person));&lt;br /&gt;c.Add(Restrictions.Eq(Property.GetFor(() =&amp;gt; new Person().FirstName), "John"));&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This is ok, but a little long winded, so I implemented another class called RestrictBy which can break down a simple lambda expression. So now I can use:&lt;br /&gt;
&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateCriteria(typeof(Person));&lt;br /&gt;c.Add(RestrictBy.Eq(() =&amp;gt; new Person().FirstName == "John"));&lt;br /&gt;c.UniqueResult();&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This also means you'll get compile time errors for incompatible types such as:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Lamba expression error" src="http://www.kowitz.net/images/kowitz_net/nhibernate_lamba_type_error.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Using the lambda expression we get to evaluate the _actual_ property and that property's type. If you wanted to clean this up some more, its not hard to then go and add some extension methods to ICriteria to produce:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;ICriteria c = session.CreateCriteria(typeof(Person));&lt;br /&gt;c.AddEq(() =&amp;gt; new Person().FirstName == "John");&lt;br /&gt;c.UniqueResult();&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;So that's it, a simple example at the moment, but it might be an option to look into a little more because the ICriteria interface is still NHibernate's native querying interface and still provides a lot of power, flexibility and programmatic building of queries.&lt;br /&gt;
&lt;/p&gt;
&lt;h2&gt;Sourcecode:&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://code.google.com/p/systembusinessobjects/source/browse/trunk/System.BusinessObjects.Framework/Helpers/RestrictBy.cs?r=79"&gt;RestrictBy.cs&lt;/a&gt; also a couple of unit tests &lt;a href="http://code.google.com/p/systembusinessobjects/source/browse/trunk/BusinessObject.Framework.Tests/RestrictionHelperTests.cs?r=79"&gt;here&lt;/a&gt;&lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.paulstovell.com/blog/strongly-typed-property-names"&gt;Paul's Property.GetFor()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style="font-weight: bold;"&gt; EDIT: &lt;/span&gt;For further reading, see the &lt;a href="http://www.kowitz.net/archive/2008/08/17/what-would-nhibernate-icriteria-look-like-in-.net-3.5.aspx"&gt;follow up&lt;/a&gt; post.&lt;img src="http://kowitz.net/aggbug/88.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2008/07/22/nhibernate-type-safety-using-lamba-expressions.aspx</guid>
            <pubDate>Mon, 21 Jul 2008 21:38:48 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/88.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2008/07/22/nhibernate-type-safety-using-lamba-expressions.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/88.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/88.aspx</trackback:ping>
        </item>
        <item>
            <title>IDataErrorInfo for ASP.NET</title>
            <link>http://kowitz.net/archive/2007/11/08/idataerrorinfo-for-asp.net.aspx</link>
            <description>&lt;p&gt;As far as I'm aware ASP.NET doesn't support &lt;a href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.idataerrorinfo(vs.80).aspx"&gt;IDataErrorInfo&lt;/a&gt;, I've asked about this in many places, including Tech.Ed '07 with no success. The closest things I've seen in terms of Business Object level validation is from Enterprise Library validation block (which is attribute based and can render out with custom EntLib web controls) and another example in the Futures &lt;a href="http://www.asp.net/downloads/futures/"&gt;Dynamic Data Controls&lt;/a&gt; using Linq (I have no idea how this magic validation magically appears). &lt;/p&gt;
&lt;p&gt;It all just seems overly complicated, so, have a look at the IDataErrorInfo interface the methods are:&lt;/p&gt;
&lt;p&gt;string this [ string columnName ] { get; }&lt;br /&gt;
string Error { get; }&lt;/p&gt;
&lt;p&gt;Simple and generic. I've been playing around with an idea about how to get this into a generic web control, introducing:&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://systembusinessobjects.googlecode.com/svn/trunk/System.BusinessObjects.Framework/Validation/WebValidationControl.cs"&gt;WebValidationControlExtender&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is an example of the control in design mode:&lt;/p&gt;
&lt;p&gt;&lt;a rel="lightbox" atomicselection="true" href="http://kowitz.net/images/kowitz_net/WindowsLiveWriter/IDataErrorInfoforASP.NET_14BFC/image_1.png"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="344" alt="image" width="393" border="0" src="http://kowitz.net/images/kowitz_net/WindowsLiveWriter/IDataErrorInfoforASP.NET_14BFC/image_thumb_1.png" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Here is an example of the control in action using an ObjectDataSource and a plain old DetailsView:&lt;/p&gt;
&lt;p&gt;&lt;a rel="lightbox" atomicselection="true" href="http://kowitz.net/images/kowitz_net/WindowsLiveWriter/IDataErrorInfoforASP.NET_14BFC/image.png"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="275" alt="image" width="492" border="0" src="http://kowitz.net/images/kowitz_net/WindowsLiveWriter/IDataErrorInfoforASP.NET_14BFC/image_thumb.png" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Here's what's going on under the hood.&lt;/p&gt;
&lt;p&gt;All you need to do is tell WebValidationControlExtender what ObjectDataSource to hook in to.&lt;br /&gt;
When the page is executing and the user tries to insert a record, the DetailsView control builds up an object and sends it into the ObjectDataSource.&lt;br /&gt;
WebValidationControlExtender is already listening for Insert and Update events, all it does is check if the object being passed through implements IDataErrorInfo.&lt;br /&gt;
If it does, WebValidationControlExtender interrogates the object's columns/properties for errors. &lt;br /&gt;
If errors are found, it adds CustomValidators back to the page then goes searching for controls that are using that object datasource (in this case the DetailsView). &lt;br /&gt;
When it finds the details view it searches for BoundFields that are bound to the properties with the error, then inserts the red * like in the picture above.&lt;/p&gt;
&lt;p&gt;The point is, you could go an implement whatever validation library suites your needs, as long as the object implements IDataErrorInfo the validation works. I just don't understand why ASP.NET doesn't already use something like this, there are so many complicated implementations for validation, I hope this brings some fresh light.&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/80.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2007/11/08/idataerrorinfo-for-asp.net.aspx</guid>
            <pubDate>Thu, 08 Nov 2007 13:42:42 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/80.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2007/11/08/idataerrorinfo-for-asp.net.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/80.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/80.aspx</trackback:ping>
        </item>
        <item>
            <title>Stopping ASP.NET web.config inheritance</title>
            <link>http://kowitz.net/archive/2007/05/16/stopping-asp.net-web.config-inheritance.aspx</link>
            <description>&lt;p&gt;If you are only ever running one ASP.NET application on a website this is not an issue. However, if you are running a site which may have an application at the root and other separate applications running in sub or virtual directories, then Settings inheritance could be a problem.&lt;/p&gt;
&lt;p&gt;You can read more about how config files get inherited &lt;a href="http://msdn2.microsoft.com/en-us/library/ms178685.aspx"&gt;on msdn&lt;/a&gt; but here's a tip for stopping settings in the root app from getting inherited. The &amp;lt;location&amp;gt; tag is the only tag I've come across which has the inheritInChildApplications attribute. So to target the main &amp;lt;system.web&amp;gt; just wrap it in the location tag as seen below. &lt;/p&gt;
&lt;pre class="xml" name="code"&gt;&amp;lt;location path="." inheritInChildApplications="false"&amp;gt;
&amp;lt;system.web&amp;gt;
 ...
&amp;lt;/system.web&amp;gt;
&amp;lt;/location&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Other Notes:&lt;/strong&gt;&lt;br /&gt;
Although I think the inheritance is in general a good feature to have, especially for inheriting down things such as security settings.  It can even support locking certain settings for child applications, but things can be problematic if the child application doesn't share the same libraries, modules, handlers, masterpages or themes.&lt;/p&gt;
&lt;p&gt;Most collections in the web.config have the &amp;lt;remove&amp;gt; tag or &amp;lt;clear&amp;gt; tag to remove irrelevant modules or handlers in the child app.  The problems I've found occur with settings relating to the &amp;lt;pages&amp;gt; tag, which most items in it don't support &amp;lt;remove&amp;gt;. This means if your child applications doesn't share or have the same registered controls, masterpages or themes then you are probably going to have issues or be forced to specify the settings on a per-page basis.  This is where the inheritInChildApplications="false" really comes in handy.&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/71.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2007/05/16/stopping-asp.net-web.config-inheritance.aspx</guid>
            <pubDate>Wed, 16 May 2007 03:11:23 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/71.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2007/05/16/stopping-asp.net-web.config-inheritance.aspx#feedback</comments>
            <slash:comments>9</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/71.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/71.aspx</trackback:ping>
        </item>
        <item>
            <title>ERROR: 42601: a column definition list is only allowed for functions returning record</title>
            <link>http://kowitz.net/archive/2007/03/15/error-42601-a-column-definition-list-is-only-allowed-for.aspx</link>
            <description>&lt;p&gt;Since the postgres forums appear to be a little quite, I'll post my error here as well. &lt;/p&gt;
&lt;p&gt;This error is in regards to the postgres .net npgsql driver and seemed to only occur when using stored procs.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;The Error&lt;/strong&gt;&lt;br /&gt;
The behavior I experienced happens when using stored procedures started out with me getting the following error:&lt;br /&gt;
&lt;strong&gt;ERROR: 42601: a column definition list is only allowed for functions returning "record"&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
After checking and double checking the stored proc and the parameters I was sending in I turned Npgsql's debugging on. The error appears to be coming from a statement that looks like the following:&lt;br /&gt;
select * from sitemenus_ins(68::int4,34::int4) as (psitemenuid int4, prowstamp timestamp )&lt;br /&gt;
This line of sql fails. &lt;/p&gt;
&lt;p&gt;However the following will work:&lt;br /&gt;
select * from sitemenus_ins(68::int4,34::int4)&lt;br /&gt;
The only difference being that the second one has the 'as(...' clause taken off.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Strange Observation:&lt;/strong&gt;&lt;br /&gt;
The snippet in question is executed automatically by the provider after the NpgsqlCommand.cs class does some other queries to try and match the list of the parameters that are in the stored procedure it is about to execute. However, the 'select' it uses to determine if it should append the 'as(..' clause is queried from the pg_proc table but is matched on the parameter types that are passed in, and not on those of the actual proc.&lt;br /&gt;
&lt;br /&gt;
For example, this means that if I passed in say a 'Text' type (25) as opposed to the defined datatype on a proc (eg. 'Varchar' 1043) The select will fail and the extra 'as (...' on the end of the statement in question will not be appended. So the function call will work&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Resolution:&lt;/strong&gt;&lt;br /&gt;
I have no idea what the ideal solution is, I don't have a firm understanding of the ins and outs of the provider, but after downloading the source and removing the check so the 'as (...' never gets appended, all CRUD operations in my unit tests pass.&lt;/p&gt;
&lt;p&gt;Another suggestion by Al is that maybe it is a piece of code left in there that was needed from a previous version of postgres (since the code has been around for a few years now).  Whatever the reason, it causes errors, I've checked the source for &lt;a target="_blank" href="http://sourceforge.net/projects/pgsqlclient"&gt;another &lt;/a&gt;postgres provider and it doesn't attempt to do the append.  The only concern I have if this is an actual bug is that it looks as though the same code has been copied into the branch for the &lt;a href="http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/npgsql/Npgsql2/"&gt;npgsql2&lt;/a&gt; provider, so those wanting to use stored procs on postgres in the future may find the same error I have.&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/70.aspx" width="1" height="1" /&gt;</description>
            <guid>http://kowitz.net/archive/2007/03/15/error-42601-a-column-definition-list-is-only-allowed-for.aspx</guid>
            <pubDate>Thu, 15 Mar 2007 11:30:35 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/70.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2007/03/15/error-42601-a-column-definition-list-is-only-allowed-for.aspx#feedback</comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/70.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/70.aspx</trackback:ping>
        </item>
        <item>
            <title>The C# @ String Literal</title>
            <link>http://kowitz.net/archive/2007/03/06/the-c-string-literal.aspx</link>
            <description>&lt;p&gt;C# is a pretty sweet language, and there are many, many, many little things that just make the code that much nicer. Have you ever been in a situation where for some reason you &lt;span style="FONT-WEIGHT: bold"&gt;NEEDED &lt;/span&gt;to have a string/code fragment/js fragment/sql statement inline in your code because you don't believe in resource files or stored procedures? &lt;br /&gt;
&lt;br /&gt;
Aside from whatever great debate about "if you should or shouldn't". If you are going to, please, please, learn to take advantage of what C# has to offer, yes I'm talking about the '@' string literal.&lt;br /&gt;
&lt;br /&gt;
Now I'm not going to target anyone in particular, but my feeling is that VB as a language seems to be more notorious for having hundreds of lines of String.Append()s. String.Append is the absolute worst, hardest and most illegible way of possibly including your fragment inline in code.&lt;br /&gt;
&lt;br /&gt;
There are also the programmers that 'know of' the @ symbol and prefix all their strings with it because it looks cool or something. Doing this without reason may actually alter the behaviour you excepted because it causes escape sequences to NOT be processed.&lt;br /&gt;
Eg. &lt;span style="COLOR: #0066ff"&gt;"c:\\my\\file.txt"&lt;/span&gt; could be done as &lt;span style="COLOR: #0066ff"&gt;@"c:\my\file.txt"&lt;/span&gt;&lt;br /&gt;
This means your \n and \t or whatever it is will also not be processed. &lt;/p&gt;
&lt;p&gt;I'd say the most precious and special super power of a string literal is its multi-line ability. So instead of writing code that may look something like:&lt;br /&gt;
&lt;span style="COLOR: #0066ff"&gt;var1 += @"some text" + Environment.NewLine;&lt;/span&gt;&lt;br style="COLOR: #0066ff" /&gt;
&lt;span style="COLOR: #0066ff"&gt;var1 += @"some more text" + Environment.NewLine;&lt;/span&gt;&lt;br style="COLOR: #0066ff" /&gt;
&lt;span style="COLOR: #0066ff"&gt;var1 += @"even more text" + Environment.NewLine;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
You could just use the @-quoting and write:&lt;br /&gt;
&lt;span style="COLOR: #0066ff"&gt;var1 = @"some text&lt;/span&gt;&lt;br style="COLOR: #0066ff" /&gt;
&lt;span style="COLOR: #0066ff"&gt;some more text&lt;/span&gt;&lt;br style="COLOR: #0066ff" /&gt;
&lt;span style="COLOR: #0066ff"&gt;event more text";&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
And yes that will compile perfectly fine. Best of all, even without going into the debate of "having inline fragments" at least I can read it and change it.&lt;br /&gt;
&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/69.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2007/03/06/the-c-string-literal.aspx</guid>
            <pubDate>Mon, 05 Mar 2007 15:10:56 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/69.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2007/03/06/the-c-string-literal.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/69.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/69.aspx</trackback:ping>
        </item>
        <item>
            <title>Search Engine Optimization for .NET</title>
            <link>http://kowitz.net/archive/2006/12/17/search-engine-optimization-for-.net.aspx</link>
            <description>&lt;p&gt;&lt;strong&gt;Search Engine Bot Detection&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So after I &lt;a href="http://www.kowitz.net/2006/12/7/Cleaning+Up+ASPNET+Sessions+in+Google.aspx"&gt;first noticed&lt;/a&gt; a large build up of strange session Urls in Google searches for my domain I've then done a little bit of &lt;a href="http://www.kowitz.net/2006/12/11/ASPNET+20+Mozilla+Browser+Detection+Hole.aspx"&gt;research&lt;/a&gt; into the issue and discovered it was .NET not detecting that the search engine spider was Mozilla/5.0 compliant and inserting some rubbish session id into the url. &lt;/p&gt;
&lt;p&gt;It's been nearly a week since my changes to correct this and there's already a small indication of the 'healing' process. The pages are not out of the index yet, (and yes I do know that I 'could' &lt;a href="http://services.google.com/urlconsole/controller"&gt;remove them manually&lt;/a&gt;) but there are a lot of urls, and I'm in no rush.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.kowitz.net/Attachment.ashx?id=WindowsLiveWriter%2fSearchEngineOptimizationfor.NET_FDE0%2fasp_net_url_cleanup%5b6%5d.jpg" rel="lightbox"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="161" alt="ASP.NET Url Cleanup" width="240" src="http://www.kowitz.net/Attachment.ashx?id=WindowsLiveWriter%2fSearchEngineOptimizationfor.NET_FDE0%2fasp_net_url_cleanup_thumb%5b4%5d.jpg" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note on Webparts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Another change I have made this week was completing stripping webparts out of my template. Now even though I think webparts are extremely cool...they render HTML Soup. So I'd probably recommend that if you have a site where you are trying to get it to rank via the content, don't use webparts. If its an admin section / personalisation portal / intranet site or any other scenario when content ranking is not important, then by all means, feel the &lt;strike&gt;soup&lt;/strike&gt; power!&lt;/p&gt;
&lt;p&gt;Apart from dropping 20k from my page here's another unexpected result:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.kowitz.net/Attachment.ashx?id=WindowsLiveWriter%2fSearchEngineOptimizationfor.NET_FDE0%2fthis_page_validates_as_xhtml_1_0_transitional%5b1%5d.jpg" rel="lightbox"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="161" alt="Frontpage validates as XHTML 1.0 Transitional" width="240" src="http://www.kowitz.net/Attachment.ashx?id=WindowsLiveWriter%2fSearchEngineOptimizationfor.NET_FDE0%2fthis_page_validates_as_xhtml_1_0_transitional.jpg" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Yey I pass &lt;a href="http://validator.w3.org/"&gt;validation&lt;/a&gt; on W3C!!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Evil ViewState&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Well I think viewstate is fantastic, its a set-and-forget automagic keep-state for all things on your form. Only problem is it renders before the content. This is a bad thing because search phrases gain more significance the closer they are to the top of the document, so the idea is to keep the soup at the bottom. A bit of Googling shows there are &lt;a href="http://www.hanselman.com/blog/MovingViewStateToTheBottomOfThePage.aspx"&gt;various&lt;/a&gt; methods that have been implemented to move it to the bottom. The method I kind of agreed with (although I've lost the link d'oh) was where a basepage class simple overrides handling the viewstate and uses the LosFormatter to store it in the session. Now I only half agree with this, I like the idea of overriding the handling of the viewstate but not putting it in the session. I simply used this but added my own HiddenControl (i.e. __VIEWSTATE_SEO) to the bottom of the form on pre-render, easy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Blog Category&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In respect of all these new things that appear to be common SEO problems I have created to new &lt;a href="http://www.kowitz.net/Posts/PostsByCategory.aspx?categoryId=1017"&gt;category&lt;/a&gt; for SEO.NET (Search Engine Optimisation for .NET) blog posts. And in addition to this I will be trying to starting a small toolkit of classes and resources that should be able to be applied to any ASP.NET 2.0 application to make it more SEO friendly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Move ViewState to the bottom of the form &lt;a href="http://www.kowitz.net/files/BasePage.zip"&gt;BasePage.cs&lt;/a&gt; or view &lt;a href="http://www.kowitz.net/files/source/BasePage.cs.txt"&gt;Source&lt;/a&gt; online&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/65.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2006/12/17/search-engine-optimization-for-.net.aspx</guid>
            <pubDate>Sat, 16 Dec 2006 15:42:36 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/65.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2006/12/17/search-engine-optimization-for-.net.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/65.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/65.aspx</trackback:ping>
        </item>
        <item>
            <title>ASP.NET 2.0 Mozilla Browser Detection Hole</title>
            <link>http://kowitz.net/archive/2006/12/11/asp.net-2.0-mozilla-browser-detection-hole.aspx</link>
            <description>&lt;p&gt;It has recently come to my attention that there is something drastically wrong with the way search engines have been indexing my ASP.NET 2.0 blog.&lt;/p&gt;
&lt;p&gt;As I've started to &lt;a href="http://www.kowitz.net/2006/12/7/Cleaning+Up+ASPNET+Sessions+in+Google.aspx"&gt;explain previously&lt;/a&gt;, this is because of the way the browser detection is set up. To give a brief rundown ASP.NET 2.0 has a default &lt;a href="http://msdn2.microsoft.com/en-us/library/ms228122(VS.80).aspx"&gt;browser definition&lt;/a&gt; which seems to assume that the default browser is fairly capable and supports common things such as javascript and cookies. A browser definition can get inherited into other definitions which can then override specific properties to update it for that specific browser or browser version.&lt;/p&gt;
&lt;p&gt;Apparently in around &lt;a href="http://www.mattcutts.com/blog/q-a-thread-march-27-2006/"&gt;March 2006&lt;/a&gt; Google started rolling out updates that changed the Googlebot's useragent string from:&lt;/p&gt;
&lt;p&gt;"Googlebot/2.1 (+http://www.googlebot.com/bot.html)" to&lt;br /&gt;
"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"&lt;/p&gt;
&lt;p&gt;Now the reason for this is so the Googlebot could identify itself as being Mozilla/5.0 compliant which should allow it to be accepted by more webservers. However this breaks the detection pattern in ASP.NET. (And was always broken in Yahoo Slurp, I just don't know if anyone ever noticed).&lt;/p&gt;
&lt;p&gt;When the useragent was just "Googlebot/2.1" it wasn't able to be matched and used the "default.browser" detection file which defaulted to a browser of reasonable capabilities. After the change it found itself in the "mozilla.browser" file because it was detected on the "Mozilla" word. So all the following sets of instructions in the "mozilla.browser" file try to establish exactly what platform and variant of Mozilla it is, for example, if its Firefox running on OSX, or if it's the older Mozilla Gecko rendering engine. But because there is no definition for a Generic Mozilla/5.0 compatible browser it gets the most relevant match, being the lowest Mozilla/1.0 compatible settings. Bad!&lt;/p&gt;
&lt;p&gt;Because of this bad detection the default Mozilla/1.0 settings assume NO COOKIES and insert the session ID into the url then issues a response status 302 (content temporarily moved). What makes this situation even worse is that the default behavior of search engines is to &lt;a href="http://www.mattcutts.com/blog/seo-advice-discussing-302-redirects/"&gt;follow these redirects&lt;/a&gt; and index the content on the other side. So basically everytime some random User-agent that claims to be Mozilla/5.0 compliant hits the site it gets Mozilla/1.0 capabilities. What is needed is something to bridge this gap.&lt;/p&gt;
&lt;p&gt;Fortunately there is something that can be done that won't even require a recompile of your ASP.NET 2.0 application. Simply create a "genericmozilla5.browser" file in your "/App_Browsers" folder in the root of your application with the following in contents:&lt;/p&gt;
&lt;pre class="xml" name="code"&gt;&amp;lt;browsers&amp;gt;
&amp;lt;browser id="GenericMozilla5" parentID="Mozilla"&amp;gt;
&amp;lt;identification&amp;gt;
&amp;lt;userAgent match="Mozilla/5\.(?'minor'\d+).*[C|c]ompatible; ?(?'browser'.+); ?\+?(http://.+)\)" /&amp;gt;
&amp;lt;/identification&amp;gt;
&amp;lt;capabilities&amp;gt;
&amp;lt;capability name="majorversion" value="5" /&amp;gt;
&amp;lt;capability name="minorversion" value="${minor}" /&amp;gt;
&amp;lt;capability name="browser" value="${browser}" /&amp;gt;
&amp;lt;capability name="Version" value="5.${minor}" /&amp;gt;
&amp;lt;capability name="activexcontrols" value="true" /&amp;gt;
&amp;lt;capability name="backgroundsounds" value="true" /&amp;gt;
&amp;lt;capability name="cookies" value="true" /&amp;gt;
&amp;lt;capability name="css1" value="true" /&amp;gt;
&amp;lt;capability name="css2" value="true" /&amp;gt;
&amp;lt;capability name="ecmascriptversion" value="1.2" /&amp;gt;
&amp;lt;capability name="frames" value="true" /&amp;gt;
&amp;lt;capability name="javaapplets" value="true" /&amp;gt;
&amp;lt;capability name="javascript" value="true" /&amp;gt;
&amp;lt;capability name="jscriptversion" value="5.0" /&amp;gt;
&amp;lt;capability name="supportsCallback" value="true" /&amp;gt;
&amp;lt;capability name="supportsFileUpload" value="true" /&amp;gt;
&amp;lt;capability name="supportsMultilineTextBoxDisplay" value="true" /&amp;gt;
&amp;lt;capability name="supportsMaintainScrollPositionOnPostback" value="true" /&amp;gt;
&amp;lt;capability name="supportsVCard" value="true" /&amp;gt;
&amp;lt;capability name="supportsXmlHttp" value="true" /&amp;gt;
&amp;lt;capability name="tables" value="true" /&amp;gt;
&amp;lt;capability name="vbscript" value="true" /&amp;gt;
&amp;lt;capability name="w3cdomversion" value="1.0" /&amp;gt;
&amp;lt;capability name="xml" value="true" /&amp;gt;
&amp;lt;capability name="tagwriter" value="System.Web.UI.HtmlTextWriter" /&amp;gt;
&amp;lt;/capabilities&amp;gt;
&amp;lt;/browser&amp;gt;
&amp;lt;/browsers&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This will match generic Mozilla compatible browsers and spiders with user-agents strings such as:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html) &lt;/li&gt;
    &lt;li&gt;Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp) &lt;/li&gt;
    &lt;li&gt;Mozilla/5.0 (compatible; AbiLogicBot/1.0; +http://www.abilogic.com/bot.html) &lt;/li&gt;
    &lt;li&gt;Mozilla/5.0 (compatible; AnyApexBot/1.0; +http://www.anyapex.com/bot.html) &lt;/li&gt;
    &lt;li&gt;Mozilla/5.0 (compatible; BecomeBot/3.0; MSIE 6.0 compatible; +http://www.become.com/site_owners.html) &lt;/li&gt;
    &lt;li&gt;Mozilla/5.0 (compatible; MojeekBot/2.0; http://www.mojeek.com/bot.html) &lt;/li&gt;
    &lt;li&gt;Mozilla/5.0 (compatible; Scrubby/2.2; +http://www.scrubtheweb.com/) &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Other Notes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The MSNBOT also never had this problem because it like the original Googlebot string was never detected and thus received the "default.browser" file settings which support the cookies.&lt;/p&gt;
My solution is not a complete fix, I think Microsoft could have done one thing better here. Because the browser string goes into the "mozilla.browser" file, they need another level where when it knows its Mozilla/5.0 compliant it gets the appropriate defaults before it starts to figure out exactly what browser it is. Even though with this approach the exact browsing useragent wouldn't be established, it would at least support future browsers claiming to be compliant at a higher level then just "Mozilla".
&lt;p&gt;&lt;strong&gt;Downloads&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://www.kowitz.net/files/genericmozilla5.zip"&gt;genericmozilla5.browser&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt; &lt;/pre&gt;
&lt;pre&gt; &lt;/pre&gt;&lt;img src="http://kowitz.net/aggbug/64.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2006/12/11/asp.net-2.0-mozilla-browser-detection-hole.aspx</guid>
            <pubDate>Mon, 11 Dec 2006 02:58:54 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/64.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2006/12/11/asp.net-2.0-mozilla-browser-detection-hole.aspx#feedback</comments>
            <slash:comments>11</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/64.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/64.aspx</trackback:ping>
        </item>
        <item>
            <title>Cleaning Up ASP.NET Sessions in Google</title>
            <link>http://kowitz.net/archive/2006/12/06/cleaning-up-asp.net-sessions-in-google.aspx</link>
            <description>&lt;p&gt;&lt;strong&gt;ASP.NET and Dirty Urls&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are two things that have been bothering me about pages that are getting indexed in Google from an ASP.NET application. The first is somehow there are ASP.NET Session Urls ending up in the Google index. This is bad because searchers that actually do click these links are likely to get a 500 error (internal server error) because they will be trying to access a page of an expired session. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.kowitz.net/Attachment.ashx?id=WindowsLiveWriter%2fCleaningUpASP.NETSessionsinGoogle_6A92%2ferror_urls%5b10%5d.jpg" rel="lightbox"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="184" alt="Indexed Session Urls in Google Sitemap tools" width="473" src="http://www.kowitz.net/Attachment.ashx?id=WindowsLiveWriter%2fCleaningUpASP.NETSessionsinGoogle_6A92%2ferror_urls_thumb%5b8%5d.jpg" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How is Google finding all these 'bad' urls?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Well apparently there is no browser definition in ASP.NET 2.0 for the Googlebot's useragent string, so when the spider hits your ASP.NET page it's browser capabilities are not defined.&lt;/p&gt;
&lt;p&gt;&lt;font color="#ff0000"&gt;Edit:&lt;/font&gt; The default browser capabilities are defined to &lt;strong&gt;&lt;font color="#000000"&gt;use cookies&lt;/font&gt;&lt;/strong&gt;, the issue occurs because the base Mozilla definition is defined to &lt;strong&gt;NOT&lt;/strong&gt; use cookies. If the browser is not able to accept cookeis .NET gets around this by inserting the session information into the Url and issues a 302 (content temporarily moved) in the response header. &lt;/p&gt;
&lt;p&gt;This default behaviour is a good and a bad thing. It's good in the fact that if I'm browsing an asp.net site on a pda that doesn't support cookies I still can. However just about every search engine spider ever created has it's own UserAgent string making it a tough task to issue the standard non-crufted url. One solution to fixing the session urls being indexed in Google is to tell your asp.net application that Googlebot supports cookies and the problem is solved. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To read more about the solution please see my &lt;a href="http://www.kowitz.net/2006/12/11/ASPNET+20+Mozilla+Browser+Detection+Hole.aspx"&gt;next post&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dynamic Captcha build-up&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Another dynamic aspect that is used on this site are Captcha images, and yes Google's image spider finds those too. Upon trying a Google image search on my domain, it's littered with Captcha images! I've also added an exclude to the robots.txt file for this.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.kowitz.net/Attachment.ashx?id=WindowsLiveWriter%2fCleaningUpASP.NETSessionsinGoogle_6A92%2fcaptcha_buildup%5b2%5d.jpg" rel="lightbox"&gt;&lt;img style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height="305" alt="Captcha image build-up in Google image search" width="331" src="http://www.kowitz.net/Attachment.ashx?id=WindowsLiveWriter%2fCleaningUpASP.NETSessionsinGoogle_6A92%2fcaptcha_buildup_thumb.jpg" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution for Captcha images build-up and stop-gap solution for Session Urls&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here is my "robots.txt" file so far for my SingleUserBlog install. *Note the last two lines, "Disallow: /(A(*" should exclude any ASP.NET session urls, (this is not recommended unless you have fixed the Mozilla detection hole). The last line should exclude any captcha images from being indexed.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;User-agent: *&lt;br /&gt;
Disallow: /LoginPage.aspx&lt;br /&gt;
Disallow: /Administration/&lt;br /&gt;
Disallow: /(A(*&lt;br /&gt;
Disallow: /Captcha.ashx*$&lt;/p&gt;
&lt;/blockquote&gt;&lt;img src="http://kowitz.net/aggbug/63.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2006/12/06/cleaning-up-asp.net-sessions-in-google.aspx</guid>
            <pubDate>Wed, 06 Dec 2006 13:49:27 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/63.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2006/12/06/cleaning-up-asp.net-sessions-in-google.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/63.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/63.aspx</trackback:ping>
        </item>
        <item>
            <title>Brendan's C# Modifier Keyword Guide</title>
            <link>http://kowitz.net/archive/2006/11/05/brendans-c-modifier-keyword-guide.aspx</link>
            <description>
		&lt;p&gt;After a little bit of thought from my last post I decided to write a small sample class and use tooltips to document what some of the most common modifiers do. So run your mouse over the boxes below to see the documentation about the keyword. &lt;/p&gt;
		&lt;p&gt;
				&lt;font color="#ff0000"&gt;Edit&lt;/font&gt;: In an effort to unbreak my RSS I've moved it to it's own page &lt;a href="/CSharp_Modifier_Keyword_Guide.aspx"&gt;http://www.kowitz.net/CSharp_Modifier_Keyword_Guide.aspx&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://kowitz.net/aggbug/62.aspx" width="1" height="1" /&gt;</description>
            <guid>http://kowitz.net/archive/2006/11/05/brendans-c-modifier-keyword-guide.aspx</guid>
            <pubDate>Sun, 05 Nov 2006 01:54:13 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/62.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2006/11/05/brendans-c-modifier-keyword-guide.aspx#feedback</comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/62.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/62.aspx</trackback:ping>
        </item>
    </channel>
</rss>