<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>ProgramGood.Net - Testing</title>
    <link>http://www.programgood.net/</link>
    <description>The journey to becoming a great programmer</description>
    <language>en-us</language>
    <copyright>Dave Mateer</copyright>
    <lastBuildDate>Wed, 21 Oct 2009 03:00:01 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.2.8279.16125</generator>
    <managingEditor>davemateer@gmail.com</managingEditor>
    <webMaster>davemateer@gmail.com</webMaster>
    <item>
      <trackback:ping>http://www.programgood.net/Trackback.aspx?guid=14c64021-c5cf-49ed-a249-cedf023631ee</trackback:ping>
      <pingback:server>http://www.programgood.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.programgood.net/PermaLink,guid,14c64021-c5cf-49ed-a249-cedf023631ee.aspx</pingback:target>
      <dc:creator>Dave Mateer</dc:creator>
      <wfw:comment>http://www.programgood.net/CommentView,guid,14c64021-c5cf-49ed-a249-cedf023631ee.aspx</wfw:comment>
      <wfw:commentRss>http://www.programgood.net/SyndicationService.asmx/GetEntryCommentsRss?guid=14c64021-c5cf-49ed-a249-cedf023631ee</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Customer tests confirm how the feature
is supposed to work as experienced by the end user.<br /><br />
Because customers generally don't want to use nUnit.. we're going to use Fitnesse,
which is more user friendly:<br /><br />
The goal is to have the customer write their own tests.<br /><br />
To setup Fitnesse.  Download the .jar and run it like this:<br /><br />
c:\apps\fitnesse -jar fitness.jar -p 8080<br /><br />
Then go and get slim for .net.  I installed it to c:\apps\slim<br /><p></p><img src="http://www.programgood.net/content/binary/screen12345678910.gif" border="0" /><br /><br />
Here is how it works for the Divider example:<br /><br />
!define TEST_SYSTEM {slim}<br />
!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,c:\apps\slim\fitsharp.dll
%p}<br />
!define TEST_RUNNER {c:\apps\slim\Runner.exe}<br />
 <br />
!path C:\code\slimexample\slimexample\bin\Debug\slimexample.dll<br /><br />
|import      |<br />
|slim_example|<br /><br />
!|Divider|<br />
|Numerator|Denominator|Quotient?|<br />
|10       |2         
|5      |<br />
|12.6     |3         
|4.2      |<br />
|22       |7         
|~=3.14   |<br />
|9        |3         
|&lt;5       |<br />
|11       |2         
|4&lt;_&lt;6    |<br />
|100      |4         
|33       |<br /><br />
Here is the C# code, I compiled to slimexample.dll<br /><pre><span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">using</span> System; <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">namespace</span> slim_example
{ <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">class</span> Divider
{ <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">double</span> Numerator
{ get; set; } <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">double</span> Denominator
{ get; set; } <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">double</span> _quotient; <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">void</span> Execute()
{ _quotient <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span> Numerator <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">/</span> Denominator;
} <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">double</span> Quotient()
{ <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">return</span> _quotient;
} } }</span></pre>Run the tests.. and we'll see that when 2 numbers are sent... then
then ? in the Fitnesse means that something should be checked.<br /><img src="http://www.programgood.net/content/binary/screen1234567891011.gif" border="0" /><br /><br />
Then we wire up to our code and test CatalogAdapter:<br /><br />
From this test we can see that I've a bug.. something wrong with the Duration.<br /><br /><img src="http://www.programgood.net/content/binary/screen123456789101112.gif" border="0" /><br /><br /><h3><b>Debugging</b></h3>
Have been working through why we are not getting the duration through.  The unit
tests on the DAL are passing fine.. in CatalogFixture, have added in 2 tracks of different
lengths.  They get pushed into the db, then pulled out using Catalog.. looks
ok.<br /><br /><img src="http://www.programgood.net/content/binary/CatalogFixtureDiagram.jpg" border="0" /><br /><br />
The next step is to look at the Service layer and see if the Duration is being written. 
Interestingly, the webservice is passing back all the correct tracks, but nothing
to do with reviewers etc..<br /><br /><img src="http://www.programgood.net/content/binary/screen12345678910111213.gif" border="0" /><br /><br /><img src="http://www.programgood.net/content/binary/screen1234567891011121314.gif" border="0" /><br />
Very interesting bug.. if I didn't specify this in my RecordingAssembler.WriteTotalRunTime:<br /><br />
dto.totalRunTimeSpecified = true;<br /><br />
then nothing would be passing back.  Same for WriteAverageRating.<br /><br /><br />
Came across another issue with the webservice, and couldn't get it to autogen.. easiest
way was to create it again.  Using source control so it if all went to custard,
could go back.<br /><br />
Been getting bogged down in detail, so have decided to push to the end of the project,
and get a front end up and running asap.<br /><br /><br /><br /><img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=14c64021-c5cf-49ed-a249-cedf023631ee" /></body>
      <title>Test Driven Development in .NET - Customer Tests the Web Service using Fitnesse (Ch7)</title>
      <guid isPermaLink="false">http://www.programgood.net/PermaLink,guid,14c64021-c5cf-49ed-a249-cedf023631ee.aspx</guid>
      <link>http://www.programgood.net/2009/10/21/TestDrivenDevelopmentInNETCustomerTestsTheWebServiceUsingFitnesseCh7.aspx</link>
      <pubDate>Wed, 21 Oct 2009 03:00:01 GMT</pubDate>
      <description>Customer tests confirm how the feature is supposed to work as experienced by the end user.&lt;br&gt;
&lt;br&gt;
Because customers generally don't want to use nUnit.. we're going to use Fitnesse,
which is more user friendly:&lt;br&gt;
&lt;br&gt;
The goal is to have the customer write their own tests.&lt;br&gt;
&lt;br&gt;
To setup Fitnesse.&amp;nbsp; Download the .jar and run it like this:&lt;br&gt;
&lt;br&gt;
c:\apps\fitnesse -jar fitness.jar -p 8080&lt;br&gt;
&lt;br&gt;
Then go and get slim for .net.&amp;nbsp; I installed it to c:\apps\slim&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img src="http://www.programgood.net/content/binary/screen12345678910.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
Here is how it works for the Divider example:&lt;br&gt;
&lt;br&gt;
!define TEST_SYSTEM {slim}&lt;br&gt;
!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,c:\apps\slim\fitsharp.dll
%p}&lt;br&gt;
!define TEST_RUNNER {c:\apps\slim\Runner.exe}&lt;br&gt;
&amp;nbsp;&lt;br&gt;
!path C:\code\slimexample\slimexample\bin\Debug\slimexample.dll&lt;br&gt;
&lt;br&gt;
|import&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br&gt;
|slim_example|&lt;br&gt;
&lt;br&gt;
!|Divider|&lt;br&gt;
|Numerator|Denominator|Quotient?|&lt;br&gt;
|10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
|5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br&gt;
|12.6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
|4.2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br&gt;
|22&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
|~=3.14&amp;nbsp;&amp;nbsp; |&lt;br&gt;
|9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
|&amp;lt;5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br&gt;
|11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
|4&amp;lt;_&amp;lt;6&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br&gt;
|100&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
|33&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;br&gt;
&lt;br&gt;
Here is the C# code, I compiled to slimexample.dll&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;namespace&lt;/span&gt; slim_example
{ &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; Divider
{ &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;double&lt;/span&gt; Numerator
{ get; set; } &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;double&lt;/span&gt; Denominator
{ get; set; } &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;double&lt;/span&gt; _quotient; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; Execute()
{ _quotient &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; Numerator &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;/&lt;/span&gt; Denominator;
} &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;double&lt;/span&gt; Quotient()
{ &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;return&lt;/span&gt; _quotient;
} } }&lt;/span&gt;&lt;/pre&gt;Run the tests.. and we'll see that when 2 numbers are sent... then
then ? in the Fitnesse means that something should be checked.&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen1234567891011.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
Then we wire up to our code and test CatalogAdapter:&lt;br&gt;
&lt;br&gt;
From this test we can see that I've a bug.. something wrong with the Duration.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen123456789101112.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h3&gt;&lt;b&gt;Debugging&lt;/b&gt;
&lt;/h3&gt;
Have been working through why we are not getting the duration through.&amp;nbsp; The unit
tests on the DAL are passing fine.. in CatalogFixture, have added in 2 tracks of different
lengths.&amp;nbsp; They get pushed into the db, then pulled out using Catalog.. looks
ok.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/CatalogFixtureDiagram.jpg" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
The next step is to look at the Service layer and see if the Duration is being written.&amp;nbsp;
Interestingly, the webservice is passing back all the correct tracks, but nothing
to do with reviewers etc..&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen12345678910111213.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen1234567891011121314.gif" border="0"&gt;
&lt;br&gt;
Very interesting bug.. if I didn't specify this in my RecordingAssembler.WriteTotalRunTime:&lt;br&gt;
&lt;br&gt;
dto.totalRunTimeSpecified = true;&lt;br&gt;
&lt;br&gt;
then nothing would be passing back.&amp;nbsp; Same for WriteAverageRating.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Came across another issue with the webservice, and couldn't get it to autogen.. easiest
way was to create it again.&amp;nbsp; Using source control so it if all went to custard,
could go back.&lt;br&gt;
&lt;br&gt;
Been getting bogged down in detail, so have decided to push to the end of the project,
and get a front end up and running asap.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=14c64021-c5cf-49ed-a249-cedf023631ee" /&gt;</description>
      <comments>http://www.programgood.net/CommentView,guid,14c64021-c5cf-49ed-a249-cedf023631ee.aspx</comments>
      <category>Object Oriented Programming</category>
      <category>Patterns</category>
      <category>Testing</category>
    </item>
    <item>
      <trackback:ping>http://www.programgood.net/Trackback.aspx?guid=f53ca405-c52f-4d44-b4f0-7cae3623b527</trackback:ping>
      <pingback:server>http://www.programgood.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.programgood.net/PermaLink,guid,f53ca405-c52f-4d44-b4f0-7cae3623b527.aspx</pingback:target>
      <dc:creator>Dave Mateer</dc:creator>
      <wfw:comment>http://www.programgood.net/CommentView,guid,f53ca405-c52f-4d44-b4f0-7cae3623b527.aspx</wfw:comment>
      <wfw:commentRss>http://www.programgood.net/SyndicationService.asmx/GetEntryCommentsRss?guid=f53ca405-c52f-4d44-b4f0-7cae3623b527</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Task:  create a WebService that returns
a recording and all its entities when specifying the id of the recording. Return type
of XML (ie not a .net dataset).<br /><br />
The DAL.Catalog returns a RecordingDataSet.Recording.<br /><br />
We need to write a DTO that takes an input and transforms(munges) it into something
else<br /><br />
Using a Service Interface Pattern.<br /><br />
Build a stub, map it into a DTO, and verify each field.<br />
First thing I did was to create a stub, to hide how the RecordingDataSet is retrieved..so
am not relying on the DAL at this point.<br /><br />
Here is the test the Stub code:<br /><pre><span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;">[TestFixture] <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">class</span> CatalogServiceStubFixture
{ RecordingDataSet.Recording recording; RecordingDataSet.Recording actual; CatalogServiceStub
service; [SetUp] <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">void</span> SetUp()
{ <span style="color: Green; background-color: Transparent; font-family: Courier New; font-size: 11px;">//
create a test recording in memory</span> recording <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span> CreateRecording();
service <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">new</span> CatalogServiceStub(recording);
actual <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span> service.FindByRecordingId(recording.Id);
} <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">private</span> RecordingDataSet.Recording
CreateRecording() { RecordingDataSet dataSet <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">new</span> RecordingDataSet();
RecordingDataSet.Recording recording <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span> dataSet.Recordings.NewRecording();
recording.Id <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span> 1; <span style="color: Green; background-color: Transparent; font-family: Courier New; font-size: 11px;">//
more code needed here to fill in the rest of the recording.</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">return</span> recording;
} [Test] <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">void</span> CheckId()
{ Assert.AreEqual(recording.Id, actual.Id); } </span></pre>Next we want a dto to transform
our dataset, into something else:<br /><br /><img src="http://www.programgood.net/content/binary/dto.gif" border="0" /><br /><br />
To specify in platform independant, we use XML.  This is still quite bulky, perhaps
JSON would be lighter now.<br /><br /><pre><span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;">&lt;?xml
version=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1.0"</span> encoding=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"utf-8"</span>?&gt;
&lt;xs:schema xmlns:tns=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"http://nunit.org/webservices"</span> elementFormDefault=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"qualified"</span> targetNamespace=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"http://nunit.org/webservices"</span> xmlns:xs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"http://www.w3.org/2001/XMLSchema"</span>&gt;
&lt;xs:element name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"Recording"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"tns:RecordingDto"</span> /&gt;
&lt;xs:complexType name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"RecordingDto"</span>&gt;
&lt;xs:sequence&gt; &lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"id"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:long"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"title"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"artistName"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"releaseDate"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"labelName"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"0"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"unbounded"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"tracks"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"tns:TrackDto"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"0"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"unbounded"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"reviews"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"tns:ReviewDto"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"0"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"totalRunTime"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:int"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"0"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"averageRating"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:int"</span> /&gt;
&lt;/xs:sequence&gt; &lt;/xs:complexType&gt; &lt;xs:complexType name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"TrackDto"</span>&gt;
&lt;xs:sequence&gt; &lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"id"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:long"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"title"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"artistName"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"duration"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"genreName"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;/xs:sequence&gt; &lt;/xs:complexType&gt; &lt;xs:complexType name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"ReviewDto"</span>&gt;
&lt;xs:sequence&gt; &lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"id"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:long"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"reviewerName"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"rating"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:int"</span> /&gt;
&lt;xs:element minOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> maxOccurs=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"1"</span> name=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"reviewContent"</span> type=<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"xs:string"</span> /&gt;
&lt;/xs:sequence&gt; &lt;/xs:complexType&gt; &lt;/xs:schema&gt;</span></pre><br /><br />
A benefit is that we can create C# from this:.. but really just getters and setters. 
See below.. this led to an interesting bug.<br /><br />
http://www.codingday.com/xml-c-class-generator-for-c-using-xsd-for-deserialization/<br /><br />
xsd asdf.xml - create an xsd<br />
xsd asdf.xsd /CLASSES  - creates a .cs<br /><br />
Then just creating an 'Assembler', which writes out the DTO...(from http://martinfowler.com/eaaCatalog/dataTransferObject.html)<br /><img src="http://www.programgood.net/content/binary/ServiceLayerDiagram.jpg" border="0" /><br /><p></p>
The Assembler has business logic in it to flatten the structure (as in the similar
example above)<br /><br />
The webservice is setup by adding it into IISAdmin.<br /><img src="http://www.programgood.net/content/binary/screen1234567.gif" border="0" /><br />
As the default ASP.NET user does not have access to my local database 
<br />
connection = new SqlConnection("Data Source=DAVEXPLAPTOP;Initial Catalog=catalog;Integrated
Security=True");<br /><br />
The easiest way to get running on dev was to add the DAVEXPLAPTOP\ASPNET user into
my SQL database.  This didn't show up under objects when adding, but I went ahead
anyway and it worked.<br /><br /><img src="http://www.programgood.net/content/binary/screen12345678.gif" border="0" /><br /><br /><br /><img src="http://www.programgood.net/content/binary/screen123456789.gif" border="0" /><br /><br /><br />
So this is what we have so far:<br /><br /><br /><img src="http://www.programgood.net/content/binary/diag.gif" border="0" /><img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=f53ca405-c52f-4d44-b4f0-7cae3623b527" /></body>
      <title>Test Driven Development in .NET - Service Layer (Ch6)</title>
      <guid isPermaLink="false">http://www.programgood.net/PermaLink,guid,f53ca405-c52f-4d44-b4f0-7cae3623b527.aspx</guid>
      <link>http://www.programgood.net/2009/10/20/TestDrivenDevelopmentInNETServiceLayerCh6.aspx</link>
      <pubDate>Tue, 20 Oct 2009 03:06:55 GMT</pubDate>
      <description>Task:&amp;nbsp; create a WebService that returns a recording and all its entities when specifying the id of the recording. Return type of XML (ie not a .net dataset).&lt;br&gt;
&lt;br&gt;
The DAL.Catalog returns a RecordingDataSet.Recording.&lt;br&gt;
&lt;br&gt;
We need to write a DTO that takes an input and transforms(munges) it into something
else&lt;br&gt;
&lt;br&gt;
Using a Service Interface Pattern.&lt;br&gt;
&lt;br&gt;
Build a stub, map it into a DTO, and verify each field.&lt;br&gt;
First thing I did was to create a stub, to hide how the RecordingDataSet is retrieved..so
am not relying on the DAL at this point.&lt;br&gt;
&lt;br&gt;
Here is the test the Stub code:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;[TestFixture] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; CatalogServiceStubFixture
{ RecordingDataSet.Recording recording; RecordingDataSet.Recording actual; CatalogServiceStub
service; [SetUp] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; SetUp()
{ &lt;span style="color: Green; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;//
create a test recording in memory&lt;/span&gt; recording &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; CreateRecording();
service &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; CatalogServiceStub(recording);
actual &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; service.FindByRecordingId(recording.Id);
} &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; RecordingDataSet.Recording
CreateRecording() { RecordingDataSet dataSet &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; RecordingDataSet();
RecordingDataSet.Recording recording &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; dataSet.Recordings.NewRecording();
recording.Id &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; 1; &lt;span style="color: Green; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;//
more code needed here to fill in the rest of the recording.&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;return&lt;/span&gt; recording;
} [Test] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; CheckId()
{ Assert.AreEqual(recording.Id, actual.Id); } &lt;/span&gt;&lt;/pre&gt;Next we want a dto to transform
our dataset, into something else:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/dto.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
To specify in platform independant, we use XML.&amp;nbsp; This is still quite bulky, perhaps
JSON would be lighter now.&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;&amp;lt;?xml
version=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1.0"&lt;/span&gt; encoding=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"utf-8"&lt;/span&gt;?&amp;gt;
&amp;lt;xs:schema xmlns:tns=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"http://nunit.org/webservices"&lt;/span&gt; elementFormDefault=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"qualified"&lt;/span&gt; targetNamespace=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"http://nunit.org/webservices"&lt;/span&gt; xmlns:xs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"http://www.w3.org/2001/XMLSchema"&lt;/span&gt;&amp;gt;
&amp;lt;xs:element name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Recording"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"tns:RecordingDto"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:complexType name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"RecordingDto"&lt;/span&gt;&amp;gt;
&amp;lt;xs:sequence&amp;gt; &amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"id"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:long"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"title"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"artistName"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"releaseDate"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"labelName"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"0"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"unbounded"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"tracks"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"tns:TrackDto"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"0"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"unbounded"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"reviews"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"tns:ReviewDto"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"0"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"totalRunTime"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:int"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"0"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"averageRating"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:int"&lt;/span&gt; /&amp;gt;
&amp;lt;/xs:sequence&amp;gt; &amp;lt;/xs:complexType&amp;gt; &amp;lt;xs:complexType name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"TrackDto"&lt;/span&gt;&amp;gt;
&amp;lt;xs:sequence&amp;gt; &amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"id"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:long"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"title"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"artistName"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"duration"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"genreName"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;/xs:sequence&amp;gt; &amp;lt;/xs:complexType&amp;gt; &amp;lt;xs:complexType name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"ReviewDto"&lt;/span&gt;&amp;gt;
&amp;lt;xs:sequence&amp;gt; &amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"id"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:long"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"reviewerName"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"rating"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:int"&lt;/span&gt; /&amp;gt;
&amp;lt;xs:element minOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; maxOccurs=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"1"&lt;/span&gt; name=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"reviewContent"&lt;/span&gt; type=&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"xs:string"&lt;/span&gt; /&amp;gt;
&amp;lt;/xs:sequence&amp;gt; &amp;lt;/xs:complexType&amp;gt; &amp;lt;/xs:schema&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;br&gt;
A benefit is that we can create C# from this:.. but really just getters and setters.&amp;nbsp;
See below.. this led to an interesting bug.&lt;br&gt;
&lt;br&gt;
http://www.codingday.com/xml-c-class-generator-for-c-using-xsd-for-deserialization/&lt;br&gt;
&lt;br&gt;
xsd asdf.xml - create an xsd&lt;br&gt;
xsd asdf.xsd /CLASSES&amp;nbsp; - creates a .cs&lt;br&gt;
&lt;br&gt;
Then just creating an 'Assembler', which writes out the DTO...(from http://martinfowler.com/eaaCatalog/dataTransferObject.html)&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/ServiceLayerDiagram.jpg" border="0"&gt;
&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
The Assembler has business logic in it to flatten the structure (as in the similar
example above)&lt;br&gt;
&lt;br&gt;
The webservice is setup by adding it into IISAdmin.&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen1234567.gif" border="0"&gt;
&lt;br&gt;
As the default ASP.NET user does not have access to my local database 
&lt;br&gt;
connection = new SqlConnection("Data Source=DAVEXPLAPTOP;Initial Catalog=catalog;Integrated
Security=True");&lt;br&gt;
&lt;br&gt;
The easiest way to get running on dev was to add the DAVEXPLAPTOP\ASPNET user into
my SQL database.&amp;nbsp; This didn't show up under objects when adding, but I went ahead
anyway and it worked.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen12345678.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen123456789.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
So this is what we have so far:&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/diag.gif" border="0"&gt;&lt;img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=f53ca405-c52f-4d44-b4f0-7cae3623b527" /&gt;</description>
      <comments>http://www.programgood.net/CommentView,guid,f53ca405-c52f-4d44-b4f0-7cae3623b527.aspx</comments>
      <category>Object Oriented Programming</category>
      <category>Patterns</category>
      <category>Testing</category>
    </item>
    <item>
      <trackback:ping>http://www.programgood.net/Trackback.aspx?guid=1331c215-9394-48c3-922e-b705c2a62ff3</trackback:ping>
      <pingback:server>http://www.programgood.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.programgood.net/PermaLink,guid,1331c215-9394-48c3-922e-b705c2a62ff3.aspx</pingback:target>
      <dc:creator>Dave Mateer</dc:creator>
      <wfw:comment>http://www.programgood.net/CommentView,guid,1331c215-9394-48c3-922e-b705c2a62ff3.aspx</wfw:comment>
      <wfw:commentRss>http://www.programgood.net/SyndicationService.asmx/GetEntryCommentsRss?guid=1331c215-9394-48c3-922e-b705c2a62ff3</wfw:commentRss>
      <title>Test Driven Development in .NET - DAL (Ch5)</title>
      <guid isPermaLink="false">http://www.programgood.net/PermaLink,guid,1331c215-9394-48c3-922e-b705c2a62ff3.aspx</guid>
      <link>http://www.programgood.net/2009/10/20/TestDrivenDevelopmentInNETDALCh5.aspx</link>
      <pubDate>Tue, 20 Oct 2009 01:03:44 GMT</pubDate>
      <description>From the nbdn course, I had some interesting code I'd like to test.  Just the business logic really, no DAL nor UI.  As I wanted to make a full application, the first though was to make a DAL which talked to a text file, or just some dummy data.  How to do this well?  De-coupled.  Tried to use poor mans dependency injection, and got confused.  So I had a coffee, and bought this book.  Because it had an end to end example of a testable application.  It uses .net1.1 mostly (which is good as there are no language constructs to learn)&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/tdd.jpg" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
Some good introduction to refactorings, and unit testing. The main meat of the book
is an example called MediaLibrary (music recordings). Chapter 5 started with testing
the DAL. 
&lt;br&gt;
&lt;br&gt;
Here are the first tests. Am showing nunit test runner.. mostly I use testdriven.net,
and have setup ctrl alt shft t to run tests.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen123.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
for source control I'm using git, and have coupled up with gvim as text editor. And
linked in beyond compare for a merge tool.&lt;br&gt;
&lt;br&gt;
The book uses Strongly Typed Datasets, which were the 'star of the show' in the .net1.0
release. By writing the sql, and having intellisense have autoproperties, this saves
writing boiler plate code.&lt;br&gt;
&lt;br&gt;
I learned about DataSets.. here is my edit (from wikipedia)..http://en.wikipedia.org/wiki/ADO.NET#DataSets&lt;br&gt;
&lt;p&gt;
ADO.NET consists of two primary parts:
&lt;/p&gt;
&lt;h3&gt;&lt;span class="editsection"&gt;&lt;/span&gt;&lt;span class="mw-headline" id="Data_provider"&gt;Data
provider&lt;/span&gt;
&lt;/h3&gt;
&lt;p&gt;
These classes provide access to a data source, such as a &lt;a href="http://en.wikipedia.org/wiki/Microsoft_SQL_Server" title="Microsoft SQL Server"&gt;Microsoft
SQL Server&lt;/a&gt;. Each data source has its own set of provider objects, but they each
have a common set of utility classes:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://en.wikipedia.org/wiki/Database_Connection" title="Database Connection" class="mw-redirect"&gt;Connection&lt;/a&gt;:
Provides a connection used to communicate with the data source. 
&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://en.wikipedia.org/wiki/Command" title="Command"&gt;Command&lt;/a&gt;: Used to
perform some action on the data source, such as reading, updating, or deleting relational
data.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://en.wikipedia.org/wiki/Parameter" title="Parameter"&gt;Parameter&lt;/a&gt;:
Describes a single parameter to a command. A common example is a parameter to a &lt;a href="http://en.wikipedia.org/wiki/Stored_procedure" title="Stored procedure"&gt;stored
procedure&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://en.wikipedia.org/wiki/DataAdapter" title="DataAdapter"&gt;DataAdapter&lt;/a&gt;:
A bridge used to transfer data between a Data source and a DataSet object (see below).&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://en.wikipedia.org/wiki/DataReader" title="DataReader"&gt;DataReader&lt;/a&gt;:
Used to efficiently process a large list of results one record at a time. It allows
records to be accessed in a read-only, forward-only mode, i.e., records have to be
accessed in sequential order; they can neither be randomly accessed nor can a record
which has been processed previously be accessed again.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;span class="editsection"&gt;&lt;/span&gt;&lt;span class="mw-headline" id="DataSets"&gt;DataSets&lt;/span&gt;
&lt;/h3&gt;
&lt;p&gt;
DataSet objects, a group of classes describing a simple in-memory &lt;a href="http://en.wikipedia.org/wiki/Relational_database" title="Relational database"&gt;relational
database&lt;/a&gt;, 
&lt;br&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
A &lt;b&gt;DataSet&lt;/b&gt; object represents a &lt;a href="http://en.wikipedia.org/wiki/Logical_schema" title="Logical schema"&gt;schema&lt;/a&gt; (either
an entire database or a subset of one). It can contain tables and relationships between
those tables. 
&lt;ul&gt;
&lt;li&gt;
A &lt;b&gt;DataTable&lt;/b&gt; object represents a single table in the database. It has a name,
rows, and columns. 
&lt;ul&gt;
&lt;li&gt;
A &lt;b&gt;DataView&lt;/b&gt; object overlays a DataTable and sorts the data (much like an &lt;a href="http://en.wikipedia.org/wiki/SQL" title="SQL"&gt;SQL&lt;/a&gt; "&lt;a href="http://en.wikipedia.org/wiki/Order_by" title="Order by" class="mw-redirect"&gt;order
by&lt;/a&gt;" clause) and filters the records (much like an SQL "&lt;a href="http://en.wikipedia.org/wiki/Where_%28SQL%29" title="Where (SQL)"&gt;where&lt;/a&gt;"
clause) if a filter is set. An in-memory index is used to facilitate these operations.
All DataTables have a default filter, while any number of additional DataViews can
be defined, reducing interaction with the underlying database and thus improving performance. 
&lt;ul&gt;
&lt;li&gt;
A &lt;b&gt;DataColumn&lt;/b&gt; represents a column of the table, including its name and type.&lt;/li&gt;
&lt;li&gt;
A &lt;b&gt;DataRow&lt;/b&gt; object represents a single row in the table; it allows reading and
updating of values in that row, likewise retrieving any rows that are related to it
through a primary-key foreign-key relationship.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
VS has a nice editor:&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen12345.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
Once I spiked up what datasets were (in simpleDatabaseTests.cs).. used this for reference:
http://www.csharp-station.com/Tutorials/AdoDotNet/Lesson05.asp&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt; [Test] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; put_data_into_a_dataset()
{ DataSet dataset &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; DataSet();
SqlDataAdapter data_adapter &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; SqlDataAdapter(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"select
id, name from Artist"&lt;/span&gt;, connection); SqlCommandBuilder sql_command_builder &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; SqlCommandBuilder(data_adapter);
data_adapter.Fill(dataset, &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Artist"&lt;/span&gt;);
Assert.IsNotNull(dataset); DataTable data_table &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; dataset.Tables[0]; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;for&lt;/span&gt; (&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;int&lt;/span&gt; i &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt;&lt; data_table.Rows.Count; i++)
            {
                DataRow data_row &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt; 0;
i =&lt;/span&gt; data_table.Rows[i]; Console.Out.Write(data_row[&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"id"&lt;/span&gt;] &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;+&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"
"&lt;/span&gt;); Console.Out.WriteLine(data_row[&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"name"&lt;/span&gt;]);
} }&gt;&lt;/pre&gt;
&lt;br&gt;
The example I'm working through uses a Table Data Gateway Pattern for the DAL. 
&lt;br&gt;
&lt;br&gt;
http://martinfowler.com/eaaCatalog/tableDataGateway.html&lt;br&gt;
"A Table Data Gateway holds all the SQL for accessing a single table or view: selects,
inserts, updates, and deletes. Other code calls its methods for all interaction with
the database."&lt;br&gt;
&lt;br&gt;
Lets take an example of ArtistFixture.cs which tests ArtistGateway.cs&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;[TestFixture] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; ArtistFixture
{ &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;static&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;readonly&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt; artistName &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Artist"&lt;/span&gt;;
SqlConnection connection; ArtistGateway gateway; RecordingDataSet recordingDataSet; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;long&lt;/span&gt; artistId;
[SetUp] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; setup_and_open_connection_pass_to_gateway_setup_data_set()
{ connection &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; SqlConnection(ConfigurationSettings.AppSettings.Get(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Catalog.Connection"&lt;/span&gt;));
connection.Open(); recordingDataSet &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; RecordingDataSet();
gateway &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; ArtistGateway(connection); &lt;span style="color: Green; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;//
insert a new artist getting its ID from the database&lt;/span&gt; artistId &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; gateway.Insert(recordingDataSet,
artistName); } [Test] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; RetrieveArtistFromDatabase()
{ &lt;span style="color: Green; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;//
create new RDS, use same gateway.&lt;/span&gt; RecordingDataSet loadedFromDB &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; RecordingDataSet();
RecordingDataSet.Artist loadedArtist &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; gateway.FindById(artistId,
loadedFromDB); Assert.AreEqual(artistId, loadedArtist.Id); Assert.AreEqual(artistName,
loadedArtist.Name); }&lt;/span&gt;&lt;/pre&gt;Here is part of ArtistGateway.cs.. gateway is newed
up with a connection passed in.. then only in Insert is it passed in a strongly typed
RecordingDataSet, which has all the SQL in it which has been auto-genned.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; ArtistGateway&lt;br&gt;
{&lt;br&gt;
SqlDataAdapter adapter;&lt;br&gt;
SqlConnection connection;&lt;br&gt;
SqlCommand command;&lt;br&gt;
SqlCommandBuilder builder;&lt;br&gt;
&lt;br&gt;
&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; ArtistGateway(SqlConnection
connection)&lt;br&gt;
{&lt;br&gt;
&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;.connection &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; connection;&lt;br&gt;
&lt;br&gt;
command &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; SqlCommand(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"select
id, name from artist where id = @id"&lt;/span&gt;,connection);&lt;br&gt;
command.Parameters.Add(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"@id"&lt;/span&gt;,
SqlDbType.BigInt);&lt;br&gt;
&lt;br&gt;
adapter &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; SqlDataAdapter(command);&lt;br&gt;
builder &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; SqlCommandBuilder(adapter);&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; RecordingDataSet.Artist
FindById(&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;long&lt;/span&gt; artistId,
RecordingDataSet recordingDataSet)&lt;br&gt;
{&lt;br&gt;
command.Parameters[&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"@id"&lt;/span&gt;].Value &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; artistId;&lt;br&gt;
adapter.Fill(recordingDataSet, recordingDataSet.Artists.TableName);&lt;br&gt;
DataRow[] rows &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; recordingDataSet.Artists.Select(String.Format(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"id={0}"&lt;/span&gt;,
artistId));&lt;br&gt;
&lt;br&gt;
&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt;&lt; 1) &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt; (rows.Length
return&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;null&lt;/span&gt;;&lt;br&gt;
&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;return&lt;/span&gt; (RecordingDataSet.Artist)
rows[0];&lt;br&gt;
}&lt;br&gt;
&gt;Class Diagram done in VS2008 with the Class Designer Powertoy http://www.codeplex.com/modeling&lt;br&gt;
To get the blue lines go to Class Diagram, Filter Lines, Show All Associations.&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/screen123456.gif" border="0"&gt;
&lt;br&gt;
&lt;/pre&gt;Sequence diagram done in Visio: (hmm - this is a bit complex... I prefer the
class diagram above with notes)&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/sequenceArtistFixture.jpg" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
Genre was next, then the rest. Then relationships between objects eg ReviewReviewer..
just testing the test data we create comes back: Have abstracted out some of the setup
code into ConnectionFixture.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt; [TestFixture] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; ReviewReviewerFixture
: ConnectionFixture { [Test] &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; ReviewerId()
{ RecordingDataSet recordingDataSet &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; RecordingDataSet();
ReviewGateway reviewGateway &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; ReviewGateway(Connection); &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;long&lt;/span&gt; reviewId &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; reviewGateway.Insert(recordingDataSet,
1, &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Review
Content"&lt;/span&gt;); ReviewerGateway reviewerGateway &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; ReviewerGateway(Connection); &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;long&lt;/span&gt; reviewerId &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; reviewerGateway.Insert(recordingDataSet, &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Reviewer
Name"&lt;/span&gt;); RecordingDataSet.Review review &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; reviewGateway.FindById(reviewId,
recordingDataSet); review.ReviewerId &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; reviewerId;
reviewGateway.Update(recordingDataSet); Assert.AreEqual(reviewerId, review.Reviewer.Id);
reviewGateway.Delete(recordingDataSet, reviewId); reviewerGateway.Delete(recordingDataSet,
reviewerId); } }&lt;/span&gt;&lt;/pre&gt;The hardest test is RecordingGateway, as it depends on
all the other 'tables'. To simplify, we abstract out the insert/del of test data to
RecordingBuilder.cs.&lt;br&gt;
&lt;br&gt;
The last class is Catalog, which is the only class that will be called from the Service
layer. In Catalog we have FindByRecordingId, which returns a RecordingDataSet.Recording
(so all the data associated with this recordingId).&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/DALOverview.jpg" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
In summary we have done this of the overall structure of the APP:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/DALDiag.gif" border="0"&gt;&lt;img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=1331c215-9394-48c3-922e-b705c2a62ff3" /&gt;</description>
      <comments>http://www.programgood.net/CommentView,guid,1331c215-9394-48c3-922e-b705c2a62ff3.aspx</comments>
      <category>Database</category>
      <category>Object Oriented Programming</category>
      <category>Patterns</category>
      <category>Testing</category>
    </item>
    <item>
      <trackback:ping>http://www.programgood.net/Trackback.aspx?guid=55ec44ed-b372-4d8b-a792-36192bb7fb9e</trackback:ping>
      <pingback:server>http://www.programgood.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.programgood.net/PermaLink,guid,55ec44ed-b372-4d8b-a792-36192bb7fb9e.aspx</pingback:target>
      <dc:creator>Dave Mateer</dc:creator>
      <wfw:comment>http://www.programgood.net/CommentView,guid,55ec44ed-b372-4d8b-a792-36192bb7fb9e.aspx</wfw:comment>
      <wfw:commentRss>http://www.programgood.net/SyndicationService.asmx/GetEntryCommentsRss?guid=55ec44ed-b372-4d8b-a792-36192bb7fb9e</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">A simple MVC (Model View Controller) implementation..code
by Jimmy Chandra<br />
http://stackoverflow.com/questions/1107720/mvc-c-simplest-possible-implementation<br /><br />
Why use MVC?  Similar reasons to MVP - testability and seperation of concerns<br /><br /><a href="http://www.programgood.net/content/binary/Simple.MVC.zip">Simple.MVC.zip
(167.25 KB)</a><br /><br /><img src="http://www.programgood.net/content/binary/Drawing4.gif" border="0" /><br /><br />
1. Program.cs runs, running Main.. as is standard in a Win Forms app.  Difference
from MVP is that main here is instantiating and running a controller class first of
all, instead of newing up the view, which calls the controller/presenter.<br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">static</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> Main()
{ Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">false</span>);
TopEmployeeController controller <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> TopEmployeeController();
Application.Run(controller.View <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">as</span> Form);
}</span></pre>2. Controller is instantiated and constructor called:<br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"> private</span> ITopEmployeeView
_view; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span> Employee
_employee; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">bool</span> _monitoring; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span> TopEmployeeController()
{ _employee <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> Employee();
_view <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> TopEmployeeForm(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">this</span>,
_employee); }<br /></span></pre>3. Controller news up an employee (dumb).. then a view of type TopEmployeeForm,
passing its self (the controller) and employee to it.<br /><br />
4. View (the observer) subscribes to the model (the subject) so that when model.OnPropertyChange
is called, view.UpdateView is called.  This is the observer pattern, made easier
in C# using events.. which is using a delegate. <pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"></span><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//
view</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span> TopEmployeeForm(ITopEmployeeController
controller, Employee model) { _controller <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> controller;
_model <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> model; <span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//Let
the model know that this view is interested if the model change</span> _model.OnPropertyChange
+= <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> Action(UpdateView);
InitializeComponent(); </span></pre>
}</span></pre>6. When Button is pressed on the view.  The controller.GetTopEmplyee
method is called.  This calls model.MontorChanges:<br /><pre><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"></span><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//
controller</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> GetTopEmployee()<br />
{<br /><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">if</span> (!_monitoring)<br />
{<br />
_monitoring <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">true</span>;<br />
_employee.MonitorChanges();<br />
}<br />
}</span><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><br /><br /><br /></span>7. MonitorChanges does some waiting code, then every second calls FirePropertyChange().
Which calls model.OnPropertyChange. 
<br />
Which is really a delegate to View.UpdateView<br /></pre><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//
model</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">event</span> Action
OnPropertyChange; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> FirePropertyChange()
{ var propChange <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> OnPropertyChange; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">if</span> (propChange
!<span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">null</span>)
{ OnPropertyChange(); } }<br /><br /></span></pre>8. The view method which runs every second and displays the name on the
form.<br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//
view</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> UpdateView()
{ <span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//
to do with threading</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">if</span> (<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">this</span>.InvokeRequired)
{ <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">this</span>.Invoke(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> Action(UpdateView));
} <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">else</span> {
TopEmployeeName <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> _model.FullName;
} }</span></pre><br /><br /><p></p><br /><a href="http://www.programgood.net/content/binary/Simple.MVC.zip"><br /></a><img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=55ec44ed-b372-4d8b-a792-36192bb7fb9e" /></body>
      <title>Simple MVC in WinForms</title>
      <guid isPermaLink="false">http://www.programgood.net/PermaLink,guid,55ec44ed-b372-4d8b-a792-36192bb7fb9e.aspx</guid>
      <link>http://www.programgood.net/2009/07/17/SimpleMVCInWinForms.aspx</link>
      <pubDate>Fri, 17 Jul 2009 20:16:06 GMT</pubDate>
      <description>A simple MVC (Model View Controller) implementation..code by Jimmy Chandra&lt;br&gt;
http://stackoverflow.com/questions/1107720/mvc-c-simplest-possible-implementation&lt;br&gt;
&lt;br&gt;
Why use MVC?&amp;nbsp; Similar reasons to MVP - testability and seperation of concerns&lt;br&gt;
&lt;br&gt;
&lt;a href="http://www.programgood.net/content/binary/Simple.MVC.zip"&gt;Simple.MVC.zip
(167.25 KB)&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/Drawing4.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
1. Program.cs runs, running Main.. as is standard in a Win Forms app.&amp;nbsp; Difference
from MVP is that main here is instantiating and running a controller class first of
all, instead of newing up the view, which calls the controller/presenter.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;static&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; Main()
{ Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;false&lt;/span&gt;);
TopEmployeeController controller &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; TopEmployeeController();
Application.Run(controller.View &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;as&lt;/span&gt; Form);
}&lt;/span&gt;&lt;/pre&gt;2. Controller is instantiated and constructor called:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt; private&lt;/span&gt; ITopEmployeeView
_view; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; Employee
_employee; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;bool&lt;/span&gt; _monitoring; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; TopEmployeeController()
{ _employee &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; Employee();
_view &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; TopEmployeeForm(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;,
_employee); }&lt;br&gt;
&lt;/span&gt;&lt;/pre&gt;3. Controller news up an employee (dumb).. then a view of type TopEmployeeForm,
passing its self (the controller) and employee to it.&lt;br&gt;
&lt;br&gt;
4. View (the observer) subscribes to the model (the subject) so that when model.OnPropertyChange
is called, view.UpdateView is called.&amp;nbsp; This is the observer pattern, made easier
in C# using events.. which is using a delegate. &lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;/span&gt;&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//
view&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; TopEmployeeForm(ITopEmployeeController
controller, Employee model) { _controller &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; controller;
_model &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; model; &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//Let
the model know that this view is interested if the model change&lt;/span&gt; _model.OnPropertyChange
+= &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; Action(UpdateView);
InitializeComponent(); &lt;/span&gt;&lt;/pre&gt;
}&lt;/span&gt;&lt;/pre&gt;6. When Button is pressed on the view.&amp;nbsp; The controller.GetTopEmplyee
method is called.&amp;nbsp; This calls model.MontorChanges:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;/span&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//
controller&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; GetTopEmployee()&lt;br&gt;
{&lt;br&gt;
&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt; (!_monitoring)&lt;br&gt;
{&lt;br&gt;
_monitoring &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;true&lt;/span&gt;;&lt;br&gt;
_employee.MonitorChanges();&lt;br&gt;
}&lt;br&gt;
}&lt;/span&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;7. MonitorChanges does some waiting code, then every second calls FirePropertyChange().
Which calls model.OnPropertyChange. 
&lt;br&gt;
Which is really a delegate to View.UpdateView&lt;br&gt;
&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//
model&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;event&lt;/span&gt; Action
OnPropertyChange; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; FirePropertyChange()
{ var propChange &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; OnPropertyChange; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt; (propChange
!&lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;null&lt;/span&gt;)
{ OnPropertyChange(); } }&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;/pre&gt;8. The view method which runs every second and displays the name on the
form.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//
view&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; UpdateView()
{ &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//
to do with threading&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt; (&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;.InvokeRequired)
{ &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;.Invoke(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; Action(UpdateView));
} &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;else&lt;/span&gt; {
TopEmployeeName &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; _model.FullName;
} }&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;br&gt;
&lt;a href="http://www.programgood.net/content/binary/Simple.MVC.zip"&gt;
&lt;br&gt;
&lt;/a&gt;&lt;img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=55ec44ed-b372-4d8b-a792-36192bb7fb9e" /&gt;</description>
      <comments>http://www.programgood.net/CommentView,guid,55ec44ed-b372-4d8b-a792-36192bb7fb9e.aspx</comments>
      <category>MVC</category>
      <category>Object Oriented Programming</category>
      <category>Patterns</category>
      <category>Testing</category>
    </item>
    <item>
      <trackback:ping>http://www.programgood.net/Trackback.aspx?guid=a4d78d60-874e-44ed-9fab-22a5620db068</trackback:ping>
      <pingback:server>http://www.programgood.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.programgood.net/PermaLink,guid,a4d78d60-874e-44ed-9fab-22a5620db068.aspx</pingback:target>
      <dc:creator>Dave Mateer</dc:creator>
      <wfw:comment>http://www.programgood.net/CommentView,guid,a4d78d60-874e-44ed-9fab-22a5620db068.aspx</wfw:comment>
      <wfw:commentRss>http://www.programgood.net/SyndicationService.asmx/GetEntryCommentsRss?guid=a4d78d60-874e-44ed-9fab-22a5620db068</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Easy to understand, working example WinForms
app using MVP (Model View Presenter) pattern.<br /><br />
Why use this pattern?  Testability and maintainability (ie loosely coupled so
less likely to break!)<br /><br />
Download <a href="http://www.programgood.net/content/binary/noddy.zip">noddy.zip (106.62
KB)</a> (VS2008)<br /><br />
Notes:<br />
View is dumb and does render logic<br />
View never talks to the model (or any business entity eg customer) directly<br />
Presenter retries data and manipulates<br />
Model is the data and business rules<br /><br />
usually MVP sits on top of an ORM or Database Abstraction / Business Logic layer:<br /><img src="http://www.programgood.net/content/binary/Drawing1.jpg" border="0" /><br /><br />
How it works:<br /><br />
1) Application comes to Program.cs which calls Form1.cs.. no MVP code here.<br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">static</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">class</span> Program
{ <span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">///
&lt;summary&gt;</span><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">///
The main entry point for the application.</span><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">///
Standard code.. nothing MVP</span><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">///
&lt;/summary&gt;</span> [STAThread] <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">static</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> Main()
{ Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">false</span>);
Application.Run(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> Form1());
} }</span></pre><br />
2) Form1 (which is the view in MVP) which implements IView interface (**why**).. instantiates
a new MainPresenter calling it presenter.<br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span> partial <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">class</span> Form1
: Form, IView { <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span> MainPresenter
presenter; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span> Form1()
{ InitializeComponent(); presenter <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> MainPresenter(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">this</span>);
} <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> btnPostCustomer_Click(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">object</span> sender,
EventArgs e) { presenter.PostCustomer(); } <span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//
IView members</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">string</span> FirstName
{ get { <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">return</span> txtFirstName.Text;
} set { txtFirstName.Text <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> value;
} } <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">string</span> LastName
{ get { <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">return</span> txtLastName.Text;
} set { txtLastName.Text <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> value;
} } <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> DisplayResult(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">string</span> result)
{ MessageBox.Show(result); } }</span></pre>3) MainPresenter constructor runs, and
is passed in the view object of type IView. (**could we have just passed it in as
a Form object?**)<br /><br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">class</span> MainPresenter
{ <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span> IView
view; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span> MainModel
model <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> MainModel(); <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span> MainPresenter(IView
view) { <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">this</span>.view <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> view;
} <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> PostCustomer()
{ Debug.Assert(view !<span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">null</span>); <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">try</span> {
Customer customer <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> Customer(view.FirstName,
view.LastName); model.PostCustomer(customer); view.DisplayResult(customer.ToString() <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">+</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"
posted"</span>); } <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">catch</span>(Exception
ex) { view.DisplayResult(ex.Message); } } }</span></pre>4) App is run, names are filled
in, and Post button is submitted.<br /><p></p><img src="http://www.programgood.net/content/binary/screendump.gif" border="0" /><br /><br />
5) View code (form1.cs) runs presenter.PostCustomer<br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">private</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> btnPostCustomer_Click(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">object</span> sender,
EventArgs e) { presenter.PostCustomer(); }</span></pre>6) presenter creates a new
customer (which could be seen as being outside of MVP, and more in an entity later,
as the model layer is usually light, and only relating the modelviews) and passes
in the names.  Nothing special on the constructor of customer.  
<br /><br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> PostCustomer()
{ Debug.Assert(view !<span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">null</span>); <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">try</span> {
Customer customer <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> Customer(view.FirstName,
view.LastName); model.PostCustomer(customer); view.DisplayResult(customer.FullName() <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">+</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"
posted"</span>); } <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">catch</span>(Exception
ex) { view.DisplayResult(ex.Message); } }<br /></span></pre>7) Presenter calls the main model to PostCustomer which writes out to
disk the Customer which has just been entered.<br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> PostCustomer(Customer
customer) { XmlSerializer serializer <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> XmlSerializer(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">typeof</span>(Customer)); <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">if</span> (File.Exists(<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"Customer.xml"</span>))
{ <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> (FileStream
stream <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> FileStream(<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"Customer.xml"</span>,
FileMode.Append, FileAccess.Write)) { serializer.Serialize(stream, customer); } } <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">else</span> { <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> (FileStream
stream <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> FileStream(<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"Customer.xml"</span>,
FileMode.Create, FileAccess.Write)) { serializer.Serialize(stream, customer); } }
}</span></pre><br /><br /><br />
8) Presenter calls the view to DisplayResult, passing in the customer data as a string.<br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> DisplayResult(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">string</span> result)
{ MessageBox.Show(result); }</span></pre><br /><br />
Included in the download are simple tests on the ViewModel and Domain model. 
Also Form2 which has a Form2Presenter.  Uses same ViewModel (hmm probably should
have a seperate one), and the same domain model (customer.cs).  Next step for
me is to get tests working on the Presenters.<br /><br /><br /><br /><br /><a href="http://www.programgood.net/content/binary/noddy.zip"></a><img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=a4d78d60-874e-44ed-9fab-22a5620db068" /></body>
      <title>Simple MVP</title>
      <guid isPermaLink="false">http://www.programgood.net/PermaLink,guid,a4d78d60-874e-44ed-9fab-22a5620db068.aspx</guid>
      <link>http://www.programgood.net/2009/07/16/SimpleMVP.aspx</link>
      <pubDate>Thu, 16 Jul 2009 02:38:59 GMT</pubDate>
      <description>Easy to understand, working example WinForms app using MVP (Model View Presenter) pattern.&lt;br&gt;
&lt;br&gt;
Why use this pattern?&amp;nbsp; Testability and maintainability (ie loosely coupled so
less likely to break!)&lt;br&gt;
&lt;br&gt;
Download &lt;a href="http://www.programgood.net/content/binary/noddy.zip"&gt;noddy.zip (106.62
KB)&lt;/a&gt; (VS2008)&lt;br&gt;
&lt;br&gt;
Notes:&lt;br&gt;
View is dumb and does render logic&lt;br&gt;
View never talks to the model (or any business entity eg customer) directly&lt;br&gt;
Presenter retries data and manipulates&lt;br&gt;
Model is the data and business rules&lt;br&gt;
&lt;br&gt;
usually MVP sits on top of an ORM or Database Abstraction / Business Logic layer:&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/Drawing1.jpg" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
How it works:&lt;br&gt;
&lt;br&gt;
1) Application comes to Program.cs which calls Form1.cs.. no MVP code here.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;static&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; Program
{ &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;///
&amp;lt;summary&amp;gt;&lt;/span&gt; &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;///
The main entry point for the application.&lt;/span&gt; &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;///
Standard code.. nothing MVP&lt;/span&gt; &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;///
&amp;lt;/summary&amp;gt;&lt;/span&gt; [STAThread] &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;static&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; Main()
{ Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;false&lt;/span&gt;);
Application.Run(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; Form1());
} }&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
2) Form1 (which is the view in MVP) which implements IView interface (**why**).. instantiates
a new MainPresenter calling it presenter.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; partial &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; Form1
: Form, IView { &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; MainPresenter
presenter; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; Form1()
{ InitializeComponent(); presenter &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; MainPresenter(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;);
} &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; btnPostCustomer_Click(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;object&lt;/span&gt; sender,
EventArgs e) { presenter.PostCustomer(); } &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//
IView members&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt; FirstName
{ get { &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;return&lt;/span&gt; txtFirstName.Text;
} set { txtFirstName.Text &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; value;
} } &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt; LastName
{ get { &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;return&lt;/span&gt; txtLastName.Text;
} set { txtLastName.Text &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; value;
} } &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; DisplayResult(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt; result)
{ MessageBox.Show(result); } }&lt;/span&gt;&lt;/pre&gt;3) MainPresenter constructor runs, and
is passed in the view object of type IView. (**could we have just passed it in as
a Form object?**)&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; MainPresenter
{ &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; IView
view; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; MainModel
model &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; MainModel(); &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; MainPresenter(IView
view) { &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;.view &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; view;
} &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; PostCustomer()
{ Debug.Assert(view !&lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;null&lt;/span&gt;); &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;try&lt;/span&gt; {
Customer customer &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; Customer(view.FirstName,
view.LastName); model.PostCustomer(customer); view.DisplayResult(customer.ToString() &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;+&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"
posted"&lt;/span&gt;); } &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;catch&lt;/span&gt;(Exception
ex) { view.DisplayResult(ex.Message); } } }&lt;/span&gt;&lt;/pre&gt;4) App is run, names are filled
in, and Post button is submitted.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img src="http://www.programgood.net/content/binary/screendump.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
5) View code (form1.cs) runs presenter.PostCustomer&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;private&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; btnPostCustomer_Click(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;object&lt;/span&gt; sender,
EventArgs e) { presenter.PostCustomer(); }&lt;/span&gt;&lt;/pre&gt;6) presenter creates a new
customer (which could be seen as being outside of MVP, and more in an entity later,
as the model layer is usually light, and only relating the modelviews) and passes
in the names.&amp;nbsp; Nothing special on the constructor of customer.&amp;nbsp; 
&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; PostCustomer()
{ Debug.Assert(view !&lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;null&lt;/span&gt;); &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;try&lt;/span&gt; {
Customer customer &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; Customer(view.FirstName,
view.LastName); model.PostCustomer(customer); view.DisplayResult(customer.FullName() &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;+&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"
posted"&lt;/span&gt;); } &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;catch&lt;/span&gt;(Exception
ex) { view.DisplayResult(ex.Message); } }&lt;br&gt;
&lt;/span&gt;&lt;/pre&gt;7) Presenter calls the main model to PostCustomer which writes out to
disk the Customer which has just been entered.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; PostCustomer(Customer
customer) { XmlSerializer serializer &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; XmlSerializer(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;typeof&lt;/span&gt;(Customer)); &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt; (File.Exists(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Customer.xml"&lt;/span&gt;))
{ &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; (FileStream
stream &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; FileStream(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Customer.xml"&lt;/span&gt;,
FileMode.Append, FileAccess.Write)) { serializer.Serialize(stream, customer); } } &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;else&lt;/span&gt; { &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; (FileStream
stream &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; FileStream(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Customer.xml"&lt;/span&gt;,
FileMode.Create, FileAccess.Write)) { serializer.Serialize(stream, customer); } }
}&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
8) Presenter calls the view to DisplayResult, passing in the customer data as a string.&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; DisplayResult(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt; result)
{ MessageBox.Show(result); }&lt;/span&gt;&lt;/pre&gt;
&lt;br&gt;
&lt;br&gt;
Included in the download are simple tests on the ViewModel and Domain model.&amp;nbsp;
Also Form2 which has a Form2Presenter.&amp;nbsp; Uses same ViewModel (hmm probably should
have a seperate one), and the same domain model (customer.cs).&amp;nbsp; Next step for
me is to get tests working on the Presenters.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://www.programgood.net/content/binary/noddy.zip"&gt;&lt;/a&gt;&lt;img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=a4d78d60-874e-44ed-9fab-22a5620db068" /&gt;</description>
      <comments>http://www.programgood.net/CommentView,guid,a4d78d60-874e-44ed-9fab-22a5620db068.aspx</comments>
      <category>MVP</category>
      <category>Patterns</category>
      <category>Testing</category>
    </item>
    <item>
      <trackback:ping>http://www.programgood.net/Trackback.aspx?guid=3836dd2e-344e-4b11-a6bb-a860ddf4c9f3</trackback:ping>
      <pingback:server>http://www.programgood.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.programgood.net/PermaLink,guid,3836dd2e-344e-4b11-a6bb-a860ddf4c9f3.aspx</pingback:target>
      <dc:creator>Dave Mateer</dc:creator>
      <wfw:comment>http://www.programgood.net/CommentView,guid,3836dd2e-344e-4b11-a6bb-a860ddf4c9f3.aspx</wfw:comment>
      <wfw:commentRss>http://www.programgood.net/SyndicationService.asmx/GetEntryCommentsRss?guid=3836dd2e-344e-4b11-a6bb-a860ddf4c9f3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <br />
        <br />
        <p>
        </p>
        <img src="http://www.programgood.net/content/binary/manAndGirl.jpg" border="0" />
        <br />
        <font size="1">Girl and man looking towards Mt Cook, NZ.</font>
        <br />
        <br />
To get nUnit working on VS 2008 Express, firstly download and install nUnit.<br /><br />
Make a new console application.  Add the 3 nunit references you see below<br /><br /><img src="http://www.programgood.net/content/binary/ref.gif" border="0" /><br /><br />
Open up the .csproj file.. in my case in: C:\code\stuff\HowNUnitInspiredConsole\HowNUnitInspiredConsole\HowNUnitInspiredConsole.csproj<br /><br />
Where you see... add in the two Startxxx lines.<br /><br />
 &lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU'
"&gt;<br /><br />
    &lt;StartAction&gt;Program&lt;/StartAction&gt;<br />
    &lt;StartProgram&gt;C:\Program Files\NUnit 2.4.8\bin\nunit.exe&lt;/StartProgram&gt;<br />
    
<br />
    &lt;DebugSymbols&gt;true&lt;/DebugSymbols&gt;<br />
    &lt;DebugType&gt;full&lt;/DebugType&gt;<br />
    &lt;Optimize&gt;false&lt;/Optimize&gt;<br />
    &lt;OutputPath&gt;bin\Debug\&lt;/OutputPath&gt;<br />
    &lt;DefineConstants&gt;DEBUG;TRACE&lt;/DefineConstants&gt;<br />
    &lt;ErrorReport&gt;prompt&lt;/ErrorReport&gt;<br />
    &lt;WarningLevel&gt;4&lt;/WarningLevel&gt;<br />
  &lt;/PropertyGroup&gt;<br /><br />
Here is my first unit test for a web app:<br /><br /><pre><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Collections.Generic; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Linq; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Text; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> NUnit.Framework; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Web.Script.Serialization; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Web.Util; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Net; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Web; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.IO; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">using</span> System.Diagnostics; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">namespace</span> HowNUnitInspiredConsole
{ <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">class</span> NUnitConsoleRunner
{ [STAThread] <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">static</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> Main(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">string</span>[]
args) { NUnit.ConsoleRunner.Runner.Main(args); } } [TestFixture] <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">class</span> FormTest
{ <span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//
1 is dev / local</span><span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;">//
2 is test</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">int</span> debugbit <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> 2; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">string</span> targetUri <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">""</span>; <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">string</span> targetUriNoHTTP <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">""</span>;
[SetUp] <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> Init()
{ <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">if</span> (debugbit
== 1) { targetUri <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"http://192.168.139.128/drink/"</span>;
targetUriNoHTTP <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"192.168.139.128/drink/"</span>;
} <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">if</span> (debugbit
== 2) { targetUri <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"http://www.davemateer.com/drink/"</span>;
targetUriNoHTTP <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"www.davemateer.com/drink/"</span>;
} } [Test] <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">public</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">void</span> helloWorld()
{ WebClient client <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> WebClient();
StreamReader reader <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">new</span> StreamReader(client.OpenRead(targetUri <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">+</span><span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"test/helloWorld.php"</span>)); <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;">string</span> responseFromServer <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;">=</span> reader.ReadToEnd();
Assert.AreEqual(<span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;">"Hello
World"</span>, responseFromServer); } } } </span></pre>When the nUnit gui popped up,
make sure it gets the correct .exe file.  I had to do a project add assembly,
while the application was running.<br /><br />
Run your application which should pop up with something like this:<br /><br /><br /><img src="http://www.programgood.net/content/binary/nunit1.gif" border="0" /><img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=3836dd2e-344e-4b11-a6bb-a860ddf4c9f3" /></body>
      <title>nUnit and Visual Studio 2008 Express</title>
      <guid isPermaLink="false">http://www.programgood.net/PermaLink,guid,3836dd2e-344e-4b11-a6bb-a860ddf4c9f3.aspx</guid>
      <link>http://www.programgood.net/2009/01/16/nUnitAndVisualStudio2008Express.aspx</link>
      <pubDate>Fri, 16 Jan 2009 02:24:03 GMT</pubDate>
      <description>&lt;br&gt;
&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img src="http://www.programgood.net/content/binary/manAndGirl.jpg" border="0"&gt;
&lt;br&gt;
&lt;font size="1"&gt;Girl and man looking towards Mt Cook, NZ.&lt;/font&gt;
&lt;br&gt;
&lt;br&gt;
To get nUnit working on VS 2008 Express, firstly download and install nUnit.&lt;br&gt;
&lt;br&gt;
Make a new console application.&amp;nbsp; Add the 3 nunit references you see below&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/ref.gif" border="0"&gt;
&lt;br&gt;
&lt;br&gt;
Open up the .csproj file.. in my case in: C:\code\stuff\HowNUnitInspiredConsole\HowNUnitInspiredConsole\HowNUnitInspiredConsole.csproj&lt;br&gt;
&lt;br&gt;
Where you see... add in the two Startxxx lines.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU'
"&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;StartAction&amp;gt;Program&amp;lt;/StartAction&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;StartProgram&amp;gt;C:\Program Files\NUnit 2.4.8\bin\nunit.exe&amp;lt;/StartProgram&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DebugSymbols&amp;gt;true&amp;lt;/DebugSymbols&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DebugType&amp;gt;full&amp;lt;/DebugType&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Optimize&amp;gt;false&amp;lt;/Optimize&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;OutputPath&amp;gt;bin\Debug\&amp;lt;/OutputPath&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DefineConstants&amp;gt;DEBUG;TRACE&amp;lt;/DefineConstants&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ErrorReport&amp;gt;prompt&amp;lt;/ErrorReport&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;WarningLevel&amp;gt;4&amp;lt;/WarningLevel&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;/PropertyGroup&amp;gt;&lt;br&gt;
&lt;br&gt;
Here is my first unit test for a web app:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Collections.Generic; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Linq; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Text; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; NUnit.Framework; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Web.Script.Serialization; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Web.Util; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Net; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Web; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.IO; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;using&lt;/span&gt; System.Diagnostics; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;namespace&lt;/span&gt; HowNUnitInspiredConsole
{ &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; NUnitConsoleRunner
{ [STAThread] &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;static&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; Main(&lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt;[]
args) { NUnit.ConsoleRunner.Runner.Main(args); } } [TestFixture] &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;class&lt;/span&gt; FormTest
{ &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//
1 is dev / local&lt;/span&gt; &lt;span style="color: Green; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;//
2 is test&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;int&lt;/span&gt; debugbit &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; 2; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt; targetUri &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;""&lt;/span&gt;; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt; targetUriNoHTTP &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;""&lt;/span&gt;;
[SetUp] &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; Init()
{ &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt; (debugbit
== 1) { targetUri &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"http://192.168.139.128/drink/"&lt;/span&gt;;
targetUriNoHTTP &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"192.168.139.128/drink/"&lt;/span&gt;;
} &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt; (debugbit
== 2) { targetUri &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"http://www.davemateer.com/drink/"&lt;/span&gt;;
targetUriNoHTTP &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"www.davemateer.com/drink/"&lt;/span&gt;;
} } [Test] &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;public&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;void&lt;/span&gt; helloWorld()
{ WebClient client &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; WebClient();
StreamReader reader &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;new&lt;/span&gt; StreamReader(client.OpenRead(targetUri &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;+&lt;/span&gt; &lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"test/helloWorld.php"&lt;/span&gt;)); &lt;span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;string&lt;/span&gt; responseFromServer &lt;span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; reader.ReadToEnd();
Assert.AreEqual(&lt;span style="color: rgb(102, 102, 102); background-color: rgb(228, 228, 228); font-family: Courier New; font-size: 11px;"&gt;"Hello
World"&lt;/span&gt;, responseFromServer); } } } &lt;/span&gt;&lt;/pre&gt;When the nUnit gui popped up,
make sure it gets the correct .exe file.&amp;nbsp; I had to do a project add assembly,
while the application was running.&lt;br&gt;
&lt;br&gt;
Run your application which should pop up with something like this:&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;img src="http://www.programgood.net/content/binary/nunit1.gif" border="0"&gt;&lt;img width="0" height="0" src="http://www.programgood.net/aggbug.ashx?id=3836dd2e-344e-4b11-a6bb-a860ddf4c9f3" /&gt;</description>
      <comments>http://www.programgood.net/CommentView,guid,3836dd2e-344e-4b11-a6bb-a860ddf4c9f3.aspx</comments>
      <category>Testing</category>
    </item>
  </channel>
</rss>