<?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/"
	>

<channel>
	<title>aaronkjackson.com</title>
	<atom:link href="http://www.aaronkjackson.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.aaronkjackson.com</link>
	<description>Life is simple and so is web development.</description>
	<pubDate>Tue, 24 Aug 2010 21:40:41 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Search and Replace &#8211; Text/HTML &#8211; DotNetNuke 5.5</title>
		<link>http://www.aaronkjackson.com/2010/08/search-and-replace-texthtml-dotnetnuke-55/</link>
		<comments>http://www.aaronkjackson.com/2010/08/search-and-replace-texthtml-dotnetnuke-55/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 21:38:47 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[DotNetNuke]]></category>

		<category><![CDATA[5.5]]></category>

		<category><![CDATA[module]]></category>

		<category><![CDATA[Text/HTML]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/08/search-and-replace-texthtml-dotnetnuke-55/</guid>
		<description><![CDATA[I couldn’t get the Engage: F3 module to work with DotNetnuke 5.5 due to a known issue.&#160; This issue will be fixed when Engage: F3 3.4 is released.&#160; However, if you need a quick fix until then you can use this script based on the F3 module.
WARNING:&#160; Backup your database before executing this script. The [...]]]></description>
			<content:encoded><![CDATA[<p>I couldn’t get the <a href="http://www.engagesoftware.com/Products/Modules/Engage_F3.aspx" target="_blank">Engage: F3 module</a> to work with DotNetnuke 5.5 due to a <a href="http://www.engagesoftware.com/Support/Forums/forumid/5/threadid/3883/scope/posts.aspx" target="_blank">known issue</a>.&#160; This issue will be fixed when Engage: F3 3.4 is released.&#160; However, if you need a quick fix until then you can use this script based on the F3 module.</p>
<p><font color="#ff0000"><strong>WARNING:&#160; Backup your database before executing this script. The script may affect every item published by the Text/HTML module and you will want to have a backup in case you make a mistake.</strong></font>&#160; </p>
<pre class="brush: sql;">DECLARE @portalId INT
DECLARE @searchValue NVARCHAR(100)
DECLARE @replaceValue NVARCHAR(100)

SET @portalId = 0
SET @searchValue = '/website/'
SET @replaceValue = '/'

DECLARE @PublishedContent TABLE (ItemId int)
INSERT INTO @PublishedContent (ItemId)
SELECT ht.ItemId
FROM [HtmlText] ht
WHERE ht.IsPublished = 1
  AND ht.LastModifiedOnDate = (SELECT MAX(LastModifiedOnDate) FROM [HtmlText] WHERE ModuleID = ht.ModuleID AND IsPublished = 1)

UPDATE [HtmlText]
SET Content = REPLACE(CAST(ht.Content AS NVARCHAR(MAX)), @searchValue, @replaceValue)
FROM [HtmlText] ht
 JOIN @PublishedContent pc ON (ht.ItemID = pc.ItemId)
 JOIN [vw_Modules] m ON (m.ModuleID = ht.ModuleID)
 JOIN [vw_Tabs] t ON (t.TabID = m.TabID)
 JOIN [vw_Portals] p ON (p.PortalID = t.PortalID)
WHERE ht.Content COLLATE SQL_Latin1_General_CP1_CS_AS LIKE '%' + REPLACE(REPLACE(@searchValue, '\', '\\'), '%', '\%') + '%' ESCAPE '\'
  AND (@portalId IS NULL OR m.PortalID = @portalId)</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/08/search-and-replace-texthtml-dotnetnuke-55/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Offsetting the time zone in MS SQL 2005</title>
		<link>http://www.aaronkjackson.com/2010/08/offsetting-the-time-zone-in-ms-sql-2005/</link>
		<comments>http://www.aaronkjackson.com/2010/08/offsetting-the-time-zone-in-ms-sql-2005/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 19:23:47 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[SQL]]></category>

		<category><![CDATA[time zone]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/08/offsetting-the-time-zone-in-ms-sql-2005/</guid>
		<description><![CDATA[I needed to offset the current time in MS SQL 2005 for a quick fix. I wanted to make sure the solution would not have to be maintained when daylight savings time changed. Taking the difference between the GETUTCDATE() and GETDATE() functions will generate the server’s current time zone offset from UTC time.
DECLARE @timezoneOffset INT
SELECT [...]]]></description>
			<content:encoded><![CDATA[<p>I needed to offset the current time in MS SQL 2005 for a quick fix. I wanted to make sure the solution would not have to be maintained when daylight savings time changed. Taking the difference between the GETUTCDATE() and GETDATE() functions will generate the server’s current time zone offset from UTC time.</p>
<pre class="brush: sql; gutter: false;">DECLARE @timezoneOffset INT
SELECT @timezoneOffset = (DATEDIFF(hh,GETDATE(),GETUTCDATE())) * -1;
SELECT DATEADD(hh, @timezoneOffset, GETUTCDATE()), GETDATE()</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/08/offsetting-the-time-zone-in-ms-sql-2005/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Silverlight 4 &#8211; Getting Started Plan</title>
		<link>http://www.aaronkjackson.com/2010/07/silverlight-4-getting-started-plan/</link>
		<comments>http://www.aaronkjackson.com/2010/07/silverlight-4-getting-started-plan/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 15:08:34 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[Web Development]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Silverlight]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/07/silverlight-4-getting-started-plan/</guid>
		<description><![CDATA[I have worked on a couple of small projects in Silverlight, but have never taken the opportunity to really understand the platform.&#160; There is a new project at the office that will be using Silverlight to create interactive dashboards, so it is now time to dive into the deep end of the Silverlight pool.&#160; 
Here [...]]]></description>
			<content:encoded><![CDATA[<p>I have worked on a couple of small projects in Silverlight, but have never taken the opportunity to really understand the platform.&#160; There is a new project at the office that will be using Silverlight to create interactive dashboards, so it is now time to dive into the deep end of the Silverlight pool.&#160; </p>
<p>Here is my learning plan.</p>
<p><b>1. </b><b><a href="http://www.silverlight.net/learn/videos/silverlight-videos/getting-started-with-silverlight-development/" target="_blank">Watch Getting Started with Silverlight Development</a>      <br /></b><b>     <br />2. </b><b><a href="http://www.silverlight.net/learn/quickstarts/" target="_blank">Silverlight QuickStart Tutorials</a></b>    <br />Start with “Beginning QuickStarts” tutorials 1 – 6 and then move on to “Working with Data QuickStarts” tutorials 1 – 3<b></b></p>
<p><strong>3.</strong> <b><a href="http://www.silverlight.net/learn/handsonlabs/" target="_blank">Silverlight 4 Hands On Labs</a></b></p>
<p>I find that my best learning comes from reviewing good code.&#160; I am looking for some sample source code that illustrates best practices and a quality Silverlight architecture.&#160; If anyone knows of a good example please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/07/silverlight-4-getting-started-plan/feed/</wfw:commentRss>
		</item>
		<item>
		<title>How to show an InfoWindow for multiple Markers using Google Maps v3</title>
		<link>http://www.aaronkjackson.com/2010/06/how-to-show-an-infowindow-for-multiple-markers-using-google-maps-v3/</link>
		<comments>http://www.aaronkjackson.com/2010/06/how-to-show-an-infowindow-for-multiple-markers-using-google-maps-v3/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 03:00:10 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[Web Development]]></category>

		<category><![CDATA[Google Maps]]></category>

		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/06/how-to-show-an-infowindow-for-multiple-markers-using-google-maps-v3/</guid>
		<description><![CDATA[Recently I have been working on an interactive map for the City of Aliso Viejo, CA using Google Maps.&#160;&#160; I chose to use version 3 of the Google Maps API, because version 2 was deprecated on May 19, 2010.&#160; I was happy to discover I no longer needed an API.&#160; However, I did not anticipate [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I have been working on an interactive map for the City of Aliso Viejo, CA using Google Maps.&#160;&#160; I chose to use version 3 of the Google Maps API, because version 2 was deprecated on May 19, 2010.&#160; I was happy to discover I no longer needed an API.&#160; However, I did not anticipate how the changes to the MVC framework affected things.&#160; My first task was to display multiple markers on a map, each marker having it’s own InfoWindow.&#160; I found plenty of v2 examples, but could not find a really good v3 example.&#160;&#160; Here is my solution to showing an InfoWindow for multiple markers using Google Maps v3.</p>
<p>In v2 GInfoWindow does not have a constructor, so an info window is displayed by calling <code>openInfoWindow() or</code>&#160;<code>openInfoWindowHtml()</code> on the GMap2 object.</p>
<pre class="brush: js;">GEvent.addListener(marker, 'click', function() {
    var markerPosn = new GLatLng(place[&quot;posn&quot;][0], place[&quot;posn&quot;][1]);
    map.openInfoWindowHtml(markerPosn ,buildPlaceInfoHtml(place),{maxWidth:275});
}); </pre>
<p>Things have changed significantly in Google Maps v3.&#160; The InfoWindow now has a constructor and <code>openInfoWindow()or</code>&#160;<code>openInfoWindowHtml()</code> have been removed.&#160; Initially I was lost trying to get each marker to show an InfoWindow with it’s own content.&#160;&#160;&#160; I then read the following from the <a href="http://code.google.com/apis/maps/documentation/javascript/overlays.html#InfoWindows" target="_blank">Google Maps v3 documentation about InfoWindow overlays</a>.</p>
<blockquote>
<p><code>InfoWindow</code>s may be attached to either <code>Marker</code> objects (in which case their position is based on the marker&#8217;s location) or on the map itself at a specified <code>LatLng</code>. If you only want one info window to display at a time (as is the behavior on Google Maps), you need only create one info window, which you can reassign to different locations or markers upon map events (such as user clicks).</p>
</blockquote>
<p>Realizing I only needed one InfoWindow object. I refactored my code to create a single InfoWindow and then set&#160; the InfoWindow content when a marker was clicked and then attach it to the appropriate marker.</p>
<pre class="brush: js;">var infoWindow = new google.maps.InfoWindow({});
var markers = new Array(); 

function setMarkers(map, locations, areaId) {
     for(var i = 0; i &lt; locations.length; i++) {
         var location = locations[i];
         var latlng = new google.maps.LatLng(location.Location[0], location.Location[1]);
         var marker = new google.maps.Marker({
             position: latlng,
             map: map,
             shadow: createMarkerShadow(location.MarkerShadow),
             icon: createMarkerImage(location.MarkerImage),
             shape: markerShape,
             title: location.Name
         });
         marker.set('location', location);
         google.maps.event.addListener(marker, &quot;click&quot;, function(event) {
            var area = this.get('location');
            var infoWindowHtml = parseTemplate($(&quot;#MarkerTemplate&quot;).html(), { location : location} );
            infoWindow.setContent(infoWindowHtml);
            infoWindow.open(map, this);
         });
         markers.push(marker);
     }
}

function clearMarkers() {
     infoWindow.close();
     for(var i = 0; i &lt; markers.length; i++) {
         markers[i].setMap(null);
     }
     markers.length = 0;
}</pre>
<p>This new code iterates through an array of locations and creates a marker for each, attaches the location object, and adds an ‘click’ event listener to each marker.&#160; Attaching the location object to the marker is the key to changing the InfoWindow content when the marker is clicked.&#160; </p>
<pre class="brush: js;">marker.set('location', location);</pre>
<p>This is made possible because the InfoWindow is built on the MVCObject prototype, which exposes accessor methods.&#160; When a marker click event fires the location object can be retrieve using the ‘get’ accessor.&#160; Now the content of the InfoWindow can be updated from the location object and attached to the marker that was clicked.</p>
<pre class="brush: js;"> google.maps.event.addListener(marker, &quot;click&quot;, function(event) {
    var area = this.get('location');
    var infoWindowHtml = parseTemplate($(&quot;#MarkerTemplate&quot;).html(), { location : location} );
    infoWindow.setContent(infoWindowHtml);
    infoWindow.open(map, this);
 });</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/06/how-to-show-an-infowindow-for-multiple-markers-using-google-maps-v3/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Create a simple REST API for an ASP.NET page</title>
		<link>http://www.aaronkjackson.com/2010/03/create-a-simple-rest-api-for-an-aspnet-page/</link>
		<comments>http://www.aaronkjackson.com/2010/03/create-a-simple-rest-api-for-an-aspnet-page/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 04:48:22 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[Web Development]]></category>

		<category><![CDATA[ASP.NET]]></category>

		<category><![CDATA[C#]]></category>

		<category><![CDATA[Web Forms]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/03/create-a-simple-rest-api-for-an-aspnet-page/</guid>
		<description><![CDATA[I needed a simple way for one page to call an action in another page.  In the spirit of a RESTful API I wanted that interaction to be called through a simple URL. 
http://localhost/Default.aspx?action=save
I initially started using a switch statement to handle the “action” passed in on the QueryString, but really wasn’t happy with the result.  [...]]]></description>
			<content:encoded><![CDATA[<p>I needed a simple way for one page to call an action in another page.  In the spirit of a <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">RESTful API</a> I wanted that interaction to be called through a simple URL. </p>
<pre class="brush: plain;">http://localhost/Default.aspx?action=save</pre>
<p>I initially started using a switch statement to handle the “action” passed in on the QueryString, but really wasn’t happy with the result.  I wasn’t interested in having to maintain a switch statement for the actions.  My first pass looked like this:</p>
<pre class="brush: csharp;">protected string Action { get; set; }

protected override void OnInit(EventArgs e)
{
    Action = Request.QueryString["action"] ?? string.Empty;
    base.OnInit(e);
}

protected void Page_Load(object sender, EventArgs e)
{
    switch (Action)
    {
        "Save":
            SaveAction();
            break;
        "Load":
            LoadAction();
            break;
        default:
            break;
    }
}

private void SaveAction()
{
    Response.Write("Save action called.");
}

private void LoadAction()
{
    Response.Write("Load action called.");
}</pre>
<p>I decided to break out the handling of the ‘action’ into a base class called ActionPage and use a event model to call the actions methods.  Following this refactoring the code behind was much easier to follow.</p>
<pre class="brush: csharp;">public partial class _Default : ActionPage
{
    protected void Page_Load(object sender, EventArgs e)
    { }

    protected override void RegisterActions()
    {
        PageActions.Add("save", SaveAction);
        PageActions.Add("load", LoadAction);
    }

    private void SaveAction()
    {
        Response.Write("Save action called.");
    }
    private void LoadAction()
    {
        Response.Write("Load action called.");
    }
}</pre>
<p>The key was creating a &#8216;PageAction&#8217; delegate that could be registered for each possible page action.  The ‘RegisterActions’ method shows the action methods being registered using the PageAction delegate.  The page is now only responsible for performing the actions and no longer has to determine what action to call.   The work of reading the action from the QueryString and calling the action have been placed into the ActionPage base class.</p>
<pre class="brush: csharp;">public class ActionPage  : System.Web.UI.Page
{
    protected delegate void PageAction();
    protected readonly IDictionary&lt;string, PageAction&gt; PageActions = new Dictionary&lt;string, PageAction&gt;();
    protected string Action { get; set; }

    public ActionPage()
    {
        RegisterActions();
    }

    protected virtual void RegisterActions()
    {
    }

    protected void HandleAction(string action)
    {
        if (PageActions.ContainsKey(action))
            PageActions[action]();
    }

    protected override void OnInit(EventArgs e)
    {
        Action = Request.QueryString["action"] ?? string.Empty;
        base.OnInit(e);
    }
    protected override void OnLoad(EventArgs e)
    {
        HandleAction(Action);
        base.OnLoad(e);
    }
}</pre>
<p>The ActionPage starts by calling ‘RegisterActions’ in the constructor.  Register actions is the pages chance to register actions with the ActionPage.  The actions is then pulled from the QueryString it the OnInit method.  Then in OnLoad the action matching the one passed on the query string is called.  In this model if an invalid action is called nothing happens and the page renders normally.</p>
<p><a href="http://www.aaronkjackson.com/wp-content/uploads/2010/03/simplerestapi.zip">SimpleRESTAPI_SampleSource.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/03/create-a-simple-rest-api-for-an-aspnet-page/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Building DotNetNuke Modules Using Web Forms MVP</title>
		<link>http://www.aaronkjackson.com/2010/03/building-dotnetnuke-modules-using-web-forms-mvp/</link>
		<comments>http://www.aaronkjackson.com/2010/03/building-dotnetnuke-modules-using-web-forms-mvp/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 06:15:33 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[AthleticHost]]></category>

		<category><![CDATA[Web Development]]></category>

		<category><![CDATA[patterns]]></category>

		<category><![CDATA[Web Forms MVP]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/03/building-dotnetnuke-modules-using-web-forms-mvp/</guid>
		<description><![CDATA[I have been looking for a good framework that would encourage good development practices through separation of concerns and testability in my DotNetNuke modules. I was listening to Scott Hanselman’s Hanselminutes Podcast #202 and discovered Web Forms MVP.&#160; Tatham Oddie and Damian Edwards have developed a framework for those us of us who are using [...]]]></description>
			<content:encoded><![CDATA[<p>I have been looking for a good framework that would encourage good development practices through separation of concerns and testability in my DotNetNuke modules. I was listening to Scott Hanselman’s <a href="http://www.hanselman.com/blog/HanselminutesPodcast202ADifferentWayToDoASPNETWebFormsWithWebFormsMVP.aspx">Hanselminutes Podcast #202</a> and discovered <a href="http://webformsmvp.com/">Web Forms MVP</a>.&#160; <a href="http://blog.tatham.oddie.com.au/">Tatham Oddie</a> and <a href="http://damianedwards.com/">Damian Edwards</a> have developed a framework for those us of us who are using web form’s in our projects.</p>
<p>Web Forms MVP provides some interesting features.&#160; A few of the features include: </p>
<ul>
<li>Composite views </li>
<li>Asynchronous tasks </li>
<li>Shared presenters </li>
<li>Presenter messaging </li>
<li>Works with HttpHandlers and web services. </li>
<li>Custom presenter factories to allow IOC integration. </li>
</ul>
<ul>To start you will need Web Forms MVP CTP 7 if you are going to be developing for DotNetNuke.&#160;&#160; I intially struggled with CTP 6 and through Tatham’s quick responses on the <a href="http://groups.google.com/group/webformsmvp">Web Forms MVP Google Group</a> found there was a fix for this in CTP 7.&#160; CTP 7 should be released soon, however, it looks like you should be able to build it from the <a href="http://webformsmvp.codeplex.com/SourceControl/list/changesets">source</a> until then.</ul>
<p>The power of the <a href="http://en.wikipedia.org/wiki/Model_View_Presenter">MVP pattern</a> allows for us to have clean markup in our user control and the ability to isolate and test the logic that drives the form.&#160; Web Forms MVP uses the <a href="http://www.martinfowler.com/eaaDev/SupervisingPresenter.html  ">supervising presenter</a> pattern with the model loosely following the <a href="http://www.martinfowler.com/eaaDev/PresentationModel.html  ">presentation model</a> pattern.</p>
</p>
<ul>The following example is a&#160; simple ‘contact us’ form.&#160;&#160; This first pass of the contact form will just display a friendly ‘thank you’ message.&#160; Later posts will include persistence and notification features for the contact form.&#160; </ul>
<p> <a href="http://www.aaronkjackson.com/wp-content/uploads/2010/03/image.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.aaronkjackson.com/wp-content/uploads/2010/03/image-thumb.png" width="240" height="63" /></a> <a href="http://www.aaronkjackson.com/wp-content/uploads/2010/03/image1.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.aaronkjackson.com/wp-content/uploads/2010/03/image-thumb1.png" width="240" height="90" /></a>
</p>
<p>Since the view doesn’t contain any logic it can be laid out using embedded code blocks (&lt;%= Model.FirstName %&gt;)</p>
<pre class="brush: csharp;">&lt;%
    panelContactUs.Visible = Model.ShowForm;
    panelMessage.Visible = !Model.ShowForm;
%&gt;
&lt;fieldset id=&quot;panelContactUs&quot; runat=&quot;server&quot; visible=&quot;true&quot; class=&quot;cssform&quot;&gt;
    &lt;legend&gt;Please enter your information and we will contact you soon.&lt;/legend&gt;
    &lt;p&gt;
        &lt;asp:Label ID=&quot;lblFirstName&quot; runat=&quot;server&quot; Text=&quot;First name:&quot; AssociatedControlID=&quot;txtFirstName&quot;&gt;&lt;/asp:Label&gt;
        &lt;asp:TextBox ID=&quot;txtFirstName&quot; runat=&quot;server&quot;&gt;&lt;/asp:TextBox&gt;
    &lt;/p&gt;
    &lt;p&gt;
        &lt;asp:Label ID=&quot;lblLastName&quot; runat=&quot;server&quot; Text=&quot;Last name:&quot; AssociatedControlID=&quot;txtLastName&quot;&gt;&lt;/asp:Label&gt;
        &lt;asp:TextBox ID=&quot;txtLastName&quot; runat=&quot;server&quot;&gt;&lt;/asp:TextBox&gt;
    &lt;/p&gt;
    &lt;div style=&quot;margin-left: 150px;&quot;&gt;
        &lt;asp:Button ID=&quot;btnSubmit&quot; runat=&quot;server&quot; Text=&quot;Submit&quot; onclick=&quot;btnSubmit_Click&quot; /&gt;
    &lt;/div&gt;
&lt;/fieldset&gt;

&lt;div id=&quot;panelMessage&quot; runat=&quot;server&quot;&gt;
    &lt;p&gt;Dear &lt;%=Model.FirstName %&gt; &lt;%=Model.LastName %&gt;,&lt;/p&gt;
    &lt;p&gt;
    Thank you for your interest in AthleticHost.  We are looking forward to working with
    you to bring your athletic department online.
    &lt;/p&gt;
    &lt;p&gt;
    We will be contacting you soon to discuss your the specific needs of your athletic program.
    &lt;/p&gt;
    &lt;p&gt;
    Please feel free to contact us at &lt;a href=&quot;mailto:support@athletichost.com&quot;&gt;support@athletichost.com&lt;/a&gt;
    &lt;/p&gt;
    &lt;p&gt;
    Sincerely,&lt;br /&gt;
    Aaron Jackson&lt;br /&gt;
    Athletic Host
    &lt;/p&gt;
&lt;/div&gt;</pre>
<p>The code behind for the control is only responsible for binding the view to the presenter and passing along the events that occur in the view, so that the presenter can react to them.&#160; Here is the code behind for the ViewContactUs control. </p>
<pre class="brush: csharp;">[PresenterBinding(typeof(ContactUsPresenter))]
partial class ViewContactUs : PortalModuleBase, IActionable, IContactUsView
{
    protected override void OnInit(EventArgs e)
    {
        PageViewHost.Register(this, Context);
        base.OnInit(e);
    }
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        OnSubmit(txtFirstName.Text, txtLastName.Text);
    }

    public event EventHandler&lt;SubmitContactUsEventArgs&gt; SubmitContactUs;
    private void OnSubmit(string firstName, string lastName)
    {
        if (SubmitContactUs != null)
        {
            SubmitContactUs(this, new SubmitContactUsEventArgs
                                      {
                                          FirstName = firstName,
                                          LastName = lastName
                                      });
        }
    }

    private ContactUsModel model;
    public ContactUsModel Model
    {
        get
        {
            if (model == null)
                throw new InvalidOperationException(&quot;The Model property is currently null, however it should have been automatically initialized by the presenter. This most likely indicates that no presenter was bound to the control. Check your presenter bindings.&quot;);

            return model;
        }
        set
        {
            model = value;
        }
    }
}</pre>
<p>Binding the view to the presenter is normally handled by inheriting from MvpUserControl, however the ViewContactUs control needs to work with DNN.&#160; DNN modules need to inherit from&#160; DNN’s PortalModuleBase and since multiple inheritance is not possible in C# we have a problem.&#160;&#160; Thankfully we can override the OnInit method and register our view with a single line of code.</p>
<pre class="brush: csharp;">protected override void OnInit(EventArgs e)
{
    PageViewHost.Register(this, Context);
    base.OnInit(e);
}</pre>
<p>Views that don’t have any events would be complete at this point.&#160; Views that react to events, such as, the click event on submit button in ContactUs need to be passed to the presenter.&#160;&#160;&#160; The presenter is responsible for subscribing to the view events when it is bound to the view.&#160; Look at the constructor of the ContactUsPresenter below.&#160; You can see the SubmitContactUs event on the view being subscribed to by the ContactUsPresenter.&#160; </p>
<pre class="brush: csharp;">public class ContactUsPresenter : Presenter&lt;IContactUsView&gt;
{
    public ContactUsPresenter(IContactUsView view)
        : base(view)
    {
        View.SubmitContactUs += View_SubmitContactUs;
        view.Model.ShowForm = true;
        view.Model.Message = string.Empty;
    }

    public override void ReleaseView()
    {
        View.SubmitContactUs -= View_SubmitContactUs;
    }

    void View_SubmitContactUs(object sender, SubmitContactUsEventArgs e)
    {
        View.Model.FirstName = e.FirstName;
        View.Model.LastName = e.LastName;
        View.Model.Message = e.FirstName + &quot; &quot; + e.LastName;
        View.Model.ShowForm = false;
    }
}</pre>
<p>Finally, a look at the unit test that was written for the presenter.&#160; I choose to use <a href="http://www.codeplex.com/xunit">xUnit</a> and <a href="http://code.google.com/p/moq/">Moq</a> to handle the testing.&#160;&#160;&#160; Since the view implements the IContactUsView interface the unit test can mock the view and allow for the presenter to be tested without dependencies on DNN.&#160;&#160; In fact, this presenter could be reused on any other web forms project.</p>
<pre class="brush: csharp;">[Fact]
public void ContactUsPresenter_Sets_Message_OnSubmit()
{
    // Arrange
    var view = new Mock&lt;IContactUsView&gt;();
    view.SetupAllProperties();
    var presenter = new ContactUsPresenter(view.Object);

    // Act
    view.Raise(v =&gt; v.Load += null, new EventArgs());
    view.Raise(v =&gt; v.SubmitContactUs += null,
        new SubmitContactUsEventArgs(&quot;Chester&quot;, &quot;Tester&quot;,
            &quot;ctester@test.com&quot;, &quot;http://www.test.com&quot;,
            &quot;This is a test of the emergancy broadcast system...&quot;));
    presenter.ReleaseView();

    // Assert
    Assert.Contains(&quot;Chester Tester&quot;, view.Object.Model.Message);
    Assert.Equal(&quot;Chester&quot;, view.Object.Model.FirstName);
    Assert.Equal(&quot;Tester&quot;, view.Object.Model.LastName);
    Assert.False(view.Object.Model.ShowForm);
}</pre>
<p><a href="http://www.aaronkjackson.com/dev/webformsmvp/ContactUsMVP.zip">Download the ContactUs module source.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/03/building-dotnetnuke-modules-using-web-forms-mvp/feed/</wfw:commentRss>
		</item>
		<item>
		<title>YUI Compressor and NAnt</title>
		<link>http://www.aaronkjackson.com/2010/02/yui-compressor-and-nant/</link>
		<comments>http://www.aaronkjackson.com/2010/02/yui-compressor-and-nant/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 07:04:11 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[AthleticHost]]></category>

		<category><![CDATA[Web Development]]></category>

		<category><![CDATA[CSS]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[NAnt]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/02/yui-compressor-and-nant/</guid>
		<description><![CDATA[I have been working on creating a DotNetNuke Skin for AthleticHost.com.   In order to simplify deployment of the skin I wanted to add it as an extension to DNN rather that upload it via FTP.   I choose to use NAnt to build the extension install file.   In an effort to increase page performance I decided [...]]]></description>
			<content:encoded><![CDATA[<p>I have been working on creating a <a href="http://www.dotnetnuke.com">DotNetNuke</a> Skin for <a href="http://www.athletichost.com/">AthleticHost.com</a>.   In order to simplify deployment of the skin I wanted to add it as an extension to DNN rather that upload it via FTP.   I choose to use <a href="http://nant.sourceforge.net/">NAnt</a> to build the extension install file.   In an effort to increase page performance I decided that the CSS and JavaScript files should be compressed and choose the <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a> for the job.</p>
<p>I created two targets.  One to minify the JavaScript and another for the CSS.</p>
<pre class="brush: xml;">&lt;target name="JavaScript.minify"&gt;
&lt;foreach item="File" property="filename"&gt;
  &lt;in&gt;
    &lt;items&gt;
      &lt;include name="${temp.dir}/**/js/**/*.js"/&gt;
    &lt;/items&gt;
  &lt;/in&gt;
  &lt;do&gt;
    &lt;echo message="${filename}" /&gt;
    &lt;exec program="java" workingdir="${YUICompressor.dir}"&gt;
      &lt;arg value="-jar" /&gt;
      &lt;arg value="yuicompressor-2.4.2.jar" /&gt;
      &lt;arg value="--type" /&gt;
      &lt;arg value="js" /&gt;
      &lt;arg value="-o" /&gt;
      &lt;arg value="${filename}.min" /&gt;
      &lt;arg value="${filename}" /&gt;
    &lt;/exec&gt;
    &lt;move file="${filename}.min" tofile="${filename}" overwrite="true" /&gt;
  &lt;/do&gt;
&lt;/foreach&gt;
&lt;/target&gt;
&lt;target name="Css.minify"&gt;
&lt;foreach item="File" property="filename"&gt;
  &lt;in&gt;
    &lt;items&gt;
      &lt;include name="${temp.dir}/**/*.css"/&gt;
    &lt;/items&gt;
  &lt;/in&gt;
  &lt;do&gt;
    &lt;echo message="${filename}" /&gt;
    &lt;exec program="java" workingdir="${YUICompressor.dir}"&gt;
      &lt;arg value="-jar" /&gt;
      &lt;arg value="yuicompressor-2.4.2.jar" /&gt;
      &lt;arg value="--type" /&gt;
      &lt;arg value="css" /&gt;
      &lt;arg value="-o" /&gt;
      &lt;arg value="${filename}.min" /&gt;
      &lt;arg value="${filename}" /&gt;
    &lt;/exec&gt;
    &lt;move file="${filename}.min" tofile="${filename}" overwrite="true" /&gt;
  &lt;/do&gt;
&lt;/foreach&gt;
&lt;/target&gt;</pre>
<p>The “Deploy” target then calls the “Css.minify” and “Javascript.minify”</p>
<pre class="brush: xml;">&lt;call target="JavaScript.minify" /&gt;
&lt;call target="Css.minify" /&gt;</pre>
<p><a href="http://www.aaronkjackson.com/wp-content/uploads/2010/02/build.xml">Download the full NAnt script.</a></p>
<p>Resouces:<br />
<a href="http://developer.yahoo.com/yui/compressor/">http://developer.yahoo.com/yui/compressor/</a><br />
<a href="http://nant.sourceforge.net/">http://nant.sourceforge.net/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/02/yui-compressor-and-nant/feed/</wfw:commentRss>
		</item>
		<item>
		<title>AthleticHost.com will be using DotNetNuke</title>
		<link>http://www.aaronkjackson.com/2010/01/athletichostcom-will-be-using-dotnetnuke/</link>
		<comments>http://www.aaronkjackson.com/2010/01/athletichostcom-will-be-using-dotnetnuke/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 15:23:15 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[AthleticHost]]></category>

		<category><![CDATA[Web Development]]></category>

		<category><![CDATA[DotNetNuke]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/01/athletichostcom-will-be-using-dotnetnuke/</guid>
		<description><![CDATA[&#160;&#160;&#160; 
I have been working on site for Timberline High School Athletics for the last four years.&#160; The site has become an important tool for the athletic department and used by the parents and student athletes to get news and information about the schools sports programs.
Through my experience with Timberline I have discovered that many [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://athletichost.com"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="athletichost_logo_143" border="0" alt="athletichost_logo_143" src="http://www.aaronkjackson.com/wp-content/uploads/2010/01/athletichost-logo-143.png" width="144" height="59" /></a>&#160;&#160;&#160; <a href="http://www.dotnetnuke.com/"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="DotNetNuke-Logo" border="0" alt="DotNetNuke-Logo" src="http://www.aaronkjackson.com/wp-content/uploads/2010/01/dotnetnukelogo.gif" width="240" height="65" /></a></p>
<p>I have been working on site for <a href="http://www.wolvesathletics.com" target="_blank">Timberline High School Athletics</a> for the last four years.&#160; The site has become an important tool for the athletic department and used by the parents and student athletes to get news and information about the schools sports programs.</p>
<p>Through my experience with Timberline I have discovered that many high school athletic programs do not have a website or have a very poor website that is not well maintained.&#160;&#160; I have been working over the past several months to create a hosting service that will provide websites for high school athletic programs.&#160; The websites will be designed to be easily maintained by athletic directors, coaches, and team parents.&#160; </p>
<p><a href="http://athletichost.com" target="_blank">AthleticHost.com</a> will be using <a href="http://www.dotnetnuke.com" target="_blank">DotNetNuke</a> (DNN) as the core platform for these sites.&#160; DNN was chosen for the following reasons:</p>
<ul>
<li>The ability to have many websites (a.k.a. portals) on a single DNN installation.</li>
<li>Site templates will allow for new sites to be quickly created.</li>
<li>Built in hosting model that includes security and payment features.</li>
<li>Skinning system that allows each portal to have its own look-and-feel.&#160;&#160; This is important because many niche web hosts sites all look the same.&#160; I want each school to have it’s own look-and-feel.</li>
<li>A security model that will allow separate security configurations for the athletic director, coaches, and team parents.</li>
<li>A good set of core modules.</li>
</ul>
<p>Hosting at <a href="http://athletichost.com" target="_blank">AthleticHost.com</a> will be available May 1, 2010. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/01/athletichostcom-will-be-using-dotnetnuke/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using FileZilla - Filename filters</title>
		<link>http://www.aaronkjackson.com/2010/01/using-filezilla-filename-filters/</link>
		<comments>http://www.aaronkjackson.com/2010/01/using-filezilla-filename-filters/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 22:46:10 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/01/using-filezilla-filename-filters/</guid>
		<description><![CDATA[I often provide web support for our clients.&#160; One of the first things I do for a new client is to pull down all of the files for the site and import them into Subversion.&#160; Often I find directories littered with backup files and lazy man version control (files copied and renamed with the date [...]]]></description>
			<content:encoded><![CDATA[<p>I often provide web support for our clients.&#160; One of the first things I do for a new client is to pull down all of the files for the site and import them into Subversion.&#160; Often I find directories littered with backup files and lazy man version control (files copied and renamed with the date changed).&#160;&#160; I am only interested in pulling down the files used by the site.&#160; </p>
<p>To avoid hand picking the files I found the “Filename filter” feature in <a href="http://filezilla-project.org/" target="_blank">FileZilla</a>.&#160; It allows you to specify a regular expression filter.&#160;&#160; Then you can drag-and-drop the entire root folder structure and only download the files that you are interested.</p>
<p>Here is a sample filter for a basic site:</p>
<p>.+\.(html|htm|css|js|jpg|png)$</p>
<p>You can use the “Filter conditions” option to reverse the filter and pull down all the junk files if you want to archive them.</p>
<p><a href="http://www.aaronkjackson.com/wp-content/uploads/2010/01/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.aaronkjackson.com/wp-content/uploads/2010/01/image-thumb.png" width="644" height="326" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/01/using-filezilla-filename-filters/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Too cheap to hire a graphic designer</title>
		<link>http://www.aaronkjackson.com/2010/01/too-cheap-to-hire-a-graphic-designer/</link>
		<comments>http://www.aaronkjackson.com/2010/01/too-cheap-to-hire-a-graphic-designer/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 07:20:46 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
		
		<category><![CDATA[Web Development]]></category>

		<category><![CDATA[design]]></category>

		<category><![CDATA[gimp]]></category>

		<category><![CDATA[timberline]]></category>

		<category><![CDATA[wolves]]></category>

		<guid isPermaLink="false">http://www.aaronkjackson.com/2010/01/too-cheap-to-hire-a-graphic-designer/</guid>
		<description><![CDATA[I am donating my time to rebuild wolvesathletics.com in ASP.NET using DotNetNuke.&#160;&#160; It will be a significant upgrade for Timberline High School’s athletics website and offer them better capabilities for editing for coaches and team parents.&#160; Since I am donating the time I didn’t want to hire a designer, so having no formal design experience [...]]]></description>
			<content:encoded><![CDATA[<p>I am donating my time to rebuild <a href="http://www.wolvesathletics.com" target="_blank">wolvesathletics.com</a> in ASP.NET using <a href="http://www.dotnetnuke.com" target="_blank">DotNetNuke</a>.&#160;&#160; It will be a significant upgrade for Timberline High School’s athletics website and offer them better capabilities for editing for coaches and team parents.&#160; Since I am donating the time I didn’t want to hire a designer, so having no formal design experience I gave it a <a href="http://aaronkjackson.com/dev/wolvesathletics/" target="_blank">shot</a>.</p>
<p>I am very interested in getting feedback about the design and what I can do to polish it up.&#160; Please leave comments on this with your ideas.</p>
<p><a href="http://aaronkjackson.com/dev/wolvesathletics/" target="_blank">Review the Wolves Athletics design concepts.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronkjackson.com/2010/01/too-cheap-to-hire-a-graphic-designer/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
