tag:blogger.com,1999:blog-24202919527338612792024-02-09T02:23:12.696+10:00MaxSoft Tech BlogA meander through Maxsoft Group's technical team's thoughts and experiences with things mostly technical.Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-2420291952733861279.post-42706776371135261242009-03-13T16:20:00.001+10:002009-03-13T16:22:50.225+10:00WCF auto generated client proxy classes - instantiation gotchaWCF auto-generated client proxy classes all implement IDisposable. This makes them candidates for instantiating via using statements i.e.:<br /><br /><span style="font-family: courier new;">using (MyServiceBindingClient client = new MyServiceBindingClient())</span><br /><span style="font-family: courier new;">{</span><br /><span style="font-family: courier new;">    client.Open();</span><br /><span style="font-family: courier new;">}</span><br /><br />This approach should not be taken when working with WCF client proxy classes. This is because if an exception is thrown within the try block above, you will never get to see the true exception:<br /><br />The problem is that if the client.Open() call (or any subsequent calls placed on the client) throws an exception, we end up leaving the using block, which causes our client’s IDisposable interface to get fired. The Dispose routine on WCF classes have a bad tendency to then fire another exception at that point, because we are attempting to perform a close() operation on the client but it has already faulted. And so the exception that eventually gets caught by any surrounding try/catch block will be the exception thrown by calling close() on a faulted client. It will not be the original exception, and the original exception is not accessable via the InnerException property.<br /><br />Microsoft’s recommended way of avoiding this situation is to not instantiate WCF clients via using statements. I.e. instantiate/use them as per non-IDisposable’s, and make sure you have appropriate exception handling and explicit calls to dispose your IDisposable.Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-30060144279730823872009-02-26T15:31:00.000+10:002009-02-26T15:33:19.462+10:00Back porting SQL Server 2005 to 2000<span style="font-weight: bold; font-style: italic;">Background</span><br /><br />We had a SQL Server 2005 DotNetNuke database full of proprietary data that we needed to back-port to SQL Server 2000, due to a limitation on the eventual destination hosting site.<br /><br /><br /><span style="font-weight: bold; font-style: italic;">The Problem</span><br /><br />SQL Server 2000 will not natively restore databases from backups made on SQL Server 2005, and will not attach SQL Server 2005 data/log files. So we needed to find an alternative way to move our data and schema objects from the SQL 2005 instance back to 2000. Something like Redgate, but perhaps a little cheaper and simpler if possible.<br /><br /><br /><span style="font-weight: bold; font-style: italic;">The Solution</span><br /><br />Microsoft offers a free download called the SQL Server 2005 Database Publishing Wizard. This tool presents a wizard-style interface that allows you to script out your database in its entirety (all data and objects) into a single SQL script. This script can be targeted at either SQL Server 2000 or 2005. <br /><br />With just a few mouse clicks we had generated a single SQL script that contained our entire database. The script ran up perfectly first time under SQL Server 2000, giving us the desired result of our DotNetNuke database being back-ported successfully to SQL Server 2000.<br /><br />The tool can be found at:<br /><br /><a href="Background%20%20We%20had%20a%20SQL%20Server%202005%20DotNetNuke%20database%20full%20of%20proprietary%20data%20that%20we%20needed%20to%20back-port%20to%20SQL%20Server%202000,%20due%20to%20a%20limitation%20on%20the%20eventual%20destination%20hosting%20site.%20%20%20The%20Problem%20%20SQL%20Server%202000%20will%20not%20natively%20restore%20databases%20from%20backups%20made%20on%20SQL%20Server%202005,%20and%20will%20not%20attach%20SQL%20Server%202005%20data/log%20files.%20%20So%20we%20needed%20to%20find%20an%20alternative%20way%20to%20move%20our%20data%20and%20schema%20objects%20from%20the%20SQL%202005%20instance%20back%20to%202000.%20%20Something%20like%20Redgate,%20but%20perhaps%20a%20little%20cheaper%20and%20simpler%20if%20possible.%20%20%20The%20Solution%20%20Microsoft%20offers%20a%20free%20download%20called%20the%20SQL%20Server%202005%20Database%20Publishing%20Wizard.%20%20This%20tool%20presents%20a%20wizard-style%20interface%20that%20allows%20you%20to%20script%20out%20your%20database%20in%20its%20entirety%20%28all%20data%20and%20objects%29%20into%20a%20single%20SQL%20script.%20%20This%20script%20can%20be%20targeted%20at%20either%20SQL%20Server%202000%20or%202005.%20%20%20%20With%20just%20a%20few%20mouse%20clicks%20we%20had%20generated%20a%20single%20SQL%20script%20that%20contained%20our%20entire%20database.%20%20The%20script%20ran%20up%20perfectly%20first%20time%20under%20SQL%20Server%202000,%20giving%20us%20the%20desired%20result%20of%20our%20DotNetNuke%20database%20being%20back-ported%20successfully%20to%20SQL%20Server%202000.%20%20The%20tool%20can%20be%20found%20at:%20%20http://www.microsoft.com/downloads/details.aspx?familyid=56E5B1C5-BF17-42E0-A410-371A838E570A&displaylang=en">http://www.microsoft.com/downloads/details.aspx?familyid=56E5B1C5-BF17-42E0-A410-371A838E570A&displaylang=en</a>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-52984508121105029172008-12-08T12:07:00.004+10:002008-12-08T12:33:42.184+10:00C# enums and aliases - weird behaviour<span style="font-size: 10pt;font-size:85%;" ><i><b>Jon has been playing with enum values, and fond some apparently inconsistent behaviour from the compiler.</b></i></span></span></p> <p lang="en-US"><span style="font-family:Verdana, sans-serif;"><span style="font-size: 10pt;font-size:85%;" >Notes from this example:</span></span></p> <ul><li><p><span style="font-family:Verdana, sans-serif;"><span style="font-size: 10pt;font-size:85%;" ><span lang="en-US">If you’re going to set an enum value, set all of them.</span></span></span></p> </li><li><p><span style="font-family:Verdana, sans-serif;"><span style="font-size: 10pt;font-size:85%;" ><span lang="en-US">If the value aligns to a table or values used in the database, always set all of the values in the enum.</span></span></span></p> </li></ul> <p><span style="font-family:Verdana, sans-serif;"><span style="font-size: 10pt;font-size:85%;" ><span lang="en-US">Also, notice how TestA becomes an alias of TestB, yet TestE becomes an alias of TestD, see how this appears to be reversed.</span></span></span></p> <p lang="en-US"><span style="font-family:Verdana, sans-serif;"><span style="font-size: 10pt;font-size:85%;" >I was quite surprised with this but it seems it has something to do with TestB being set prior to TestE being set.</span></span></p> <p><br /><br /></p> <p style="margin-bottom: 0cm;"><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">using</span></span></span></span> <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">System;<br /></span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">namespace</span></span></span></span> <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestConsoleApp<br />{<br /></span></span></span>   <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">class</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Program<br /></span></span></span></span>   <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">{<br /></span></span></span>      <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">enum</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType<br /></span></span></span></span>      <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">{<br /></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestA, </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// TestA is an alias of TestB<br /></span></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestB = 0,<br /></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestC,<br /></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestD,<br /></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestE = 2, </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// TestE is an alias of TestD<br /></span></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestF,<br /></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestG = 6,<br /></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestH<br /></span></span></span>      <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">}<br /></span></span></span> <br />      <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">static</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> </span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">void</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> Main(</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">string</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">[] args)<br /></span></span></span>      <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">{<br /></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> dc1 = </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestB;<br /></span></span></span> <br />         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">if</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> (dc1 == </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestA)<br /></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">{ <br /></span></span></span>            <span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// since TestA is just an alias to TestB this works.<br /></span></span></span></span>            <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"No compile warning is bad."</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">);<br /></span></span></span>         <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">}<br /></span></span></span> <br />         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> a = (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestA; </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// alias of TestB<br /></span></span></span></span>         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> b = (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestB;<br /></span></span></span>         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> c = (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestC;<br /></span></span></span>         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> d = (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestD;<br /></span></span></span>         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> e = (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestE; </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// alias of TestD<br /></span></span></span></span>         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> f = (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestF;<br /></span></span></span>         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> g = (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestG;<br /></span></span></span>         <span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> h = (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestH;<br /></span></span></span> <br />         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestA, a); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestB – 0'<br /></span></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestB, b); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestB – 0'<br /></span></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestC, c); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestC – 1'<br /></span></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestD, d); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestD – 2'<br /></span></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestE, e); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestD – 2'<br /></span></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestF, f); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestF – 3'<br /></span></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestG, g); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestG – 6'<br /></span></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, </span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.TestH, h); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestH – 7'<br /></span></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine();<br /></span></span></span> <br />         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US"> type = (</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Enum</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.Parse(</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">typeof</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">(</span></span></span><span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">TestType</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">), </span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"TestA"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">);<br /></span></span></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.WriteLine(</span></span></span><span style="color:#a31515;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">"{0} - {1}"</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">, type, (</span></span></span><span style="color:#0000ff;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">int</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">)type); </span></span></span><span style="color:#008000;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">// Prints 'TestB – 0'</span></span></span></span></p> <p style="margin-bottom: 0cm;"><span style="color:#008000;"> <br /></span>         <span style="color:#2b91af;"><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">Console</span></span></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">.ReadKey();<br /></span></span></span>      <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">}<br /></span></span></span>   <span style="font-family:Courier New;"><span style="font-size:85%;"><span lang="en-US">}<br />}<br /></span></span></span><br /></p> <p><br /><br /></p> <p style="margin-bottom: 0cm;"><br /></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-14230790873630365912008-10-24T13:56:00.002+10:002008-10-24T13:59:59.934+10:00SQL Server - Date Time accuracy<p class="MsoNormal">This does not work as expected:<o:p style="font-family: courier new;"><br /></o:p></p> <p class="MsoNormal"><span style="font-family: courier new;">SET @day1159pm = DATEADD(millisecond,-1,DATEADD(day,1,@dayMidnight))</span><o:p><br /></o:p></p> <p class="MsoNormal">If <span style="font-family: courier new;">@dayMidnight</span> was 1/1/01 then <span style="font-family: courier new;">@day1159pm</span> will equal 2/1/01. It seems that it doesn’t keep <span style="font-family: courier new;">DATETIME </span>with enough precision to subtract 1 millisecond. Use this instead:<o:p><br /></o:p></p> <p style="font-family: courier new;" class="MsoNormal">SET @day1159pm = DATEADD(<b><s><span style="background: yellow none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">milli</span></s></b>second,-1,DATEADD(day,1,@dayMidnight))<o:p></o:p></p> <p class="MsoNormal"><o:p>---</o:p></p><p class="MsoNormal"><o:p><br />The reason for this is provided in the Transact-SQL reference:</o:p></p><p class="indent">Date and time data from January 1, 1753 through December 31, 9999<span style="color: red;">, <b>to an accuracy of one three-hundredth of a second</b></span> (equivalent to 3.33 milliseconds or 0.00333 seconds). Values are rounded to increments of .000, .003, or .007 seconds, as shown in the table.<o:p></o:p></p> <table class="MsoNormalTable" style="width: 428.25pt;" width="571" border="1" cellpadding="0"> <tbody> <tr> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal" style="text-align: center;" align="center"><b><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">Example<o:p></o:p></span></b></p></td> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal" style="text-align: center;" align="center"><b><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">Rounded example<o:p></o:p></span></b></p></td></tr> <tr> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal"><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">01/01/98 23:59:59.999<o:p></o:p></span></p></td> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal"><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">1998-01-02 00:00:00.000<o:p></o:p></span></p></td></tr> <tr> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal"><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">01/01/98 23:59:59.995,<br />01/01/98 23:59:59.996,<br />01/01/98 23:59:59.997, or<br />01/01/98 23:59:59.998<o:p></o:p></span></p></td> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal"><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">1998-01-01 23:59:59.997<o:p></o:p></span></p></td></tr> <tr> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal"><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">01/01/98 23:59:59.992,<br />01/01/98 23:59:59.993,<br />01/01/98 23:59:59.994<o:p></o:p></span></p></td> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal"><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">1998-01-01 23:59:59.993<o:p></o:p></span></p></td></tr> <tr> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal"><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">01/01/98 23:59:59.990 or<br />01/01/98 23:59:59.991<o:p></o:p></span></p></td> <td style="padding: 1.5pt; width: 50%;" valign="top" width="50%"> <p class="MsoNormal"><span style="font-size: 12pt; font-family: 'Times New Roman','serif';">1998-01-01 23:59:59.990<o:p></o:p></span></p></td></tr></tbody></table> <p class="MsoNormal"><span style="color: rgb(31, 73, 125);"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="color: rgb(31, 73, 125);"><o:p> </o:p></span></p><p class="MsoNormal"><br /><o:p></o:p></p><p class="MsoNormal"><o:p><br /></o:p></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-82135322113966910162008-08-06T15:05:00.002+10:002008-08-06T15:12:54.361+10:00Memory leak in FAXCOMEXLib<!--[if gte mso 9]><xml> <w:worddocument> <w:view>Normal</w:View> <w:zoom>0</w:Zoom> <w:punctuationkerning/> <w:validateagainstschemas/> <w:saveifxmlinvalid>false</w:SaveIfXMLInvalid> <w:ignoremixedcontent>false</w:IgnoreMixedContent> <w:alwaysshowplaceholdertext>false</w:AlwaysShowPlaceholderText> <w:compatibility> <w:breakwrappedtables/> <w:snaptogridincell/> <w:wraptextwithpunct/> <w:useasianbreakrules/> <w:dontgrowautofit/> </w:Compatibility> <w:browserlevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:latentstyles deflockedstate="false" latentstylecount="156"> </w:LatentStyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; mso-ansi-language:EN-AU; mso-fareast-language:EN-AU;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 89.85pt 72.0pt 89.85pt; mso-header-margin:35.45pt; mso-footer-margin:35.45pt; mso-paper-source:0;} div.Section1 {page:Section1;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]--> <p class="MsoNormal"><span style=""><o:p><span style="font-style: italic;">Yuan has been working on a fax / e-mail / SMS etc server we use internally and also give to our clients, and has come across some strange behavior in Microsoft's COM wrapper to the fax console.</span><br /></o:p></span></p><br /> <p class="MsoNormal"><span style="">Recently I have been working on our communications toolset – which manages our SMTP, FTP, SMS and Fax sending..</span></p><span style=""></span><br /><p class="MsoNormal"><span style="">The application has 2 major components: An ASP.NET application to view, search and manage messages and message batches being sent; And a windows service which periodically queries the database to send any queued messages.<o:p></o:p></span></p> <br /> <p class="MsoNormal"><span style="">Each of the message types is run in its own thread with SMTP, FTP and SMS working for years with no problem. <o:p></o:p></span></p> <br /> <p class="MsoNormal"><span style="">However, a few weeks after deploying the new Fax component, we began to receive “Out of memory” log traces.<o:p></o:p></span></p> <br /> <p class="MsoNormal"><span style="">After a little investigation, I narrowed down the problem to a FAXCOMEXLib memory leak. Read below fo the details:<o:p></o:p></span></p> <br /> <p class="MsoNormal"><span style="">To queue a fax, we use FAXCOMEXLib - which is a Microsoft COM wrapper to the windows fax console. <span style=""> </span>Once the server sends a fax to the console, the fax thread polls to check whether the fax job terminated successfully. The code we use to poll the fax queue is shown below:<o:p></o:p></span></p> <br /> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">         <span style="color: blue;">Try<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            faxServer.Folders.OutgoingArchive.Refresh()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            iterator = faxServer.Folders.OutgoingArchive.GetMessages(FAX_QUEUE_DEFAULT_PREFETCH) <span style="color: green;">' This routine exhibits the memory leak</span><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            iterator.MoveFirst()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            <span style="color: blue;">For</span> i <span style="color: blue;">As</span> <span style="color: blue;">Integer</span> = 1 <span style="color: blue;">To</span> filesCount<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               iterator.MoveNext()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: blue;">If</span> <span style="color: blue;">Not</span> iterator.Message <span style="color: blue;">Is</span> <span style="color: blue;">Nothing</span> <span style="color: blue;">Then<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: blue;">Dim</span> FaxRecipient <span style="color: blue;">As</span> Recipient = GetRecipientForFax(iterator.Message.Id)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: green;">'<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: green;">'     Recipient will be null if the fax job was added to the fax server<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: green;">'     by anything other than this service.<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: green;">'<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: blue;">If</span> <span style="color: blue;">Not</span> FaxRecipient <span style="color: blue;">Is</span> <span style="color: blue;">Nothing</span> <span style="color: blue;">AndAlso</span> FaxRecipient.Status <> FaxRecipient.Statuses.sent.ToString() <span style="color: blue;">Then<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     <span style="color: green;">' Acknowledge fax has been sent<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     FaxRecipient.ActMarkAsSent()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     FaxRecipient.save()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     <span style="color: blue;">Dim</span> LogMessage <span style="color: blue;">As</span> <span style="color: blue;">String</span> = <span style="color: blue;">String</span>.Format("CR_ID: {0} Fax sent successfully", FaxRecipient.ID)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     Log.write(MaxSoft.Common.Log.LevelEnum.INFO, <span style="color: blue;">Me</span>, LOG_AREA, LogMessage)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: blue;">End</span> <span style="color: blue;">If<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  Marshal.ReleaseComObject(iterator.Message)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: blue;">End</span> <span style="color: blue;">If<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            <span style="color: blue;">Next<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">         <span style="color: blue;">Finally<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            faxServer.Disconnect()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            Marshal.ReleaseComObject(faxServer.Folders.OutgoingArchive)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            Marshal.ReleaseComObject(faxServer)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            <span style="color: blue;">If</span> <span style="color: blue;">Not</span> iterator <span style="color: blue;">Is</span> <span style="color: blue;">Nothing</span> <span style="color: blue;">Then<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               Marshal.ReleaseComObject(iterator)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            <span style="color: blue;">End</span> <span style="color: blue;">If<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            iterator = <span style="color: blue;">Nothing<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            faxServer = <span style="color: blue;">Nothing<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">         <span style="color: blue;">End</span> <span style="color: blue;">Try<o:p></o:p></span></span></p> <br /> <p class="MsoNormal"><span style="">As you can see in the code above, we iterate through the files in the OutgoingArchive folder of the fax console and match the id with the id stored in our message queue. Unfortunately, every time we call the </span><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">faxServer.Folders.OutgoingArchive.GetMessages </span><span style="">the Microsoft COM dll leaks memory. With a little more research, we determined that if the ArchiveFolder was empty, there was no memory leak, and that the size of the memory leak was directly proportional to the number of files in the FAXCOMEXLib folder. <o:p></o:p></span></p> <br /> <p class="MsoNormal"><span style="">Once tracked down, we tried a number of options to dispose the object correctly including using Marshal.REleaseComObject, but with no luck. It appears that the problem is not in the disposal of the FAXCOMEXLib object, but in one of the underlying private objects or code used by FAXCOMEXLib. Since these objects are not exposed via COM, we cannot code around the memory leak.<o:p></o:p></span></p> <br /> <p class="MsoNormal"><span style="">After briefly considering restarting the windows service periodically I went and had a cup of coffee, and the solution came to me. Don't use FAXCOMEXLib.<o:p></o:p></span></p><br /><span style="">Since I know that FAXCOMEXLib persists the completed faxes as a physical file in a known location, and that the filenames are the same as the id, we can get to the completed faxes by going through the physical filesystem rather then through the FAXCOMEXLib queue.<o:p></o:p></span><br /><br /> <p class="MsoNormal"><span style="">H</span><span lang="EN-AU">ere is the refactored code with no leaking:</span></p> <br /> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">         <span style="color: blue;">Try<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            <span style="color: blue;">Dim</span> unsentFaxRecipientTrackings <span style="color: blue;">As</span> <span style="color: blue;">New</span> RecipientDeliveryTrackingList<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            unsentFaxRecipientTrackings.loadFromSQL(<span style="color: red;">"SELECT tr.* FROM tblCommRecipientDeliveryTracking tr JOIN tblCommRecipient cr ON tr.CR_Id = cr.CR_Id WHERE cr.CR_Status = 'sending'"</span>, <span style="color: blue;">Nothing</span>, CommandType.Text, -1)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            <span style="color: blue;">If</span> unsentFaxRecipientTrackings.Count > 0 <span style="color: blue;">Then<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: blue;">Dim</span> archiveFolder <span style="color: blue;">As</span> <span style="color: blue;">String</span> = faxServer.Folders.OutgoingArchive.ArchiveFolder<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: blue;">Dim</span> allFiles <span style="color: blue;">As</span> <span style="color: blue;">New</span> Hashtable<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: green;">' Load files into hashtable<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: blue;">For</span> <span style="color: blue;">Each</span> fileName <span style="color: blue;">As</span> <span style="color: blue;">String</span> <span style="color: blue;">In</span> System.IO.Directory.GetFiles(archiveFolder)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: green;">' The file name format is LoginUserID$MessageID.tif<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: blue;">If</span> fileName.Split(<span style="color: red;">"$"</span>).Length > 1 <span style="color: blue;">Then<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     fileName = fileName.Split("$"c)(1).Replace(<span style="color: red;">".tif"</span>, <span style="color: red;">""</span>)</span></p><p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     allFiles.Add(fileName, fileName)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: blue;">End</span> <span style="color: blue;">If<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: blue;">Next<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New"; color: blue;" lang="EN-AU"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: blue;">For</span> <span style="color: blue;">Each</span> FaxTracking <span style="color: blue;">As</span> RecipientDeliveryTracking <span style="color: blue;">In</span> unsentFaxRecipientTrackings<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: blue;">If</span> allFiles.ContainsKey(FaxTracking.FaxDocId) <span style="color: blue;">Then<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     <span style="color: blue;">Dim</span> recipient <span style="color: blue;">As</span> <span style="color: blue;">New</span> recipient<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     recipient.loadFromSQL(<span style="color: red;">"SELECT * FROM tblCommRecipient WHERE CR_Id = "</span> & FaxTracking.CR_Id.ToString(), <span style="color: blue;">Nothing</span>, CommandType.Text, -1)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     <span style="color: green;">' Might be a chance that someone remove the record from database manually<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     <span style="color: blue;">If</span> <span style="color: blue;">Not</span> recipient.isNew <span style="color: blue;">Then<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                        recipient.ActMarkAsSent()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                        recipient.save()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                        <span style="color: blue;">Dim</span> LogMessage <span style="color: blue;">As</span> <span style="color: blue;">String</span> = <span style="color: blue;">String</span>.Format(<span style="color: red;">"CR_ID: {0} Fax sent successfully"</span>, FaxTracking.CR_Id)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                        Log.write(MaxSoft.Common.Log.LevelEnum.INFO, <span style="color: blue;">Me</span>, LOG_AREA, LogMessage)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                     <span style="color: blue;">End</span> <span style="color: blue;">If<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">                  <span style="color: blue;">End</span> <span style="color: blue;">If<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">               <span style="color: blue;">Next<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            <span style="color: blue;">End</span> <span style="color: blue;">If<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">         <span style="color: blue;">Finally<o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            faxServer.Disconnect()<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">            Marshal.ReleaseComObject(faxServer)<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New";" lang="EN-AU">         <span style="color: blue;">End</span> <span style="color: blue;">Try</span></span><span style="font-size: 11pt; font-family: Calibri;" lang="EN-AU"><o:p></o:p></span></p> <br /> <p class="MsoNormal"><span style="">So, rather than ask FAXCOMEXLib to return a list of messages, I go to the file system and get them myself. Happily FAXCOMEXLib aids with this approach, and will happily provide the physical path to </span><span lang="EN-AU">Folders.OutgoingArchive.ArchiveFolder. </span></p> <br /> <p class="MsoNormal"><span lang="EN-AU">Since failed messages do not go into the OutgoingArchive.ArchiveFolder, we do not need any additional fax metadata. </span></p> <br /> <p class="MsoNormal"><span lang="EN-AU">Result: After running for 1 week, no memory leak found.</span></p> <p class="MsoNormal"><span lang="EN-AU">Tools: .NET Memory Profiler</span><span style="font-size: 11pt; font-family: Calibri;"><o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU"><o:p> </o:p></span></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com1tag:blogger.com,1999:blog-2420291952733861279.post-41873669420494175732008-07-04T13:51:00.001+10:002008-07-04T15:25:58.184+10:00QUT adds up the benefits of SmartaPayQUT announced today that Queensland based company SmartaPay had completed installation of the SmartaPay solution. For the first time students will be able to pay ALL their University and Student fees through a new custom designed payment solution built by SmartaPay, specifically for QUT<br /><br />QUT and SmartaPay have spent the past 18 months designing and building the payment solution to ensure that the functionality of SmartaPay’s solution will provide all QUT businesses with<br />• Shopping Cart<br />• Online Catalogue<br />• Pay Now and Pay Later<br />• Invoice Generation and Payment<br />• Reconciliation<br /><br />“We made a decision two years ago to replace our previous student payment option with a more sophisticated and integrated payment solution" said Terry Leighton, Director of Corporate Finance at Queensland University of Technology. "This is just another step in ensuring our University stays at the forefront of Technology advancements as we provide the optimum solutions for our current students and our future students.”<br /><br />QUT, ‘the University for the Real World’, is one of Australia’s largest universities servicing in excess of 35,000 students across four campuses. QUT aims to strengthen its distinctive national and international reputation by combining academic strength and practical engagement with the world of the professions, industry, government, and the broader community.<br />Tony Irvine, Chief Operating Officer of SmartaPay, “We’re excited to be chosen by QUT as a partner in building the University’s new Payment Solution. This solution will be a market leader in the education arena and an achievement that both QUT and SmartaPay will be justly proud of.”<br /><br />SmartaPay is a payment facilitator for Universities and Private Schools Australia wide. SmartaPay’s solution will cater for all types of payers and payment channels, from online internet payments to paying fees over the counter or by cheque, and deliver a single interface to QUT.<br /><br />“SmartaPay’s business is built on a foundation of providing unique and fully integrated end to end billing and payment solutions” explains Dorian Borin, Chief Information Officer of SmartaPay. “We have a proven track record in providing customized solutions to all our SmartaPay clients”.<br /><br />For more information please contact SmartaPay on 07 5575 7422 or email info@smartapay.com.auKent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-24550983945902852972008-06-17T13:45:00.003+10:002008-06-17T13:56:29.386+10:00Simple dynamic compiling to mock a Console Application<span style="font-style: italic;">Toby has written a follow up to ‘Spawning a console application and tracking its Standard Output’ found <a href="http://maxsoft-tech.blogspot.com/2008/02/spawning-console-application-and.html">here</a>.</span><br /><br /><span style="font-style: italic;">This article deals with unit testing an application that relies on interaction with a console application.</span><br /><br />The problem is making the console application behave in a specific manner for the unit tests. For instance, simulating network issues, file access issues, strange multiple file issues and so on can be a right pain in the neck. Throw in other factors such as the speed of the unit tests with a large console application running, trying to automate the setting up of an entire staged environment and invoking a complex, production only and sometimes cranky console application makes this a challenge I'm keen to avoid.<br /><br />A simpler approach is to mock the external console application, so that the mocked application returns exactly what you need to test the behaviour of your own application.<br /><br />We have a few options to solve this, along with the negatives of the approach:<br /><ul><li>Making a <span style="font-weight: bold;">simple batch file</span> to accept input, and spit out the correct text on demand<br />- Limited interaction potential, validation etc<br />- No access to .NET goodness</li><li>Writing a <span style="font-weight: bold;">bunch of .NET console apps</span> which are compiled as part of the solution<br />- Too many projects to maintain<br />- Hard coded and not flexible for different environments</li><li><span style="font-weight: bold;">Dynamically generate</span> console apps on the fly with environmental changes as needed<br />- Sounds like a solution to me !!!</li></ul><br /><span style="font-weight: bold;font-size:130%;" >Writing the mocked console application</span><br /><br />The following test code sample shows messages being written to Standard Output and files being created. You will need a separate mock application for each test that you need to perform.<br /><br /><span style="font-size:85%;"><span style="font-family:courier new;">namespace TestApplication<br />{<br />   class Program<br />   {<br />      static void Main(string[] args)<br />      {<br />         Console.WriteLine(@"Connected to www.externalserver.com made.");<br />         // put download files here<br />         StreamWriter sw = new StreamWriter(@"C:\DownloadFiles\File1");<br />         Console.WriteLine("Downloading file File1");<br />         sw.Write("Text Content of File 1");<br />         sw.Close();<br /><br />         sw = new StreamWriter(@"C:\DownloadFiles\File2");<br />         Console.WriteLine("Downloading file File2");<br />         sw.Write("Text Content of File 2");<br />         sw.Close();<br /><br />         Console.WriteLine(@"Closed Connection.");<br />      }<br />   }<br />}</span></span><br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Dynamically generating mock console applications on the fly</span></span><br /><br />The source code for each test application is included in my solution as a string resource called TestScript. The source code is then compiled on the fly to an executable file. The code to compile the resource is:<br /><br /><span style="font-size:85%;"><span style="font-family:courier new;">Microsoft.CSharp.CSharpCodeProvider cscp = new Microsoft.CSharp.CSharpCodeProvider();<br />System.CodeDom.Compiler.CompilerParameters param = new System.CodeDom.Compiler.CompilerParameters();<br />param.GenerateExecutable = true;<br />param.OutputAssembly = @"c:\App.EXE";<br /><br />foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())<br />{<br />    param.ReferencedAssemblies.Add(assembly.Location);<br />}<br />System.CodeDom.Compiler.CompilerResults results = cscp.CompileAssemblyFromSource(param, TestScript.Test1);</span></span><br /><br />Because this works from text, there is also the opportunity to use <span style="font-family: courier new;font-size:85%;" >string.Replace </span>to manage paths specific to the testing environment.<br /><br />Setting <span style="font-family: courier new;font-size:85%;" >param.GenerateExecutable </span>to true causes an executable to be generated instead of a dll. Put the file name to generate to in <span style="font-size:85%;"><span style="font-family: courier new;">param.OutputAssembly</span></span>.<br /><br />The above code assumes that the assemblies required to be referenced are the same as the currently executing application. This is achieved via the for loop. This can be altered by adding specific assemblies to <span style="font-family: courier new;font-size:85%;" >param.ReferencedAssemblies</span> in addition to, or instead of this loop.<br /><br />If you are in an experimenting mood, any compiler directives available via the compiler options in Visual Studio are available to you. Have a play with <span style="font-size:85%;"><span style="font-family: courier new;">System.CodeDom.Compiler.CompilerParameters.CompilerOptions;</span></span>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-62265104266406155712008-06-02T09:54:00.001+10:002008-06-02T09:55:37.375+10:00XP SP3 changes the Remote Desktop Connection command<p class="MsoNormal"><span lang="EN-US">After installing XP SP 3 you will need to use this to connect to the console session on a server:<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p style="font-family: courier new;"></o:p><span style="font-family: courier new; color: rgb(51, 102, 255);">mstsc /admin</span><o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Instead of<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><span style="font-family: courier new; color: rgb(51, 102, 255);">mstsc /console</span><o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-58699684900752735632008-05-28T17:07:00.002+10:002008-05-28T17:26:34.076+10:00Creating a service using a batch file<span style="font-weight: bold; font-style: italic;">Sometimes we need a quick and dirty method of installing a windows service. </span><br /><br /><span style="font-weight: bold; font-style: italic;">The official method via the DOS prompt is uses the SC command. This command is one of the most unusual command line tools I have seen for a while ... the syntax for the parameters is "xxx= yy" - the space after the = and the lack of space before the = sign is mandatory. Adding quotes around pathnames requires escaping a quote after the initial quote. SC CREATE also appears not to set the ERRORLEVEL parameter for the batch file.</span><br /><br /><span style="font-weight: bold; font-style: italic;">This all makes SC a highly infuriating tool.</span><br /><br /><span style="font-weight: bold; font-style: italic;">Because of this, some users prefer hacking the registry directly while others create WIX install packages (the preferred method, but a but hard for a quick and dirty test). </span><br /><br /><span style="font-weight: bold; font-style: italic;">The code sample below shows a batch file that can easily be modified to add a service with a dependancy on the TCPIP service that will automatically start up when Windows cranks up. There's another one below that to delete the service, but unfortunately, you seem to have to reboot to really get rid of the service.<br /><br />It uses a nifty method to get the path of the batch file.<br /><br />It really needs to be rewritten to use Windows PowerShell.<br /></span><br /><span style="font-family: courier new;">@echo off</span><br /><br /><span style="font-family: courier new;">REM Installs A service</span><br /><span style="font-family: courier new;">REM -----------------------------------------</span><br /><span style="font-family: courier new;">REM Created by MaxSoft Group KB</span><br /><span style="font-family: courier new;">REM (c) 2008</span><br /><br /><span style="font-family: courier new;">REM -----------------------------------------</span><br /><span style="font-family: courier new;">REM CHANGE THESE VARIABLES BELOW TO REFLECT</span><br /><span style="font-family: courier new;">REM THE SERVICE PARAMETERS</span><br /><span style="font-family: courier new;">REM Set up the specific variables</span><br /><span style="font-family: courier new;">REM Assumes that the service is from the same directory as the batch file unless specified as the first parameter</span><br /><br /><span style="font-family: courier new;">SET PROGRAM_NAME=BroadcastEventService.exe</span><br /><span style="font-family: courier new;">SET SERVICE_NAME=SP_BroadcastEvents</span><br /><span style="font-family: courier new;">SET DISPLAY_NAME=StrataPay Broadcast Events</span><br /><span style="font-family: courier new;">SET INSTALL_DIR=%1</span><br /><br /><span style="font-family: courier new;">REM -----------------------------------------</span><br /><span style="font-family: courier new;">REM DO NOT CHANGE ANY TEXT BELOW THIS LINE</span><br /><br /><span style="font-family: courier new;">SET OLD_PROMPT=%PROMPT%</span><br /><span style="font-family: courier new;">PROMPT $f$f$f$f</span><br /><br /><span style="font-family: courier new;">IF "%INSTALL_DIR%"=="" GOTO GET_CURRENTPATH</span><br /><span style="font-family: courier new;">GOTO INSTALL</span><br /><br /><span style="font-family: courier new;">:GET_CURRENTPATH</span><br /><span style="font-family: courier new;">REM Get the directory of the install without destroying the current directory with the new PUSHD command</span><br /><span style="font-family: courier new;">pushd %0\..</span><br /><span style="font-family: courier new;">rem cd /d %0\..</span><br /><span style="font-family: courier new;">SET INSTALL_DIR=%CD%</span><br /><span style="font-family: courier new;">popd</span><br /><br /><span style="font-family: courier new;">:INSTALL</span><br /><span style="font-family: courier new;">REM Now install the service</span><br /><span style="font-family: courier new;">REM SC does not seem to set the errorlevel, resulting in commands</span><br /><span style="font-family: courier new;">REM being executed regardless of the success of the SC CREATE.</span><br /><br /><span style="font-family: courier new;">@echo on</span><br /><span style="font-family: courier new;">SC CREATE %SERVICE_NAME% binpath= "\"%INSTALL_DIR%\%PROGRAM_NAME%\"" displayname= "%DISPLAY_NAME%" depend= Tcpip start= auto</span><br /><span style="font-family: courier new;">@IF %ERRORLEVEL% NEQ 0 GOTO ERROR</span><br /><br /><span style="font-family: courier new;">NET START %SERVICE_NAME%</span><br /><span style="font-family: courier new;">@IF %ERRORLEVEL% NEQ 0 GOTO ERROR</span><br /><br /><span style="font-family: courier new;">:GOOD</span><br /><span style="font-family: courier new;">GOTO END</span><br /><br /><span style="font-family: courier new;">:ERROR</span><br /><span style="font-family: courier new;">@echo off</span><br /><span style="font-family: courier new;">echo ))))-----------------------------------------------</span><br /><span style="font-family: courier new;">echo ))))An error occurred.</span><br /><span style="font-family: courier new;">echo ))))-----------------------------------------------</span><br /><br /><span style="font-family: courier new;">:END</span><br /><span style="font-family: courier new;">PROMPT %OLD_PROMPT%</span><br /><br /><br /><span style="font-weight: bold; font-style: italic;">The command to delete a service is shown below (Less generic but just as easy):</span><br /><br /><br /><span style="font-family: courier new;">@echo off</span><br /><span style="font-family: courier new;">REM Delete the service</span><br /><br /><span style="font-family: courier new;">NET STOP SP_BroadcastEvents</span><br /><span style="font-family: courier new;">SC delete SP_BroadcastEvents</span><br /><br /><span style="font-family: courier new;">echo</span><br /><span style="font-family: courier new;">echo You will have to restart the machine to action this command</span>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-36325651398681594992008-05-28T13:41:00.003+10:002008-05-28T13:46:23.801+10:00SQL Error handling<span style="font-weight: bold; font-style: italic;">SQL Server is a great tool, but when you are handling large volumes of queries that run automatically, you need a good framework wrapped around each query to ensure that if something out of the ordinary happens, you not only know about it, but it does not adversely imact your data.</span><br /><br /><span style="font-weight: bold; font-style: italic;">Below is the an excerpt from our SQL Server wiki</span><br /><br />Critical Errors can cause unexpected results within a transaction. Actions taken before the critical error will be rolled back and the transaction closed. Remaining actions will be performed without a transaction wrappper. <p> To overcome this we have developed a template for scripts that provide a reasonable expectation of all or nothing output for scripted updates. </p><p> This template is recommended for changes to existing schema particularly if data is present in the table being modified. </p><p> The template consists of a generic header and footer for the transaction handling. Each command is followed by a generic code block to ensure a transaction remains in effect.<br /></p><br /><code><span style="font-family: Courier New; font-size: 10pt;"><code><span style="font-family: Courier New; font-size: 10pt;"><br /><span style="color: green; font-style: italic;">-----------------------------------------------------------------</span><br /><span style="color: green; font-style: italic;">-- STANDARD ERROR HANDLING - HEADER START</span><br /><span style="color: green; font-style: italic;">-----------------------------------------------------------------</span><br /><span style="color: blue;">IF</span> <span style="color: blue;">EXISTS</span> <span style="color: silver;">(</span><span style="color: blue;">SELECT</span> <span style="color: silver;">*</span><br /> <span style="color: blue;">FROM</span> <span style="color: maroon;">tempdb</span><span style="color: silver;">.</span><span style="color: silver;">.</span><span style="color: maroon;">sysobjects</span><br /> <span style="color: blue;">WHERE</span> <span style="color: maroon;">id</span> <span style="color: silver;">=</span> <span style="color: fuchsia; font-weight: bold;">Object_id</span><span style="color: silver;">(</span><span style="color: red;">'tempdb..#tmpErrors'</span><span style="color: silver;">)</span><span style="color: silver;">)</span><br /> <span style="color: blue;">DROP</span> <span style="color: blue;">TABLE</span> <span style="color: maroon;">#tmperrors</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">CREATE</span> <span style="color: blue;">TABLE</span> <span style="color: maroon;">#tmperrors</span> <span style="color: silver;">(</span><br /> <span style="color: maroon;">error</span> <span style="color: black;">INT</span><span style="color: silver;">)</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">SET</span> <span style="color: maroon;">xact_abort</span> <span style="color: maroon;">on</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">SET</span> <span style="color: blue;">TRANSACTION</span> <span style="color: maroon;">isolation</span> <span style="color: blue;">LEVEL</span> <span style="color: maroon;">serializable</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">BEGIN</span> <span style="color: blue;">TRANSACTION</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: green; font-style: italic;">-----------------------------------------------------------------</span><br /><span style="color: green; font-style: italic;">-- STANDARD ERROR HANDLING - HEADER END</span><br /><span style="color: green; font-style: italic;">-----------------------------------------------------------------</span><br /><br /><span style="color: green; font-style: italic;">-- INSERT YOUR FIRST STATEMENT HERE</span><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">IF</span> <span style="color: fuchsia;">@@ERROR</span> <span style="color: silver;"><></span> <span style="color: black;">0</span><br /> <span style="color: blue;">AND</span> <span style="color: fuchsia;">@@TRANCOUNT</span> <span style="color: silver;">></span> <span style="color: black;">0</span><br /> <span style="color: blue;">ROLLBACK</span> <span style="color: blue;">TRANSACTION</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">IF</span> <span style="color: fuchsia;">@@TRANCOUNT</span> <span style="color: silver;">=</span> <span style="color: black;">0</span><br /> <span style="color: blue;">BEGIN</span><br /> <span style="color: blue;">INSERT</span> <span style="color: blue;">INTO</span> <span style="color: maroon;">#tmperrors</span><br /> <span style="color: silver;">(</span><span style="color: maroon;">error</span><span style="color: silver;">)</span><br /> <span style="color: blue;">SELECT</span> <span style="color: black;">1</span><br /> <br /> <span style="color: blue;">BEGIN</span> <span style="color: blue;">TRANSACTION</span><br /> <span style="color: blue;">END</span><br /><br /><span style="color: blue;">GO</span> <br /><br /><span style="color: green; font-style: italic;">-- INSERT YOUR SECOND STATEMENT HERE AND REPEAT THE BELOW BLOCK AFTER EACH SUBSEQUENT STATEMENT</span><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">IF</span> <span style="color: fuchsia;">@@ERROR</span> <span style="color: silver;"><></span> <span style="color: black;">0</span><br /> <span style="color: blue;">AND</span> <span style="color: fuchsia;">@@TRANCOUNT</span> <span style="color: silver;">></span> <span style="color: black;">0</span><br /> <span style="color: blue;">ROLLBACK</span> <span style="color: blue;">TRANSACTION</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">IF</span> <span style="color: fuchsia;">@@TRANCOUNT</span> <span style="color: silver;">=</span> <span style="color: black;">0</span><br /> <span style="color: blue;">BEGIN</span><br /> <span style="color: blue;">INSERT</span> <span style="color: blue;">INTO</span> <span style="color: maroon;">#tmperrors</span><br /> <span style="color: silver;">(</span><span style="color: maroon;">error</span><span style="color: silver;">)</span><br /> <span style="color: blue;">SELECT</span> <span style="color: black;">1</span><br /> <br /> <span style="color: blue;">BEGIN</span> <span style="color: blue;">TRANSACTION</span><br /> <span style="color: blue;">END</span><br /><br /><span style="color: blue;">GO</span> <br /><br /><span style="color: green; font-style: italic;">-----------------------------------------------------------------</span><br /><span style="color: green; font-style: italic;">-- STANDARD ERROR HANDLING - FOOTER START</span><br /><span style="color: green; font-style: italic;">-----------------------------------------------------------------</span><br /><span style="color: blue;">IF</span> <span style="color: blue;">EXISTS</span> <span style="color: silver;">(</span><span style="color: blue;">SELECT</span> <span style="color: silver;">*</span><br /> <span style="color: blue;">FROM</span> <span style="color: maroon;">#tmperrors</span><span style="color: silver;">)</span><br /> <span style="color: blue;">ROLLBACK</span> <span style="color: blue;">TRANSACTION</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">IF</span> <span style="color: fuchsia;">@@TRANCOUNT</span> <span style="color: silver;">></span> <span style="color: black;">0</span><br /> <span style="color: blue;">BEGIN</span><br /> <span style="color: blue;">PRINT</span> <span style="color: red;">'The database update succeeded'</span><br /> <br /> <span style="color: blue;">COMMIT</span> <span style="color: blue;">TRANSACTION</span><br /> <span style="color: blue;">END</span><br /><span style="color: blue;">ELSE</span><br /> <span style="color: blue;">PRINT</span> <span style="color: red;">'The database update failed'</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">DROP</span> <span style="color: blue;">TABLE</span> <span style="color: maroon;">#tmperrors</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: blue;">IF</span> <span style="color: fuchsia;">@@TRANCOUNT</span> <span style="color: silver;">></span> <span style="color: black;">0</span><br /> <span style="color: blue;">BEGIN</span><br /> <span style="color: blue;">PRINT</span> <span style="color: red;">'CRITICAL PROBLEM - TRANSACTION STILL OPEN - '</span> <span style="color: silver;">+</span> <span style="color: fuchsia; font-weight: bold;">CONVERT</span><span style="color: silver;">(</span><span style="color: black;">VARCHAR</span><span style="color: silver;">,</span><span style="color: fuchsia;">@@TRANCOUNT</span><span style="color: silver;">)</span> <span style="color: silver;">+</span> <span style="color: red;">' STILL ACTIVE'</span><br /> <span style="color: blue;">END</span><br /><br /><span style="color: blue;">GO</span><br /><br /><span style="color: green; font-style: italic;">-----------------------------------------------------------------</span><br /><span style="color: green; font-style: italic;">-- STANDARD ERROR HANDLING - FOOTER END</span><br /><span style="color: green; font-style: italic;">-----------------------------------------------------------------</span></span></code></span></code>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-25863197145264702322008-04-22T16:39:00.004+10:002008-04-23T08:33:05.887+10:00XHTML<p class="MsoNormal"><i style=""><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">Dorian: Never really looked at XHTML before. All I know was you had to close your tags. I learned a little more today.<o:p></o:p></span></i></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">All tags have to be lower case e.g. <img .. instead of <IMG.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">I had to convert some HTML 4.01 markup to XHTML 1.0. Here is what I did.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">I used <a href="http://validator.w3.org/" title="blocked::http://validator.w3.org/">http://validator.w3.org/</a> to check my code. It will take a URL, a file upload or you can cut and paste your source in. I just cut and pasted my source as the site wasn’t public and it was derived markup from ASP.Net 3.5.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">At first seeing 50 errors was daunting but it wasn’t hard to trim down to perfection.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">The bulk of the issues it found were unclosed <br> tags which should be <br/> and unclosed <img …> tags. Every upper case <IMG> tag generated lots of errors because it also complained about each attribute because upper case IMG is an unknown tag. Making the <IMG> tags lower case stripped off heaps of errors.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri; color: rgb(31, 73, 125);" lang="EN-US">The other big error count creator is no quotes on attributes. E.g. <table cellspacing=0> instead of <table cellspacing=”0”><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">The one that took me a little more time to absorb was the markup like this:<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><div><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><span><o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><div><o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"></div><o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><div><o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"></div><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"></span><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"></div><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">The inner divs are invalid. You can’t have a div in a span in XHTML. The probably was the inner divs needed to be full width blocks. The span was automatically generated by a standard ASP.Net control. The way to solve it was this:<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><div><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><span><o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><span style=”display:block;”><o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"></span><o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><span style=”display:block;”><o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"></span><o:p></o:p></span></p> <p class="MsoNormal" style="text-indent: 36pt;"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"></span><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"></div><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">Of course I used CSS rather than doing a ugly style attribute hack.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US">So that was my 10 mins self learning intro into HTML to XHTML conversion. Interestingly while it seems popular Thinking that XHTML is the better way to go for future proofing HTML 5 which is still in draft has support for both nice XML tagging and old style HTML using different doc types. They probably don’t want to break the world.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri; color: rgb(31, 73, 125);">One thing I’m yet to solve is that this is invalid.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri; color: rgb(31, 73, 125);"><a href=”http://somewhere” disabled=”disabled”>something</a><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri; color: rgb(31, 73, 125);">There appears to be no way to disable a link from being clicked without javascript. ASP.Net generates this markup. The only work around it to render the disabled links as labels.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 11pt; font-family: Calibri;" lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><o:p> </o:p></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-83582800778931523082008-04-22T16:35:00.001+10:002008-04-22T16:37:20.131+10:00ASP.NET tips<div class="Section1"> <p class="MsoNormal"><span lang="EN-US"><span style="font-style: italic;">From Dorian: Here is a summary of the tips I’ve come up with so that you can build websites that can be deployed with precompilation.</span><br /><o:p> </o:p></span><br /><b><u><span lang="EN-US">TIP: Don’t use duplicate class names<o:p></o:p></span></u></b></p> <p class="MsoNormal"><span lang="EN-US"><o:p></o:p>While developing ASP.Net will keep all your pages and controls in separate dlls. It groups some controls together into one dll if they are in the same folder but at other times is keeps them separate. I’ve not determine exactly how it chooses. With this partitioning you would not very lucky run into a problem with two classes in your web site with the same name. If you attempt to merge the site into one dll (using aspnet_merge) however it would fail. I recommend naming your classes based on the directory structure using an _ instead of a slash. That will keep class names unique.<br /><o:p> </o:p></span></p> <p class="MsoNormal"><b><u><span lang="EN-US">TIP: Don’t assume .ascx or .master files exist</span></u></b><span lang="EN-US"><o:p><br /></o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Whilst in a development environment the .ascx and .master files exist under the website. After precompilation they do not. Never assume that they exist. The reason for doing this would be dynamic <b>user</b> control loading. Dynamic user control loading should be done by attempting to load the class and caching its presence. You will need to catch an exception to detect failure. I’ve spent a couple of hours looking for a work around and there is none that I can see.<br /><o:p> </o:p></span></p> <p class="MsoNormal"><b><u><span lang="EN-US">TIP: Don’t reference generated classes</span></u></b><span lang="EN-US"><o:p><br /></o:p></span></p> <p class="MsoNormal"><span lang="EN-US">The following shows examples of good and bad. Whilst the bad code will work while you develop you will not be able to deploy with precompiliation.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span><br /><b><u>User Control Reference</u></b><br />Bad:<br /><br />Dim singleProductDisplay As ASP.bvmodules_controls_singleproductdisplay_ascx = DirectCast(row.FindControl("SingleProductDisplay"), ASP.bvmodules_controls_singleproductdisplay_ascx)<br /><br />Good:<br /><br />Dim singleProductDisplay As <b><span style="color: rgb(153, 0, 0);">BVModules_Controls_SingleProductDisplay</span></b> = DirectCast(row.FindControl("SingleProductDisplay"), <b><span style="color: rgb(153, 0, 0);">BVModules_Controls_SingleProductDisplay</span></b>)<br /><br /><b><u>Master Page Reference</u></b><br />Bad:<br /><br />If TypeOf Me.Master Is ASP.bvadmin_bvadminproduct_master Then<br />DirectCast(Me.Master, ASP.bvadmin_bvadminproduct_master).ShowProductDisplayPanel = False<br /><br />Good:<br /><br />If TypeOf Me.Master Is <b><span style="color: rgb(153, 0, 0);">BVAdmin_BVAdminProduct</span></b> Then<br />DirectCast(Me.Master, <b><span style="color: rgb(153, 0, 0);">BVAdmin_BVAdminProduct</span></b>).ShowProductDisplayPanel = False<o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> <p class="MsoNormal"><b><u>ASP.Net Precompilation</u></b><o:p><br /></o:p></p> <p class="MsoNormal"><span lang="EN-US">ASP.Net precompilation has a variety of options. You can chose to leave your aspx and ascx files in place and precompile the rest. This lets you change the HTML of those controls after deployment without recompilation. This is the same as VS2003 did it. You can chose to precompile everything. And you can go one step further to merge all the dlls into one big dll. For both VS2005 and VS2008 you can install a Web Deployment Project type into VS that will make it easier to do all this.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p></div>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-48163567169976737212008-04-10T16:58:00.003+10:002008-04-10T17:13:22.037+10:00Validating web service content against an XSD<p class="MsoNormal" style=""><br /><i><span style="" lang="EN-AU">Rodney has been working with a SOA implementation at one of our clients. As a result, we have changed how we deal with web services, to provide additional clarity and robustness to the WS-I standards that Microsoft utilises.<br /></span></i><span style="" lang="EN-AU"><br />Recently we decided to split our web service definitions into 3 distinct files:</span><o:p></o:p></p> <ol start="1" type="1"><li class="MsoNormal" style=""><span style="" lang="EN-AU">An XSD to define the structure of the data (the parameters and returned data).</span><o:p></o:p></li><li class="MsoNormal" style=""><span style="" lang="EN-AU">A WSDL to define the operations that the web service will make available.</span><o:p></o:p></li><li class="MsoNormal" style=""><span style="" lang="EN-AU">A second WSDL to define the bindings (such as SOAP) used to communicate with the web service.</span><o:p></o:p></li></ol> <p class="MsoNormal" style=""><span style="" lang="EN-AU">We create a C# interface from these three files using wsdl.exe. We create a web service in our web site, add this interface into our library and tweak the code to make it implicitly implement the interface.</span><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">This is quite easy and works very effectively. There is however one overlooked problem with this approach. Although the interface and associated classes were generated from an XSD and WSDL, the XSD is not strongly enforced from the web service. For example, the XSD may define a string maximum length:</span><br /><span style="font-size: 12pt; font-family: courier new;" lang="EN-AU"><br />  </span><span style="font-size: 12pt; font-family: courier new; color: blue;">   <</span><span style="font-size: 12pt; font-family: courier new; color: rgb(163, 21, 21);">xsd:simpleType</span><span style="font-size: 12pt; font-family: courier new; color: blue;"> </span><span style="font-size: 12pt; font-family: courier new; color: red;">name</span><span style="font-size: 12pt; font-family: courier new; color: blue;">=</span><span style="font-size: 12pt; font-family: courier new;">"<span style="color: blue;">String20</span>"<span style="color: blue;">></span><br /></span><span style="font-size: 12pt; font-family: courier new; color: blue;">      <</span><span style="font-size: 12pt; font-family: courier new; color: rgb(163, 21, 21);">xsd:restriction</span><span style="font-size: 12pt; font-family: courier new; color: blue;"> </span><span style="font-size: 12pt; font-family: courier new; color: red;">base</span><span style="font-size: 12pt; font-family: courier new; color: blue;">=</span><span style="font-size: 12pt; font-family: courier new;">"<span style="color: blue;">xsd:string</span>"<span style="color: blue;">></span><br /></span><span style="font-size: 12pt; font-family: courier new; color: blue;">         <</span><span style="font-size: 12pt; font-family: courier new; color: rgb(163, 21, 21);">xsd:maxLength</span><span style="font-size: 12pt; font-family: courier new; color: blue;"> </span><span style="font-size: 12pt; font-family: courier new; color: red;">value</span><span style="font-size: 12pt; font-family: courier new; color: blue;">=</span><span style="font-size: 12pt; font-family: courier new;">"<span style="color: blue;">20</span>"<span style="color: blue;">/></span><br /></span><span style="font-size: 12pt; font-family: courier new; color: blue;">      </</span><span style="font-size: 12pt; font-family: courier new; color: rgb(163, 21, 21);">xsd:restriction</span><span style="font-size: 12pt; font-family: courier new; color: blue;">></span><span style="font-size: 12pt; font-family: courier new;"><br /></span><span style="font-size: 12pt; font-family: courier new; color: blue;">   </</span><span style="font-size: 12pt; font-family: courier new; color: rgb(163, 21, 21);">xsd:simpleType</span><span style="font-size: 12pt; font-family: courier new; color: blue;">></span><span style="font-size: 12pt; font-family: courier new;" lang="EN-AU"><br /> </span><span style="font-size: 12pt; font-family: "Times New Roman";"><!--[endif]--></span><span style=";font-family:CodingFontTobi;color:blue;" ><br /></span>The problem is that the web service created in this manner will allow a client to pass a string of length > 20. Not the desired outcome, since the XSD should be doing the work for us.<o:p></o:p></p> <p class="MsoNormal" style=""><br /><span style="" lang="EN-AU">The reason this happens is that the web service doesn’t reference the XSD, nor does it define any attributes on a property to restrict the length. When you look at the schema automatically generated from the web service (http://myserver/mywebservice.asmx?schema=schema1), it uses the class structure to define the schema and therefore does not have the restrictions.</span><br /><span style="" lang="EN-AU">Validating all the values using code can be quite cumbersome and might not necessarily match the validation of the XSD. If the XSD is changed, then the code will also need to be altered to reflect the changes made to the XSD. Again, not a desired outcome.</span><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">Another approach is to validate the input data against the XSD from within the body of the web method. This can cause some problems since every individual parameter needs to be serialized to XML and compared to the XSD. Again, if the XSD changes and a new parameter is added, then the programmer has to remember to add the new parameter and ensure that it is validated against the schema. If this is a really large web service, on a high load site, this can be a significant overhead.</span><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">Enter SoapExtensions.</span><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">SoapExtensions allow you to perform validation on the incoming XML string before it is de-serialised into CLR objects.</span><o:p></o:p></p> <p class="MsoNormal" style=""><b><u><span style="" lang="EN-AU">Once Only Setup</span></u></b><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">SoapExtensions require a once only setup to create custom attribute classes stored in your reusable library.</span><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">A number of classes derived from the SoapAttribute abstract class need to be created. Some will be used to decorate the web service class to define the schemas while others are required to decorate the web methods to force validation. Coded correctly, these allow you to pass in a specific XSD or a directory full of XSD files to validate against at runtime.</span><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">In addition you will need to create a ValidationExtension class to perform the actual validation using the .NET XML library on the incoming XML message stream and XSD collection.<br />The full detail of the implementation can be found at <a href="http://msdn2.microsoft.com/en-us/magazine/cc164115.aspx">http://msdn2.microsoft.com/en-us/magazine/cc164115.aspx</a>.</span><o:p></o:p></p> <p class="MsoNormal" style=""><b><u><span style="" lang="EN-AU">Web Service Specific Setup</span></u></b><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">Armed with these new classes, validation on the incoming XML stream is now achieved via the following simple steps:<br /></span><br />1. <b><span style="" lang="EN-AU">Setup the web.config to use the new ValidationExtension class</span></b><br /><br /><span style="font-size: 12pt; font-family: "Courier New"; color: blue;"><</span><span style="font-size: 12pt; font-family: "Courier New"; color: rgb(163, 21, 21);">webServices</span><span style="font-size: 12pt; font-family: "Courier New"; color: blue;">></span><span style="font-size: 12pt; font-family: "Courier New";"><br /><span style="color: blue;">    <</span><span style="color: rgb(163, 21, 21);">soapExtensionTypes</span><span style="color: blue;">></span><br /><span style="color: blue;">        <</span><span style="color: rgb(163, 21, 21);">add</span><span style="color: blue;"> </span><span style="color: red;">type</span><span style="color: blue;">=</span>"<span style="color: blue;">MaxSoft.Web.Services.Validation.ValidationExtension, MaxSoftDll</span>" <span style="color: red;">priority</span><span style="color: blue;">=</span>"<span style="color: blue;">1</span>"<span style="color: blue;"> </span><span style="color: red;">group</span><span style="color: blue;">=</span>"<span style="color: blue;">High</span>"<span style="color: blue;"> /></span><br /><span style="color: blue;">    </</span><span style="color: rgb(163, 21, 21);">soapExtensionTypes</span><span style="color: blue;">></span><br /><span style="color: blue;"></</span><span style="color: rgb(163, 21, 21);">webServices</span><span style="color: blue;">><br /> <!--[if !supportLineBreakNewLine]--></span></span><br /><b>2. Decorate your class to point to the XSD file(s)</b><o:p></o:p></p> <p class="MsoNormal" style="">If you follow the msdn article above you will be able to point to a specific XSD, or a directory of XSD schema files. Both are shown below.<o:p></o:p></p> <p class="MsoNormal" style=""><span style=";font-family:";" >[<span style="color: rgb(43, 145, 175);">ValidationSchemaCache</span>(<span style="color: rgb(163, 21, 21);">"~/Schemas/"</span>)]<br />[<span style="color: rgb(43, 145, 175);">ValidationSchema</span>(<span style="color: rgb(163, 21, 21);">"~/Schemas/MySchema.xsd"</span>)]<br /></span><br /><b>3. Decorate your web method to trigger the actual validation</b><o:p></o:p></p> <p class="MsoNormal" style=""><span style=";font-family:";" >[<span style="color: rgb(43, 145, 175);">Validation</span>(CheckAssertions = <span style="color:blue;">false</span>)]<o:p></o:p></span></p> <p class="MsoNormal" style=""><b><span style="" lang="EN-AU">4. Optionally you can add more complex validation to compliment the XSD</span></b><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">If CheckAssertions is set to true, you can provide additional validation logic which cannot be expressed in the XSD schema. An example is shown below: </span><o:p></o:p></p> <p class="MsoNormal" style=""><span style=";font-family:";" >[<span style="color: rgb(43, 145, 175);">Assert</span>(<span style="color: rgb(163, 21, 21);">"(//t:length > //t:width)"</span>, <span style="color: rgb(163, 21, 21);">"Length must be greater than width"</span>)]<o:p></o:p></span></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">Although the capability is there, we don't use this feature.</span> In fact, we have set the default value of CheckAssertions to false.<o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">Not only does CheckAssertions add overhead to the validation, but it stores important business logic in an attribute of the web method rather than in the entity library, obviously poor practice. This additional business logic should be in a library for reuse, testability and for a raft of other reasons.</span><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">Note:</span><o:p></o:p></p> <p class="MsoNormal" style=""><span style="" lang="EN-AU">This code in Microsoft's was written in 1.1 and you need to make some significant changes for it to run against newer versions of .Net as many of the classes are now marked as obsolete.</span><o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-27841379595147984152008-04-02T15:59:00.014+10:002008-04-02T17:10:06.812+10:00HP RDYMSG DISPLAY is funIt was April 01 a few days ago, and I decided to pull a small prank on the office. Unfortunately, it was a little subtle(No one has commented yet), but it was fun to put the code together.<br /><br />The prank is based on some old l0pht code hanging around on this web site: http://www.irongeek.com/i.php?page=security/hphack which sent some HP Printer Job Language code to a networked printer, changing the "READY" prompt to whatever you choose.<br /><br />I guess the next logical step is to interrogate the Active Directory and automate the process ... or more evil would be to interrogate an IP range, since that would give you access to printers you cannot access via the AD. Evil.<br /><br />The entire HP command set I found here: http://printers.necsam.com/public/printers/pclcodes/pcl5hp.htm<br /><br />Guys, don't do this at work.<br /><br />As always, blogger eats non breaking spaces, spaces and pretty much any type of indentation I can think of. [Edit and replace all spaces with &#160;]<br /><br /><br /> <p class="MsoNormal"><span style="font-size: 10pt; font-family: "Courier New"; color: blue;">using</span><span style="font-size: 10pt; font-family: "Courier New";"> System;<br /><span style="color: green;">//using System.Collections.Generic;<br /></span><span style="color: blue;">using</span> System.Text;<br /><span style="color: blue;">using</span> System.Net;<br /><span style="color: blue;">using</span> System.Net.Sockets;<br /><br /><span style="color: blue;">namespace</span> HPPrnDisp<br />{<br />    <span style="color: blue;">class</span> <span style="color: rgb(43, 145, 175);">hp<br /></span>    {<br />        <span style="color: blue;">const</span> <span style="color: blue;">int</span> HP_PJL_PORT = 9100;<br />        <span style="color: blue;">const</span> <span style="color: blue;">string</span> HP_RDYMSG_HEADER = <span style="color: rgb(163, 21, 21);">"\u001B%-12345X@PJL RDYMSG DISPLAY = \""</span>;<br />        <span style="color: blue;">const</span> <span style="color: blue;">string</span> HP_RDYMSG_FOOTER = <span style="color: rgb(163, 21, 21);">"\"\r\n\u001B%-12345X\r\n"</span>;<br /><br />        <span style="color: green;">// Changes the READY display text for a range of HP Printers<br /></span>        <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">int</span> Main(<span style="color: blue;">string</span>[] args)<br />        {<br /><br />            <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"HP Display Hack -- sili@l0pht.com 12/8/97"</span>);<br />            <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"-- Re-coded by Kent Bolton 02 APR 2008 --"</span>);<br /><br /><br />            <span style="color: green;">// Ensure that there are only two arguments<br /></span>            <span style="color: blue;">if</span> ( args.Length != 2 ) {<br />                <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"Usage: printer \"message\""</span>);<br />                <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"\tMessage can be up to 16 characters long (44 on 5si's)"</span>);<br />                <span style="color: blue;">return</span> 1;<br />            }<br /><br />            <span style="color: green;">// Process the arguments<br /></span>            <span style="color: rgb(43, 145, 175);">String</span> host = args[0];<br />            <span style="color: rgb(43, 145, 175);">String</span> message = args[1];<br /><br />            <span style="color: green;">// No more than 44 chars - not sure what happens if there are more<br /></span>            <span style="color: blue;">if</span> (message.Length > 44)<br />            {<br />                message = message.Substring(0, 44);<br />            }<br /><br />            <span style="color: green;">// Let the user know we know what is needed<br /></span>            <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"Hostname: {0}"</span>, host);<br />            <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"Message : {0}"</span>, message);<br /><br />            <span style="color: green;">// Set up the IP Connections ...<br /></span>            <span style="color: rgb(43, 145, 175);">IPAddress</span> addr = <span style="color: blue;">null</span>;<br />            <span style="color: rgb(43, 145, 175);">IPEndPoint</span> endPoint = <span style="color: blue;">null</span>;<br />            <span style="color: blue;">try<br /></span>            {<br />                addr = <span style="color: rgb(43, 145, 175);">Dns</span>.GetHostEntry(host).AddressList[0];<br />                endPoint = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">IPEndPoint</span>(addr, HP_PJL_PORT);<br />            }<br />            <span style="color: blue;">catch</span> (<span style="color: rgb(43, 145, 175);">Exception</span> e)<br />            {<br />                <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"Unknown host: "</span> + e.ToString());<br />                <span style="color: blue;">return</span> 1;<br />            }<br /><br />            <span style="color: green;">// Format strings<br /></span>            <span style="color: rgb(43, 145, 175);">StringBuilder</span> textOut = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">StringBuilder</span>(100);<br />            textOut.Append(HP_RDYMSG_HEADER);<br />            textOut.Append (message);<br />            textOut.Append(HP_RDYMSG_FOOTER);<br /><br />            <span style="color: green;">// Now everything is set up, push the string through as an ASCII byte stream<br /></span>            <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"Connecting ..."</span>);<br />            <span style="color: blue;">try<br /></span>            {<br />                <span style="color: green;">// Prepare basic socket and encoding stuff<br /></span>                <span style="color: rgb(43, 145, 175);">Socket</span> sock = <span style="color: blue;">null</span>;<br />                System.Text.<span style="color: rgb(43, 145, 175);">ASCIIEncoding</span> encoding = <span style="color: blue;">new</span> System.Text.<span style="color: rgb(43, 145, 175);">ASCIIEncoding</span>();<br /><br />                <span style="color: green;">// Open socket and pump out the bits<br /></span>                sock = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">Socket</span>(<span style="color: rgb(43, 145, 175);">AddressFamily</span>.InterNetwork, <span style="color: rgb(43, 145, 175);">SocketType</span>.Stream, <span style="color: rgb(43, 145, 175);">ProtocolType</span>.IP);<br />                sock.Connect(endPoint);<br />                sock.Send(encoding.GetBytes(textOut.ToString()));<br />                sock.Close();<br />            }<br />            <span style="color: blue;">catch</span> (<span style="color: rgb(43, 145, 175);">Exception</span> e)<br />            {<br />                <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"IO error: "</span> + e.ToString());<br />                <span style="color: blue;">return</span> 1;<br />            }<br /><br />            <span style="color: green;">// Happy message and bail with no error code<br /></span>            <span style="color: rgb(43, 145, 175);">Console</span>.WriteLine(<span style="color: rgb(163, 21, 21);">"Sent {0} bytes"</span>, textOut.Length);<br />            <span style="color: blue;">return</span> 0;<br /><br /><br />        }<br />    }<br />}<br /></span><br /> <!--[if !supportLineBreakNewLine]--><br /> <!--[endif]--></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-80713193078327790022008-03-31T12:00:00.004+10:002008-03-31T12:08:26.089+10:00VS2008 Express - Launching nUnit on F5<div class="Section1"> <p class="MsoNormal"><span lang="EN-US">Here is the How To:<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p></o:p>Add these two lines into the <propertygroup> section of your project .csproj.user file.<o:p></o:p></propertygroup></span></p><p class="MsoNormal" style="font-family:courier new;"><span lang="EN-US"></span></p><blockquote><p style="font-family: courier new;" class="MsoNormal"><span lang="EN-US"> <StartAction>Program</span><span lang="EN-US"><</span><span lang="EN-US">/StartAction</span><span lang="EN-US">></span></p> <p class="MsoNormal"><span style="font-family: courier new;" lang="EN-US"> </span><span style="font-family: courier new;" lang="EN-US"><</span><span style="font-family: courier new;" lang="EN-US">StartProgram</span><span style="font-family: courier new;" lang="EN-US">></span><span style="font-family: courier new;" lang="EN-US">C:\DEV TOOLS\Program Files\NUnit 2.4.3\bin\nunit.exe</span><span style="font-family: courier new;" lang="EN-US"><</span><span style="font-family: courier new;" lang="EN-US">/StartProgram</span><span style="font-family: courier new;" lang="EN-US">></span><span lang="EN-US"> </span></p><p class="MsoNormal" style="font-family:courier new;"><span lang="EN-US"><startprogram></startprogram><br /></span></p><p class="MsoNormal" style="font-family:courier new;"><span lang="EN-US"><startprogram></startprogram> <o:p></o:p></span></p><p class="MsoNormal"><span lang="EN-US"></span></p></blockquote><p class="MsoNormal"><span lang="EN-US">Pressing F5 will launch NUnit now and start debugging.<o:p></o:p></span></p><br /></div>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-13286856398250227752008-03-27T16:16:00.002+10:002008-03-27T16:18:51.649+10:00Web development 2008 ! We've come a long way ! Now where’s Notepad ?<span style="font-style: italic;">Darren, our framework developer who plays with all the new cool tech had a play with VS2008 web development, and the results were not very pretty.</span><br /><br /> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;"><rant><o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;"><o:p></o:p>Today I had a simple task; Make a small application to demonstrate the new features in Visual Studio 2008 for Webform development. I had attended the <st1:place st="on"><st1:city st="on">Brisbane</st1:City></st1:place> "Heroes Happen 2008" Microsoft launch event the previous day and thought "A quick 20 minute job". Hmmmm...<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">The Agenda...<o:p></o:p></span></p> <ol><li><span style="font-size: 10pt; font-family: Arial;">The impressive UpdatePanel</span></li><li><span style="font-size: 10pt; font-family: Arial;">Intellisense in JavaScript editing</span></li><li><span style="font-size: 10pt; font-family: Arial;">Debugging JavaScript in Visual Studio<o:p></o:p></span></li></ol> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">I should say at this point that I am a dyed-in-the-wool Winforms developer although I have developed a fair few websites in my time. I've built web apps (mostly modestly sized affairs) using everything from Visual Interdev (remember that?), Notepad, and all .NET Visual Studio editions. I've done it but I have to say I don't like it. Why? If I'm brutally honest I hate the pace of development, the fact the tools aren't properly integrated and browsers that can't agree how to render anything useful; These are just my top 3 hates.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;"><o:p></o:p>Anyway, yesterday I was truly impressed with the demos and found myself thinking maybe web development could be fun at last...<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">How wrong I was.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">I had about 90% of the demo complete well within my initial estimate and then proceeded to put the breakpoint on the JavaScript code in the page and entered a world of pain. I use Firefox as my main browser and, naturally, VS 2008 JavaScript debugging doesn't work there. Okay, set IE 7 as my default browser for the web project, problem solved... well, no. Hmmm... Reboot? No. Repair install of Visual Studio? No. Another reboot? No. Go moan to someone else about how s@#t web development is? Worked like a charm.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">Somebody please explain how bringing someone over to your PC and showing them how something doesn't work can suddenly kick it into life. I say this, but it didn't work the *first* time, just the second and every time since.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">Its things like this that give me killer headaches and make me want to go back to the nice cosy world of framework development...<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">Aside from a nice preview of the 'design' and the (admittedly) cool CSS stuff there aren't a lot of compelling reasons to spend a large wad of cash rather than just use notepad. I mean, if I'm going to get stressed and generally harassed by technology that isn't reliable, doesn't work and then magically cooperates I may as well start in the position of expecting things to be tough and just use everyone's favourite free web development tool.<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;"></rant><o:p></o:p></span></p> <p style="font-style: italic;" class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">PS I don’t really mean that we should be using notepad because it would be really frustrating. The issue is that Visual Studio 2008 is so close, but so frustratingly far from being a great web development environment.<o:p></o:p></span></p> <p style="font-style: italic;" class="MsoNormal"><span style="font-size: 10pt; font-family: Arial;">PPS I love everything else about Visual Studio.<o:p></o:p></span></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-71327305909058007982008-03-26T12:06:00.003+10:002008-03-26T12:07:57.520+10:00FXCop and string culture<span style="font-style: italic;">Rules are great, unless blindly followed. </span><br /><br /><div class="Section1"> <p class="MsoNormal"><span lang="EN-US">I thought I would just send this out as a reminder. While everyone is eager to do right by FxCop we should not forget to use the Invariant Culture where appropriate.<o:p><br /></o:p></span></p> <p class="MsoNormal"><span lang="EN-US">FxCop will complain about any string formatting without an explicit culture. If you are formatting for internal use and not for display you really should consider using </span><span style="font-size: 10pt; color: rgb(43, 145, 175); font-family: 'Courier New';">CultureInfo</span><span style="font-size: 10pt; font-family: 'Courier New';">.InvariantCulture</span><span lang="EN-US">. This is particularly important if you plan to consume the string with software. Using the current culture would mean the string potentially could not be consumed by another server/PC. For example, if you used BCMax in Dubai it would have a different culture to the StrataMax server running here.<o:p><br /></o:p></span></p> <p class="MsoNormal"><span lang="EN-US">So if it is an internal string not for display or to be interpreted by software anywhere consider doing this:<o:p><br /></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';">receiptNumber.ToString(<span style="color: rgb(163, 21, 21);">"#"</span>, <span style="color: rgb(43, 145, 175);">CultureInfo</span>.<span style="color: red;">InvariantCulture</span>);<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p></o:p>Instead of this:<o:p><br /></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';">receiptNumber.ToString(<span style="color: rgb(43, 145, 175);">CultureInfo</span>.<span style="color: red;">CurrentCulture</span>);<o:p></o:p></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p><br /></o:p></span></p></div>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-61534152231682735032008-03-06T12:36:00.004+10:002008-03-06T12:47:08.563+10:00Exception handling in ASP.Net with Anthem and Web Services<p class="MsoNormal"><span lang="EN-US"><span style="font-style: italic;">Dorian, our CIO, has been busily hammering the VB.NET based shopping cart selected for a large client into shape.<br /></span></span></p><p class="MsoNormal"><span style="font-style: italic;">Anthem.NET is a free, cross-browser AJAX toolkit for the ASP.NET development environment that works with both ASP.NET 1.1 and 2.0. http://anthem-dot-net.sourceforge.net/</span></p><p class="MsoNormal"><span style="font-style: italic;">Please ignore lack of indenting ... blogger keeps eating my directives. Kent Bolton</span><br /><br /><span lang="EN-US">Before Anthem it was enough to put an error handler in the Global.asax on the Application_Error event to log the error and use the <customerrors> tag in the web.config to redirect errors to a common error page.<o:p></o:p></customerrors></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p></o:p>Anthem complicates things.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US">In Anthem it is possible to have Ajax call backs to the web page, controls or even custom methods decorated. Exceptions could be raised on the methods called or even on methods not directly called by these methods such as load events for controls that Anthem causes to load dynamically.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p></o:p>If an error occurs during an Anthem Callback the exception will not be caught by Application_Error and won't follow <customerrors> instructions. On the server side the only thing you can do to catch an Anthem Error is catch it on the page using a Page_Error method. This method will also catch regular page exceptions thus preventing Application_Error from firing. It may look something like this:<o:p></o:p></customerrors></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span style=";font-family:ProggyCleanTTSZ;color:blue;" > Private</span><span style="font-family:ProggyCleanTTSZ;"><span style="font-family:courier new;"> </span><span style=";font-family:courier new;color:blue;" >Sub</span><span style="font-family:courier new;"> Page_Error(</span><span style=";font-family:courier new;color:blue;" >ByVal</span><span style="font-family:courier new;"> sender </span><span style=";font-family:courier new;color:blue;" >As</span><span style="font-family:courier new;"> </span><span style=";font-family:courier new;color:blue;" >Object</span><span style="font-family:courier new;">, </span><span style=";font-family:courier new;color:blue;" >ByVal</span><span style="font-family:courier new;"> e </span><span style=";font-family:courier new;color:blue;" >As</span><span style="font-family:courier new;"> EventArgs) </span><span style=";font-family:courier new;color:blue;" >Handles</span><span style="font-family:courier new;"> </span><span style=";font-family:courier new;color:blue;" >MyBase</span><span style="font-family:courier new;">.Error</span><br /><span style="font-family:courier new;">Response.Redirect(</span><span style="color: rgb(163, 21, 21);font-family:courier new;" >"http://somewhere/"</span><span style="font-family:courier new;">)</span><br /><span style=";font-family:courier new;color:blue;" >End</span><span style="font-family:courier new;"> </span><span style="color:blue;"><span style="font-family:courier new;">Sub</span><o:p></o:p></span></span></p> <p class="MsoNormal"><span style=";font-family:ProggyCleanTTSZ;color:blue;" ><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">In order to avoid putting this method on every page it must be placed on the base page class for the entire website. There is a small downside to this which is a page can no longer define its own Page_Error method because control would be lost in the event execution chain when a Response.Redirect is started (it aborts the thread). This is however a necessary evil as there doesn’t seem to be another way to catch Anthem exceptions.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p></o:p>Because we are on the topic of Anthem and error handling here is a couple more useful facts. You can catch errors in Anthem call backs on the client by adding a JavaScript method to pages calls Anthem_Error. If a server side error occurs in an Anthem callback any previously registered JavaScript to execute will still be executed. For example if you had an Anthem button which looked like this:<o:p></o:p></span></p><p style="font-family: courier new;font-family:courier new;" class="MsoNormal" > <span style="color:blue;">Protected</span> <span style="color:blue;">Sub</span> btnNext_Click(<span style="color:blue;">ByVal</span> sender <span style="color:blue;">As</span> <span style="color:blue;">Object</span>, <span style="color:blue;">ByVal</span> e <span style="color:blue;">As</span> System.Web.UI.ImageClickEventArgs) <span style="color:blue;">Handles</span> btnNext.Click<o:p></o:p></p><p style="font-family: courier new;font-family:courier new;" class="MsoNormal" >SomeHiddenPanel.Visible = <span style="color:blue;">True</span><o:p></o:p></p><p style="font-family: courier new;font-family:courier new;" class="MsoNormal" > Anthem.Manager.AddScriptForClientSideEval(<span style="color: rgb(163, 21, 21);">"if (typeof document.someform != ""undefined"") { documentsomeform.submit(); }"</span>)<o:p></o:p></p> <p class="MsoNormal"><span style="font-family:ProggyCleanTTSZ;"> <span style="font-family: courier new;font-family:courier new;color:blue;" >End</span><span style="font-family: courier new;font-family:courier new;" > </span><span style="color:blue;"><span style="font-family: courier new;font-family:courier new;" >Sub</span><o:p></o:p></span></span></p> <p class="MsoNormal"><span style="font-family:ProggyCleanTTSZ;"><o:p></o:p></span><span lang="EN-US">And after this code executed a server side error occurred (perhaps in rendering SomeHiddenPanel) the JavaScript added would still be executed. It is important to write such JavaScript to be tolerate of an error occurring. The code above checks for the existence of the form which SomeHiddenPanel would make visible before it calls submit().<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p></o:p>Web services are another nasty for exception handling. Basically, you need to try catch every web service method and handle all exceptions. The same error logging routine could be use by web services and page errors if it was tolerant of information that may not be present on web service requests. View state is one example. Don’t expect to find that in a web service.<o:p></o:p></span></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-67657740601276783782008-02-26T13:41:00.006+10:002008-02-26T16:50:35.844+10:00Preventing Web Caching in ASP.NETWe are working on a shopping cart application in ASP.NET. that needed to prevent web caching. The code is in VB.NET, since the best practice source we bought was VB.NET based.<br /><br />With the proliferation of browsers, and the variety of ways that they interpret directives, a number of strategies have to be employed.<br /><br />Caching can occur in any of the following locations:<br /><ul><li>Any – cache anywhere including client, server and proxy server.</li><li>Client – cache in client browser. </li><li>Downstream – any cacheable devices but not the original server that participates in the request.</li><li>Server – cache on the web server</li><li>None – no cache</li></ul>(Please ignore the lack of indenting ... blogger kept losing my directives<br /><br /><span style=";font-size:85%;color:blue;" >Public</span><span style="font-size:85%;"> </span><span style=";font-size:85%;color:blue;" >Shared</span><span style="font-size:85%;"> </span><span style=";font-size:85%;color:blue;" >Sub</span><span style="font-size:85%;"> NoCachePage(</span><span style=";font-size:85%;color:blue;" >ByVal</span><span style="font-size:85%;"> currentPage </span><span style=";font-size:85%;color:blue;" >As</span><span style="font-size:85%;"> System.Web.UI.Page)</span><p class="MsoNormal" style="font-family:courier new;"><span style="background: lime none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:78%;" >' This will turn off the cache for the above locations</span><br /></p><p class="MsoNormal" style="font-family:courier new;"><span style="font-size:85%;"> currentPage.Response.Cache.SetCacheability (Web.HttpCacheability.NoCache)<br /> currentPage.Response.Cache.SetNoStore()<br /> currentPage.Response.Cache.SetExpires (DateTime.Now().AddDays(-366))<br /> currentPage.Response.Cache.SetMaxAge (</span><span style=";font-size:85%;color:blue;" >New</span><span style="font-size:85%;"> TimeSpan(0))<br /> currentPage.Response.Cache.AppendCacheExtension (</span><span style="color: rgb(163, 21, 21);font-size:85%;" >"must-revalidate, proxy-revalidate"</span><span style="font-size:85%;">)</span></p><p class="MsoNormal" style="font-family:courier new;"><span style="background: lime none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:78%;" >' This is to explicitly add to header to avoid being cached in the client browser, without the above code the page might still be cached on the server but just not in the client. For </span><span style="background: lime none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-size:78%;" >example cache is set to Server and the following codes are also added</span> <o:p></o:p></p> <p class="MsoNormal" style="font-family:courier new;"> <span style=";font-size:85%;color:blue;" > Dim</span><span style="font-size:85%;"> Expires </span><span style=";font-size:85%;color:blue;" >As</span><span style="font-size:85%;"> </span><span style=";font-size:85%;color:blue;" > New</span><span style="font-size:85%;"> Web.UI.HtmlControls.HtmlMeta()<br /> Expires.Name = </span><span style="color: rgb(163, 21, 21);font-size:85%;" >"Expires"</span><span style="font-size:85%;"><br /> Expires.Content = </span><span style="color: rgb(163, 21, 21);font-size:85%;" >"0"</span><span style="font-size:85%;"><br /> currentPage.Header.Controls.Add(Expires)<o:p><br /></o:p></span></p> <p class="MsoNormal" style="font-family:courier new;"> <span style=";font-size:85%;color:blue;" > Dim</span><span style="font-size:85%;"> CacheControl </span><span style=";font-size:85%;color:blue;" >As</span><span style="font-size:85%;"> </span><span style=";font-size:85%;color:blue;" > New</span><span style="font-size:85%;"> Web.UI.HtmlControls.HtmlMeta()<br /> CacheControl.Name = </span><span style="color: rgb(163, 21, 21);font-size:85%;" >"Cache-Control"</span><span style="font-size:85%;"><br /> CacheControl.Content = </span><span style="color: rgb(163, 21, 21);font-size:85%;" >"no-cache"</span><span style="font-size:85%;"><br /> currentPage.Header.Controls.Add(CacheControl)<o:p></o:p></span></p> <p class="MsoNormal" style="font-family:courier new;"><span style="font-size:85%;"><o:p> </o:p></span> <span style=";font-size:85%;color:blue;" > Dim</span><span style="font-size:85%;"> Pragma </span><span style=";font-size:85%;color:blue;" >As</span><span style="font-size:85%;"> </span><span style=";font-size:85%;color:blue;" >New</span><span style="font-size:85%;"> Web.UI.HtmlControls.HtmlMeta()<br /> Pragma.Name = </span><span style="color: rgb(163, 21, 21);font-size:85%;" >"Pragma"</span><span style="font-size:85%;"><br /> Pragma.Content = </span><span style="color: rgb(163, 21, 21);font-size:85%;" >"no-cache"</span><span style="font-size:85%;"><br /> currentPage.Header.Controls.Add(Pragma)<o:p></o:p></span></p> <p class="MsoNormal"><span style=";font-family:courier new;font-size:85%;" > <span style="color:blue;">End</span> <span style="color:blue;">Sub</span></span><span lang="EN-US"><o:p></o:p></span></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-33581306256814729022008-02-22T11:01:00.002+10:002008-02-22T11:08:47.684+10:00Spawning a console application and tracking its Standard Output<span style="font-style: italic;">Toby Cosham, our Accounting Guru, has the first tech oriented blog post to contribute, helping us achieve our milestone of at least a post a week. Thanks Toby.</span><br /><blockquote></blockquote><br /><span lang="EN-AU">Sometimes programs we write must interact with a console application that does not integrate easily into our framework.<span style=""> </span>The application may be designed for use in a manual environment, but you need to automate it.<span style=""> </span>Any errors produced may be displayed only on the screen via Standard Output.<o:p> </o:p></span><p class="MsoNormal"><span lang="EN-AU"><o:p></o:p>This happened to me recently.<span style=""> </span>My program was written using the .NET framework.<span style=""> </span>It is pretty simple to run another program from the .NET framework.<span style=""> </span>I used System.Diagnostics.Process to launch the other software (I’ll call it ABCD) using Process.Start, and waited for it to complete using Process.WaitForExit.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU">The purpose of ABCD is to send and receive data over the internet.<span style=""> </span>It is a command driven program, with an interface similar to FTP.<span style=""> </span>After testing its responses, it became apparent that it was unreliable.<span style=""> </span>Not only could it return errors about failing to connect to its server, but also logon failure and timeouts.<span style=""> </span>In addition, there were some more obscure, but regular, failures – corrupted stream and handshake failure.<span style=""> </span>There was no way to predict these failures, but trying again immediately almost always worked.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU">The requirements for my program included executing ABCD many times each day, starting at 1am and finishing at 7pm.<span style=""> </span>If it did not work, immediate action needed to be taken.<span style=""> </span>At MaxSoft, we have a library that handles sending the SMS, so sending the message was not a problem.<span style=""> </span>However, since the SMS was to our CIO, it was important to identify the problem and attempt to rectify it first.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU">ABCD does not return an error code.<span style=""> </span>It does not log its results to a database, or a file.<span style=""> </span>The only way it notifies its results is directly to the screen.<span style=""> </span>In addition, when it downloads files as a batch, the batch can contain multiple files of the same name.<span style=""> </span>The first file gets overwritten by the second file with the same name.<span style=""> </span>This meant that I could not pipe the standard output of ABCD to a file and interpret it after it had executed – some files would have been lost by then.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU">The answer was to use some of the features of System.Diagnostics.Process.<span style=""> </span>This class allows for the Standard Output (which normally is displayed on the screen) to be captured as it occurs.<span style=""> </span>It also allows for Standard Error to be captured, and for Standard Input to be written to.<span style=""> </span>I passed the commands to ABCD by writing to the StandardInput stream, allowing me to protect the user id and password.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU">I then set Process.EnableRaisingEvent to true and called Process.BeginOutputReadLine.<span style=""> </span>This activates the OutputDataReceived event, which I set to call my OutputDataReceived function.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU">I set up an array of strings for the expected result.<span style=""> </span>The output was the same all the time, except the list of files produced, which I added as a place-holder string to the expected result.<span style=""> </span>Each time OutputDataReceived was called, I compared the text that had been added to StandardOutput to the next item in the expected results.<span style=""> </span>If it matched, I removed that section from the expected results and exited the OutputDataReceived function.<span style=""> </span>If it did not match, I recorded the error and exited the function.<span style=""> </span>When Process.WaitForExit completes, this error information is checked to determine if the process has run correctly or not.<span style=""> </span>The placeholder string is used to identify when the list of files is being processed.<span style=""> </span>This is only removed from the expected result when the following expected result is received.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU">Having written this, I was getting all errors reported.<span style=""> </span>I wanted to reduce the calls our CIO received early in the morning (So did he), so I processed the error message.<span style=""> </span>If any of the three errors that could be retried occurred, I looped back to where ABCD was being set up and ran it again.<span style=""> </span>Along with providing the maximum number of retries, this eliminated alerts being generated on transient errors.<span style=""> </span>If any other error occurred, ABCD was not rerun, and the alert was sent straight away.<o:p></o:p></span></p> <p class="MsoNormal"><span lang="EN-AU">Issues that I had resolved include:</span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;"><!--[if !supportLists]--><span lang="EN-AU"><span style=""></span></span>- calling a console application using System.Diagnostics.Process<span lang="EN-AU"><o:p></o:p></span></p> <p class="MsoNormal" style=""><span style="font-size: 10pt; font-family: "Courier New";"><span style=""> </span><span style="color: rgb(43, 145, 175);">Process</span> p = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">Process</span>();<br /><span style=""> </span><span style="color: rgb(43, 145, 175);">ProcessStartInfo</span> si = <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">ProcessStartInfo</span>(application);<br /><span style=""> </span>p.StartInfo = si;<br /><span style=""> </span>si.Arguments = arguments;<br /><span style=""> </span>si.UseShellExecute = <span style="color: blue;">false</span>;<br /><span style=""> </span>p.Start();<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;"><span style="font-size: 10pt; font-family: "Courier New";"><o:p> </o:p></span><br /><!--[if !supportLists]--><span lang="EN-AU"><span style="">-<span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span></span><!--[endif]--><span lang="EN-AU">retrieving and interpreting text output to the screen<o:p></o:p></span></p> <p class="MsoNormal" style=""><span style="font-size: 10pt; font-family: "Courier New";"><span style=""> </span>si.RedirectStandardOutput = <span style="color: blue;">true</span>;<br /><span style=""> </span>p.EnableRaisingEvents = <span style="color: blue;">true</span>;<br /><span style=""> </span>p.OutputDataReceived += <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);">DataReceivedEventHandler</span>(OutputDataReceived);<br /><span style=""> </span>p.BeginOutputReadLine();<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;"><!--[if !supportLists]--><span lang="EN-AU"><o:p> </o:p><br /><span style="">-<span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span></span><!--[endif]--><span lang="EN-AU">timeouts and other retryable errors<o:p></o:p></span></p> <p class="MsoNormal" style=""><span style="font-size: 10pt; font-family: "Courier New";"><span style=""> </span><span style="color: blue;">void</span> OutputDataReceived(<span style="color: blue;">object</span> sender, <span style="color: rgb(43, 145, 175);">DataReceivedEventArgs</span> e)<br /><span style=""> </span>{<br /><span style=""> </span><span style="color: blue;">if</span> (e.Data == <span style="color: blue;">null</span>)<br /><span style=""> </span><span style="color: blue;">return</span>;<o:p><br /></o:p></span></p> <p class="MsoNormal" style=""><span style="font-size: 10pt; font-family: "Courier New";"><span style=""> </span><span style="color: green;">// check e.Data for retryable errors and set flag indicating retry required</span><br /><span style=""> </span>}<o:p></o:p></span></p> <p class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;"><span style="font-size: 10pt; font-family: "Courier New";"><o:p> </o:p></span><br /><!--[if !supportLists]--><span lang="EN-AU"><span style="">-<span style="font-family: "Times New Roman"; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"> </span></span></span><!--[endif]--><span lang="EN-AU">preventing the console application for running forever by using WaitForExit with a time limit<o:p></o:p></span></p> <p class="MsoNormal" style=""><span style="font-size: 10pt; font-family: "Courier New";"><span style=""> </span><span style="color: blue;">if</span> (!p.WaitForExit(<span style="color: rgb(43, 145, 175);">Config</span>.TimeoutSeconds * 1000))<br /><span style=""> </span>{<br /><span style=""> </span>p.Kill();<br /><span style=""> </span>}<br /><span style=""> </span>p.Close();<o:p></o:p></span></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-19474759286956751392008-02-13T02:46:00.002+10:002008-02-14T12:53:50.329+10:00Regular catch up meetings come full circle<p style="margin-bottom: 0cm;">In the IT department here at MaxSoft, we hold fortnightly catchups with the guys. Since there are currently ten guys involved in these regular catchups with me, I have one scheduled every day of the week. We cover three main points religiously:</p> <ol><li><p style="margin-bottom: 0cm;">What have you done in the four hours a week we give you to develop your skills</p> </li><li><p style="margin-bottom: 0cm;">What are your priorities and work issues</p> </li><li><p style="margin-bottom: 0cm;">How are you going generally and what improvements can be made to your environment</p> </li></ol> <p style="margin-bottom: 0cm;">We cover a lot of ground in these meetings. In a recent catch up, we covered the contrasts between other workplaces and the environment here. The discussion on other workplaces verged into toxic workplaces, and terrible management types.<br /></p><p style="margin-bottom: 0cm;">I was reminded of a subject I had covered a few years ago, dragged out a book called “Mask of Sanity” by Hervey Cleckley. It is available as a free pdf download, and covers the pathological personality type. Get it from <a href="http://www.cassiopaea.org/cass/sanity_1.PdF">http://www.cassiopaea.org/cass/sanity_1.PdF</a> </p> <p style="margin-bottom: 0cm;">A summary covered at <a href="http://www.cassiopaea.com/cassiopaea/psychopath.htm">http://www.cassiopaea.com/cassiopaea/psychopath.htm</a> describes this personality type as follows:<br /><br /></p> <p><span style="font-family:Bitstream Vera Sans,sans-serif;"><span style="font-size:85%;">Imagine - if you can - not having a conscience, none at all, no feelings of guilt or remorse no matter what you do, no limiting sense of concern for the well-being of strangers, friends, or even family members. Imagine no struggles with shame, not a single one in your whole life, no matter what kind of selfish, lazy, harmful, or immoral action you had taken. </span></span> </p> <p><span style="font-family:Bitstream Vera Sans,sans-serif;"><span style="font-size:85%;">And pretend that the concept of responsibility is unknown to you, except as a burden others seem to accept without question, like gullible fools. </span></span> </p> <p><span style="font-family:Bitstream Vera Sans,sans-serif;"><span style="font-size:85%;">Now add to this strange fantasy the ability to conceal from other people that your psychological makeup is radically different from theirs. Since everyone simply assumes that conscience is universal among human beings, hiding the fact that you are conscience-free is nearly effortless. </span></span> </p> <p><span style="font-family:Bitstream Vera Sans,sans-serif;"><span style="font-size:85%;">You are not held back from any of your desires by guilt or shame, and you are never confronted by others for your cold-bloodedness. The ice water in your veins is so bizarre, so completely outside of their personal experience, that they seldom even guess at your condition.</span></span></p> <p style="margin-bottom: 0cm;">Around 4%, or 1 in 25 people will have this personality defect. There are a lot of sociopaths in jail and just as many in senior management.<br /></p> <p style="margin-bottom: 0cm;">My original motivation for reading this tome was to try to fathom the behaviour of a colleague of mine while working in a large organisation. He was charming, fearless and ruthless, and his superiors loved him. He also seemed not to care an iota about anyone, nor about getting the job done. His actions included borrowing a subordinate's laptop to test a program he found on the web. The install process included disabling the corporate virus and malware protection suite and led to the first ever major outbreak of a virus at this company. When it was obvious that the forensics clearly pointed to his employee's laptop, he loudly and publicly led the charge to have him sacked, while privately telling the employee to sit tight. The employee was saved from dismissal by a divisional general manager who intervened. When the employee confided in me six months later, it was because his boss had neither thanked him nor apologised for his behaviour. </p> <p style="margin-bottom: 0cm;">I'm sure most of you with a few years under the belt have had experiences with personality types you never, ever want to be involved with again. There are some that you'd especially go to great lengths to make sure that you never had to work for again.</p><p style="margin-bottom: 0cm;">What I am particularly interested in is how to use this feedback about the negatives of other workplaces into something that can be used positively.<br /></p> <p style="margin-bottom: 0cm;">The impact management, and especially the direct manager has on employees is massive. Any manager potentially can create an environment that is going to drive away not only your best and brightest, but your best and brightest in training. And you may never know about this until it is far too late.<br /></p> <p style="margin-bottom: 0cm;">If you care about care about getting great results for your business, the quality of the code your team produces, and the team itself, you need to provide an environment which not only stops your guys worrying about your reaction to situations, but also has them telling recruiters to stop calling for anything other than another dream job that pays twice as much.</p> <p style="margin-bottom: 0cm;">Regular catch up sessions are a vital component to ensure that your guys are not only happy and productive, but also that you are not making them ticked off and distracted.</p> <p style="margin-bottom: 0cm;">Some useful tips for these regular sessions:<br /></p> <ul><li><p style="margin-bottom: 0cm;">Have a predictable agenda of open questions designed to open up conversation rather than confine it.</p> </li><li><p style="margin-bottom: 0cm;">It is a two way street - your performance should be discussed as well.</p> </li><li><p style="margin-bottom: 0cm;">Don't cancel these meetings too often – if they are run well, there's not many things that are more important.</p> </li><li><p style="margin-bottom: 0cm;">Personalise the meeting to the needs of the employee. Take notes if you do not have a good memory.</p> </li></ul> <p style="margin-bottom: 0cm;">Run well, these meetings should be able to nip potential problems in the bud, fine tune your department's priorities, improve your management style and also help you establish a quality relationship with the people you should value most in your company.</p> <p style="margin-bottom: 0cm;">Even better, your annual or six monthly review process should be easy, painless and contain no big surprises.</p> <p style="margin-bottom: 0cm;">By the way, we are currently looking to increase my regular catchup meeting workload by hiring more .NET engineers wanting to work in an environment that cares about employee development and producing great code.</p> <p style="margin-bottom: 0cm;">If you are interested, e-mail me, Kent Bolton. I can be contacted via kbolton with an at sign here maxsoft.com.au. Please only apply if you are able to work on the gold coast in Australia, and have a serious passion for coding.</p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-20727015966927604242008-02-08T00:05:00.000+10:002008-02-08T13:11:37.448+10:00In interviews, test for the corner casesThis article deals with interviewing corner cases. It veers off the beaten path a little, and I'm keen to know if this is a good or bad thing. <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;">We interviewed someone face to face today. </p> <p style="margin-bottom: 0cm;">That little nugget of info is not so uncommon that I'm compelled to blog about it ... we currently hold about three or so face to face interviews a week.</p> <p style="margin-bottom: 0cm;">The coder looks good on paper ... twelve years coding, the last three years hands on C# - and self rated at 7 through 9.5 out of 10 for technical skills.</p> <p style="margin-bottom: 0cm;">Our first icebreaker exam question is designed to settle the candidate's nerves by being nice and simple. It's a property. “Tell us about it” I ask. </p> <p style="margin-bottom: 0cm;">This guy proceeds to tell us in no uncertain terms that our three line code snippet was plain bad coding. I was intrigued, so I gave him the keyboard.</p> <p style="margin-bottom: 0cm;">The keyboard I use for the interviews is a weird wireless Microsoft one. It has a super sized delete key that invades the space where the Insert key should be, and has the added bonus of weird key spacing. It's pretty horrible really, unless you are forewarned and expecting it, or have one just like it at home. I'm just starting to get used to it. It's taken me close to a year. The really great coders we interview never seem to have much trouble with it.</p> <p style="margin-bottom: 0cm;">Well he starts fumbling away and out it comes – I recognise three different languages and some new form of pseudo code. There's not one identifiable C# keyword (admittedly there is a semicolon that is in the right place). It's a mashup of sorts. It's not Web 2.0. It's not the sort to get you hired as a senior coder. Well, certainly not for a C# role. Well, not _this_ C# role.</p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;">Terminating the interview within five minutes is unfortunately far from uncommon. Lots of coders with brilliant CVs bomb out on the warm up questions – questions even those cramming C# for dummies while sucking on Red Bull the night before should get right.</p> <p style="margin-bottom: 0cm;">The reason for this is that lots of coders lie through their teeth on their CVs. There must be a reason – and I know that someone's been rewarding these time thieves with a job somewhere along the line.</p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"><b>For both your and the common good, you should never, ever interview candidates without the aid of a standardised exam that allows you to compare previous answers to gauge exactly where this candidate fits on the totem pole. This applies to every type of candidate I have helped to hire - accountants, office managers, junior network engineers etc. You Need An Exam. </b> </p> <p style="margin-bottom: 0cm;"><b>This exam should be pitched for the corner cases. It needs to be interactive – rather than having them fill out the answers and then you marking it, you need to be there, listening and prompting them for more clarity. It should be as close to real world as possible. </b> </p> <p style="margin-bottom: 0cm;"><b>The test results should be:</b></p> <ul><li><p style="margin-bottom: 0cm;"><b>The really bad candidates should fall out immediately.</b></p> </li><li><p style="margin-bottom: 0cm;"><b>The OK ones should be guided swiftly though to the end; and </b> </p> </li><li><p style="margin-bottom: 0cm;"><b>The really really seriously talented coders should make the exam so much fun you miss dinner with the kids. </b> </p> </li></ul> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;">The exam should be first cab off the rank - no time wasting chit chat or bonding before hand (you can do this if they are a good match) – my order of proceedings is offer freshly ground coffee, tea or iced water, remind them that they were warned about the tough exam, then hand it to them and provide instructions on how to navigate it.</p> <p style="margin-bottom: 0cm;">This way they get to show us just how good they are. All the guys we have hired since I started at MaxSoft have gone through this exam, and _all_ of them loved it. For the right person, it's a blast ... a bunch of techie guys rabbiting on about code and objects and heaps and more code stuff. I learn a lot from these interviews, and am sometimes amazed at just how smart and quick and good some coders actually are.</p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;">I've gotten about three more pages on the cutting floor that I'm going to turn into more articles over the next few days. Here's some ideas I have:<br /><br /></p> <ol><li><p style="margin-bottom: 0cm;">Why I created this exam, and how it has morphed</p> </li><li><p style="margin-bottom: 0cm;">My four step interview process</p> </li><li><p style="margin-bottom: 0cm;">Some bizarre personality types I have interviewed</p> </li></ol><br /><p style="margin-bottom: 0cm;"><br /></p>Hopefully the guys will be submitting some interesting code samples ... CruiseControl, controlling batch driven software and Vista certification are all in the pipeline <p style="margin-bottom: 0cm;"><br /></p>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com0tag:blogger.com,1999:blog-2420291952733861279.post-36009009264613730562008-02-06T00:45:00.004+10:002008-03-03T16:53:03.723+10:00First Post<i style=""><span lang="EN-AU">This article was submitted by William, and is designed to give you an insight into our team and workplace.</span></i><span lang="EN-AU"><o:p><br /></o:p></span> <h2><span lang="EN-AU">The IT Team</span></h2> <p class="MsoNormal"><span lang="EN-AU">First things first, “us”…</span></p> <p class="MsoNormal"><span lang="EN-AU">The Development and QA teams are from varied professional backgrounds (such as Mining, Finance Sector, Retail, Transport, and Gaming) as well as places of origin (QLD, VIC, <st1:city st="on">NSW</st1:city>, <st1:country-region st="on">UK</st1:country-region>, <st1:country-region st="on"><st1:place st="on">China</st1:place></st1:country-region> and even exotic NZ). This “rich mix” has lead to good balance and experience coverage on design and support tasks.</span></p> <p class="MsoNormal"><span lang="EN-AU">MaxSoft encourage skill and knowledge development, so most of us are undertaking MSCE courses (partially during work hours and with paid for online courseware). Others are furthering education via University (ie Masters Degree).</span></p> <p class="MsoNormal"><span lang="EN-AU">We are a small group (under 20) most of us located in the one area – which allows for problems to be solved / discussed quickly and without the need of excessive emails! We do occasionally work offsite.</span></p> <p class="MsoNormal"><span lang="EN-AU">We all get along pretty well – except for the Games/LAN nights when we show no mercy :)</span><span lang="EN-AU"> These are every few months, and are additional to the regular company social activities.</span></p> <h2><span lang="EN-AU">The Environment</span></h2> <p class="MsoNormal"><span lang="EN-AU">OK, the gear and stuff we use…</span></p> <p class="MsoNormal"><span lang="EN-AU"><span style=""> </span><span style="font-size:130%;"><span style="font-weight: bold;">Typical Developer Kit is;</span></span></span></p> <p class="MsoNormal"><span lang="EN-AU"><span style=""> </span>H/W: Core 2 Duo 3.0Ghz +, 2GB RAM, Dual 19” LCD Screens<br /><span style=""> </span>OS: MS Server 2003 or XP (A few copies of <st1:place st="on">Vista</st1:place> on test VMs)</span></p> <p class="MsoNormal"><span lang="EN-AU"><span style=""> </span><span style="font-weight: bold;">Tools & Languages</span></span></p>MS-Visual Studio 2008 [C# and Web (Services, Forms)]<br />MS-Visual Studio 2005 [C# & VB.NET, ASP.NET]<br />MS-Visual Studio 2003 [C# & VB.NET, ASP.NET]<br />Some of us even have a copy of VB6 for legacy systems<br />nUnit<br />RhinoMocks<br />FxCop for coding standards<br />WATiN for web testing<br /><p class="MsoNormal"><span lang="EN-AU"><o:p> </o:p><br /><span style=""> </span><span style="font-weight: bold;">Databases</span></span></p> <p class="MsoNormal"><span lang="EN-AU"><span style=""> </span>MS-SQLServer 2000 & 2005<br /><span style=""> </span>MySQL<br /><span style=""> </span>PostGreSQL</span></p> <br /><span lang="EN-AU">Some of us have “natural keyboards” some view this as very un-natural.</span><br /><span lang="EN-AU">Some of use wear head phones and play music whilst we work. The others throw things (usually rubber balls) to get peoples attention.</span><div> </div><p style="text-align: left;" class="MsoNormal"><span lang="EN-AU"><o:p> </o:p>We are developing a new build and test server, running VMWare ESX, running CruiseControl.NET, MSBuild , nUnit, nCover, FxCop, memory profilers, WIX and other tools.</span></p> <p class="MsoNormal"><span lang="EN-AU"><o:p> </o:p>We take peer reviews very seriously (this is as close to pair programming we feel is necessary), and have a QA department which is part of IT.<o:p><br /></o:p></span></p> <h2><span lang="EN-AU">The Systems</span></h2> <p class="MsoNormal"><!--[if !supportLists]--></p>What we do….<br />• Payments web service channel (for a number of branded payment types – Rent, Strata Levies, Schools)<br />• Windows client based Strata Manager Office software<br />• Donation web service channel<br />• We write banking software for the banking services we provide<br /><br /><p class="MsoNormal"><span lang="EN-AU"><o:p> </o:p></span></p> <h2><span lang="EN-AU">The Future</span></h2> <p class="MsoNormal"><b style=""><span lang="EN-AU">Where we are going….<o:p></o:p></span></b></p> <p class="MsoNormal"><span lang="EN-AU">New systems are being constructed now and some major ones just around the corner. Our life is not a static one.</span></p> <p class="MsoNormal"><span lang="EN-AU">We strive for generic approaches for extensibility.</span></p> <p class="MsoNormal"><span lang="EN-AU">The new framework platform we are targeting is in essence;</span></p> <ul style="margin-top: 0cm;" type="disc"><li class="MsoNormal" style=""><span lang="EN-AU">2008 .Net C# 3.5 (including lots of method extenders)</span></li><li class="MsoNormal" style=""><span lang="EN-AU">nHibernate and nVelocity for the code gen and back end</span></li><li class="MsoNormal" style=""><span lang="EN-AU">Targets Microsoft SQL Server / PostgreSQL / MySQL database</span></li><li class="MsoNormal" style=""><span lang="EN-AU">Mostly Active Record with some domain concepts thrown in</span></li><li class="MsoNormal" style=""><span lang="EN-AU">Lots of custom libraries to speed up development and maintenance</span></li></ul>Kent Boltonhttp://www.blogger.com/profile/10006964614226875866noreply@blogger.com1