<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DataBatrix &#187; .NET 2.0</title>
	<atom:link href="http://www.databatrix.com/category/net-2-0/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.databatrix.com</link>
	<description>The workings of Eric Bridges</description>
	<lastBuildDate>Thu, 01 Dec 2011 23:47:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.3</generator>
		<item>
		<title>Populate TreeView From Custom Object Using Serializer</title>
		<link>http://www.databatrix.com/2010/12/populate-treeview-from-custom-object-using-serializer/</link>
		<comments>http://www.databatrix.com/2010/12/populate-treeview-from-custom-object-using-serializer/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 17:40:41 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[.NET 3.5]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[Serialize]]></category>
		<category><![CDATA[TreeView]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=321</guid>
		<description><![CDATA[From time to time I need to spit out the public properties of an object for various reasons.  A typical use would be to show user friendly results from a web service that returns a complex object.  There could be tons of other uses!  After doing this a few times, I finially decided to post [...]]]></description>
			<content:encoded><![CDATA[<p>From time to time I need to spit out the public properties of an object for various reasons.  A typical use would be to show user friendly results from a web service that returns a complex object.  There could be tons of other uses!  After doing this a few times, I finially decided to post this so I can always reference it.  Anytime I do any recursive methods, it always takes me a couple of tweaks before getting it right.</p>
<p>The idea is that I have a custom object that I need to spin through to populate a <span style="color: #0000ff;">TreeView</span>.  I created a couple of simple methods to do such.  I though about using <span style="color: #0000ff;">Reflection</span>, but my method starting getting larger and larger because I was having to put in special code to handle certain Types (i.e. <span style="color: #0000ff;">String</span>, <span style="color: #0000ff;">ICollection</span>, etc).  Since my typical Use Case was to spit out the results of a complex object returned from a ASMX or WCF service, I decided to go the Serialize route.  My DTO class was typically already decorated with the [<span style="color: #008080;">Serializable</span>] attribute, if not, it was simple enought to add.</p>
<p>So first we serialize the object into a string of XML, then stuff that into a XmlDocument.  Then you can loop through the elements while creating each <span style="color: #0000ff;">TreeViewNode</span>.  That&#8217;s it!</p>
<pre class="brush:csharp">        public void PopulateTreeView(object obj, TreeView tv)
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
            System.Text.StringBuilder sb = new System.Text.StringBuilder();  // StringBuilder to hold the XML
            using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(sb))
            {
                serializer.Serialize(writer, obj); // Serialize the object to XML
                System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
                xDoc.LoadXml(sb.ToString());  // Shove it in a XmlDocument
                tv.Nodes.Add(PopulateNode(xDoc));  // Add the Nodes to the TreeView
            }
        }

        public TreeNode PopulateNode(System.Xml.XmlNode node)
        {
            TreeNode treenode = new TreeNode(node.Name);  // Add the Name to the Node
            if (node.ChildNodes.Count == 1) //Prevents ParentNode from displaying all of the InnerText
                treenode.Text += "=" + node.InnerText; // If only 1 ChildNode then add the InnerText

            for (int i = 0; i &lt; node.ChildNodes.Count; i++)
            {
                if (node.ChildNodes[i].HasChildNodes)
                {
                    treenode.ChildNodes.Add(PopulateNode(node.ChildNodes[i]));
                }
            }
            return treenode;
        }</pre>
<p>Then call the method to populate where &#8220;customObject&#8221; is the object you want displayed in your TreeView:</p>
<pre class="brush:csharp">            PopulateTreeView(customObject, TreeView1);</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2010/12/populate-treeview-from-custom-object-using-serializer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Automatically Add RequiredFieldValidator to TextBox Controls</title>
		<link>http://www.databatrix.com/2010/11/automatically-add-requiredfieldvalidator-to-textbox-controls/</link>
		<comments>http://www.databatrix.com/2010/11/automatically-add-requiredfieldvalidator-to-textbox-controls/#comments</comments>
		<pubDate>Sat, 13 Nov 2010 14:56:55 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[.NET 3.5]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[RequiredFieldValidator]]></category>
		<category><![CDATA[ValidatorCalloutExtender]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=274</guid>
		<description><![CDATA[If you are like me, you hate having to create the required field validators for a bunch of TextBox controls.  Even more if you are adding Ajax ValidatorCallout controls to all of them.  Sure, you could create another server control to extent the Textbox to automatically include this&#8230;but here is a simple alternative. I created [...]]]></description>
			<content:encoded><![CDATA[<p>If you are like me, you hate having to create the required field validators for a bunch of TextBox controls.  Even more if you are adding Ajax ValidatorCallout controls to all of them.  Sure, you could create another server control to extent the Textbox to automatically include this&#8230;but here is a simple alternative.</p>
<p>I created a method that cycles through all of the controls and checks to see if it has the attribute &#8220;Required&#8221;, and if so, then add the RequiredFieldValidator and Ajax callout controls automatically. You could obviously expand on this to meet your specific needs.<br />
Here is how you would markup your TextBox control:<br />
&lt;asp:TextBox Required=&#8221;true&#8221; ValidationGroup=&#8221;valGroup&#8221; ID=&#8221;TextBox1&#8243; runat=&#8221;server&#8221; /&gt;<br />
<br />
Here is the method in the code behind:</p>
<pre class="brush:csharp">private void AddRequiredValidations(ControlCollection controls)
{
    List requiredValidators = new List();
    for (int i = 0; i &lt; controls.Count; i++)
    {
        if (controls[i] is TextBox)
        {
            TextBox tb = (TextBox)controls[i];
            if (tb.Attributes["Required"] != null &amp;&amp; Convert.ToBoolean(tb.Attributes["Required"]))
            {
                RequiredFieldValidator requiredValidator = new RequiredFieldValidator();
                requiredValidator.ErrorMessage = "Required";
                requiredValidator.ID = "required" + tb.ID;
                requiredValidator.Display = ValidatorDisplay.None;
                requiredValidator.ValidationGroup = tb.ValidationGroup;
                requiredValidator.ControlToValidate = tb.ID;
                // Add the RequiredFieldValidator to a list to be added later
                // Since we can't add them to the control as we are cycling through them
                requiredValidators.Add(requiredValidator); 

                tb.CausesValidation = true;
            }
        }

        if (controls[i].HasControls()) // If this control has child controls
        {
            AddRequiredValidations(controls[i].Controls); // Search the child controls too
        }
    }

    // Now we can actually add the RequiredFieldValidators since we are done cycling through the existing controls
    for (int i = 0; i &lt; requiredValidators.Count; i++)
    {

        AjaxControlToolkit.ValidatorCalloutExtender callout = new AjaxControlToolkit.ValidatorCalloutExtender();
        callout.TargetControlID = requiredValidators[i].ID;
        callout.ID = requiredValidators[i].ID + "Callout";
        controls.Add(requiredValidators[i]);
        controls.Add(callout);
    }
}</pre>
<p>Then all you have to do is call it in your Page_Load() method:</p>
<pre class="brush:csharp">AddRequiredValidations(this.Controls);</pre>
<p>
This will work not only for a singe TextBox control, but also for TextBox controls buried inside a GridView or Repeater!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2010/11/automatically-add-requiredfieldvalidator-to-textbox-controls/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ListSearchExtender not finding some numeric values</title>
		<link>http://www.databatrix.com/2010/11/listsearchextender-not-finding-some-numeric-values/</link>
		<comments>http://www.databatrix.com/2010/11/listsearchextender-not-finding-some-numeric-values/#comments</comments>
		<pubDate>Wed, 10 Nov 2010 17:20:26 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[.NET 3.5]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[IsSorted]]></category>
		<category><![CDATA[ListSearchExtender]]></category>
		<category><![CDATA[numeric]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=265</guid>
		<description><![CDATA[I was working on a project when I noticed something strange with my ListSearchExtender.  This was happening on 2 different controls.  One ListSearchExtender was extending a ListBox and another was on a DropDown.  Both of these controls were populated with mostly numeric values (ID numbers) sorted in order ascending order.  The DropDown box was populated [...]]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste">I was working on a project when I noticed something strange with my ListSearchExtender.  This was happening on 2 different controls.  One ListSearchExtender was extending a ListBox and another was on a DropDown.  Both of these controls were populated with mostly numeric values (ID numbers) sorted in order ascending order.  The DropDown box was populated with about 1200 ID numbers while the ListBox was populated with about 600 ID numbers along with a small description of each item.  I was using the ListSearchExtender so that the user could easily jump to a specific item if they already knew the ID number.  The proplem I was having was that the ListSearchExtender did not find and jump to certain ID numbers even though they were in the list.  Particularly this seem to happen when the ID number started with the number one (1).  For example, let&#8217;s say the ListBox/DropDown contained these values:</div>
<div id="_mcePaste">23</div>
<div id="_mcePaste">45</div>
<div id="_mcePaste">89</div>
<div id="_mcePaste">101</div>
<div id="_mcePaste">109</div>
<div id="_mcePaste">111</div>
<div id="_mcePaste">140</div>
<div id="_mcePaste">204</div>
<div id="_mcePaste">226</div>
<div id="_mcePaste">1005</div>
<div id="_mcePaste">Using the ListSearchExtender extender, I would not find 101 or 109.  Below is the markup for the ListSearchExtender:</div>
<pre class="brush:html">&lt;ajax:ListSearchExtender ID="lseAjaxDdlFilter" runat="server" TargetControlID="ddlFilter" IsSorted="true" PromptPosition="Top" /&gt;</pre>
<div id="_mcePaste">I discovered that the root of my problem was <strong>IsSorted=&#8221;true&#8221;</strong>.  Since my data was already sorted I had set this value to true to increase the performance.  I am guessing the ListSearchExtender IsSorted property is assuming the sort is by text/string instead of treating them as integers.  The same list above sorted as text would be in this order: 1005, 101, 109, 111, 140, 204, 226, 23, 45, 89.  This would throw off the functionality.  So I set <strong>IsSorted=&#8221;false&#8221;</strong> and everything works as it should!</div>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2010/11/listsearchextender-not-finding-some-numeric-values/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>IE: scrollTop Not Working As Expected</title>
		<link>http://www.databatrix.com/2010/08/ie-scrolltop-not-working-as-expected/</link>
		<comments>http://www.databatrix.com/2010/08/ie-scrolltop-not-working-as-expected/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 02:04:10 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[.NET 3.5]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[div]]></category>
		<category><![CDATA[overflow]]></category>
		<category><![CDATA[scrollTop]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=254</guid>
		<description><![CDATA[I banged my head on this one for a couple of days.  Still got a defect out of the deal, but finally got it working.  I had an ajax tabcontainer with several tabs.  In some of these tabs was GridView.  I had overflow set on a DIV that the GridView was placed in so that [...]]]></description>
			<content:encoded><![CDATA[<p>I banged my head on this one for a couple of days.  Still got a defect out of the deal, but finally got it working.  I had an ajax tabcontainer with several tabs.  In some of these tabs was GridView.  I had overflow set on a DIV that the GridView was placed in so that I would get vertical scrollbars within the page.  The issue was that I needed to keep the position of the DIV scroll on a postback.  Should not have been an issue since I have the exact same scenario on another page within the same website which work perfectly.  But for some reason, using the same code, it would not work on this particular page.  Both pages use MasterPages, tabcontainers, and a little javascript and cookies to save the scroll position.</p>
<p>When debugging the issue, I would find that it would save and get the correct scroll position from the cookie; however, when setting the scrollTop:</p>
<pre class="brush:javascript">document.getElementById('myDiv').scrollTop = scrollPosition;</pre>
<p>It would not set.  The DIV&#8217;s scrollTop would be 0 before and after the statement above even after verifying that scrollPosition had an actual value!</p>
<p>I will also mention that the grid did have a decent about of data.  Actually, enough to make the page size about 3.5 MBs by the time HTML was rendered&#8230;almost 1 MB taken up by ViewState alone!  Because of AJAX and the amount of data in the grid, there was a noticeable amount of lag when using the page&#8230;not a lot, but noticeable.</p>
<p>Work Around:</p>
<p>I started to wonder if the above javascript (which ran on window.onload) may be running too quickly&#8230;or rather, ran before IE could finish with the rest of the AJAX/javascript code on the page.  So I tried this line instead of the one above:</p>
<pre class="brush:javascript">setTimeout(function() { document.getElementById('myDiv').scrollTop = scrollPosition; }, 250);</pre>
<p>So basically, I wanted to wait 250 milliseconds before setting the scrollTop.  Much to my surprise, this worked!  By this point I was too exhausted to keep knocking down the delay to see how low it could go and still work.  I couldn&#8217;t really notice the 250 delay in setting the scroll position, so that is where I ended.</p>
<p>Your mileage may vary, but in case you have a similar issue&#8230;try a small delay when setting the scrollTop before attempting to re-engineer the whole page.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2010/08/ie-scrolltop-not-working-as-expected/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>.NET Serialization: Binary, SOAP, and XML (VB)</title>
		<link>http://www.databatrix.com/2009/10/net-serialization-binary-soap-and-xml-vb/</link>
		<comments>http://www.databatrix.com/2009/10/net-serialization-binary-soap-and-xml-vb/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 23:43:50 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[.NET 3.5]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Binary]]></category>
		<category><![CDATA[Serialization]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=227</guid>
		<description><![CDATA[In .NET when you need to shrink an object into a more portable format you have 3 choices.  Binary, SOAP, or XML.  The process of shrinking and expanding the object is called serialization and deserialization.  Each option has it&#8217;s own advantages which I will explain. Binary You can serialize an object into binary format quite [...]]]></description>
			<content:encoded><![CDATA[<p>In .NET when you need to shrink an object into a more portable format you have 3 choices.  Binary, SOAP, or XML.  The process of shrinking and expanding the object is called serialization and deserialization.  Each option has it&#8217;s own advantages which I will explain.</p>
<h2>Binary</h2>
<p>You can serialize an object into binary format quite easily using the .NET Framework.  This is the quickest and smallest way to serialize; however, the binary format can only be deserialized using the same .NET Framework.  This may be a problem for interoperability.  It must be noted that this format will serialize Public and Private members (unlike XML serialization).</p>
<p>The example below shows how to serialize an object called &#8220;newCustomer&#8221;:</p>
<pre class="brush:vb">        Dim newCustomer As Contact = GetSampleContact()

        Using fs As New IO.FileStream(filePathandName &amp; ".bin", IO.FileMode.Create)
            Dim binFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
            binFormatter.Serialize(fs, newCustomer)
        End Using</pre>
<p>And here is the reverse to deserialize:</p>
<pre class="brush:vb">        Dim readCustomer As Contact

        Using fs As New IO.FileStream(filePathandName &amp; ".bin", IO.FileMode.Open, IO.FileAccess.Read)
            Dim binFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
            readCustomer = CType(binFormatter.Deserialize(fs), Contact)
        End Using</pre>
<h2>SOAP</h2>
<p>SOAP is another method.  This is similar to the binary method except the serialized data is stored in a standardized form (SOAP) which will easily allow interoperability.  Public and Private members are serialized using this method as well.<br />
To serialize:</p>
<pre class="brush:vb">        Dim newCustomer As Contact = GetSampleContact()
        Using fs As New IO.FileStream(filePathandName &amp; "SOAP.xml", IO.FileMode.Create)
            Dim soapFormattter As New Runtime.Serialization.Formatters.Soap.SoapFormatter()
            soapFormattter.Serialize(fs, newCustomer)
        End Using</pre>
<p>And to deserialize:</p>
<pre class="brush:vb">        Dim readCustomer As Contact
        Using fs As New IO.FileStream(filePathandName &amp; "SOAP.xml", IO.FileMode.Open, IO.FileAccess.Read)
            Dim soapFormattter As New Runtime.Serialization.Formatters.Soap.SoapFormatter()
            readCustomer = CType(soapFormattter.Deserialize(fs), Contact)
        End Using</pre>
<h2>XML</h2>
<p>A third choice is using the XMLSerializer class.  This method will only serialize Public properties and members and the object must be marked with the Serializable attribute and contain an empty constructor.  This method of serialization will be smaller in size than the SOAP method since less information is serialized.  Here is an example of such class:</p>
<pre class="brush:vb">     &lt;Serializable()&gt; Class Contact

        Private _FirstName As String
        Public Property FirstName() As String
            Get
                Return _FirstName
            End Get
            Set(ByVal value As String)
                _FirstName = value
            End Set
        End Property

        Private _LastName As String
        Public Property LastName() As String
            Get
                Return _LastName
            End Get
            Set(ByVal value As String)
                _LastName = value
            End Set
        End Property

        Private _MiddleI As String
        Public Property MiddleI() As String
            Get
                Return _MiddleI
            End Get
            Set(ByVal value As String)
                _MiddleI = value
            End Set
        End Property

        Private _PIN As String
        Public WriteOnly Property PIN() As String
            Set(ByVal value As String)
                _PIN = value
            End Set
        End Property

        Sub New()

        End Sub

        Sub New(ByVal fName As String, ByVal middleI As String, ByVal lName As String, ByVal p As String)
            _FirstName = fName
            _MiddleI = middleI
            _LastName = lName
            _PIN = p
        End Sub
    End Class</pre>
<p>Here is how you would serialize using the XMLSerializer:</p>
<pre class="brush:vb">        Dim newCustomer As Contact = GetSampleContact()
        Using fs As New IO.FileStream(filePathandName &amp; ".xml", IO.FileMode.Create)
            Dim xmlFormatter As New Xml.Serialization.XmlSerializer(GetType(Contact))
            xmlFormatter.Serialize(fs, newCustomer)
        End Using</pre>
<p>And to deserialize:</p>
<pre class="brush:vb">        Dim readCustomer As Contact
        Using fs As New IO.FileStream(filePathandName &amp; ".xml", IO.FileMode.Open, IO.FileAccess.Read)
            Dim xmlFormatter As New Xml.Serialization.XmlSerializer(GetType(Contact))
            readCustomer = CType(xmlFormatter.Deserialize(fs), Contact)
        End Using</pre>
<p><img class="alignnone size-full wp-image-232" title="Serialization Demo" src="http://www.databatrix.com/wp-content/uploads/2009/10/Serialization.JPG" alt="Serialization Demo" width="505" height="336" /></p>
<p>You can download a sample serialization demo project that I created to demonstrate: <a title="Serialization Demo Project.zip" href="http://www.databatrix.com/wp-content/uploads/2009/10/SerializationDemo.zip">SerializationDemoProject.zip</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2009/10/net-serialization-binary-soap-and-xml-vb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JobTime: Time Clock Web Application And Job Cost Tracking</title>
		<link>http://www.databatrix.com/2009/09/jobtime-time-clock-web-application-and-job-cost-tracking/</link>
		<comments>http://www.databatrix.com/2009/09/jobtime-time-clock-web-application-and-job-cost-tracking/#comments</comments>
		<pubDate>Sat, 05 Sep 2009 13:18:06 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Web Applications]]></category>
		<category><![CDATA[Payroll]]></category>
		<category><![CDATA[Timeclock]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=214</guid>
		<description><![CDATA[Background The company needed to track time logged to particular jobs/projects.  The initial idea was to use a site like ClickTime.  However, for an employee to log time against a job, you would need to tell ClickTime all of your jobs (which would be tedious) or configure an integration app to automatically populate the available [...]]]></description>
			<content:encoded><![CDATA[<h3>Background</h3>
<p>The company needed to track time logged to particular jobs/projects.  The initial idea was to use a site like <a href="http://www.clicktime.com/" target="_blank">ClickTime</a>.  However, for an employee to log time against a job, you would need to tell ClickTime all of your jobs (which would be tedious) or configure an integration app to automatically populate the available jobs/projects.</p>
<h3>Solution</h3>
<p>I created a web application that would allow employees to log time against jobs/projects.  It would search instantly against their project management software for a list of available jobs.  The type of work was categorized for reporting.  Since we would have the employee&#8217;s hours, it would be used for payroll.  I implemented an export feature for preparing the payroll information for ADP and EDH.  Work time for each project was then entered into the project management software to be calculated as job cost.  As a bonus, you could use the gathered data to calculate each employees &#8220;utilization&#8221;.</p>
<table border="0">
<tbody>
<tr>
<td>
<p><div id="attachment_217" class="wp-caption alignnone" style="width: 160px"><a href="http://www.databatrix.com/wp-content/uploads/2009/09/MainScreen.JPG"><img class="size-thumbnail wp-image-217" title="MainScreen" src="http://www.databatrix.com/wp-content/uploads/2009/09/MainScreen-150x150.jpg" alt="Landing page." width="150" height="150" /></a><p class="wp-caption-text">Landing page.</p></div></td>
<td>
<p><div id="attachment_216" class="wp-caption alignnone" style="width: 160px"><a href="http://www.databatrix.com/wp-content/uploads/2009/09/EnterTime.JPG"><img class="size-thumbnail wp-image-216" title="EnterTime" src="http://www.databatrix.com/wp-content/uploads/2009/09/EnterTime-150x150.jpg" alt="Enter time for a particular project/job." width="150" height="150" /></a><p class="wp-caption-text">Enter time for a particular project/job.</p></div></td>
</tr>
<tr>
<td>
<p><div id="attachment_215" class="wp-caption alignnone" style="width: 160px"><a href="http://www.databatrix.com/wp-content/uploads/2009/09/ApplyJobCost.JPG"><img class="size-thumbnail wp-image-215" title="ApplyJobCost" src="http://www.databatrix.com/wp-content/uploads/2009/09/ApplyJobCost-150x150.jpg" alt="Apply costs to each job." width="150" height="150" /></a><p class="wp-caption-text">Apply costs to each job.</p></div></td>
<td>
<p><div id="attachment_218" class="wp-caption alignnone" style="width: 160px"><a href="http://www.databatrix.com/wp-content/uploads/2009/09/PayRoll.JPG"><img class="size-thumbnail wp-image-218" title="PayRoll" src="http://www.databatrix.com/wp-content/uploads/2009/09/PayRoll-150x150.jpg" alt="Payroll export options." width="150" height="150" /></a><p class="wp-caption-text">Payroll export options.</p></div></td>
</tr>
<tr>
<td>
<p><div id="attachment_219" class="wp-caption alignnone" style="width: 160px"><a href="http://www.databatrix.com/wp-content/uploads/2009/09/Utilization.JPG"><img class="size-thumbnail wp-image-219" title="Utilization" src="http://www.databatrix.com/wp-content/uploads/2009/09/Utilization-150x150.jpg" alt="Utilization" width="150" height="150" /></a><p class="wp-caption-text">Utilization</p></div></td>
<td> </td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2009/09/jobtime-time-clock-web-application-and-job-cost-tracking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cross-thread operation not valid: .NET Cross Threading To Update Form Control</title>
		<link>http://www.databatrix.com/2009/09/cross-thread-operation-not-valid-net-cross-threading-to-update-form-control/</link>
		<comments>http://www.databatrix.com/2009/09/cross-thread-operation-not-valid-net-cross-threading-to-update-form-control/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 13:18:45 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[.NET 3.5]]></category>
		<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Cross-thread]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=204</guid>
		<description><![CDATA[So you get the &#8220;Cross-thread operation not valid&#8221; error because you are trying to update an object on your form from a thread. I am not going to try to &#8220;glamor&#8221; you (True Blood reference) with fundamentals of delegates, threading, etc. If that is what you are looking for, search Google and you will find [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_206" class="wp-caption alignleft" style="width: 466px"><a href="http://www.databatrix.com/wp-content/uploads/2009/09/CrossThread.JPG"><img class="size-full wp-image-206" title="Cross-thread operation not valid" src="http://www.databatrix.com/wp-content/uploads/2009/09/CrossThread.JPG" alt="Cross-thread operation not valid" width="456" height="256" /></a><p class="wp-caption-text">Cross-thread operation not valid</p></div>
<p>So you get the &#8220;Cross-thread operation not valid&#8221; error because you are trying to update an object on your form from a thread.  I am not going to try to &#8220;glamor&#8221; you (True Blood reference) with fundamentals of delegates, threading, etc.  If that is what you are looking for, search Google and you will find tons of references that are overly complicated using all of the proper terminology that typically makes my head hurt.  I WILL show you the few bits of code in Visual Basic that are needed to get around the error.  Or perhaps you just need to update a form control from a background process so the application does not hang.</p>
<p>In the example below, I am needing to update a ListBox control from a separate thread.  I need 2 items: a method to update the ListBox which takes a string as a parameter and a Delegate with a matching parameter signature.</p>
<p>Here is the Delegate:</p>
<pre class="brush: vb">Private Delegate Sub UpdateListboxDelegate(ByVal s As String)</pre>
<p>And here is the method that actually updates the ListBox:</p>
<pre class="brush: vb">Private Sub UpdateListbox(ByVal s As String)
   If Me.InvokeRequired Then
      Me.BeginInvoke(New UpdateListboxDelegate(AddressOf UpdateListbox), New Object() {s})
      Return
   End If
   ListBox1.Items.Add(s)
End Sub</pre>
<p>Here would be a sample of the main sub that is slow to process:</p>
<pre class="brush: vb">Public Sub LongProcess()
   For i As Integer = 0 To 100
      System.Threading.Thread.Sleep(5000)
      UpdateListbox("Currently on count: " &amp; i)
   Next
End Sub</pre>
<p>Now to kick off the thread:</p>
<pre class="brush: vb">ListBox1.Items.Clear()
Dim thread As New Threading.Thread(AddressOf LongProcess)
thread.Start()</pre>
<p>That&#8217;s it!  The easiest solution without getting overly complicated.</p>
<p><b>&#8230;and in case you are looking for C# (it&#8217;s growing on me too):</b></p>
<pre class="brush:csharp">
        private delegate void UpdateListboxDelegate(string s);

        private void UpdateListbox(string s)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new UpdateListboxDelegate(UpdateListbox), new object[] { s });
                return;
            }
            listBox1.Items.Add(s);
        }

        public void LongProcess()
        {
            for (int i = 0; i < 10; i++)
            {
                System.Threading.Thread.Sleep(1000);
                UpdateListbox("Currently on count: " + i.ToString());
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            System.Threading.Thread thread = new System.Threading.Thread(LongProcess);
            thread.Start();
        }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2009/09/cross-thread-operation-not-valid-net-cross-threading-to-update-form-control/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatic Email Alerts From Any SQL Query</title>
		<link>http://www.databatrix.com/2009/09/automatic-email-alerts-from-any-sql-query/</link>
		<comments>http://www.databatrix.com/2009/09/automatic-email-alerts-from-any-sql-query/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 13:24:40 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[Desktop Applications]]></category>
		<category><![CDATA[MS SQL]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=188</guid>
		<description><![CDATA[Problem Reminder emails were needed to be sent out to remind sales staff to follow up on projects. Solution I developed a simple command line executable that takes 1 parameter which is an XML file.  The contents of the XML file would look something like: &#60;?xml version="1.0" encoding="utf-8" ?&#62; &#60;Settings&#62; &#60;ErrorEmail&#62; &#60;Email&#62;email@gmail.com&#60;/Email&#62; &#60;/ErrorEmail&#62; &#60;SummaryEmail&#62; &#60;Email&#62;email@gmail.com&#60;/Email&#62; [...]]]></description>
			<content:encoded><![CDATA[<h3>Problem</h3>
<p>Reminder emails were needed to be sent out to remind sales staff to follow up on projects.</p>
<h3>Solution</h3>
<p>I developed a simple command line executable that takes 1 parameter which is an XML file.  The contents of the XML file would look something like:</p>
<pre class="brush: xml">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;Settings&gt;
	&lt;ErrorEmail&gt;
		&lt;Email&gt;email@gmail.com&lt;/Email&gt;
	&lt;/ErrorEmail&gt;
	&lt;SummaryEmail&gt;
		&lt;Email&gt;email@gmail.com&lt;/Email&gt;
	&lt;/SummaryEmail&gt;
	&lt;Query&gt;
		SELECT * FROM Projects
		WHERE Cancelled = 0 And Completed = 0 AND BookDate IS NULL
		AND FollowUpBy &lt;= getdate()
	&lt;/Query&gt;
	&lt;SQLConnectionString&gt;Server=SQLServer;Database=MainDatabase;Persist Security Info=True;Integrated Security=true&lt;/SQLConnectionString&gt;
	&lt;TemplateEmailFileName&gt;EmailTemplate.txt&lt;/TemplateEmailFileName&gt;
	&lt;EmailSubject&gt;Alert Email For Project#&lt;:ProjectID:&gt;&lt;/EmailSubject&gt;
	&lt;EmailDomain&gt;mycompany.com&lt;/EmailDomain&gt;
	&lt;ToAddressDatabaseField&gt;Salesperson&lt;/ToAddressDatabaseField&gt;
	&lt;ToAddressFieldIsEmail&gt;0&lt;/ToAddressFieldIsEmail&gt;
	&lt;SMTPSettings&gt;
		&lt;SMTPServer&gt;smtp.gmail.com&lt;/SMTPServer&gt;
		&lt;EnableSSL&gt;1&lt;/EnableSSL&gt;
		&lt;RequiresAuthentication&gt;1&lt;/RequiresAuthentication&gt;
		&lt;Username&gt;email@gmail.com&lt;/Username&gt;
		&lt;Password&gt;*******&lt;/Password&gt;
		&lt;Port&gt;587&lt;/Port&gt;
		&lt;FromAddress&gt;email@gmail.com&lt;/FromAddress&gt;
	&lt;/SMTPSettings&gt;
	&lt;LogFileDirectory&gt;Daily&lt;/LogFileDirectory&gt;
&lt;/Settings&gt;</pre>
<p>The command line executable would then run the query (&lt;Query&gt;) against the supplied database in the XML file.  For each row returned, the program will send out an email to the user.  Which user?  What email?  The recipients email address would need to be one of the fields returned from the query and noted in the XML file in the element &lt;ToAddressDatabaseField&gt;.  The template for the email body is supplied by the &lt;TemplateEmailFileName&gt; element.   To make the email custom, it is possible to insert fields returned from the database into the email template.  For example, lets say the query returned a field called &#8220;FirstName&#8221;.  In the email template text file, you could have:</p>
<pre>Hello &lt;:FirstName:&gt;,</pre>
<p>When the program ran, it would swap &#8220;&lt;:FirstName:&gt;&#8221; with the contents from the database.  This is similar to a mail merge for emails.  Since all of the values are configurable in the XML file, the usage possibilities are unlimited!  Let say you needed to run this once a week, no problem.  Set up a Windows Scheduled Task to run the executable at the specified interval.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2009/09/automatic-email-alerts-from-any-sql-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A .NET Bit.ly API Helper Class (Visual Basic.NET)</title>
		<link>http://www.databatrix.com/2009/08/a-net-bit-ly-api-helper-class-visual-basic-net/</link>
		<comments>http://www.databatrix.com/2009/08/a-net-bit-ly-api-helper-class-visual-basic-net/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 21:19:19 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[bit.ly]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=162</guid>
		<description><![CDATA[I decided to write a helper class for using the Bit.ly API for creating short urls.  You know, those tiny links that you see all over Facebook, Twitter, etc.  The snippet below shows how you would use the helper class.  Not only can you shorten an url, you can shorted multiple urls in a single [...]]]></description>
			<content:encoded><![CDATA[<p>I decided to write a helper class for using the Bit.ly API for creating short urls.  You know, those tiny links that you see all over Facebook, Twitter, etc.  The snippet below shows how you would use the helper class.  Not only can you shorten an url, you can shorted multiple urls in a single call as well as get stats and info about a bit.ly url.  If you are looking to incorporate bit.ly short urls in your application using their API access, this will save you some time.  The class uses the XmlSerializer for reading bit.ly&#8217;s response.</p>
<pre class="brush: vb">        ' Pass username and API key to instantiate
        Dim newbitlyAPI As New DataBatrix.bitlyAPI.bitlyAPI("bitlyapidemo", "R_0da49e0a9118ff35f52f629d2d71bf07")

        ' Sample of creating 1 short URL
        Dim shortenResponse As DataBatrix.bitlyAPI.bitlyShortenResponse = newbitlyAPI.Shorten("http://www.databatrix.com")
        Dim shortURL As String = ""
        If shortenResponse.results.Count &gt; 0 Then
            shortURL = shortenResponse.results(0).shortUrl
        End If

        ' Sample of creating multiple short URLs
        Dim longUrls() As String = {"http://www.databatrix.com", "http://www.google.com"}
        Dim shortenResponses As DataBatrix.bitlyAPI.bitlyShortenResponse = newbitlyAPI.Shorten(longUrls)
        Dim shortURLs(1) As String
        For i As Integer = 0 To shortenResponses.results.Count - 1
            shortURLs(i) = shortenResponses.results(i).shortUrl

        Next

        ' Sample of getting bit.ly info...
        Dim info As DataBatrix.bitlyAPI.bitlyInfoResponse = newbitlyAPI.Info("2bYgqR")

        ' Sample of getting bit.ly stats...
        Dim stats As DataBatrix.bitlyAPI.bitlyStatsResponse = newbitlyAPI.Stats("http://bit.ly/1RmnUT")</pre>
<p>Below is the helper class that I created.  You can download the VB file <a href="http://www.databatrix.com/wp-content/uploads/2009/08/bitlyAPI.vb">bitlyAPI.vb</a> or a sample project <a href="http://www.databatrix.com/wp-content/uploads/2009/08/TestBitly.zip">TestBitly Project Files</a>.</p>
<pre class="brush: vb">Imports System.Web
Imports System.Xml
Imports System.Xml.Serialization

Namespace DataBatrix.bitlyAPI
    Public Class bitlyAPI
        Const BaseAPIUrl As String = "http://api.bit.ly/"
        Const version As String = "2.0.1"
        Const format As String = "xml"

        Public login As String = String.Empty
        Public apiKey As String = String.Empty

        Sub New(ByVal login As String, ByVal apiKey As String)
            Me.login = login
            Me.apiKey = apiKey

        End Sub

        Private Function BuildBaseRequestURL(ByVal applicationName As String) As System.Text.StringBuilder
            Dim RequestUrl As New System.Text.StringBuilder()
            With RequestUrl
                .Append(BaseAPIUrl &amp; HttpUtility.UrlEncode(applicationName) &amp; "?")
                .Append("version=" &amp; HttpUtility.UrlEncode(version) &amp; "&amp;")
                .Append("format=" &amp; HttpUtility.UrlEncode(format) &amp; "&amp;")
                .Append("login=" &amp; HttpUtility.UrlEncode(login) &amp; "&amp;")
                .Append("apiKey=" &amp; HttpUtility.UrlEncode(apiKey) &amp; "&amp;")
            End With
            Return RequestUrl
        End Function

        Public Function Shorten(ByVal longUrl As String) As bitlyShortenResponse
            Dim logUrls() As String = {longUrl}
            Return Shorten(logUrls)
        End Function

        Public Function Shorten(ByVal longUrl() As String) As bitlyShortenResponse
            Dim RequestUrl As System.Text.StringBuilder = BuildBaseRequestURL("shorten")
            For Each s As String In longUrl
                RequestUrl.Append("&amp;longUrl=" &amp; HttpUtility.UrlEncode(s))

            Next
            Dim responseObj As DataBatrix.bitlyAPI.bitlyShortenResponse = Nothing
            Try
                Dim serializer = New XmlSerializer(GetType(DataBatrix.bitlyAPI.bitlyShortenResponse))
                Using reader As XmlTextReader = New XmlTextReader(RequestUrl.ToString())
                    responseObj = CType(serializer.Deserialize(reader), DataBatrix.bitlyAPI.bitlyShortenResponse)
                End Using

            Catch ex As Exception

            End Try

            If responseObj.errorCode &gt; 0 Then
                Throw New ApplicationException("Error from bit.ly: " &amp; responseObj.errorMessage)
            End If
            Return responseObj
        End Function
        Public Function Info(ByVal hash As String) As bitlyInfoResponse
            Dim RequestUrl As System.Text.StringBuilder = BuildBaseRequestURL("info")
            With RequestUrl
                .Append("hash=" &amp; HttpUtility.UrlEncode(hash))
            End With

            Dim responseObj As DataBatrix.bitlyAPI.bitlyInfoResponse = Nothing
            Try
                Dim serializer = New XmlSerializer(GetType(DataBatrix.bitlyAPI.bitlyInfoResponse))
                Using reader As XmlTextReader = New XmlTextReader(RequestUrl.ToString())
                    responseObj = CType(serializer.Deserialize(reader), DataBatrix.bitlyAPI.bitlyInfoResponse)
                End Using

            Catch ex As Exception
                Throw New ApplicationException("API Error: " &amp; ex.Message)
            End Try
            If responseObj.errorCode &gt; 0 Then
                Throw New ApplicationException("Error from bit.ly: " &amp; responseObj.errorMessage)
            End If
            Return responseObj
        End Function

        Public Function Stats(ByVal shortUrl As String) As bitlyStatsResponse
            Dim RequestUrl As System.Text.StringBuilder = BuildBaseRequestURL("stats")
            With RequestUrl
                .Append("shortUrl=" &amp; HttpUtility.UrlEncode(shortUrl))

            End With

            Dim responseObj As DataBatrix.bitlyAPI.bitlyStatsResponse = Nothing
            Try
                Dim serializer = New XmlSerializer(GetType(DataBatrix.bitlyAPI.bitlyStatsResponse))
                Using reader As XmlTextReader = New XmlTextReader(RequestUrl.ToString())
                    responseObj = CType(serializer.Deserialize(reader), DataBatrix.bitlyAPI.bitlyStatsResponse)
                End Using

            Catch ex As Exception
                Throw New ApplicationException("API Error: " &amp; ex.Message)
            End Try
            If responseObj.errorCode &gt; 0 Then
                Throw New ApplicationException("Error from bit.ly: " &amp; responseObj.errorMessage)
            End If
            Return responseObj
        End Function

    End Class

    Public MustInherit Class bitlyResponseBase
        &lt;Xml.Serialization.XmlElement("errorCode")&gt; _
        Public errorCode As Integer = 0

        &lt;Xml.Serialization.XmlElement("errorMessage")&gt; _
        Public errorMessage As String = String.Empty

        &lt;Xml.Serialization.XmlElement("statusCode")&gt; _
        Public statusCode As String = String.Empty

    End Class

    &lt;System.Serializable(), Xml.Serialization.XmlRoot("bitly")&gt; _
    Public Class bitlyShortenResponse
        Inherits bitlyResponseBase

        &lt;Xml.Serialization.XmlArray("results"), Xml.Serialization.XmlArrayItem("nodeKeyVal")&gt; _
        Public results As New List(Of KeyVal)

        Public Class KeyVal
            &lt;Xml.Serialization.XmlElement("userHash")&gt; _
             Public userHash As String

            &lt;Xml.Serialization.XmlElement("shortKeywordUrl")&gt; _
             Public shortKeywordUrl As String

            &lt;Xml.Serialization.XmlElement("hash")&gt; _
             Public hash As String

            &lt;Xml.Serialization.XmlElement("nodeKey")&gt; _
             Public longUrl As String

            &lt;Xml.Serialization.XmlElement("shortUrl")&gt; _
             Public shortUrl As String

        End Class
    End Class

    &lt;System.Serializable(), Xml.Serialization.XmlRoot("bitly")&gt; _
    Public Class bitlyInfoResponse
        Inherits bitlyResponseBase

        &lt;Xml.Serialization.XmlArray("results"), Xml.Serialization.XmlArrayItem("doc")&gt; _
        Public results As New List(Of bitlyInfoResultItem)

        Public Class bitlyInfoResultItem
            &lt;Xml.Serialization.XmlElement("shortenedByUser")&gt; _
            Public shortenedByUser As String
            &lt;Xml.Serialization.XmlElement("keywords")&gt; _
            Public keywords As String
            &lt;Xml.Serialization.XmlElement("hash")&gt; _
            Public hash As String
            &lt;Xml.Serialization.XmlElement("exif")&gt; _
            Public exif As String
            &lt;Xml.Serialization.XmlElement("surbl")&gt; _
            Public surbl As String
            &lt;Xml.Serialization.XmlElement("contentLength")&gt; _
            Public contentLength As String
            &lt;Xml.Serialization.XmlElement("id3")&gt; _
            Public id3 As String
            &lt;Xml.Serialization.XmlElement("calais")&gt; _
            Public calais As String
            &lt;Xml.Serialization.XmlElement("longUrl")&gt; _
            Public longUrl As String
            &lt;Xml.Serialization.XmlElement("version")&gt; _
            Public version As String
            &lt;Xml.Serialization.XmlElement("htmlMetaDescription")&gt; _
            Public htmlMetaDescription As String
            &lt;Xml.Serialization.XmlElement("htmlMetaKeywords")&gt; _
            Public htmlMetaKeywords As String
            &lt;Xml.Serialization.XmlElement("calaisId")&gt; _
            Public calaisId As String
            &lt;Xml.Serialization.XmlElement("thumbnail")&gt; _
            Public thumbnail As thumbnailObj
            &lt;Xml.Serialization.XmlElement("contentType")&gt; _
            Public contentType As String
            &lt;Xml.Serialization.XmlArray("users"), Xml.Serialization.XmlArrayItem("item")&gt; _
            Public users As List(Of String)
            &lt;Xml.Serialization.XmlElement("globalHash")&gt; _
            Public globalHash As String
            &lt;Xml.Serialization.XmlElement("htmlTitle")&gt; _
            Public htmlTitle As String
            &lt;Xml.Serialization.XmlElement("metacarta")&gt; _
            Public metacarta As String
            &lt;Xml.Serialization.XmlElement("mirrorUrl")&gt; _
            Public mirrorUrl As String
            &lt;Xml.Serialization.XmlElement("keyword")&gt; _
            Public keyword As String
            &lt;Xml.Serialization.XmlElement("calaisResolutions")&gt; _
            Public calaisResolutions As String
            &lt;Xml.Serialization.XmlElement("userHash")&gt; _
            Public userHash As String

            Public Class thumbnailObj
                &lt;Xml.Serialization.XmlElement("large")&gt; _
                Public large As String
                &lt;Xml.Serialization.XmlElement("small")&gt; _
                Public small As String
                &lt;Xml.Serialization.XmlElement("medium")&gt; _
                Public medium As String
            End Class

        End Class
    End Class

    &lt;System.Serializable(), Xml.Serialization.XmlRoot("bitly")&gt; _
Public Class bitlyStatsResponse
        Inherits bitlyResponseBase

        &lt;Xml.Serialization.XmlElement("hash")&gt; _
        Public hash As String
        &lt;Xml.Serialization.XmlElement("clicks")&gt; _
        Public clicks As String

        Public Class bitlyStatsResultItem
            &lt;Xml.Serialization.XmlElement("None")&gt; _
            Public None As String
            &lt;Xml.Serialization.XmlElement("direct")&gt; _
            Public direct As String
            &lt;Xml.Serialization.XmlArray("nodeKeyVal"), XmlArrayItem("nodeKeyVal")&gt; _
            Public nodeKeyValue As List(Of KeyValue)
            &lt;Xml.Serialization.XmlElement("nodeKey")&gt; _
            Public nodeKey As String

            Public Class KeyValue
                &lt;Xml.Serialization.XmlElement("nodeValue")&gt; _
            Public nodeValue As String
                &lt;Xml.Serialization.XmlElement("nodeKey")&gt; _
                Public nodeKey As String
            End Class
        End Class
    End Class

End Namespace</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2009/08/a-net-bit-ly-api-helper-class-visual-basic-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Replace with Regular Expressions in .NET</title>
		<link>http://www.databatrix.com/2009/08/custom-replace-with-regular-expressions-in-net/</link>
		<comments>http://www.databatrix.com/2009/08/custom-replace-with-regular-expressions-in-net/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 19:05:34 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[.NET 2.0]]></category>
		<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Regular Expressions]]></category>
		<category><![CDATA[Delegates]]></category>

		<guid isPermaLink="false">http://www.databatrix.com/?p=149</guid>
		<description><![CDATA[This is the second time I have had to do something like this.  So this time I am posting it for my reference.  Regular expressions are amazing and amazingly difficult to understand sometimes, but they come in very handy.  I was in a situation where I was going to need to  feed in a custom [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second time I have had to do something like this.  So this time I am posting it for my reference.  Regular expressions are amazing and amazingly difficult to understand sometimes, but they come in very handy.  I was in a situation where I was going to need to  feed in a custom template to be used similar to a &#8220;mail merge&#8221; situation.  I would query a database, then for each record I would fill out an email using an email template.  I decided to go with &lt;:FieldName:&gt; as the nomenclature of how a field would be inserted.  For example, here are the query results:</p>
<table border="0">
<tbody>
<tr>
<td>FirstName</td>
<td>LastName</td>
<td>Company</td>
</tr>
<tr>
<td>Eric</td>
<td>Bridges</td>
<td>DataBatrix</td>
</tr>
</tbody>
</table>
<p>My email template may look something like this:</p>
<pre>Dear &lt;:FirstName:&gt; &lt;:LastName:&gt;,</pre>
<pre>You work for &lt;:Company:&gt;!</pre>
<p>For the purpose of my project, I did not know what fields were going to be returned or what the email template looked like.  I needed a simple way to replace all of the field placeholders with actual data.  Regular expressions to the rescue!  You can use a delegate to run your own replace function.  I called my method MatchHandler which is passed a Match variable (the match that is found).  In my example below, I replaced it with the corresponding item from _reader (my sqldatareader row).</p>
<pre class="brush: vb">    Private Function MatchHandler(ByVal m As Match) As String
        Dim fieldName As String = m.Groups("fieldName").ToString()
        If HasField(fieldName) Then
            Return _reader(fieldName)
        Else
            Return m.ToString()
        End If
    End Function</pre>
<p>Next we have to create our delegate.  Delegates are basically pointers for methods (functions/subs).  I called my delegate &#8220;MatchDelegate&#8221; and pass it the address of my function I created above.</p>
<pre class="brush: vb">    Dim MatchDelegate As New MatchEvaluator(AddressOf MatchHandler)</pre>
<p>Now to make it work!  Define your regular expression pattern and instantiate a new RegularExpression object.  Use the Replace method and pass the string to search and the delegate that we created.</p>
<pre class="brush: vb">    Private Function MergeFields(ByVal body As String) As String
        Dim returnValue As String = ""
        Dim pattern As String = "&lt;:(?&lt;fieldName:&gt;(.+?)):&gt;"
        Dim regex As New Text.RegularExpressions.Regex(pattern)
        returnValue = regex.Replace(body, MatchDelegate)
        Return returnValue
    End Function</pre>
<p>That&#8217;s it!  Now you can do whatever you like when a match is found in your Replace method.</p>
<p>In case you were wondering what &#8220;(?&lt;fieldName:&gt;(.+?))&#8221; in the pattern was all about, check out <a href="http://www.regular-expressions.info/named.html" target="_blank">this link talking about regular expression groups</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.databatrix.com/2009/08/custom-replace-with-regular-expressions-in-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

