<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Steve Sheldon</title><link>http://weblogs.asp.net/stevesheldon/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Simple Cryptography Block</title><link>http://weblogs.asp.net/stevesheldon/archive/2008/10/25/simple-cryptography-block.aspx</link><pubDate>Sat, 25 Oct 2008 19:23:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6704148</guid><dc:creator>sodablue</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/stevesheldon/rsscomments.aspx?PostID=6704148</wfw:commentRss><comments>http://weblogs.asp.net/stevesheldon/archive/2008/10/25/simple-cryptography-block.aspx#comments</comments><description>&lt;P mce_keep="true"&gt;I was looking around for a piece of code which would take a string and encrypt it&amp;nbsp;into a&amp;nbsp;Base64 encoded string such that I could later decrypt the string and obtain the message.&amp;nbsp;&amp;nbsp;This was to be used in a confirmation email.&amp;nbsp; The message being urlencoded onto a&amp;nbsp;confirmation url that the user could click and verify his email address was correct, or to redirect to a password setup page.&amp;nbsp; I found some examples in MSDN, but none did quite what I wanted.&amp;nbsp; I also wanted to use the key from the machineKey section of web.config.&lt;/P&gt;
&lt;P mce_keep="true"&gt;I came up with this and thought others might find some use for it.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;STYLE type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;
&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Text;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Security.Cryptography;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Web.Configuration;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.IO;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System.Configuration;

&lt;SPAN class=kwrd&gt;namespace&lt;/SPAN&gt; SodaBlue.Utility
{
  &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; Cryptography
  {
    &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; EncryptAESToBase64(&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; dataToEncrypt)
    {
      &lt;SPAN class=rem&gt;//Get the decryption key from the machine key section of the web.config&lt;/SPAN&gt;
      MachineKeySection machineKey = (MachineKeySection)ConfigurationManager.GetSection(&lt;SPAN class=str&gt;"system.web/machineKey"&lt;/SPAN&gt;);
      &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; key = machineKey.DecryptionKey;
      &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[] keyBytes = UTF8Encoding.UTF8.GetBytes(key);
      Rfc2898DeriveBytes rfc = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Rfc2898DeriveBytes(key, keyBytes, 1000);

      &lt;SPAN class=rem&gt;// Use the AES managed encryption provider&lt;/SPAN&gt;
      AesManaged encryptor = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; AesManaged();
      encryptor.Key = rfc.GetBytes(16);
      encryptor.IV = rfc.GetBytes(16);

      &lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; (MemoryStream ms = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; MemoryStream())
      {
        &lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; (CryptoStream encrypt = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
        {
          &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[] dataBytes = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; UTF8Encoding(&lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;).GetBytes(dataToEncrypt);
          encrypt.Write(dataBytes, 0, dataBytes.Length);
          encrypt.FlushFinalBlock();
          encrypt.Close();
          &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; Convert.ToBase64String(ms.ToArray());
        }
      }
    }

    &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; DecryptAESFromBase64(&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; dataToDeCrypt)
    {
      &lt;SPAN class=rem&gt;//Get the decryption key from the machine key section of the web.config&lt;/SPAN&gt;
      MachineKeySection machineKey = (MachineKeySection)ConfigurationManager.GetSection(&lt;SPAN class=str&gt;"system.web/machineKey"&lt;/SPAN&gt;);
      &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; key = machineKey.DecryptionKey;
      &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[] keyBytes = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; UTF8Encoding(&lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;).GetBytes(key);
      Rfc2898DeriveBytes rfc = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; Rfc2898DeriveBytes(key, keyBytes, 1000);

      AesManaged decryptor = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; AesManaged();
      decryptor.Key = rfc.GetBytes(16);
      decryptor.IV = rfc.GetBytes(16);

      &lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; (MemoryStream ms = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; MemoryStream())
      {
        &lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; (CryptoStream decrypt = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
        {
          &lt;SPAN class=kwrd&gt;byte&lt;/SPAN&gt;[] dataBytes = Convert.FromBase64String(dataToDeCrypt);
          decrypt.Write(dataBytes, 0, dataBytes.Length);
          decrypt.FlushFinalBlock();
          decrypt.Close();

          &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; UTF8Encoding(&lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;).GetString(ms.ToArray());
        }
      }
    }

  }
}
&lt;/PRE&gt;
&lt;P&gt;And a simple unit test to validate we can encrypt and decrypt&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; System;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; NUnit.Framework;
&lt;SPAN class=kwrd&gt;using&lt;/SPAN&gt; sbCommunity.Core.Infrastructure;

&lt;SPAN class=kwrd&gt;namespace&lt;/SPAN&gt; sbCommunity.UnitTests
{
  [TestFixture]
  &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; CryptographyTest
  {
    [Test]
    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; TestEncrypt()
    {
      &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; cTest = &lt;SPAN class=str&gt;"Now is the time for all good men to come to the aid of our countries"&lt;/SPAN&gt;;
      &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; encrypted = Cryptography.EncryptAESToBase64(cTest);
      &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; decrypted = Cryptography.DecryptAESFromBase64(encrypted);
      Assert.AreEqual(cTest, decrypted);
    }
  }
}
&lt;/PRE&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6704148" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/stevesheldon/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/stevesheldon/archive/tags/Crypotgraphy/default.aspx">Crypotgraphy</category><category domain="http://weblogs.asp.net/stevesheldon/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>A Method to Handle Audit Fields in LINQ to SQL</title><link>http://weblogs.asp.net/stevesheldon/archive/2008/02/23/a-method-to-handle-audit-fields-using-linq-to-sql.aspx</link><pubDate>Sun, 24 Feb 2008 01:27:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5847932</guid><dc:creator>sodablue</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/stevesheldon/rsscomments.aspx?PostID=5847932</wfw:commentRss><comments>http://weblogs.asp.net/stevesheldon/archive/2008/02/23/a-method-to-handle-audit-fields-using-linq-to-sql.aspx#comments</comments><description>&lt;P mce_keep="true"&gt;Subsonic has this convention where it&amp;nbsp;does this automatically for you, if&amp;nbsp;the table had columns CreatedOn, CreatedBy, ModifiedOn, ModifiedBy.&amp;nbsp;DLINQ doesn't really have anything like this built-in.&amp;nbsp;&amp;nbsp;This isn't something&amp;nbsp;one wishes to do manually, as to remember to update these columns every time you save something would be&amp;nbsp;prone to forgetfulness as well as being a lot of extra typing.&amp;nbsp; So how might we wire up something similar to what SubSonic does?&lt;/P&gt;
&lt;P mce_keep="true"&gt;I did a few searches on the internet, and while I found a couple of suggestions I didn't find an easy solution.&amp;nbsp; One suggestion was to extend the partial methods of the DataContext for Insert and Update.&amp;nbsp; This worked, but it means for every entity in your model you have to extend Insert and Update.&amp;nbsp; Fairly quickly you have several dozen of these things and you notice they're all doing the same thing.&amp;nbsp; Another suggestion involved extending SubmitChanges() in the DataContext, but it was rather complicated and relied upon reflecting upon the properties of the class to check if they had the right keywords in them set them appropriately.&amp;nbsp; I don't want to do reflection if I can otherwise avoid it.&lt;/P&gt;
&lt;P mce_keep="true"&gt;What if we used our own convention?&amp;nbsp; Our tables use the same audit field names, just like with Subsonic.&amp;nbsp; When we pull the tables into the LINQ to SQL class builder, it creates all of our entity classes for us with properties for those fields.&amp;nbsp; Since the classes are partials, we can also extend them and claim they implement a common interface.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Examples are in C#, and you'll need to remember to&amp;nbsp;create the interfaces and&amp;nbsp;classes in the appropriate namespaces.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;First, we create an interface to define our contract. We create an IAuditable interface with properties for our audit fields.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;STYLE type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}

.csharpcode pre { margin: 0em; }

.csharpcode .rem { color: #008000; }

.csharpcode .kwrd { color: #0000ff; }

.csharpcode .str { color: #006080; }

.csharpcode .op { color: #0000c0; }

.csharpcode .preproc { color: #cc6633; }

.csharpcode .asp { background-color: #ffff00; }

.csharpcode .html { color: #800000; }

.csharpcode .attr { color: #ff0000; }

.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}

.csharpcode .lnum { color: #606060; }
&lt;/STYLE&gt;
&lt;PRE class=csharpcode&gt;    &lt;SPAN class=kwrd&gt;internal&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;interface&lt;/SPAN&gt; IAuditable
    {
        &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; CreatedBy { get; set; }
        DateTime CreatedOn { get; set; }
        &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; ModifiedBy { get; set; }
        DateTime ModifiedOn { get; set; }
    }&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;Now, we extend the classes created by LINQ to SQL, and note that they implement our interface.&amp;nbsp; This is relatively easy to do as they were partial classes.&amp;nbsp;The properties should already be in the classes as they were created by LINQ to SQL based on our table definitions.&amp;nbsp; Here I just use a couple of example table classes, you'll need to remember to add the same syntax for each table as you add it to LINQ to SQL.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;PRE class=csharpcode&gt;    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;partial&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Calendar : IAuditable
    {
    }

    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;partial&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Photo : IAuditable
    {
    }

    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;partial&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Content : IAuditable
    {
    }

    &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;partial&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Discussion : IAuditable
    {
    }
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;Now, we override SubmitChanges in our DataContext.&amp;nbsp; I have it call a routine which updates the auditfields, passing in the list of all objects being managed by the datacontext.&amp;nbsp; It's nice that the DataContext method GetChangeSet() has lists for Inserts or Updates.&amp;nbsp; I'm using a utility class to perform the work.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;PRE class=csharpcode&gt;        &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;override&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; SubmitChanges(System.Data.Linq.ConflictMode failureMode)
        {
            AuditUtility.ProcessInserts(&lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.GetChangeSet().Inserts);
            AuditUtility.ProcessUpdates(&lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.GetChangeSet().Updates);
            
            &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.SubmitChanges(failureMode);
        }
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;And then finally our AuditUtility class.&amp;nbsp; Basically, it iterates through the list, checks to see if the object implements the IAuditable interface we created, and if so sets the auditfields.&amp;nbsp; This allows us to have tables which don't have audit fields, in which case they are simple ignored. I have a GetUserName() method inside that tries to identify the authenticated user whether it's web or local windows context, although this may need to be modified to handle the specifics of your app.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;PRE class=csharpcode&gt;    &lt;SPAN class=kwrd&gt;internal&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; AuditUtility
    {
        &lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; GetUserName()
        {
            &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; userName = &lt;SPAN class=str&gt;""&lt;/SPAN&gt;;
            &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (System.Web.HttpContext.Current != &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;)
                userName = System.Web.HttpContext.Current.User.Identity.Name;
            &lt;SPAN class=kwrd&gt;else&lt;/SPAN&gt;
                userName = Environment.UserName;

            &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; userName;
        }

        &lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; ProcessAuditFields(IList&amp;lt;System.Object&amp;gt; list, &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; UpdateCreatedFields)
        {
            &lt;SPAN class=kwrd&gt;foreach&lt;/SPAN&gt; (var item &lt;SPAN class=kwrd&gt;in&lt;/SPAN&gt; list)
            {
                IAuditable entity = item &lt;SPAN class=kwrd&gt;as&lt;/SPAN&gt; IAuditable;
                &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (entity != &lt;SPAN class=kwrd&gt;null&lt;/SPAN&gt;)
                {
                    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (UpdateCreatedFields)
                    {
                        entity.CreatedBy = GetUserName();
                        entity.CreatedOn = DateTime.Now;
                    }
                
                    entity.ModifiedBy = GetUserName();
                    entity.ModifiedOn = DateTime.Now;
                }
            }
        }

        &lt;SPAN class=kwrd&gt;internal&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; ProcessInserts(IList&amp;lt;System.Object&amp;gt; list)
        {
            ProcessAuditFields(list, &lt;SPAN class=kwrd&gt;true&lt;/SPAN&gt;);
        }

        &lt;SPAN class=kwrd&gt;internal&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; ProcessUpdates(IList&amp;lt;System.Object&amp;gt; list)
        {
            ProcessAuditFields(list, &lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;);
        }

    }&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;I hope that this technique can be of some use to others, and would value any feedback on how to make it work better.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5847932" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/stevesheldon/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://weblogs.asp.net/stevesheldon/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/stevesheldon/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Good Afternoon</title><link>http://weblogs.asp.net/stevesheldon/archive/2008/01/23/good-afternoon.aspx</link><pubDate>Wed, 23 Jan 2008 16:58:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5640285</guid><dc:creator>sodablue</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/stevesheldon/rsscomments.aspx?PostID=5640285</wfw:commentRss><comments>http://weblogs.asp.net/stevesheldon/archive/2008/01/23/good-afternoon.aspx#comments</comments><description>&lt;P mce_keep="true"&gt;I want to thank Joe Stagner for his invitation for people to blog at the asp.net site.&amp;nbsp; I feel like an AOL&amp;nbsp;n00b joing usenet back in '94.&lt;/P&gt;
&lt;P mce_keep="true"&gt;By day I work for a financial services company supporting an asp.net website with Microsoft Analysis Services on the backend.&amp;nbsp; By night, I've been spending my time most recently creating a personal project with the ASP.NET MVC framework CTP, LINQ and anything .Net 3.5, and I hope to write about things here as I discover them.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5640285" width="1" height="1"&gt;</description></item></channel></rss>
