<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>.NET</title>
        <link>http://www.kowitz.net/category/3.aspx</link>
        <description>.NET</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>NHibernate Compatible Shared Hosts</title>
            <link>http://kowitz.net/archive/2008/03/28/nhibernate-compatible-shared-hosts.aspx</link>
            <description>&lt;p&gt;NHibernate is a remarkable ORM, however with all the magic comes a few caveats, these being the difficulties running NHibernate apps in a shared hosting environment. I'm still convinced that it's entirely possible, so I've decided to start compiling a list of success and failures that others (and myself) have had in getting things working.&lt;/p&gt;
&lt;h2&gt;Compatible Shared Hosts&lt;/h2&gt;
&lt;table width="400" cellspacing="0" cellpadding="2" border="0"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td width="134" valign="top"&gt;&lt;strong&gt;Host Name&lt;/strong&gt;&lt;/td&gt;
            &lt;td width="145" valign="top"&gt;&lt;strong&gt;Comment&lt;/strong&gt;&lt;/td&gt;
            &lt;td width="119" valign="top"&gt;&lt;strong&gt;Reference&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td width="134" valign="top"&gt;&lt;a href="http://www.webhost4life.com/" target="_blank"&gt;Webhost4life&lt;/a&gt; &lt;/td&gt;
            &lt;td width="157" valign="top"&gt;Reportedly works with "no hacks"&lt;/td&gt;
            &lt;td width="151" valign="top"&gt;[&lt;a href="http://www.gavaghan.org/blog/2007/08/21/nhibernate-in-a-medium-trust-environment/" target="_blank"&gt;ref&lt;/a&gt;]&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td style="vertical-align: top;"&gt;&lt;a href="http://www.discountasp.net/" target="_blank"&gt;DiscountAsp&lt;/a&gt;&lt;/td&gt;
            &lt;td style="vertical-align: top;"&gt;I think this should work with IIS7 / Win 2008&lt;/td&gt;
            &lt;td style="vertical-align: top;"&gt;[&lt;a href="http://kb.discountasp.net/article.aspx?id=10574"&gt;ref&lt;/a&gt;]&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td style="vertical-align: top;"&gt;&lt;a href="http://www.xhostsolutions.com/" target="_blank"&gt;XHostSolutions&lt;/a&gt;&lt;/td&gt;
            &lt;td style="vertical-align: top;"&gt;Simply email support and ask to have your application run as Full Trust&lt;br /&gt;
            &lt;/td&gt;
            &lt;td style="vertical-align: top;"&gt; This is the host I use.&lt;br /&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Shared Hosts known &lt;strong&gt;not&lt;/strong&gt; to work&lt;/h2&gt;
&lt;table width="400" cellspacing="0" cellpadding="2" border="0"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td width="132" valign="top"&gt;&lt;strong&gt;Host Name&lt;/strong&gt;&lt;/td&gt;
            &lt;td width="133" valign="top"&gt;&lt;strong&gt;Comment&lt;/strong&gt;&lt;/td&gt;
            &lt;td width="133" valign="top"&gt;&lt;strong&gt;Reference&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td width="132" valign="top"&gt;&lt;a href="http://www.godaddy.com/" target="_blank"&gt;Godaddy&lt;/a&gt; &lt;/td&gt;
            &lt;td width="149" valign="top"&gt; &lt;/td&gt;
            &lt;td width="165" valign="top"&gt;[&lt;a href="http://forum.hibernate.org/viewtopic.php?t=980538&amp;amp;highlight=medium+trust" target="_blank"&gt;ref&lt;/a&gt;]&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td width="132" valign="top"&gt;&lt;a href="http://www.crystaltech.com/" target="_blank"&gt;Crystaltech&lt;/a&gt; &lt;/td&gt;
            &lt;td width="149" valign="top"&gt; &lt;/td&gt;
            &lt;td width="165" valign="top"&gt;
            &lt;p&gt;[&lt;a href="http://forum.castleproject.org/viewtopic.php?t=3104" target="_blank"&gt;ref&lt;/a&gt;]&lt;/p&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Untested / Unknown&lt;/h2&gt;
&lt;table width="400" cellspacing="0" cellpadding="2" border="0"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td width="133" valign="top"&gt;&lt;strong&gt;Host Name&lt;/strong&gt;&lt;/td&gt;
            &lt;td width="133" valign="top"&gt;&lt;strong&gt;Comment&lt;/strong&gt;&lt;/td&gt;
            &lt;td width="133" valign="top"&gt;&lt;strong&gt;Reference&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td width="133" valign="top"&gt;&lt;a href="http://www.discountasp.net/" target="_blank"&gt;DiscountAsp&lt;/a&gt;&lt;/td&gt;
            &lt;td width="133" valign="top"&gt; &lt;/td&gt;
            &lt;td width="133" valign="top"&gt; &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Useful References / Alternate Ideas&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://blechie.com/WPierce/archive/2008/02/17/Lazy-Loading-with-nHibernate-Under-Medium-Trust.aspx"&gt;Lazy Loading with nHibernate Under Medium Trust&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://kowitz.net/aggbug/84.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2008/03/28/nhibernate-compatible-shared-hosts.aspx</guid>
            <pubDate>Fri, 28 Mar 2008 13:21:04 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/84.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2008/03/28/nhibernate-compatible-shared-hosts.aspx#feedback</comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/84.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/84.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>Another SubText Blog</title>
            <link>http://kowitz.net/archive/2007/06/09/hello-subtext.aspx</link>
            <description>&lt;p&gt;Yes, I'm one of the crowd now, all because my old host Jumba is turning off the last of their Windows boxes, and coincidentally, the one I was hosted on. This has happened &lt;a href="http://www.kowitz.net/archive/2006/10/12/server-move-sub-and-mysql-dataprovider.aspx"&gt;previously&lt;/a&gt; when they shut down some legacy Windows servers and forced everyone on it to upgrade.&lt;/p&gt;
&lt;p&gt;Since Jumba is now no longer offering HELM windows hosting they have &lt;a href="http://forums.whirlpool.net.au/forum-replies.cfm?t=758042"&gt;recommended&lt;/a&gt; &lt;a href="http://www.xhostsolutions.com.au/"&gt;xHostSolutions&lt;/a&gt; who have pretty comparative deals to what I was previously on, only better. This now gives me access to an MS Sql Server database, so I thought I'd take the opportunity to install &lt;a href="http://subtextproject.com/"&gt;SubText&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I still think that &lt;a href="http://www.codeplex.com/SUB"&gt;Single User Blog&lt;/a&gt; is a great place to start when you want to start sinking your teeth into ASP.NET 2.0, its very easy to get your head around and start using all the cool features that ASP.NET has to offer. This is one thing, but I'm now itching to try something a little more feature rich such as SubText. I do admire what wordpress has achieved in the blogging world, but I just can't seem to stray away from .NET, and not to mention the fact that wordpress is written in &lt;a href="http://www.youtube.com/watch?v=p5EIrSM8dCA"&gt;PHP&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/72.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Brendan Kowitz</dc:creator>
            <guid>http://kowitz.net/archive/2007/06/09/hello-subtext.aspx</guid>
            <pubDate>Sat, 09 Jun 2007 11:14:22 GMT</pubDate>
            <comments>http://kowitz.net/archive/2007/06/09/hello-subtext.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/72.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/72.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>A Free, FreeTextBox Alternative</title>
            <link>http://kowitz.net/archive/2007/02/21/a-free-freetextbox-alternative.aspx</link>
            <description>&lt;p&gt;I don't know why but &lt;a href="http://freetextbox.com/" target="_blank"&gt;FreeTextBox&lt;/a&gt; has just never cut it for me.  It's wonderful and easy to install and it comes as a nice control in a .NET assembly.  &lt;span style="font-weight: bold;"&gt;But &lt;/span&gt;it doesn't give you the nicest HTML back, in fact I'd go as far as to say, it mutates GOOD HTML you put in there yourself, this is bad.  Luckily there are some other free alternatives such as &lt;a href="http://tinymce.moxiecode.com/" target="_blank"&gt;TinyMCE&lt;/a&gt;, which is a nice little editor.  The only catch is it's pure javascript and requires a little manual intervention to work with your serverside code.&lt;br /&gt;
&lt;br /&gt;
On a side note: The guys over at &lt;a target="_blank" href="http://code.communityserver.org/?path=CS+Tree%5cCS+2.1%5cControls%5cEditor%5cITextEditor.cs"&gt;CommunityServer&lt;/a&gt; probably saw this problem and thought; no matter which editor you pick someone was going to complain, so they implemented the editor control in a Provider model. Clever.&lt;br /&gt;
&lt;br /&gt;
I'm not using CommunityServer so changing my little SUB editor still requires two lines of code change and a recompile, but the flavor of the week for me is &lt;a href="http://www.obout.com/editor_new/index.aspx" target="_blank" rel="nofollow"&gt;Obout's HTML Editor&lt;/a&gt;.  This little beauty is free for personal use, and commercial use requires only a small registration fee.&lt;br /&gt;
&lt;br /&gt;
This editor not only gives better HTML then FTB but also has some cool things like a Built-in spell checker, quick-formatting and bunches of other little options.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;UPDATE(29-Mar-07): &lt;/span&gt;I have now had a change to try out &lt;a target="_blank" href="http://www.fckeditor.net"&gt;FCKEditor&lt;/a&gt;, and it does seem to work very smoothly.  Also I did notice an option when using it under Mozilla to format 'span' tags rather then the out dated 'font' tags.&lt;/p&gt;
&lt;p&gt;It also appears that Obout may have changed their policy since I've made this post because I can no longer see any indication that they want anyone to use the editor for free, they seem to now be pushing downloading it as part of their new suite.  So in light of this, FCKEditor may be your best alternative.&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/67.aspx" width="1" height="1" /&gt;</description>
            <guid>http://kowitz.net/archive/2007/02/21/a-free-freetextbox-alternative.aspx</guid>
            <pubDate>Tue, 20 Feb 2007 23:57:36 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/67.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2007/02/21/a-free-freetextbox-alternative.aspx#feedback</comments>
            <slash:comments>6</slash:comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/67.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/67.aspx</trackback:ping>
        </item>
        <item>
            <title>Hello IronPython for ASP.NET</title>
            <link>http://kowitz.net/archive/2007/02/04/hello-ironpython-for-asp.net.aspx</link>
            <description>&lt;p&gt;Although this is not new news (released November 2006 I think), I'd like to point out how cool having &lt;a href="http://www.asp.net/ironpython/default.aspx?tabid=62"&gt;Python run ASP.NET&lt;/a&gt; is.  I don't actually know how to program python...yet...but programming Python appears intuitive be nature. &lt;/p&gt; &lt;p&gt;To get an HelloWorld IronPython ASP.NET application running, it took me all of about 5 minutes, 3 to download and install the add-in, 1 to open Visual Studio, then another minute to type in some stuff and run it.  Sweet.  At this point the intellisense has nothing of your other standard languages like C#, but I'm sure that's coming.&lt;/p&gt; &lt;p&gt;One of the biggest issues I see with a a large number of languages is a good IDE.  Not to say that Python doesn't already have a number of good IDEs, but, I haven't used an IDE yet that actually beats Visual Studio.  So since IronPython can make the effort to actually integrate with Visual Studio and be compatible with all my existing .NET libraries, maybe I'll just have to make more of an effort to check it out.&lt;/p&gt;&lt;img src="http://kowitz.net/aggbug/66.aspx" width="1" height="1" /&gt;</description>
            <guid>http://kowitz.net/archive/2007/02/04/hello-ironpython-for-asp.net.aspx</guid>
            <pubDate>Sun, 04 Feb 2007 11:14:35 GMT</pubDate>
            <wfw:comment>http://kowitz.net/comments/66.aspx</wfw:comment>
            <comments>http://kowitz.net/archive/2007/02/04/hello-ironpython-for-asp.net.aspx#feedback</comments>
            <wfw:commentRss>http://kowitz.net/comments/commentRss/66.aspx</wfw:commentRss>
            <trackback:ping>http://kowitz.net/services/trackbacks/66.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>
    </channel>
</rss>