Rock Solid Knowledge Blogs" 26/06/2010 21:31:35 http://www.rocksolidknowledge.com An aggregation of all the Rock Solid Knowledge Blogs http://blogs.mantiso.com/blog/kevin/2010/06/26/formelement-is-null-in-ASP-Net-MVC-Validation http://blogs.mantiso.com/blog/kevin/2010/06/26/formelement-is-null-in-ASP-Net-MVC-Validation formelement is null in ASP.Net MVC Validation I'm buidling a really simple MVC application as a demo and I've been getting a Javascript "formelement is null" error. A quick google throws up a bunch of 'make sure you add the correct .js files" but I had all those <pre class="brush: html"> <script src="../../Scripts/MicrosoftAjax.debug.js" type="text/javascript"></script> <script src="../../Scripts/MicrosoftMvcAjax.debug.js" type="text/javascript"></script> <script src="../../Scripts/MicrosoftMvcValidation.debug.js" type="text/javascript"></script> </pre> Turns out that I had added a Master page using a template and thet template contains a <pre class="brush: html"> <form runat="server"> </pre> element. This screwa up the validation. Removing that tag fixes the problem http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0cf7f2c1-78f5-43d6-820d-849d5cd5fee0.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0cf7f2c1-78f5-43d6-820d-849d5cd5fee0.aspx Software Architect Conference 2010 <p> <a href="http://www.dotnetconsult.co.uk/weblog2/content/binary/WindowsLiveWriter/SoftwareArchitectConference2010_98EF/Speaker_SA2010_120x120_4.jpg"><img style="border-right-width: 0px; margin: 0px 15px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Speaker_SA2010_120x120" border="0" alt="Speaker_SA2010_120x120" align="left" src="http://www.dotnetconsult.co.uk/weblog2/content/binary/WindowsLiveWriter/SoftwareArchitectConference2010_98EF/Speaker_SA2010_120x120_thumb_1.jpg" width="124" height="124"></a> </p> <p> I’m speaking at Software Architect 2010 in October. I’m going to be delivering two sessions on Windows Workflow Foundation 4.0: the first explains the basic architecture and looks at using workflow as a Visual Scripting environment to empower business users. The second looks at building big systems with workflow concentrating on the WCF integration features. </p> <p> In addition to that I’ll be delivering two all-day workshops with <a href="http://andyclymer.blogspot.com/">Andy Clymer</a>: Building Applications the .NET 4.0 Way and Moving to the Parallel Mindset with .NET 4.0. The first of these will take a number of new features of .NET 4.0 and show how they can be combined to create compelling applications. The second will look at the Parallel Framework Extensions (PFx) introduced in .NET 4.0 examining both the rich functionality of the library, how it can be best leveraged avoiding common parallel pitfalls and finally looking at patterns that aid parallelisation of your code </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=0cf7f2c1-78f5-43d6-820d-849d5cd5fee0" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,adb974bc-7595-4e06-827b-12f7c09208ae.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,adb974bc-7595-4e06-827b-12f7c09208ae.aspx Unity, Multiple Constructors and Configuration <p> I’ve been working with the <a href="http://unity.codeplex.com/wikipage?title=Unity2">Unity IoC container</a> from Microsoft Patterns and Practices recently. Its mostly straightforward as IoC containers go but one thing had me puzzled for a while as its not really documented or blogged as far as I can see; so I decided to blog it so hopefully others looking will stumble across this article </p> <p> Lets start off with a simple example: I have two interfaces: <font face="Consolas">IService</font> and <font face="Consolas">IRepository</font> that live in the Interfaces class library </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">interface</span> IService</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">void</span> DoWork();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> }</pre> <!--CRLF--> </div> </div> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">interface</span> IRepository</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">string</span> GetStuff();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> }</pre> <!--CRLF--> </div> </div> I also have two implementations in the Services class library: <font face="Consolas">MyRepository</font>&nbsp; <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MyRepository : IRepository</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> GetStuff()</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">return</span> <span style="color: #006080">"TADA!!"</span>;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> }</pre> <!--CRLF--> </div> </div> <p> </p> <p> </p> <p> </p> <p> and <font face="Consolas">MyService</font> </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MyService : IService</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">private</span> IRepository repository;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">public</span> MyService(IRepository repository)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #0000ff">this</span>.repository = repository;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoWork()</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> Console.WriteLine(repository.GetStuff());</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> }</pre> <!--CRLF--> </div> </div> <p> </p> <p> Notice that <font face="Consolas">MyService</font> needs an <font face="Consolas">IRepository</font> to do its work. Now the idea here is I’m going to wire this together via dependency injection and the Unity IoC container. So I have my application </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">class</span> Program</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> UnityContainer container = <span style="color: #0000ff">new</span> UnityContainer();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection(<span style="color: #006080">"unity"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> section.Configure(container);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> IService svc = container.Resolve&lt;IService&gt;();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> svc.DoWork();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> }</pre> <!--CRLF--> </div> </div> <p> </p> <p> Notice as we’re using IoC that there are no hard coded dependencies – everything is wired up via the container. However, there must be some information about how the interfaces map to concrete types and this is in the config file </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="unity"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">configSections</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">unity</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">typeAliases</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #008000">&lt;!-- Lifetime Managers --&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">typeAlias</span> <span style="color: #ff0000">alias</span><span style="color: #0000ff">="singleton"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="Microsoft.Practices.Unity.ContainerControlledLifetimeManager"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #008000">&lt;!-- Interfaces --&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">typeAlias</span> <span style="color: #ff0000">alias</span><span style="color: #0000ff">="IService"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="Interfaces.IService,Interfaces"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">typeAlias</span> <span style="color: #ff0000">alias</span><span style="color: #0000ff">="IRepository"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="Interfaces.IRepository,Interfaces"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> <span style="color: #008000">&lt;!-- Implementations --&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">typeAlias</span> <span style="color: #ff0000">alias</span><span style="color: #0000ff">="service"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="Services.MyService, Services"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">typeAlias</span> <span style="color: #ff0000">alias</span><span style="color: #0000ff">="repository"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="Services.MyRepository, Services"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">typeAliases</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">containers</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">container</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">types</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">type</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="IService"</span> <span style="color: #ff0000">mapTo</span><span style="color: #0000ff">="service"</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">lifetime</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="singleton"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">type</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">type</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="IRepository"</span> <span style="color: #ff0000">mapTo</span><span style="color: #0000ff">="repository"</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27"> 27:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">lifetime</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="singleton"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28"> 28:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">type</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29"> 29:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">types</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30"> 30:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">container</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31"> 31:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">containers</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32"> 32:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">unity</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33"> 33:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">configuration</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--> </div> </div> <p> </p> <p> Now all of this works fine and is simple Unity stuff. We use constructor injection to get the repository implementation into the service constructor. However, I’ve decided the service needs a timeout that I will generally configure in the config file. However to make Unit Testing simple I’ll add another constructor to <font face="Consolas">MyService</font> so I can pass a specific timeout </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> MyService : IService</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">private</span> IRepository repository;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> TimeSpan timeout;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff">public</span> MyService(IRepository repository, TimeSpan timeout)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #0000ff">this</span>.timeout = timeout;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #0000ff">public</span> MyService(IRepository repository)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> <span style="color: #0000ff">this</span>.repository = repository;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> timeout = GetTimeoutFromConfig();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> <span style="color: #0000ff">private</span> TimeSpan GetTimeoutFromConfig()</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> <span style="color: #0000ff">return</span> <span style="color: #0000ff">default</span>(TimeSpan);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoWork()</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span> Console.WriteLine(repository.GetStuff());</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> }</pre> <!--CRLF--> </div> </div> <p> </p> <p> Now I try to run the application and I get a pretty ugly error </p> <font size="2" face="Consolas"><font size="2" face="Consolas"> <p> Unhandled Exception: Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, <br> type = "Interfaces.IService", name = "(none)".<br> Exception occurred while: while resolving.<br> Exception is: InvalidOperationException - The type Int32 cannot be constructed.<br> You must configure the container to supply this value. </font></font>> <p> <font face="Consolas"><font face="Consolas"><font size="2" face="Trebuchet MS">Now that’s weird – I have no types that take an <font face="Consolas">Int32</font>! This is caused by Unity’s default behavior where it will try to resolve on the constructor with the most parameters (on the basis that this one will have the most dependencies that can be injected). It tried to resolve the <font face="Consolas">TimeSpan</font> and so looks at the <font face="Consolas">TimeSpan</font> and tries to resolve its constructor which can take an <font face="Consolas">Int32</font>. I actually want to tell it to use a different constructor and I can do this in two ways: annotate the constructor I want to use with the <font face="Consolas">[InjectionConstructor]</font> attribute</font></font></font> </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> [InjectionConstructor]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff">public</span> MyService(IRepository repository)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">this</span>.repository = repository;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> timeout = GetTimeoutFromConfig();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> }</pre> <!--CRLF--> </div> </div> <font size="2" face="Consolas"><font size="2" face="Consolas"></font></font> <p> But personally I don’t like this. It forces the services assembly to take a dependency on Unity and the service has knowledge about how its being constructed. What I really want to do is specify this in config. This isn’t very well documented from what I can see but what you do it specify the constructor and how to resolve the parameters against the type mapping in the config – i.e. </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">type</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="IService"</span> <span style="color: #ff0000">mapTo</span><span style="color: #0000ff">="service"</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">lifetime</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="singleton"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">constructor</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">param</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="repository"</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">dependency</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">param</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">constructor</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">type</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--> </div> </div> <p> </p> As well as specifying dependencies you can also give explicit values by using <font face="Consolas">&lt;value/&gt;</font> instead of <font face="Consolas">&lt;dependency/&gt;</font>. This model I think is a lot cleaner than the attribute approach.<img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=adb974bc-7595-4e06-827b-12f7c09208ae" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0542f45a-40cc-4b2c-9bc4-b4b2740b2af4.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0542f45a-40cc-4b2c-9bc4-b4b2740b2af4.aspx Windows AppFabric Hits the Streets <p> Announced today at TechEd – Windows AppFabric is now available </p> <p> <a href="http://blogs.msdn.com/b/endpoint/archive/2010/06/07/windows-server-appfabric-now-generally-available.aspx">http://blogs.msdn.com/b/endpoint/archive/2010/06/07/windows-server-appfabric-now-generally-available.aspx</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=0542f45a-40cc-4b2c-9bc4-b4b2740b2af4" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,c12e0817-7c4b-4d6b-abce-a2afeeb258ce.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,c12e0817-7c4b-4d6b-abce-a2afeeb258ce.aspx Visual Studio 2010 Power Tools <p> The <a href="http://visualstudiogallery.msdn.microsoft.com/en-us/d0d33361-18e2-46c0-8ff2-4adea1e34fef">Visual Studio 2010 Power Tools</a> have just been released. There’s all sorts of goodness in here: new flexible tab handling in the VS shell (vertical tab groups, tabs grouped by project, dropping of rarely used tabs, etc); a new searchable Add Reference dialog; new editor enhancements to make navigation easier and much more </p> <p> I’ve been playing with it for the last couple of hours and its very neat. Of course I don’t use <a href="http://www.jetbrains.com/resharper/">Resharper</a> or <a href="http://www.devexpress.com/Products/Visual_Studio_Add-in/Coding_Assistance/">CodeRush</a> (I use too many machines I don’t control to become dependent on them) so some of these features may be available in those tools. But for me the power tools are a welcome addition to the IDE </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=c12e0817-7c4b-4d6b-abce-a2afeeb258ce" /> tag:blogger.com,1999:blog-30604582.post-8646374059620055218 http://andyclymer.blogspot.com/2010/06/software-architecture-2010.html Software Architecture 2010 <p>Myself and other Rock Solid Knowledge guys have had various talks accepted for Software Architecture conference this October in London.</p> <p>Rich and myself will be spending a day talking about how to use various bits of .NET 4 technology to build a MVC, WF and&#160; Entity Framework based application.&#160; The aim to build the app live, so you really get to see how this tech actually ticks.</p> <p>Through out the week I’ll be doing stuff on Patterns, and Parallel programming.</p> <p>Finishing the week with another day with Rich talking about parallel programming, all using the latest bits of .NET 4.</p> <p>Hopefully see you there…</p> <p><a href="http://www.software-architect.co.uk" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Speaker_SA2010_360x50" border="0" alt="Speaker_SA2010_360x50" src="http://lh4.ggpht.com/_OxnULoaN7CE/TAjpKB3vy5I/AAAAAAAAAqk/PpkqV3u2Hqo/Speaker_SA2010_360x50%5B4%5D.jpg?imgmax=800" width="244" height="37" /></a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8646374059620055218?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-2913322138003962057 http://andyclymer.blogspot.com/2010/04/devweek-2011.html Devweek 2011 <p>Just heard that Dev Week in London is going to run 14th to 18th March 2011.&#160;&#160; Rock Solid Knowledge will be submitting a variety of talks…If you have some ideas let us know and we will do our best to accommodate.</p> <p>And yep I’m sure Dr Rock Man will be back for the drop in consultations.</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2913322138003962057?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,332e063e-732b-45b7-a04b-2051785e0877.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,332e063e-732b-45b7-a04b-2051785e0877.aspx Rock Solid Knowledge Screencasts now Available via iTunes <p> Rock Solid Knowledge on iTunes is live! We’ve taken the feed to our free screencasts and they are now available through iTunes via the following link </p> <p> <a href="http://itunes.apple.com/gb/podcast/rock-solid-knowledge-screencasts/id365244375">http://itunes.apple.com/gb/podcast/rock-solid-knowledge-screencasts/id365244375</a> </p> <p> Now you can watch them on the move </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=332e063e-732b-45b7-a04b-2051785e0877" /> tag:blogger.com,1999:blog-30604582.post-3511313567790335548 http://andyclymer.blogspot.com/2010/03/demos-from-devweek-2010.html Demos from DevWeek 2010 Thanks to everyone who attended any of the Rock Solid Knowledge sessions at DevWeek we now have all our demos available for <a href="http://www.rocksolidknowledge.com/conferences.mvc">download</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3511313567790335548?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-2702075436619285294 http://andyclymer.blogspot.com/2010/03/devweek-2010.html DevWeek 2010 <p>Had a great time again at <a href="http://www.devweek.com">DevWeek 2010</a>.</p> <p>All my demos are <a href="http://www.rocksolidknowledge.com/Conferences.mvc/">uploaded</a> to our conference page. </p> <p>It was the first year we ran our “Ask the Doctor” booth for all those that dropped in I hope you found the advice useful…we certainly had a great time digging into interesting issues, from unit testing, Entity Framework, WCF and general architecture issues..</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2702075436619285294?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,ab2a4f9a-b925-4903-8792-fb0a3bc3386c.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,ab2a4f9a-b925-4903-8792-fb0a3bc3386c.aspx Demos from DevWeek 2010 <p> Thanks to everyone who attended my sessions at DevWeek 2010. I’ve now uploaded the demos which you can find at the following locations </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/demos/DevWeek2010DayOf4.0.zip">A Day of .NET 4.0 Demos</a> </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/demos/DevWeek2010WF4.zip">Windows Workflow Foundation 4.0 Demos</a> </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/demos/DevWeek2010WFServices.zip">Creating WCF Services using WF4 Demos</a> </p> <p> I’ll be around for the rest of the conference so drop by for a chat at our <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,93eeba3c-1dda-4f49-980d-03485fe9572e.aspx">developer clinic</a> in the exhibition area </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=ab2a4f9a-b925-4903-8792-fb0a3bc3386c" /> tag:blogger.com,1999:blog-30604582.post-3241539277798126119 http://andyclymer.blogspot.com/2010/03/ef4-and-repository-pattern.html EF4 And Repository Pattern <p>Just released a screencast on one possible way to implement the repository pattern using EF4. I’ve been very down on EF over the past year or so, but its nice at last to see it actually starting to be usable.</p> <p>You can listen to this screencast or other RSK screencasts <a href="http://www.rocksolidknowledge.com/screencasts">here</a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3241539277798126119?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,cd224eac-11f1-495e-a0f5-6b7678e2f35e.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,cd224eac-11f1-495e-a0f5-6b7678e2f35e.aspx Using advanced filters for custom routing logic in the Routing Service <p> In <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,7e558c12-f091-4c02-99c6-90eeca251641.aspx">my last post</a> I pointed to a screencast I had recorded that showed how to create a custom message filter to plug your own logic into the WCF 4.0 Routing Service. However, the simple custom filter is only the start – you can actually take control of part of the routing table which allows you to make global decisions about which filters match a particular request. On that basis I have created another screencast that shows how to build one of these more complex custom filters. in this case I use the example of a round robin load balancer where you can use a file on the file system to indicate whether a specific endpoint should be considered part of the load balancing algorithm </p> <p> You can find this last in the series of screencasts on the routing service, along with all the others here, on the <a href="http://rocksolidknowledge.com/">Rock Solid Knowledge</a> site </p> <p> <a href="http://rocksolidknowledge.com/ScreenCasts.mvc">http://rocksolidknowledge.com/ScreenCasts.mvc</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=cd224eac-11f1-495e-a0f5-6b7678e2f35e" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,7e558c12-f091-4c02-99c6-90eeca251641.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,7e558c12-f091-4c02-99c6-90eeca251641.aspx Using Custom Message Filters with the Routing Service <p> I’ve just uploaded a new screencast on the the <a href="http://www.rocksolidknowledge.com/">Rock Solid Knowledge site</a>. This one shows you how to plug your own routing logic into the new Routing Service that is part of WCF 4.0. It uses a custom message filter that can be used to supplement the existing set of filters such as matching on XPath and Action. </p> <p> You can find the screencast (along with the previous ones in the series) here </p> <p> <a href="http://www.rocksolidknowledge.com/ScreenCasts.mvc"><u><font color="#0066cc">http://www.rocksolidknowledge.com/ScreenCasts.mvc</font></u></a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=7e558c12-f091-4c02-99c6-90eeca251641" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,8a42e2b0-18e9-4730-add9-b2bbf8911bf5.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,8a42e2b0-18e9-4730-add9-b2bbf8911bf5.aspx Data Dependent Routing with the Routing Service <p> Continuing my screencast series on the Routing Service in WCF 4.0, I have just uploaded one on Data Dependent Routing </p> <p> You can get to the latest screencast (and all of the others) here <a href="http://rocksolidknowledge.com/ScreenCasts.mvc"><u><font color="#0066cc">http://rocksolidknowledge.com/ScreenCasts.mvc</font></u></a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=8a42e2b0-18e9-4730-add9-b2bbf8911bf5" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,aa6a1657-4815-4f33-b05f-ddea272abb86.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,aa6a1657-4815-4f33-b05f-ddea272abb86.aspx Failover and Multicast with the Routing Service <p> I have just published my second screencast on one of the new features of WCF 4.0 – the Routing Service. This screencast focuses on enabling multicast and failover with the Routing Service </p> <p> You can get to the screencast from here <a href="http://rocksolidknowledge.com/ScreenCasts.mvc"><u><font color="#0066cc">http://rocksolidknowledge.com/ScreenCasts.mvc</font></u></a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=aa6a1657-4815-4f33-b05f-ddea272abb86" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,ac4f4eaf-2b2d-475a-98b4-1bffb59b8e7b.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,ac4f4eaf-2b2d-475a-98b4-1bffb59b8e7b.aspx Demos from BASTA! <p> Thanks to everyone who attended my two sessions at <a href="http://it-republik.de/dotnet/basta10spring/">BASTA!</a> – another thoroughly enjoyable conference. I’ve uploaded the demos </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/downloads/BASTAWF4.zip">What’s new in Workflow 4.0</a> – this includes the application with the rehosted designer </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/downloads/BASTAWFServices.zip">Building WCF services with Workflow 4.0</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=ac4f4eaf-2b2d-475a-98b4-1bffb59b8e7b" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,acafcfb9-2d8a-46d3-8a02-b4414e203cf8.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,acafcfb9-2d8a-46d3-8a02-b4414e203cf8.aspx Creating Rich Composite Activities <p> I my <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,c3394709-1aaf-486a-8d1f-51050ce94ecc.aspx">last post</a> I showed that creating a custom composite activity (one that can have one or more children) requires deriving from <font face="Courier New">NativeActivity</font>. The <font face="Courier New">Retry</font> activity that I showed was fairly simple and in particular didn’t try to share data with its child. There appears to be a <a href="http://en.wikipedia.org/wiki/Catch-22_(logic)">catch-22</a> in this situation when it comes to overriding <font face="Courier New">CacheMetadata</font>: if I add a <font face="Courier New">Variable</font> to the metadata (<font face="Courier New">AddVariable</font>) then it can be used exclusively by its children – i.e. the activity itself can’t manipulate the state; if I add a variable as implementation data to the metadata (<font face="Courier New">AddImplementationVariable</font>) then the children cant see it as its seen as purely used for this activities implementation. How then do we create data that can be both manipulated by the activity and accessed by the parent? </p> <p> The secret to achieving this is a feature called <font face="Courier New">ActivityAction</font> - <a href="http://blogs.msdn.com/mwinkle/">Matt Winkler</a> talks about it <a href="http://blogs.msdn.com/mwinkle/archive/2009/12/24/swiss-cheese-and-wf4-or-an-introduction-to-activityaction.aspx">here</a>. The idea is that I can bind an activity to one or more parent defined pieces of data then schedule the activity where it will have access to the data. Its probably best to show this with an example so I have written a <font face="Courier New">ForEachFile</font> activity that you give a directory and then it passes its child the file name of each file in the directory in turn. I’ll show the code in its entirety and then walk through each piece in turn </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> [ContentProperty(<span style="color: #006080">"Body"</span>)]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> [Designer(<span style="color: #0000ff">typeof</span>(ForEachFileDesigner))]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ForEachFile : NativeActivity, IActivityTemplateFactory</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">public</span> InArgument&lt;<span style="color: #0000ff">string</span>&gt; Directory { get; set; }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> [Browsable(<span style="color: #0000ff">false</span>)]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #0000ff">public</span> ActivityAction&lt;<span style="color: #0000ff">string</span>&gt; Body { get; set; }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> <span style="color: #0000ff">private</span> Variable&lt;IEnumerator&lt;FileInfo&gt;&gt; files = <span style="color: #0000ff">new</span> Variable&lt;IEnumerator&lt;FileInfo&gt;&gt;(<span style="color: #006080">"files"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> CacheMetadata(NativeActivityMetadata metadata)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> metadata.AddDelegate(Body);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> RuntimeArgument arg = <span style="color: #0000ff">new</span> RuntimeArgument(<span style="color: #006080">"Directory"</span>, <span style="color: #0000ff">typeof</span>(<span style="color: #0000ff">string</span>), ArgumentDirection.In);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> metadata.AddArgument(arg);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> metadata.AddImplementationVariable(files);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Execute(NativeActivityContext context)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> DirectoryInfo dir = <span style="color: #0000ff">new</span> DirectoryInfo(Directory.Get(context));</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span> IEnumerable&lt;FileInfo&gt; fileEnum = dir.GetFiles();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> IEnumerator&lt;FileInfo&gt; fileList = fileEnum.GetEnumerator();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27"> 27:</span> files.Set(context, fileList);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28"> 28:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29"> 29:</span> <span style="color: #0000ff">bool</span> more = fileList.MoveNext();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30"> 30:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31"> 31:</span> <span style="color: #0000ff">if</span> (more)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32"> 32:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33"> 33:</span> context.ScheduleAction&lt;<span style="color: #0000ff">string</span>&gt;(Body, fileList.Current.FullName, OnBodyComplete);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34"> 34:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35"> 35:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36"> 36:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37"> 37:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> OnBodyComplete( NativeActivityContext context, ActivityInstance completedInstance)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38"> 38:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39"> 39:</span> IEnumerator&lt;FileInfo&gt; fileList = files.Get(context);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40"> 40:</span> <span style="color: #0000ff">bool</span> more = fileList.MoveNext();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum41"> 41:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum42"> 42:</span> <span style="color: #0000ff">if</span> (more)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum43"> 43:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum44"> 44:</span> context.ScheduleAction&lt;<span style="color: #0000ff">string</span>&gt;(Body, fileList.Current.FullName, OnBodyComplete);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum45"> 45:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum46"> 46:</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum47"> 47:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum48"> 48:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum49"> 49:</span> <span style="color: #cc6633">#region</span> IActivityTemplateFactory Members</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum50"> 50:</span> <span style="color: #0000ff">public</span> Activity Create(DependencyObject target)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum51"> 51:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum52"> 52:</span> var fef = <span style="color: #0000ff">new</span> ForEachFile();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum53"> 53:</span> var aa = <span style="color: #0000ff">new</span> ActivityAction&lt;<span style="color: #0000ff">string</span>&gt;();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum54"> 54:</span> var da = <span style="color: #0000ff">new</span> DelegateInArgument&lt;<span style="color: #0000ff">string</span>&gt;();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum55"> 55:</span> da.Name = <span style="color: #006080">"item"</span>;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum56"> 56:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum57"> 57:</span> fef.Body = aa;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum58"> 58:</span> aa.Argument = da;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum59"> 59:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum60"> 60:</span> <span style="color: #0000ff">return</span> fef;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum61"> 61:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum62"> 62:</span> <span style="color: #cc6633">#endregion</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum63"> 63:</span> }</pre> <!--CRLF--> </div> </div> <p> </p> <p> Ok lets start with the core functionality then we’ll look at each of the pieces that help make this fully usable. As you can see the class derives from <font face="Courier New">NativeActivity</font> and overrides <font face="Courier New">CacheMetadata</font> and <font face="Courier New">Execute</font> – we’ll look at their implementations in a minute. There are three member variables in the class: the <font face="Courier New">InArgument&lt;string&gt;</font> for the directory; an implementation variable to hold the iterator as we move through the files in the directory; the all important <font face="Courier New">ActivityAction&lt;string&gt;</font> which we will use to pass the current file name to the child activity. </p> <p> Lets look at <font face="Courier New">CacheMetadata</font> more closely. Because we want to do interesting things with some of the state the default implementation won’t work so we override it. As we don’t call the base class version we need to specify how we use all of the state. We add the <font face="Courier New">ActivityAction</font> as a delegate, we bind the <font face="Courier New">Directory</font> argument to a <font face="Courier New">RuntimeArgument</font> and specify the iterator as an implementation variable – we don’t want the child activity to have access to that directly. </p> <p> Next lets look at <font face="Courier New">Execute</font>. The first couple of lines are nothing unusual – we get the directory and get hold of the list of files. Now we have to store the retrieved iterator in the implementation variable, <font face="Courier New">fileList</font>. We move to the first file in the iteration, if it returns <font face="Courier New">false</font> the list was empty so as long as <font face="Courier New">MoveNext</font> returned <font face="Courier New">true</font> we want to schedule the child activity passing the current file. To do this we use the <font face="Courier New">ScheduleAction&lt;T&gt;</font> member on the context. However, because we’re going to process each one sequentially, we also need to know when the child is finished so we pass a completion callback, <font face="Courier New">OnBodyComplete</font>. </p> <p> Now in <font face="Courier New">OnBodyComplete</font> we simply get the iterator, move to the next item in the iteration and as long as we’re not finished iterating re-schedule the child again passing the new item in the iteration. </p> <p> That really is the “functional” part of the activity – everything else is there to support the designer. So why does the designer need help? Well lets look at what we would have to do to build this activity correctly if we were going to execute it from main </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> Activity workflow = <span style="color: #0000ff">new</span> ForEachFile</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> Body = <span style="color: #0000ff">new</span> ActivityAction&lt;<span style="color: #0000ff">string</span>&gt;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> Argument = <span style="color: #0000ff">new</span> DelegateInArgument&lt;<span style="color: #0000ff">string</span>&gt;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> Name = <span style="color: #006080">"item"</span>,</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> },</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> Handler = <span style="color: #0000ff">new</span> WriteLine</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> Text = <span style="color: #0000ff">new</span> VisualBasicValue&lt;<span style="color: #0000ff">string</span>&gt;(<span style="color: #006080">"item"</span>)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> },</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> Directory = <span style="color: #006080">@"c:\windows"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> };</pre> <!--CRLF--> </div> </div> <p> </p> <p> As you can see, its not a matter of simply creating the <font face="Courier New">ForEachFile</font>, we have to build the internal structure too – something needs to create that structure for the designer - this is the point of <font face="Courier New">IActivityTemplateFactory</font>. When you drag an activity on to the design surface normally it just creates the XAML for that activity. However, before it does that it does a speculative cast for <font face="Courier New">IActivityTemplateFactory</font> and if the activity supports that it calls the interface’s <font face="Courier New">Create</font> method instead and serializes the resulting activity to XAML. </p> <p> So going back to the <font face="Courier New">ForEachFile</font> activity, you can see it implements <font face="Courier New">IActivityTemplateFactory</font> and therefore, as far as the designer is concerned, this is the interesting functionality – lets take a look at the <font face="Courier New">Create</font> method.We create the <font face="Courier New">ForEachFile</font> and wire an <font face="Courier New">ActivityAction&lt;string&gt;</font> to its <font face="Courier New">Body</font> property. <font face="Courier New">ActivityAction&lt;string</font>&gt; needs a slot to store the data to be presented to the child activity. This is modelled by<font face="Courier New"> DelegateArgument&lt;string&gt;</font> and this gets wired to the <font face="Courier New">Argument</font> member of the <font face="Courier New">ActvityAction</font>. We also name the argument as we want a default name for the state so the child activity can use it. Notice, however, we don’t specify the child activity itself (it would be a pretty useless composite if we hard coded this). The child will be placed on the <font face="Courier New">Handler</font> property of the <font face="Courier New">ActivityAction</font> but that will be done in the <font face="Courier New">ActivityDesigner</font> using data binding. </p> <p> Before we look at the designer lets highlight a couple of “polishing” features of the code: the class declared a <font face="Courier New">ContentProperty</font> via an attribute – that just makes the XAML parsing cleaner as the child doesn’t need to be specified using <a href="http://msdn.microsoft.com/en-us/library/ms788723.aspx#PESyntax">property element syntax</a>; the <font face="Courier New">Body</font> is set to non-browsable – we don’t want the activities user to try to set this value in the property grid. </p> <p> OK on to the designer. If you read my previous article there are a couple of new things here. Lets look at the markup – again there is no special code in the code behind file, everything is achieved using data binding </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sap:ActivityDesigner</span> <span style="color: #ff0000">x:Class</span><span style="color: #0000ff">="ActivityLib.ForEachFileDesigner"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #ff0000">xmlns</span><span style="color: #0000ff">="http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #ff0000">xmlns:x</span><span style="color: #0000ff">="http://schemas.microsoft.com/winfx/2006/xaml"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #ff0000">xmlns:s</span><span style="color: #0000ff">="clr-namespace:System;assembly=mscorlib"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #ff0000">xmlns:conv</span><span style="color: #0000ff">="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #ff0000">xmlns:sap</span><span style="color: #0000ff">="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #ff0000">xmlns:sapv</span><span style="color: #0000ff">="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #ff0000">xmlns:me</span><span style="color: #0000ff">="clr-namespace:ActivityLib"</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sap:ActivityDesigner.Resources</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">conv:ArgumentToExpressionConverter</span> <span style="color: #ff0000">x:Key</span><span style="color: #0000ff">="expressionConverter"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">sap:ActivityDesigner.Resources</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">Grid</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">Grid.RowDefinitions</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">RowDefinition</span> <span style="color: #ff0000">Height</span><span style="color: #0000ff">="Auto"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">RowDefinition</span> <span style="color: #ff0000">Height</span><span style="color: #0000ff">="*"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">Grid.RowDefinitions</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">StackPanel</span> <span style="color: #ff0000">Orientation</span><span style="color: #0000ff">="Horizontal"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">TextBlock</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">="For each file "</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">TextBox</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">="{Binding ModelItem.Body.Argument.Name}"</span> <span style="color: #ff0000">MinWidth</span><span style="color: #0000ff">="50"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">TextBlock</span> <span style="color: #ff0000">Text</span><span style="color: #0000ff">=" in "</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sapv:ExpressionTextBox</span> <span style="color: #ff0000">Expression</span><span style="color: #0000ff">="{Binding Path=ModelItem.Directory, Converter={StaticResource expressionConverter}}"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span> <span style="color: #ff0000">ExpressionType</span><span style="color: #0000ff">="s:String"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span> <span style="color: #ff0000">OwnerActivity</span><span style="color: #0000ff">="{Binding ModelItem}"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">StackPanel</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27"> 27:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sap:WorkflowItemPresenter</span> <span style="color: #ff0000">Item</span><span style="color: #0000ff">="{Binding ModelItem.Body.Handler}"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28"> 28:</span> <span style="color: #ff0000">HintText</span><span style="color: #0000ff">="Drop activity"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29"> 29:</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Row</span><span style="color: #0000ff">="1"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="6"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30"> 30:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31"> 31:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">Grid</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32"> 32:</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33"> 33:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">sap:ActivityDesigner</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--> </div> </div> <p> Here’s what this looks like in the designer </p> <p> <a href="http://www.dotnetconsult.co.uk/weblog2/content/binary/WindowsLiveWriter/CreatingRichCompositeActivities_C385/ForEachFile_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="ForEachFile" border="0" alt="ForEachFile" src="http://www.dotnetconsult.co.uk/weblog2/content/binary/WindowsLiveWriter/CreatingRichCompositeActivities_C385/ForEachFile_thumb.png" width="244" height="84"></a> </p> <p> So the TextBox at line 21 displays the argument name that our IActivityTemplateFactory implementation set up. The ExpressionTextBox is bound to the directory name but allows VB.NET expressions to be used. The WorkflowItemPresenter is bound to the Handler property of the Body ActivityAction, This designer is then associated with the activity using the [Designer] attribute. </p> <p> So as you can see, ActivityAction and IActivityTemplateFactory work together to allow us to build rich composite activities with design time support </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=acafcfb9-2d8a-46d3-8a02-b4414e203cf8" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,c3394709-1aaf-486a-8d1f-51050ce94ecc.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,c3394709-1aaf-486a-8d1f-51050ce94ecc.aspx NativeActivity &ndash; A Tricky Beast <p> I’m writing <a href="http://www.develop.com/course/windows-workflow-foundation-csharp-4">Essential Windows Workflow Foundation 4.0</a> with <a href="http://msmvps.com/blogs/theproblemsolver/default.aspx">Maurice</a> for <a href="http://www.develop.com">DevelopMentor</a>. One of the things that I think is less than obvious is the behavior of NativeActivity. </p> <p> What is NativeActivity I hear you ask? Well there are a number of models for building custom activities in WF4. Most “business” type custom activities will be built using a declarative model in XAML by assembling building blocks graphically. However, what if you are missing a building block? At this point you have to fall back to writing code and there are three options for your base class when writing an activity in code: </p> <p> <strong><font size="2">CodeActivity</font></strong> <br> You use CodeActivity when you have a simple synchronous activity. All work happens in Execute and it has no child activities </p> <p> <strong>AsyncCodeActivity</strong> <br> This is new to WF4. Here you have the ability to implement the async pattern (BeginExecute / EndExecute) to perform short lived async operations where you do not want the workflow persisted (e.g. an async WebRequest) </p> <p> NativeActivity<br> This gives you full access to the power of the workflow execution engine. However, in the words of <a href="http://en.wikipedia.org/wiki/Uncle_Ben">Spiderman’s Uncle</a>, “with great power comes great responsibility”. NativeActivity can be a bit tricky so that is what this article is about </p> <p> I’m going to walk through the code for a Retry activity – where a child activity can be rerun a number of times upon failure. The activity has two InArguments: <font face="Courier New">MaxRetries</font> and <font face="Courier New">RetryDelay</font>. <font face="Courier New">MaxRetries</font> says how many times you will retry the child before giving up. <font face="Courier New">RetryDelay</font> says how long to wait between retries. We could use a <font face="Courier New">Thread.Sleep</font> to do the delay but this would not be good for the workflow engine: we block a thread it could use and there is no way for the engine to persist the workflow – what if we wanted to retry in 2 days? So instead, as part of our implementation, we’ll use a <font face="Courier New">Delay</font> activity. </p> <p> Now to explain the code we have to take a slight diversion and talk about the relationship between Activity, ActivityInstance and ExecutionContext. I talked about is a while back <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,5a7759a2-c6c3-41f6-af58-ba4f82becc9a.aspx">here</a> when the PDC CTP first came out (that’s what the reference to some base class called WorkflowElement is about) but to expand a little: The Activity is really just a template containing the code to execute for the activity. The ActivityInstance is the actual thing that is executing. It holds the state for this instance of the activity template. Now we need a way to bind the template code to the currently running instance of the activity and this is the role of the ExecutionContext. If you are using a CodeActivity base class then most of this is hidden from you except that you have to access arguments by passing in the ExecutionContext. However, with NativeActivity you have to get more directly involved with this model. </p> <p> Now how does the workflow engine know what data you need to store in the ActivityInstance? Well it turns out you need to tell it. NativeActivity has a virtual method called CacheMetadata (<a href="http://blogs.msdn.com/tilovell/archive/2010/02/06/nativeactivity-cachemetadata-for-fun-and-profit.aspx">this post</a> talks about it to some degree). The point being that the activity has to register all of the “stuff” that it wants to use during its execution. Now the base class implementation will do some fairly reasonable default actions but it cannot know, for example, that part of your functionality is there purely for implementation details and should not be public. Therefore, you will often override this when you create a NativeActivity </p> <p> So without more ado – here’s the code for the Retry activity. I’ll then walk through it </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> [Designer(<span style="color: #0000ff">typeof</span>(ForEachFileDesigner))]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Retry : NativeActivity</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">public</span> InArgument&lt;<span style="color: #0000ff">int</span>&gt; MaxRetries { get; set; }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">public</span> InArgument&lt;TimeSpan&gt; RetryDelay { get; set; }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff">private</span> Delay Delay = <span style="color: #0000ff">new</span> Delay();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #0000ff">public</span> Activity Body { get; set; }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> Variable&lt;<span style="color: #0000ff">int</span>&gt; CurrentRetry = <span style="color: #0000ff">new</span> Variable&lt;<span style="color: #0000ff">int</span>&gt;(<span style="color: #006080">"CurrentRetry"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> CacheMetadata(NativeActivityMetadata metadata)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> metadata.AddChild(Body);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> metadata.AddImplementationVariable(CurrentRetry);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> RuntimeArgument arg = <span style="color: #0000ff">new</span> RuntimeArgument(<span style="color: #006080">"MaxRetries"</span>, <span style="color: #0000ff">typeof</span>(<span style="color: #0000ff">int</span>), ArgumentDirection.In);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> metadata.Bind(MaxRetries, arg);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> metadata.AddArgument(arg);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> Delay.Duration = RetryDelay;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> metadata.AddImplementationChild(Delay);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Execute(NativeActivityContext context)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27"> 27:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28"> 28:</span> CurrentRetry.Set(context, 0);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29"> 29:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30"> 30:</span> context.ScheduleActivity(Body, OnFaulted);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31"> 31:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32"> 32:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33"> 33:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> OnFaulted(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34"> 34:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35"> 35:</span> <span style="color: #0000ff">int</span> current = CurrentRetry.Get(faultContext);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36"> 36:</span> <span style="color: #0000ff">int</span> max = MaxRetries.Get(faultContext);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37"> 37:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38"> 38:</span> <span style="color: #0000ff">if</span> (current &lt; max)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39"> 39:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40"> 40:</span> faultContext.CancelChild(propagatedFrom);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum41"> 41:</span> faultContext.HandleFault();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum42"> 42:</span> faultContext.ScheduleActivity(Delay, OnDelayComplete);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum43"> 43:</span> CurrentRetry.Set(faultContext, current + 1);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum44"> 44:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum45"> 45:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum46"> 46:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum47"> 47:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> OnDelayComplete(NativeActivityContext context, ActivityInstance completedInstance)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum48"> 48:</span> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum49"> 49:</span> context.ScheduleActivity(Body, OnFaulted);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum50"> 50:</span> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum51"> 51:</span> }</pre> <!--CRLF--> </div> </div> <p> </p> <p> So lets look at the code: first the class derives from NativeActivity (we’ll come to the designer later). This means I want to do fancy things like have child activities or perform long running asynchronous work. Next we see the two InArguments that are passed to the Retry. The Delay is an implementation detail of how we will pause between retry attempts and the Body property is where the activity we are going to retry lives. Finally we have a Variable, CurrentRetry, where we store how many retry attempts we have made. That is the data in the class but remember we need to tell the workflow engine about what we need to store and why – this is the point of CacheMetadata (I read this method name as “here is the metadata for the cache” rather than “I am going to cache some metadata”) </p> <p> In CacheMetadata the first thing we do is specify that the Body is our child activity. Next we tell the engine that we want to be able to get hold of the CurrentRetry but that its only there for our implementation – we’re not expecting the child activity to try to make use of it. The next 3 lines (17-19) seem a little strange but essentially we’re saying that the MaxRetries argument needs to be accessed over the whole lifetime of the ActivityInstance so we need a slot for that. We next configure out Delay activity passing the RetryDelay as its duration (this is how long we want to wait between retries). Finally we add the Delay, not as a normal child, but as an implementation detail. </p> <p> OK, Execute is pretty simple – we initialize the CurrentRetry and then schedule the Body. But, because we want to retry on failure, we also pass in a fault handler (OnFaulted) </p> <p> OnFaulted does the main work. It fires if the child fails. So it checks to see if we have exceeded the retry count and if not retries the Body activity. However, it doesn’t do this directly, first it tells the context that it has handled the error – it also, strangely has to cancel the current child (which is odd as its already faulted) – Maurice talks about this oddity <a href="http://msmvps.com/blogs/theproblemsolver/archive/2010/02/09/error-handling-in-a-nativeactivity.aspx">here</a>. Next it schedules the Delay as we have to wait for the retry delay and wires up a completion handler (OnDelayComplete) so we know when the delay is finished. Finally it updates the CurrentRetry. </p> <p> OnDelayComplete simply reschedules the Body activity, remembering to pass the fault handler again in case the activity fails again. </p> <p> Oh one thing I said I’d come back to – the designer. I have written a designer to go with this (designers in WF4 are WPF based). The XAML for this is here: </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sap:ActivityDesigner</span> <span style="color: #ff0000">x:Class</span><span style="color: #0000ff">="WordActivities.ForEachFileDesigner"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #ff0000">xmlns</span><span style="color: #0000ff">="http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #ff0000">xmlns:s</span><span style="color: #0000ff">="clr-namespace:System;assembly=mscorlib"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #ff0000">xmlns:x</span><span style="color: #0000ff">="http://schemas.microsoft.com/winfx/2006/xaml"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #ff0000">xmlns:sap</span><span style="color: #0000ff">="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #ff0000">xmlns:sapv</span><span style="color: #0000ff">="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #ff0000">xmlns:conv</span><span style="color: #0000ff">="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation"</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #ff0000">mc:Ignorable</span><span style="color: #0000ff">="d"</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #ff0000">xmlns:d</span><span style="color: #0000ff">="http://schemas.microsoft.com/expression/blend/2008"</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> <span style="color: #ff0000">xmlns:mc</span><span style="color: #0000ff">="http://schemas.openxmlformats.org/markup-compatibility/2006"</span> <span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sap:ActivityDesigner.Resources</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">conv:ArgumentToExpressionConverter</span> <span style="color: #ff0000">x:Key</span><span style="color: #0000ff">="expressionConverter"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">sap:ActivityDesigner.Resources</span><span style="color: #0000ff">&gt;</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">Grid</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">Grid.RowDefinitions</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">RowDefinition</span> <span style="color: #ff0000">Height</span><span style="color: #0000ff">="Auto"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">RowDefinition</span> <span style="color: #ff0000">Height</span><span style="color: #0000ff">="Auto"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">RowDefinition</span> <span style="color: #ff0000">Height</span><span style="color: #0000ff">="*"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">Grid.RowDefinitions</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">Grid.ColumnDefinitions</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">ColumnDefinition</span> <span style="color: #ff0000">Width</span><span style="color: #0000ff">="Auto"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">ColumnDefinition</span> <span style="color: #ff0000">Width</span><span style="color: #0000ff">="*"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">Grid.ColumnDefinitions</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">TextBlock</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Row</span><span style="color: #0000ff">="0"</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Column</span><span style="color: #0000ff">="0"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">&gt;</span>Max. Retries:<span style="color: #0000ff">&lt;/</span><span style="color: #800000">TextBlock</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sapv:ExpressionTextBox</span> <span style="color: #ff0000">Expression</span><span style="color: #0000ff">="{Binding Path=ModelItem.MaxRetries, Converter={StaticResource expressionConverter}}"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27"> 27:</span> <span style="color: #ff0000">ExpressionType</span><span style="color: #0000ff">="s:Int32"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28"> 28:</span> <span style="color: #ff0000">OwnerActivity</span><span style="color: #0000ff">="{Binding ModelItem}"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29"> 29:</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Row</span><span style="color: #0000ff">="0"</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Column</span><span style="color: #0000ff">="1"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30"> 30:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31"> 31:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">TextBlock</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Row</span><span style="color: #0000ff">="1"</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Column</span><span style="color: #0000ff">="0"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">&gt;</span>Retry Delay:<span style="color: #0000ff">&lt;/</span><span style="color: #800000">TextBlock</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32"> 32:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sapv:ExpressionTextBox</span> <span style="color: #ff0000">Expression</span><span style="color: #0000ff">="{Binding Path=ModelItem.RetryDelay, Converter={StaticResource expressionConverter}}"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33"> 33:</span> <span style="color: #ff0000">ExpressionType</span><span style="color: #0000ff">="s:TimeSpan"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34"> 34:</span> <span style="color: #ff0000">OwnerActivity</span><span style="color: #0000ff">="{Binding ModelItem}"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35"> 35:</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Row</span><span style="color: #0000ff">="1"</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Column</span><span style="color: #0000ff">="1"</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36"> 36:</span> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37"> 37:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">sap:WorkflowItemPresenter</span> <span style="color: #ff0000">Item</span><span style="color: #0000ff">="{Binding ModelItem.Body}"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38"> 38:</span> <span style="color: #ff0000">HintText</span><span style="color: #0000ff">="Drop Activity"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39"> 39:</span> <span style="color: #ff0000">Margin</span><span style="color: #0000ff">="6"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40"> 40:</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Row</span><span style="color: #0000ff">="2"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum41"> 41:</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">Column</span><span style="color: #0000ff">="0"</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum42"> 42:</span> <span style="color: #ff0000">Grid</span>.<span style="color: #ff0000">ColumnSpan</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">/&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum43"> 43:</span>&nbsp; </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum44"> 44:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">Grid</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum45"> 45:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">sap:ActivityDesigner</span><span style="color: #0000ff">&gt;</span></pre> <!--CRLF--> </div> </div> <p> There is no special code behind, everything is done via databinding. </p> <p> So as you can see, there are a lot of pieces that need to be put into place for something that seems fairly simple. The critical issue is getting the implementation of CacheMetadata correct – once you have identified all of the pieces of data you need stored the rest falls out nicely. </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=c3394709-1aaf-486a-8d1f-51050ce94ecc" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,b9c1ff65-8823-4a5e-ae07-7531c258a5ac.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,b9c1ff65-8823-4a5e-ae07-7531c258a5ac.aspx EF4 Self Tracking Entities &ndash; the new DataSet? <p> A while back I wrote <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0a7cd196-c36b-4afa-ab02-5e4e6829c42d.aspx">a blog post about DataSets</a> and why you shouldn’t use them on service boundaries. The fundamental issues are: </p> <ol> <li> No non-.NET client has any idea what the data looks like you are sending them</li> <li> Hidden, non essential data is being passes up and down the wire</li> <li> Your client gets coupled to the shape of your data (usually a product of the Data Access Layer)</li> </ol> <p> So when I saw that Entity Framework 4.0 supports Self Tracking Entities (STEs) I was interested to see how they would work – after all, automated change tracking is one of the reasons people wanted to use DataSets in service contracts. The idea is that as you manipulate the state the object itself tracks the changes to properties and whether it has been created new or marked for deletion. It does this by implementing an interface called <font face="Courier New">IObjectWithchangeTracker</font> which is then used by the <font face="Courier New">ObjectContext</font> to work out what needs to be done in terms of persistence. There is an extension method on the <font face="Courier New">ObjectContext</font> called <font face="Courier New">ApplyChanges</font> which does the heavy lifting. </p> <p> The Entity Framework team has released a <a href="http://msdn.microsoft.com/en-us/library/bb126445.aspx">T4 Template</a> to generate these STEs from an EDMX file and the nice thing is that the generated entities themselves have no dependency on the Entity Framework. Only the generated context class has this dependency and, so the story goes, the client needs to know nothing about Entity Framework, only the service does. The client, and the entities, remain ignorant of the persistence model. For this reason STEs have been touted as a powerful tool in n-tier based architectures </p> <p> All of this seems almost too good to be true … and unfortunately it is. </p> <p> To understand what the issue is with STEs we have to remember what two of the main goals of Service based systems are: </p> <ol> <li> Support heterogeneous systems – the service ecosystem is not bound to one technology</li> <li> Decoupling – to ensure changes in a service do not cascade to consumers of the service for technical reasons (there may obviously be business reasons why we might want a change in a service to effect the consumers such as changes in law or legislation) </li> </ol> <p> So to understand the problem with STEs we need to look at the generated code.Here’s the model I’m using: </p> <p> <a href="http://www.dotnetconsult.co.uk/weblog2/content/binary/WindowsLiveWriter/EF4SelfTrackingEntitiesthenewDataSet_B3E9/edmx_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="edmx" border="0" alt="edmx" src="http://www.dotnetconsult.co.uk/weblog2/content/binary/WindowsLiveWriter/EF4SelfTrackingEntitiesthenewDataSet_B3E9/edmx_thumb.png" width="244" height="135"></a> </p> <p> Now lets look at the T4 Template generated code for, say, the <font face="Courier New">OrderLine</font> </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">[DataContract(IsReference = <span style="color: #0000ff">true</span>)]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">[KnownType(<span style="color: #0000ff">typeof</span>(Order))]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">partial</span> <span style="color: #0000ff">class</span> OrderLine: IObjectWithChangeTracker, INotifyPropertyChanged</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #cc6633">#region</span> Primitive Properties</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> [DataMember]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> id</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> _id; }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> set</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (_id != <span style="color: #0000ff">value</span>)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> ChangeTracker.RecordOriginalValue(<span style="color: #006080">"id"</span>, _id);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> _id = <span style="color: #0000ff">value</span>;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> OnPropertyChanged(<span style="color: #006080">"id"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> _id;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #008000">// more details elided for clarity</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--> </div> </div> <p> A few things to notice: firstly this is a <font face="Courier New">DataContract</font> and therefore is designed to be used on WCF contracts – that is its intent; secondly a bit of work takes place inside the generated property setters. The property setters check to see if the data is actually changed, then it records the old value and raises calls <font face="Courier New">OnPropertyChanged</font> to raise the <font face="Courier New">PropertyChanged</font> event (defined on <font face="Courier New">INotifyPropertyChanged</font>). Lets have a look inside <font face="Courier New">OnPropertyChanged</font>: </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">virtual</span> <span style="color: #0000ff">void</span> OnPropertyChanged(String propertyName)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (ChangeTracker.State != ObjectState.Added && ChangeTracker.State != ObjectState.Deleted)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> ChangeTracker.State = ObjectState.Modified;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (_propertyChanged != <span style="color: #0000ff">null</span>)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> _propertyChanged(<span style="color: #0000ff">this</span>, <span style="color: #0000ff">new</span> PropertyChangedEventArgs(propertyName));</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--> </div> </div> <p> </p> <p> Ok so maybe a bit more than raising the event. It also marks the object as modified in the <font face="Courier New">ChangeTracker</font>. The <font face="Courier New">ChangeTracker</font> state is partly how the STE serializes its self tracked changes. It is this data that is used by the <font face="Courier New">ApplyChanges</font> extension method to work out what has changed. So the thing to remember here is that the change tracking is performed by <strong>code generated into the property setters</strong>. </p> <p> Well the T4 Template has done its work so we create our service contract using these conveniently generated types and the client uses metadata and Add Service Reference to build its proxy code. It gets the <font face="Courier New">OrderLine</font> from the service, updates the quantity and sends it back. The service calls <font face="Courier New">ApplyChanges</font> on the context and then saves the changes and … <em>nothing changes in the Database</em>. What on earth went wrong? </p> <p> At this point we have to step back and think about what those types we use in service contracts are actually doing. <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx">Those types are nothing more than serialization helpers</a> – to help us bridge the object world to the XML one. The metadata generation uses the type definition and the attribute annotations to generate a schema (XSD) definition of the data in the class. Notice we’re only talking about data – there is no concept of behavior. And this is the problem When the Add Service Reference code generation takes place its based on the schema in the service metadata – so the objects *look* right, just the all important code in the property setters is missing. So you can change the state of entities in the client and the service will never be able to work out if the state has changed – so changes don’t get propagated to the database. </p> <p> There is a workaround for this problem. You take the generated STEs and put them in a separate assembly which you give to the client. Now the client has all of the change tracking code available to it, changes get tracked and the service can work out what has changed and persist it. </p> <p> But what have we just done? We have forced the client to be .NET. Not only that, we’ve probably compiled against .NET 4.0 and so we are requiring the client to be .NET 4.0 aware – we might as well have taken out a dependency on Entity Framework 4.0 in the client at this point. In addition, changes I make to the EDMX file are going to get reflected in the T4 generated code – I have coupled my client to my data access layer. Lets go back to the problems with using DataSets on service boundaries again. We’re back where we pretty much started – although the data being transmitted is more controlled. </p> <p> So STEs at first glance look very attractive, but in service terms they are in fact similar to using DataSets in terms of the effect on the service consumer. So what is the solution? We’ll we’re back with our old friends DTOs and <a href="http://www.codeplex.com/AutoMapper">AutoMapper</a>. To produce real decoupling and allow heterogeneous environments we have to explicitly model the *data* being passed at service boundaries. How this is patched this into our data access layer is up to the service. Entity Framework 4.0 certainly improves matters here over 1.0 as we can use POCOs which aid testability and flexibility of our service </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=b9c1ff65-8823-4a5e-ae07-7531c258a5ac" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,93eeba3c-1dda-4f49-980d-03485fe9572e.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,93eeba3c-1dda-4f49-980d-03485fe9572e.aspx Dr Rockman is IN! <p> I’ve just noticed that <a href="http://andyclymer.blogspot.com/2010/02/ask-doctor-devweek-2010.html">Andy has blogged</a> about our drop in clinic we are running at <a href="http://www.devweek.com/welcome.asp">DevWeek 2010</a>. All of the <a href="http://rocksolidknowledge.com/Home.mvc/us">Rock Solid Knowledge guys</a> will be at the conference so come over and let us help solve your design and coding problems – whether it be WCF, Workflow, Multithreading, WPF, Silverlight, ASP.NET MVC,&nbsp; Design Patterns or whatever you are currently wrestling with. We’re also doing a bunch of talks (detailed on our <a href="http://rocksolidknowledge.com/Conferences.mvc/">Conferences page</a>) </p> <p> <a href="http://rocksolidknowledge.com/"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DrRockman" border="0" alt="DrRockman" src="http://www.dotnetconsult.co.uk/weblog2/content/binary/WindowsLiveWriter/DrRockmanisIN_BB50/DrRockman_3.png" width="144" height="244"></a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=93eeba3c-1dda-4f49-980d-03485fe9572e" /> tag:blogger.com,1999:blog-30604582.post-7903810114861561910 http://andyclymer.blogspot.com/2010/02/ask-doctor-devweek-2010.html Ask the doctor ( Devweek 2010) <pre>Dr Rockman is In!</pre><br /><br /><p>At <a href="http://www.devweek.com" target="_blank">DevWeek 2010</a> Rock Solid Knowledge will be running a drop in clinic where our consultants will help you solve your design and development issues.&#160; The whole team will be there so whether its WPF, Silverlight, .NET 4.0, WCF , Design Patterns, Multithreading, Web Development or anything else, we’ll be on hand to lend a sympathetic ear and hopefully solve your problems.&#160; In addition the RSK crew will be delivering pre and post conference days and a whole bunch of sessions which you can see on our <a href="http://www.rocksolidknowledge.com/Conferences.mvc" target="_blank">conference page</a>.</p><br /><br /><p></p><br /><br /><p><a href="http://lh5.ggpht.com/_OxnULoaN7CE/S2qq4t6IAKI/AAAAAAAAAqU/EKSCAzu1WMA/s1600-h/image%5B2%5D.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_OxnULoaN7CE/S2qq5oV1XfI/AAAAAAAAAqY/9m97LN_2DU0/image_thumb.png?imgmax=800" width="142" height="244" /></a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-7903810114861561910?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-6586621841968635898 http://andyclymer.blogspot.com/2010/02/visual-studio-ctrltab-sticking.html Visual Studio Ctrl+Tab Sticking <p>I use Ctrl+Tab inside VS to move between different source files…one day I noticed that when I Ctrl+Tab to the file I wish to view and simply let go of the Ctrl and Tab keys it just sat there, I needed to hit enter to confirm the selection.&#160; This started to get annoying other people had mentioned similar problem.&#160; It seemed to happen when I was training, and finally the penny dropped…..On Windows 7 I use the magnifier via Windows Key and Plus, to highlight bits of code, and then use Windows Key and minus to revert back to normal resolution.&#160; The Magnifier app continues running, it appears that with the magnifier app enabled I have to use Enter to select my file without Ctrl+Tab just works fine…</p> <p>So now I close the magnifier app so that Ctrl+Tab continues to work.</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6586621841968635898?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,67272417-08bb-4bb0-b01c-b91a44d0f433.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,67272417-08bb-4bb0-b01c-b91a44d0f433.aspx DevWeek on the Horizon <p> I’ve just realised that <a href="http://www.devweek.com/">DevWeek 2010</a> is on the horizon. DevWeek is one of my favourite conferences&nbsp; - lots of varied talks, vendor independence and I get to hang out with lots of friends for the week. </p> <p> This year I’m doing a preconference talk and two sessions: </p> <p> <font size="4">A Day of .NET 4.0 <br> </font><font size="2">Mon 15th March 2010</font><small> <br> <font size="2"><i>WORKSHOP REF: M1</i> <br> .NET 4.0 is a major release of .NET, including the first big changes to the .NET runtime since 2.0. In this series of talks we will look at the big changes in this release in C#, multithreading, data access and workflow.<br> The best-known change in C# is the introduction of dynamic typing. However, there have been other changes that may affect your lives as developers more, such as support for generic variance, named and optional parameters. There is a whole library for multithreading, PFx, that not only assists you in parallelizing algorithms but in fact replaces the existing libraries for multithreading with a unified, powerful single API.<br> Entity Framework has grown up – the initial release, although gaining some popularity, missed features that made it truly usable in large-scale systems. The new release, version 4.0, introduces a number of features, such as self-tracking objects, that assist using Entity Framework in n-tier applications.<br> Finally, workflow gets a total rewrite to allow the engine to be used far more widely, having overcome limitations in the WF 3.5 API.<br> This workshop will take you through all of these major changes, and we’ll also talk about some of the other smaller but important ones along the way.</font></small> </p> <p> <small><font size="2"></font></small><small><font size="2"><font size="4">An Introduction to Windows Workflow Foundation 4.0</font> <br> Tues 16th March 2010<small> <br> </small>.NET 4.0 introduces a new version of Windows Workflow Foundation. This new version is a total rewrite of the version introduced with .NET 3.0. In this talk we look at what Microsoft are trying to achieve with WF 4.0, why they felt it necessary to rewrite rather than modify the codebase, and what new features are available in the new library. Along the way we will be looking at the new designer, declarative workflows, asynchronous processing, sequential and flowchart workflows and how workflow’s automated persistence works.</font></small> </p> <p> <small><font size="2"><font size="4">Creating Workflow-based WCF Services<br> </font>Tues 16th March 2010<br> </font></small><small><font size="2">There are very good reasons for using a workflow to implement a WCF service: workflows can provide a clear platform for service composition (using a number of building block services to generate a functionally richer service); workflow can manage long running stateful services without having to write your own plumbing to achieve this. The latest version of Workflow, 4.0, introduces a declarative model for authoring workflows and new activities for message based interaction. In addition we have a framework for flexible message correlation that allows the contents of a message to determine which workflow the message is destined for. In this session we will look at how you can consume services from workflow and expose the resulting workflow itself as a service.</font></small> </p> <p> <small><font size="2">As well as these you may well see me popping up as a guest code-monkey in the other <a href="http://rocksolidknowledge.com/Conferences.mvc/">Rock Solid Knowledge</a> sessions. Hope to see you there</font></small> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=67272417-08bb-4bb0-b01c-b91a44d0f433" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,3d5766cb-4d78-46c3-b9ab-57c3c72678c1.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,3d5766cb-4d78-46c3-b9ab-57c3c72678c1.aspx New Screencast &ndash; Introducing the Routing Service <p> The Routing Service is a new feature of WCF 4.0 (shipping with Visual Studio 2010). It is an out-of-the-box SOAP Intermediary able to perform protocol bridging, multicast, failover and data dependent routing. I’ve just uploaded a new screencast walking through setting up the Routing Service and showing a simple example of protocol bridging (the client sends messages over HTTP and the service receives them over NetTcp). This screencast is one of a series I will be recording about the Routing Service. You can find the screencast <a href="http://rocksolidknowledge.com/ScreenCasts.mvc">here</a>. </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=3d5766cb-4d78-46c3-b9ab-57c3c72678c1" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,3c481d20-caf5-49c7-9b6a-aa3c9a5663bd.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,3c481d20-caf5-49c7-9b6a-aa3c9a5663bd.aspx Executing Workflows from XAML Files <p> Seeing as this has changed completely from WF 3.5 I thought I’d post a quick blog entry to describe how to run a workflow declared in a XAML file. </p> <p> You may have heard that the WF 4.0 default authoring model is now XAML. However, the Visual Studio 2010 workflow projects store the XAML as a resource in the binary rather than as a text file. So if you want to deploy your workflows as XAML text files how do you run them? In .NET 3.5 you could pass the workflow runtime an <font face="Courier New">XmlReader</font> pointing at the XAML file but in WF 4.0 there is no <font face="Courier New">WorkflowRuntime</font> class. It turns out you need to load the XAML slightly indirectly by creating a special activity called a <font face="Courier New">DynamicActivity</font> </p> <p> <font face="Courier New">DynamicActivity</font> has an <font face="Courier New">Implementation</font> member that points to a <font face="Courier New">Func&lt;Activity&gt;</font> delegate – in other words you wire up a method that returns an activity (the workflow). Here’s an example: </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> DynamicActivity dyn = <span style="color: #0000ff">new</span> DynamicActivity();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #008000">// this line wires up the workflow creator method</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> dyn.Implementation = CreateWorkflow;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&nbsp;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> WorkflowInvoker.Invoke(dyn);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&nbsp;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">static</span> Activity CreateWorkflow()</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #008000">// we use the new XamlServices utility class to deserialize the XAML</span></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Activity act = (Activity)XamlServices.Load(<span style="color: #006080">@"..\..\workflow1.xaml"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">&nbsp;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> act;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--> </div> </div> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=3c481d20-caf5-49c7-9b6a-aa3c9a5663bd" /> tag:blogger.com,1999:blog-30604582.post-9005723126562487702 http://andyclymer.blogspot.com/2009/12/devweek-2010.html Devweek 2010 <p>Rock Solid Knowledge are pleased to announce that we have had a host of talks accepted for <a href="http://www.devweek.com" target="_blank">Devweek 2010</a>, including the latest advances in Silverlight, Designing for testing, Enterprise and OO Design Patterns, Workflow and a full day of whats new in .NET 4.&#160; Hope to see you there…</p> <p>For a full list of talks <a href="http://www.rocksolidknowledge.com/Conferences.mvc">click here</a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-9005723126562487702?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,2e3ac342-e003-4587-b577-f05f86a131fc.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,2e3ac342-e003-4587-b577-f05f86a131fc.aspx Demos from Last Week&rsquo;s Guerrilla.NET <p> Thanks to everyone who attended <a href="http://www.develop.com/course/guerrilla-net">Guerrilla.NET</a> last week. As promised the demos are now online and you can find them here </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/demos/GNET261009.zip">http://rocksolidknowledge.blob.core.windows.net/demos/GNET261009.zip</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=2e3ac342-e003-4587-b577-f05f86a131fc" /> tag:blogger.com,1999:blog-30604582.post-4726905440936790528 http://andyclymer.blogspot.com/2009/10/vs2010-beta-2-download.html VS2010 Beta 2 Download <p>VS2010 Beta 2 is now available for download for MSN subscribers.</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-4726905440936790528?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-6639321273049544484 http://andyclymer.blogspot.com/2009/10/geometric-decomposition-screencast.html Geometric Decomposition Screencast <p>I’ve posted a new screen cast on the Rock Solid Knowledge screen casts side that provides an example of how to partition a set of data for parallel processing.</p> <p>The screen cast covers a simple way using Parallel.ForEach, and a more efficient version combining the use of Barrier.</p> <p>You can checkout the screen cast and others <a href="http://www.rocksolidknowledge.com/screencasts">here</a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6639321273049544484?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-1308038182278811880 http://andyclymer.blogspot.com/2009/10/parallel-utilities.html Parallel utilities <p>Whilst working with .NET 4 parallel extensions I often find the need to extend the framework to assist me in various day to day tasks.&#160; I’ve finally got around to compiling a library of such extensions.</p> <p>The extensions include the following</p> <ul> <li>Set Process Affinity, so I can see how my algorithm scales on a different number of cores.&#160; Will select non hyperthreaded cores first.</li> <li>Determine the number of Real cores, not including hyperthreading ones.</li> <li>A Range type that supports the partitioning of a range so that I can farm sub ranges out to different tasks</li> <li>A Sequence class for building non integer parallel loops or loops with steps other than 1</li> <li>Finally a simplified way to handle aggregated exceptions.</li> </ul> <p>You can download the library from <a href="http://rocksolidknowledge.blob.core.windows.net/downloads/ParallelUtilities.zip">here</a></p> <p>Its a Visual Studio 2010 project, containing the library and a unit test project which should provide enough insight to how the library works.</p> <p>Im very keen to know what people think of the aggregate exception handling.</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-1308038182278811880?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,51443278-6c7c-4eba-8335-075d97b9f66d.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,51443278-6c7c-4eba-8335-075d97b9f66d.aspx Slides and Demos from Software Architect 2009 are now available <p> I just got back from speaking at <a href="http://www.software-architect.co.uk/">Software Architect 2009</a>. I had a great time at the conference and thanks to everyone who attended my sessions. As promised the slides and demos are now available on the <a href="http://rocksolidknowledge.com">Rock Solid Knowledge</a> website and you can get them from the <a href="http://rocksolidknowledge.com/Conferences.mvc/">Conferences</a> page. </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=51443278-6c7c-4eba-8335-075d97b9f66d" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0a7f5b10-21c1-4a01-91d3-62dee7cbd03a.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0a7f5b10-21c1-4a01-91d3-62dee7cbd03a.aspx WSCF Blue Goes RTM <p> I had a lucky coincidence while speaking at <a href="http://www.software-architect.co.uk/">Software Architect 2009</a>. Four hours before I gave a talk on Contract First Design with WCF the WSCF Blue guys released version 1.0 of their tool. Contract first design is the most robust way to build services that potentially have to exist in a heterogeneous environment – it essentially means you start from the WSDL which means everyone can consume the service as no implementation details leak on to the wire. The major stumbling block in the WCF world has been there is no tool that can take a WSDL document and generate the skeleton of a service that implements the defined contract. Finally we have a released tool that does this very thing in the shape of WSCF Blue. In fact it can go further than that because writing WSDL by hand is too much like heavy lifting for many people – so WSCF Blue can also take one or more schema and runs a wizard to build a WSDL document that creates a contract based on the messages in the schema documents. </p> <p> WSCF Blue solves a problem that has been there since WCF 3.0 and the great thing is that its free – <a href="http://wscfblue.codeplex.com/">being release on codeplex</a> </p> <p> Enjoy! </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=0a7f5b10-21c1-4a01-91d3-62dee7cbd03a" /> tag:blogger.com,1999:blog-30604582.post-1586267789374191916 http://andyclymer.blogspot.com/2009/10/are-singletons-evil.html Are Singletons Evil ? <p>Finally got around to delivering a conference talk on this subject this week at <a href="http://www.software-architect.co.uk/">Software Architecture Week</a>, its a topic myself and Kevin Jones are constantly being asked.&#160; Of course a quick google reveals the answer there are numerous rants about this evil pattern.&#160; But like most things in life its not as simple as yes or no.&#160; </p> <p>Our goal for this talk was to expose the areas were this pattern causes a developer a whole load of pain.&#160; In fact one member of the audience was experiencing such pain in his attempt to take legacy code base heavily utilising singletons and start to write unit tests.&#160; </p> <p>So whilst the majority of the time was spent examining the consequences of using the singleton pattern we also took time to&#160; highlight that one or two singletons correctly positioned in your application could in fact enable unit testing, and coding to interface without having to refactor large areas of a legacy code base.</p> <p>This talk took the format of a short geeky play, featuring two developers trying to wrestle with getting the job done and unit testing.&#160; You can download the <a href="http://rocksolidknowledge.blob.core.windows.net/demos/Evil+Singleton+Script.pdf">script</a> and accompanying <a href="http://rocksolidknowledge.blob.core.windows.net/demos/SA2009+EvilSingleton.zip">code</a></p> <p><em>So like all good consultants our answer to this question is “It Depends”</em></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-1586267789374191916?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,f72e977b-bf54-41a5-bf20-d23e3f6bc561.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,f72e977b-bf54-41a5-bf20-d23e3f6bc561.aspx MVP&rsquo;d Once More <p> I used to be a C# MVP a couple of years ago. When I took on the role of CTO of DevelopMentor I found I had a far smaller amount of time to devote to community based activity and so I lost my MVP status. I stepped down as DevelopMentor’s CTO back in January and as a result suddenly found I had time again and so can often be found hanging out at the MSDN WCF forum, speaking at conferences, etc. Consequently I have just heard that I’ve been awarded MVP status for Connected Systems :-) - nice to be back in the fold </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=f72e977b-bf54-41a5-bf20-d23e3f6bc561" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,539cffbc-01e3-4079-a6e3-738c3a3b29ed.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,539cffbc-01e3-4079-a6e3-738c3a3b29ed.aspx Slides and Demos from BASTA! <p> Thanks to everyone who came to my sessions at <a href="http://it-republik.de/dotnet/basta09/micro">BASTA!</a> My first time at that conference and I had a great time. Here are the slides and demos </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/demos/BastaWF4.zip?timeout=300">What’s New in Workflow 4.0</a> </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/demos/BastaContractFirst.zip?timeout=300">Contract First Development with WCF</a> </p> <p> <a href="http://rocksolidknowledge.blob.core.windows.net/demos/BastaBeyondListOfT.zip?timeout=300">Generics, Extension Methods and Lambdas – Beyond List&lt;T&gt;</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=539cffbc-01e3-4079-a6e3-738c3a3b29ed" /> http://blogs.mantiso.com/blog/kevin/2009/08/18/Microsoft-Mouse-Preventing-Screen-Saver-Working http://blogs.mantiso.com/blog/kevin/2009/08/18/Microsoft-Mouse-Preventing-Screen-Saver-Working Microsoft Mouse Preventing Screen Saver Working I've just installed Windows 2008 R2 and I could not get the screen saver or power management to work. Turns out I needed to install the correct drivers for my mouse. This is the Wireless Laser 5000, the drivers can be found <a href="http://www.microsoft.com/hardware/download/download.aspx?category=MK">here</a>. tag:blogger.com,1999:blog-30604582.post-4010793382963962797 http://andyclymer.blogspot.com/2009/08/fluent-parallel-while.html Fluent Parallel While <p>During devweek 2009 <a href="http://www.sturmnet.org/blog">Oliver</a> introduced me to Fluent Api's, I personally love programs that naturally read, after all programs are read far more often than written.&#160; This week a <a href="http://blogs.msdn.com/pfxteam/archive/2009/08/12/9867246.aspx">posting</a> on the Parallel Extensions blog demonstrated how to achieve parallel while, since we only have Parallel.For and Parallel.ForEach</p> <p>&#160;</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)<br /> {<br /> ConcurrentQueue&lt;<span style="color: #0000ff">int</span>&gt; queue = <span style="color: #0000ff">new</span> ConcurrentQueue&lt;<span style="color: #0000ff">int</span>&gt;();<br /><br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i &lt; 10; i++)<br /> {<br /> queue.Enqueue(i);<br /> }<br /><br /> <br /> Action&lt;ParallelLoopState&gt; processQueue = (lps) =&gt;<br /> {<br /> <span style="color: #0000ff">int</span> item;<br /> <span style="color: #0000ff">if</span> (queue.TryDequeue(<span style="color: #0000ff">out</span> item))<br /> {<br /> Console.WriteLine(<span style="color: #006080">&quot; Thread Id = {0} Task Id = {1} : {2}&quot;</span>, Thread.CurrentThread.ManagedThreadId, Task.Current.Id, item);<br /> }<br /> };<br /><br /> Func&lt;<span style="color: #0000ff">bool</span>&gt; queueContainsItems = () =&gt; queue.IsEmpty == <span style="color: #0000ff">false</span>;<br /><br /> ParallelUtil.While(<span style="color: #0000ff">new</span> ParallelOptions(), queueContainsItems, processQueue);<br /> }</pre><br /><br /> <br /></div><br /><br /><p>I thought I’d combine both these ideas and produce what I would consider a more&#160; Fluent version</p><br /><br /><div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> ParallelUtil<br /> {<br /> <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> IEnumerable&lt;<span style="color: #0000ff">bool</span>&gt; Infinite()<br /> {<br /> <span style="color: #0000ff">while</span> (<span style="color: #0000ff">true</span>) <span style="color: #0000ff">yield</span> <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span>;<br /> }<br /><br /> <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> ParallelOptions NoParallelOptions = <span style="color: #0000ff">new</span> ParallelOptions();<br /><br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> InParallelWhile(<span style="color: #0000ff">this</span> Action&lt;ParallelLoopState&gt; action, Func&lt;<span style="color: #0000ff">bool</span>&gt; condition, ParallelOptions options = <span style="color: #0000ff">null</span>)<br /> {<br /> <span style="color: #0000ff">if</span> (options == <span style="color: #0000ff">null</span>) options = NoParallelOptions;<br /><br /> Parallel.ForEach(IterateForever(), options , <br /> (ignored, loopState) =&gt;<br /> {<br /> <span style="color: #0000ff">if</span> (!condition())<br /> {<br /> loopState.Stop();<br /> }<br /> <span style="color: #0000ff">else</span><br /> {<br /> action(loopState);<br /> }<br /> });<br /><br /> }<br /><br /> <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> IEnumerable&lt;<span style="color: #0000ff">bool</span>&gt; IterateForever()<br /> {<br /> <span style="color: #0000ff">while</span> (<span style="color: #0000ff">true</span>)<br /> {<br /> <span style="color: #0000ff">yield</span> <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span>;<br /> }<br /> }<br /> }<br /> <span style="color: #0000ff">class</span> Program<br /> {<br /> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)<br /> {<br /> ConcurrentQueue&lt;<span style="color: #0000ff">int</span>&gt; queue = <span style="color: #0000ff">new</span> ConcurrentQueue&lt;<span style="color: #0000ff">int</span>&gt;();<br /><br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i &lt; 10; i++)<br /> {<br /> queue.Enqueue(i);<br /> }<br /><br /> <br /> Action&lt;ParallelLoopState&gt; processQueue = (lps) =&gt;<br /> {<br /> <span style="color: #0000ff">int</span> item;<br /> <span style="color: #0000ff">if</span> (queue.TryDequeue(<span style="color: #0000ff">out</span> item))<br /> {<br /> Console.WriteLine(<span style="color: #006080">&quot; Thread Id = {0} Task Id = {1} : {2}&quot;</span>, Thread.CurrentThread.ManagedThreadId, Task.Current.Id, item);<br /> }<br /> };<br /><br /> Func&lt;<span style="color: #0000ff">bool</span>&gt; queueContainsItems = () =&gt; queue.IsEmpty == <span style="color: #0000ff">false</span>;<br /><br /> processQueue.InParallelWhile(queueContainsItems);<br /> }<br /> }<br />}</pre><br /><br /> <br /></div><br /><br /><p></p><br /><br /><p></p><br /><br /><p>The key difference is the first example you use the following line to process the queue in parallel</p><br /><br /><p><font face="Courier New">ParallelUtil.While(new ParallelOptions(), queueContainsItems, processQueue);</font></p><br /><br /><p>As opposed to the second version with a perhaps more fluent implementation</p><br /><br /><p><font face="Courier New">processQueue.InParallelWhile(queueContainsItems);</font></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-4010793382963962797?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-3337112004554795471 http://andyclymer.blogspot.com/2009/07/linq-for-nhibernate.html Linq for NHibernate <p>Its been a while coming, but there it is no possible to use LINQ against NHibernate..I think its a shame that MS didn’t get behind the Hibernate family when they first created LINQ as its a marriage made in heaven, combining a mature ORM with a language integrated query.&#160; Rather than spending all that time ( and still ) on trying to create their own ORM.</p> <p>I’ve yet to try out the integration, but hopefully will be over the next few weeks…</p> <p><a href="http://ayende.com/Blog/archive/2009/07/26/nhibernate-linq-1.0-released.aspx">Click Here for the announcement</a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3337112004554795471?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-7689065185619919110 http://andyclymer.blogspot.com/2009/07/warningcancellation-support-may-makes.html WARNING..Cancellation support may makes things go slow…. <p>.NET 4 Tasks offers much better support for task cancellation, unlike QueueUserWorkItem tasks can be cancelled before commencing, and the Task library offers a standard way for running tasks to detect and report cancellation.&#160; I recently recorded a <a href="http://www.rocksolidknowledge.com/screencasts">screencast</a> that demonstrated the new Task API including the cancellation support.&#160;&#160; This blog post isn’t so much about the cancellation mechanics but some guidance on how best to use it if you don’t want to change the throughput of your task.</p> <p>Below is some code that calculates pi, it is expecting to be run inside a task and is supporting the notion of cancellation. </p> <p>&#160;</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">double</span> AbortableCalculatePi()<br /> {<br /> <span style="color: #0000ff">double</span> pi = 1;<br /> <span style="color: #0000ff">double</span> multiplier = -1;<br /><br /> <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> N_ITERATIONS = 500000000;<br /><br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> nIter = 3; nIter &lt; N_ITERATIONS; nIter += 2)<br /> {<br /> <br /> <span style="color: #0000ff">if</span> (Task.Current.IsCancellationRequested)<br /> {<br /> Task.Current.AcknowledgeCancellation();<br /> <span style="color: #0000ff">return</span> 0.0;<br /> }<br /> <br /><br /> pi += (1.0 / (<span style="color: #0000ff">double</span>)nIter) * multiplier;<br /> multiplier *= -1;<br /><br /> }<br /> <span style="color: #0000ff">return</span> pi * 4.0;<br /> }</pre><br /><br /> <br /></div><br /><br /><p>So all well and good until you benchmark it and compare it to the version with no cancellation support and it runs almost twice as slow.&#160; The reason being that the cost of detecting cancellation is high in relation to the work being done.&#160; The important aspect to cancellation is being able to respond in&#160; a meaningful time for the client, at present we are being way over aggressive in checking.</p><br /><br /><p>One option would be to only check every N iterations..</p><br /><br /><div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">double</span> BetterAbortableCalculatePi()<br /> {<br /> <span style="color: #0000ff">double</span> pi = 1;<br /> <span style="color: #0000ff">double</span> multiplier = -1;<br /><br /> <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> N_ITERATIONS = 500000000;<br /><br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> nIter = 3; nIter &lt; N_ITERATIONS; nIter += 2)<br /> {<br /><br /> <span style="color: #0000ff">if</span> ((nIter - 3) % 100000 == 0)<br /> {<br /> <span style="color: #0000ff">if</span> (Task.Current.IsCancellationRequested)<br /> {<br /> Task.Current.AcknowledgeCancellation();<br /> <span style="color: #0000ff">return</span> 0.0;<br /> }<br /> }<br /><br /><br /> pi += (1.0 / (<span style="color: #0000ff">double</span>)nIter) * multiplier;<br /> multiplier *= -1;<br /><br /> }<br /> <span style="color: #0000ff">return</span> pi * 4.0;<br /> }</pre><br /><br /> <br /></div><br /><br /><p>This&#160; took a third less time than the previous more aggressive version.&#160; However the if block’s effect on the pipeline and the additional maths is still an additional cost over the version that had no cancellation support.</p><br /><br /><p>So a third approach is called for this time refactoring the algorithm to use two loops instead of one, were the check for cancellation is done once per iteration of the outerloop, this results in little additional cost.</p><br /><br /><div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">double</span> OptimisedAbortableCalculatePi()<br /> {<br /> <span style="color: #0000ff">double</span> pi = 1;<br /> <span style="color: #0000ff">double</span> multiplier = -1;<br /><br /> <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> N_ITERATIONS = 500000000 / 2;<br /><br /> <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> OUTER_ITERATIONS = 10000;<br /> <span style="color: #0000ff">const</span> <span style="color: #0000ff">int</span> INNER_ITERATIONS = N_ITERATIONS / OUTER_ITERATIONS;<br /><br /> <span style="color: #0000ff">int</span> i = 3;<br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> outerIndex = 0; outerIndex &lt; OUTER_ITERATIONS; outerIndex++)<br /> {<br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> nIter = 0; nIter &lt; INNER_ITERATIONS; nIter++)<br /> {<br /> pi += (1.0 / i) * multiplier;<br /> multiplier *= -1;<br /> i += 2;<br /> }<br /><br /> <span style="color: #0000ff">if</span> (Task.Current.IsCancellationRequested)<br /> {<br /> Task.Current.AcknowledgeCancellation();<br /> <span style="color: #0000ff">return</span> 0.0;<br /> }<br /> <br /> }<br /> <span style="color: #0000ff">return</span> pi * 4.0;<br /> }</pre><br /><br /> <br /></div><br /><br /><p>Here are the timings are got from the various approaches</p><br /><br /><p>NoAbortableCalculatePi = 3.14159264958921 took 00:00:03.7357873 <br /> <br />AbortableCalculatePi = 3.14159264958921 took 00:00:09.6137173 <br /><br /> <br />BetterAbortableCalculatePi = 3.14159264958921 took 00:00:06.3826212 <br /><br /> <br />OptimisedAbortableCalculatePi = 3.14159265758921 took 00:00:03.6883268</p><br /><br /><p>As the figures show there is virtually no difference between the first and last run, but a considerable difference when cancellation is inserted into the core of the computation.</p><br /><br /><p>So to sum up whilst cancellation support is good the frequency you check for could have an impact on the overall performance of your algorithm.&#160; Cancellation is something we want to support but in general users probably don’t need it so we need to strike the right balance between throughput and responding to cancellation in an appropriate timeframe.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-7689065185619919110?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-6343934717838821287 http://andyclymer.blogspot.com/2009/07/net-4-tasks-and-ui-programming.html .NET 4 Tasks and UI Programming <p>Just upload a new <a href="http://www.rocksolidknowledge.com/screencasts">screencast</a> covering how to marshal results from .NET 4 Tasks back on to the UI thread.&#160; One method is to continue to utilise the same API’s from previous versions of .NET thus utilising SynchronizationContext.Post, the Task based API offers an alternative and in some cases more elegant solution using the ContinueWith method.</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6343934717838821287?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,386102ab-f8ce-4189-b189-7e6039d3e541.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,386102ab-f8ce-4189-b189-7e6039d3e541.aspx Throttling changes in WCF 4.0 <p> <a href="http://blogs.msdn.com/wenlong/archive/2009/07/26/wcf-4-higher-default-throttling-settings-for-wcf-services.aspx">Wenlong Dong has just posted</a> about changes to the WCF thottling defaults in WCF 4.0. The new throttle defaults are going to be based on the number of processors/cores in the machine – this means the more powerful the machine the higher the throttle will be - which is a good thing. The throttle that always hit people first were either session, if they had a session as a result of contract/binding settings or, no session, concurrent calls. Now the changes (100 * processor count for session and 16 * processor count for calls) will mean that either one would bite first. </p> <p> As Wenlong says, the original values were always too low for enterprise applications. What they did do, however, is force people to address throttling if they were writing enterprise apps. And Wenlong is right that that sometimes meant people putting the throttles up to int.MaxValue which is really the same as no throttle at all. But although, in general, I think the change is the right move (it mostly works out of the box), it will lead to people facing performance problems with absolutely no idea why they might be taking place. </p> <p> What I mean by this is problems caused by the current throttles are really easy to spot “as soon as I put more than 10 calls though it breaks”. You can google that and find the problem and the solution. The new values make it hugely non-obvious why an application suddenly has problems with more than 400 clients (NetTcpBinding on machine with 4 cores for example). Good time to be a consultant in the <a href="http://rocksolidknowledge.com/">UK</a> and <a href="http://www.thinktecture.com">Europe</a> I guess ;-) </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=386102ab-f8ce-4189-b189-7e6039d3e541" /> tag:blogger.com,1999:blog-30604582.post-5029671162503603147 http://andyclymer.blogspot.com/2009/07/my-first-silverlight-3-app.html My First Silverlight 3 App <p>Had a brief rest from patterns and parallel stuff to have a quick play with Silverlight 3.&#160; I mainly wanted to see the out of browser aspect, as I think the idea of being able to build RIA that also run on the desktop is very compelling….</p> <p>So what to build, I really like the iPhone weather app so I thought I’d have a go at reproducing it in Silverlight, below is a screen shot showing it running out of the browser.</p> <p><a href="http://lh6.ggpht.com/_OxnULoaN7CE/Smhwkk6TLRI/AAAAAAAAAYs/xZFy5nJUVHw/s1600-h/image%5B2%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_OxnULoaN7CE/SmhwlmjIjeI/AAAAAAAAAYw/XYeFTLLnxKM/image_thumb.png?imgmax=800" width="198" height="244" /></a> </p> <p>I’m using isolated storage to store the list of weather centre’s of interest, a more typical line of business app would store app config on the web server/cloud and potentially locally to support true client roaming, but I’ll leave that for another day.</p> <p>One thing to note is that the method for enabling Out Of Browser mode for you application is now different from pre-release versions of Silverlight 3, so there are many old blog posts that are unfortunately wrong now.&#160; The good news is now it is trivial, view the project properties, and under the Silverlight tab there is an option to enable the app to support out of browser.&#160; This then creates the OutOfBrowserSettings.xml file.</p> <p><a href="http://lh5.ggpht.com/_OxnULoaN7CE/Smhwma5b4WI/AAAAAAAAAY0/qbBhuIe7KSY/s1600-h/image%5B16%5D.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_OxnULoaN7CE/SmhwmyCB7pI/AAAAAAAAAY4/hyO2NIohb_I/image_thumb%5B6%5D.png?imgmax=800" width="342" height="207" /></a> </p> <p>You can download the source via <a href="http://rocksolidknowledge.blob.core.windows.net/downloads/SilverlightWeather.zip?timeout=300">here</a> or to just see the app in action click <a href="http://www.rocksolidknowledge.com/weather">here</a>.&#160; I’ll let you decide if its as cool as the iPhone….</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5029671162503603147?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-8998650310582213025 http://andyclymer.blogspot.com/2009/07/testing-on-varying-number-of-cores.html Testing on varying number of cores <p>I’ve written many blog articles in the past that show that the performance of a piece of parallel code can vary dramatically based on the number of available cores. With that it mind, its obviously desirable even when given a machine with 8 cores that you test your code against a machine that could have substantially less.&#160; You can resort to task manager and set Process Affinity and reduce the number of cores available for the process, but this is tedious.&#160; There is a .NET API that allows access to controlling which cores to make available for a process.&#160; The API requires the use of a bitmask to identity which cores to use, that's a bit ( no pun intended) overkill for what I'm trying to do, so I created a&#160; facade that allows me to simply say use N cores.</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> Cores<br /> {<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> Max<br /> {<br /> get<br /> {<br /> <span style="color: #0000ff">return</span> Environment.ProcessorCount;<br /> }<br /> }<br /> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> CoresInUse <br /> {<br /> get<br /> {<br /> IntPtr cores = <br /> Process.<br /> GetCurrentProcess()<br /> .ProcessorAffinity;<br /><br /><br /> <span style="color: #0000ff">int</span> nCores = 0;<br /> <span style="color: #0000ff">while</span>( cores != IntPtr.Zero )<br /> {<br /> <span style="color: #0000ff">if</span> ( ((<span style="color: #0000ff">int</span>)cores &amp; 1) == 1 )<br /> {<br /> nCores++;<br /> }<br /> cores = (IntPtr)((<span style="color: #0000ff">int</span>)cores &gt;&gt; 1);<br /> }<br /> <span style="color: #0000ff">return</span> nCores;<br /> }<br /><br /> set<br /> {<br /> <span style="color: #0000ff">if</span> ((<span style="color: #0000ff">value</span> &lt; 1) || (<span style="color: #0000ff">value</span> &gt; Environment.ProcessorCount))<br /> {<br /> <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArgumentException(<span style="color: #006080">&quot;Illegal number of cores&quot;</span>);<br /> }<br /><br /> <span style="color: #0000ff">int</span> cores = 1;<br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> nShift = 0; nShift &lt; <span style="color: #0000ff">value</span>-1; nShift++)<br /> {<br /> cores = 1 | (cores &lt;&lt; 1);<br /> }<br /><br /> Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)cores;<br /> }<br /> }<br /> }</pre><br /><br /> <br /></div><br /><br /><p>The following code prints out the number of active cores and then reduces the number of cores to 4</p><br /><br /><div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">Console.WriteLine(<span style="color: #006080">&quot;Using {0} out of {1}&quot;</span> , Cores.CoresInUse , Cores.Max);<br />Cores.CoresInUse = 4;<br />Console.WriteLine(<span style="color: #006080">&quot;Using {0} out of {1}&quot;</span>, Cores.CoresInUse, Cores.Max);</pre><br /><br /> <br /></div><br /><style type="text/css"><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8998650310582213025?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,8ed9b492-1f24-49e3-8af6-2469295f7f9c.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,8ed9b492-1f24-49e3-8af6-2469295f7f9c.aspx Azure platform pricing announced <p> It has been one of the bug bears for me as I have given talks on the Azure platform that I have not been able to answer any question that involved commercial details with anything other than “we’ll have to see the prices when they announce them. Finally, today, the team have announced the pricing model and availability </p> <p> <a href="http://blogs.msdn.com/windowsazure/archive/2009/07/14/confirming-commercial-availability-and-announcing-business-model.aspx">http://blogs.msdn.com/windowsazure/archive/2009/07/14/confirming-commercial-availability-and-announcing-business-model.aspx</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=8ed9b492-1f24-49e3-8af6-2469295f7f9c" /> tag:blogger.com,1999:blog-30604582.post-8246786142682466081 http://andyclymer.blogspot.com/2009/07/guerilla-net-demos-from-6th-july-2009.html Guerilla .NET Demos from 6th July 2009 <p>Had loads of fun as normal teaching Guerilla .NET with Rich and Marcus , All the demos from class <a href="http://www.rocksolidknowledge.com/Download.mvc">here</a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8246786142682466081?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,8c509806-8bdb-47ae-a763-495002fc9972.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,8c509806-8bdb-47ae-a763-495002fc9972.aspx WSCF Blue goes into Beta <p> One of the frustrations with the current WCF tooling is that, although I can generate the client proxy code from a WSDL document I cannot generate the server side skeleton that matches the WSDL. In situations where two parties agree a contract based on WSDL this makes implementing the service side error prone. Back in the ASMX days WSDL.EXE had a /s switch that would create the service side skeleton, but this feature was not carried through into SVCUTIL.EXE. </p> <p> Fortunately the WSCF (Web Service Contract First) guys&nbsp; have finally released a beta of a WCF compatible version of their tool that allows you to build up a model of the service and then generate the client and/or service </p> <p> Here’s Santosh’s <a href="http://santoshbenjamin.wordpress.com/2009/07/04/wscf-blue-beta-1/">announcement</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=8c509806-8bdb-47ae-a763-495002fc9972" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,9601b6a2-e1f5-4edd-bb8b-cdda9e6a481f.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,9601b6a2-e1f5-4edd-bb8b-cdda9e6a481f.aspx New Screencast: Streamed Messages in WCF <p> In my <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0464ef2a-cbaf-4cd1-8f05-d058a0503a2f.aspx">last post</a> I linked to the screencast I made on processing large messages in WCF using buffering. I also said that I would be putting up another one on streaming messages shortly. That second screencast has now gone live on the <a href="http://rocksolidknowledge.com/">Rock Solid Knowledge website</a>. In part 2 of the large message handling screencast I talk about enabling streaming, designing contracts for streaming and how this affects the way the receiver has to process the data. You can find the new screencast here </p> <p> <a href="http://rocksolidknowledge.com/ScreenCasts.mvc">http://rocksolidknowledge.com/ScreenCasts.mvc</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=9601b6a2-e1f5-4edd-bb8b-cdda9e6a481f" /> tag:blogger.com,1999:blog-30604582.post-234054834965745851 http://andyclymer.blogspot.com/2009/06/parallelfor-and-parallelforeachmoving.html Parallel.For and Parallel.ForEach…moving past Thread.Sleep <p>Just released a screen cast demoing Parallel.For and Parallel.ForEach where we are not demoing the virtues of Parallel Sleep….</p> <p><a href="http://www.rocksolidknowledge.com/screencasts">Click here to see this and many other Rock Solid Knowledge Screen casts</a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-234054834965745851?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-7348832457973955962 http://andyclymer.blogspot.com/2009/06/short-and-long-running-tasks-in-net-4.html Short and Long running tasks in .NET 4 <p>Just added a screen cast on how to create short and long running tasks in .NET 4.&#160; You can get to all the Rock Solid Knowledge screen casts via <a href="http://www.rocksolidknowledge.com/screencasts">www.rocksolidknowledge.com/screencasts</a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-7348832457973955962?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0464ef2a-cbaf-4cd1-8f05-d058a0503a2f.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0464ef2a-cbaf-4cd1-8f05-d058a0503a2f.aspx New Screencast: Working with Large Messages in WCF (Part 1) <p> I’ve just uploaded a new screencast on to <a href="http://rocksolidknowledge.com">Rock Solid Knowledge</a>. This one walks though configuring WCF to be able to pass large messages between client and service. Its the of two parts, this one talks about the default mode WCF uses for transferring data – buffering. I’ll be doing another one soon that looks at WCF in streaming mode. </p> <p> You can find the screencast <a href="http://rocksolidknowledge.com/ScreenCasts.mvc">here</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=0464ef2a-cbaf-4cd1-8f05-d058a0503a2f" /> tag:blogger.com,1999:blog-30604582.post-8879104492652421425 http://andyclymer.blogspot.com/2009/06/rock-solid-knowledge-at-software.html Rock Solid Knowledge at Software Architect 2009 <p>Just to say that we will be delivering talks at <a href="http://www.software-architect.co.uk/">Software Architect 2009</a>, here is a full list of our <a href="http://www.rocksolidknowledge.com/Conferences.mvc">sessions</a>. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8879104492652421425?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-6714077885692627164 http://andyclymer.blogspot.com/2009/06/long-or-short-running-tasks.html Long or Short running tasks <p>Been playing around with the new version of Pfx for .NET.&#160; I must say Ive been very impressed with the improvements since the last CTP for .NET 3.5.&#160; So here goes a series of blogs and screen casts on some on various bits of Pfx for .NET 4 BETA 1.</p> <p>The one thing that really shouts is that the original&#160; Pfx types are no longer something for just&#160; fine grained parallelism its is a unification of the various threading API’s.&#160; Unifying Api’s is something not new to the .NET framework its been happening since 1.1.&#160; As developers its great that whilst the framework is evolving a constant effort is being made to refactor and simplify previous complexity.</p> <p>So previously If&#160; I wanted to create a short running piece of background work I would favour the thread pool, if I was to write a long running piece of background activity I would have to create my own custom thread.&#160;&#160; Creating a short running thread using the thread pool meant either QueueUserWorkItem or Delegate.BeginInvoke, and a long running via new Thread(), and calling Start.</p> <p>Now for either types of situation&#160; you simply create a new Task using the new Task type, either via the Task Factory ( not a real GOF Factory, but don’t get me started on that ), or via new Task()</p> <p>Task bgTask = Task.Factory.StartNew( MyShortRunningTask);</p> <p>For a long running task we use the same API but this time giving it a hint that this is a long running task and shouldn’t therefore use a thread pool thread, but create a new thread outside the thread pool</p> <p>Task bgTask = Task.Factory.StartNew( MyLongRunningTask, TaskCreationOptions.LongRunning);</p> <p>So too very similar calls but leaving it up to the framework to decide how best to schedule the work.&#160; </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6714077885692627164?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-8290982047326723763 http://andyclymer.blogspot.com/2009/06/vs2010-edit-window-outside-ide.html VS2010 Edit window outside the IDE <p>Just noticed that I can drag source windows outside the IDE in VS2010, this is something Ive wanted for ages…Now I can really use multiple monitors</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8290982047326723763?l=andyclymer.blogspot.com' alt='' /></div> tag:blogger.com,1999:blog-30604582.post-3046195843711500440 http://andyclymer.blogspot.com/2009/06/pfx-team-examples-moving-into-real.html Pfx team examples moving into the real world <p>I’ve written many articles on my blog about how Im sick of trade show demos of Pfx ( Parallel framework extensions ).&#160; You know the ones using simple Parallel.For with Thread.Sleep or Thread.SpinWait as the piece of work.&#160; These examples scale wonderfully but the moment people take those simple examples and apply them to their own for loops terrible performance often results.&#160; Thankfully the Pfx team have written a blog article offering some suggestions about what to do when the piece of work inside the for loop is too small. ( <a href="http://blogs.msdn.com/pfxteam/archive/2009/06/06/9703059.aspx">Blog article</a> ).&#160; Interesting this is the first time I’ve seen them utilise the number of processors in the machine to determine the number of tasks, something I’ve advocated many times in the past for tasks of equal cost.&#160; </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3046195843711500440?l=andyclymer.blogspot.com' alt='' /></div> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,b891610a-6b78-4b54-b9a6-4ec81c82b7c0.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,b891610a-6b78-4b54-b9a6-4ec81c82b7c0.aspx WCF Duplex Messaging <p> I am one of the moderators of the <a href="http://social.msdn.microsoft.com/Forums/en-US/wcf/threads">MSDN WCF Forum</a>. One of the main areas of questions on the forum is duplex messaging – particularly using the WSDualHttpBinding. So instead of typing long messages repeating the same thing in answer to these questions I’ve decided to write this blog post to give a bit of background about duplex messaging and then discuss the options for bindings and common problems people have. </p> <h5>What is Duplex Messaging? </h5> <p> There are many ways that messages can be exchanged between two parties in a service based system: the client can send messages to the server and never get any back; the client can send a message and wait for a response; the client and service can send eachother messages without any pre-defined pattern; the client can send the service a message but not wait synchronously for a response and then then service can send a message back asynchronously; and there are many others. However, the first three of these are supported natively in WCF and are known as One-way, request/response and duplex. </p> <p> So Duplex messaging is where, unsolicited, the client and service can send eachother messages. Most commonly this is characterized by the service sending the client “events” or notifications or progress of “interesting things”. </p> <h5>Duplex Contracts in WCF </h5> <p> To send messages to eachother the client and service must have an idea of what operations are available and what messages are sent and received during the communication. In WCF this idea is modelled by the contract. Now normally a contract just determines what functionality is available at the service. However, now the service is going to be sending messages to the client that the client isn’t specifically waiting for so it needs an idea of what messages the client can deal with. So we need a contract that models both directions of the conversation. </p> <p> A bi-directional contract is modelled using two interfaces bound together with a ServiceContract – like this: </p> <p> </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">[ServiceContract(<strong>CallbackContract=<span style="color: #0000ff">typeof</span>(IPizzaProgress)</strong>)]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">interface</span> IOrderPizza</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> [OperationContract]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">void</span> PlaceOrder(<span style="color: #0000ff">string</span> PizzaType);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">interface</span> IPizzaProgress</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> [OperationContract]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">void</span> TimeRemaining(<span style="color: #0000ff">int</span> minutes);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> [OperationContract]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">void</span> PizzaReady();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--> </div> </div> <p> The import bit here is the CallbackContract that establishes the relationship between the service’s and client’s contracts. </p> <h5>Writing the Service </h5> <p> The service is implemented normally apart from two issues: firstly it needs to access the callback contract to be able to send messages back to the client; secondly the communication infrastructure (modelled by the binding) needs to be able to cope with duplex messaging. Firstly lets look at accessing the callback contract: </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">class</span> PingService : IOrderPizza</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> IPizzaProgress callback;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> PlaceOrder(<span style="color: #0000ff">string</span> PizzaType)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <strong>callback = OperationContext.Current.GetCallbackChannel<IPizzaProgress> (); </strong></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Action preparePizza = PreparePizza;</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> preparePizza.BeginInvoke(ar => preparePizza.EndInvoke(ar), <span style="color: #0000ff">null</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">void</span> PreparePizza()</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 10 - 1; i >= 0; i--)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> callback.TimeRemaining(i);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Thread.Sleep(1000);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> callback.PizzaReady();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--> </div> </div> <p> </p> <p> The critical line here is calling GetCallbackContract on the OperationContext. This gives the service access to a proxy to call back to the client. </p> <p> Now the service also needs to use a contract that is compatible with duplex messaging. WSHttpBinding is the default for the built in WCF projects but it does not support duplex messaging. People generally then move to the WSDualHttpBinding which is similar to the WSHttpBinding but does support duplex. I will go into more depth about bindings for duplex shortly but for now lets stick to this for now - it will work in our test rig on a single machine without issue. </p> <h5>Writing the Client </h5> <p> If the client is going to receive these messages it needs to provide an implementation of the callback contract. It can gets its definition from either a shared contract assembly or from metadata. If using metadata the callback contract will be named the same as the service’s contract but with the work Callback appended. It will also need to supply this implementation to the WCF infrastructure and it does this by wrapping an instance in an InstanceContext object and passing it to the proxy constructor. So here is the client: </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">class</span> Program</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><strong> InstanceContext ctx = <span style="color: #0000ff">new</span> InstanceContext(<span style="color: #0000ff">new</span> Callback());</strong></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> OrderPizzaClient proxy = <span style="color: #0000ff">new</span> OrderPizzaClient(ctx);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> proxy.PlaceOrder(<span style="color: #006080">"Pepperoni"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Console.WriteLine(<span style="color: #006080">"press enter to exit"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Console.ReadLine();</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><strong><span style="color: #0000ff">class</span> Callback : IOrderPizzaCallback</strong></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> TimeRemaining(<span style="color: #0000ff">int</span> minutes)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Console.WriteLine(<span style="color: #006080">"{0} seconds remaining"</span>, minutes);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> PizzaReady()</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Console.WriteLine(<span style="color: #006080">"Pizza is ready"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--> </div> </div> <p> Running the service and the client will have this working quite happily – so it would seem that duplex messaging and WCF works very well … so why on earth do people keep asking questions about it on the WCF forums? </p> <h5>It Worked on My Machine but Broke when we Deployed It! </h5> <p> Ahh well you probably did the thing that is obvious but almost always a bad idea. You went and chose WSDualHttpBinding as your duplex binding. To understand why this is a bad idea we need to dig a little deeper into how the WSDualHttpBinding works. HTTP is a unidirectional protocol: the client makes a request and the server sends a response. There is no way for a server to initiate an exchange with the client. So how on earth is duplex messaging going to work because it requires exactly this facility? Well the “Dual” in the name is significant, the WSDualHttpBinding actually consists of two connections: one outbound from client to server and one inbound from server to client – this second connection may already be ringing alarm bells with you. The are a two big problems with inbound connections to a client: firewalls very often block inbound connections to clients; the client may not be reachable from the server, it may be using NAT translation behind a router and so cannot be contacted without port forwarding being set up on the router. Both of these issues are showstoppers in real network topologies. You can take some small steps to help – you can specify what port the client should listen on for example by using the clientBaseAddress property of the WSDualHttpBinding. This means the network admin will only have to punch one hole in their firewall (but lets face it, network admins don’t allow any holes to be punched in the firewall). </p> <p> So if you really shouldn’t use WSDualHttpBinding for duplex, what should you use instead? Well NetTcpBinding supports duplex out of the box and the nice thing about this is that the outbound connection that it establishes can also be used be used for inbound traffic – suddenly we don;t have the inbound connection firewall/NAT issues. “But hold on, isn’t NetTcpBinding for intranet? I’ve read books that tell me that in their ‘which binding should I use?’ flowcharts!” Well it turns out those flowcharts are talking rubbish – NetTcpBinding works very happily over the internet, its just not interoperable by design. “Aha! but I need interop so WSDualHttpBinding is for me!” Well unfortunately not, NetTcpBinding is non-interoperable by design, WSDualHttpBinding is non-interoperable despite its design. From the name it would suggest interoperability but Arun Gupta from Sun wrote <a href="http://blogs.sun.com/arungupta/entry/wshttpdualbinding_a_non_interoperable_binding">this excellent post</a> describing why it wasn’t. </p> <p> So now seeing that we really are not talking about interop anyway, NetTcpBinding is far more useful than WSDualHttpBinding. Its not bullet proof, if the firewall only allows outbound port 80 but also allows inbound port 80, then WSDualHttpBinding would work where NetTcpBinding wouldn’t – but in this situation we’re really talking server to server and so I’d argue its probably better to roll your own bidirectional communication with two standard HTTP based connections. </p> <p> The final option you have for duplex communication is to add a piece of infrastructure into the mix. <a href="http://www.microsoft.com/azure/servicebus.mspx">The .NET Services Service Bus</a> (part of the Azure platform) allows two parties to exchange messages both making outbound connections – potentially even using HTTP port 80. The two outbound connections rendezvous in the Service Bus which mediates their message exchanges. If the receiver has had to use outbound port 80 then it polls to receive message bound for it. </p> <h5>It Worked for the First 10 Clients and then the Rest Timed Out! </h5> <p> Irrespective if which of the standard bindings you are using, duplex assumes a constant relationship between proxy and service. In WCF this idea is modelled by the concept of session. All duplex bindings require session. A while back <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,af6e6325-2e30-42e3-acb9-57e1363fa51e.aspx">I wrote in some detail about sessions</a>. You will have to either put up with increasing the session throttle (see the linked article for details) or roll your own custom binding that can do duplex without session – you can find an example of this <a href="http://blogs.msdn.com/ralph.squillace/archive/2006/10/10/Sessionless-duplex-services_3F00_-No-problem.-Small-issues_2C00_-yes_3B00_-problems_2C00_-no_2E00_.aspx">here</a>. </p> <h5>I Use the Callback While the Client is calling the Service and it Deadlocks! </h5> <p> This is because your client is probably a Rich Client GUI based application (Windows Forms or WPF). To understand why this is a problem we need to step back briefly and look at UI clients, threading and WCF threading. UI applications have a rule: you must only update the UI from the thread that created those UI components. In general a GUI application has one UI thread so anything that changes the UI needs to be done from that thread. .NET 2.0 introduced a new construct to simplify the process of a background thread updating the UI: SynchronizationContext. The idea is that a UI framework creates an implementation of a SynchronizationContext derived class that handles the mechanics of marshalling a call on to the UI thread. An instance of this implementation is then made available on the UI and accessible via the SynchronizationContext.Current. </p> <p> WCF adds more complexity into the mix by enforcing a rule that says “unless you tell me otherwise I will only allow one thread at a time into an object that I control”. You see this with singleton services that will only allow one call at a time by default. The same is also true of the callback implementation object – so WCF will only allow one active thread in the client at a time. So while WCF is performing an outbound call it will not allow an inbound call into the object. This causes the initial problem with the deadlock that the service’s callback cannot be dispatched while the client’s outbound call is in progress. To solve this we use the “unless you tell me otherwise” part of the above rule. You do this by annotating the callback implementation class with a [CallbackBehavior] attribute like this: </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><strong>[CallbackBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]</strong></pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">class</span> Callback : IOrderPizzaCallback</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> TimeRemaining(<span style="color: #0000ff">int</span> minutes)</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Console.WriteLine(<span style="color: #006080">"{0} seconds remaining"</span>, minutes);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> PizzaReady()</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Console.WriteLine(<span style="color: #006080">"Pizza is ready"</span>);</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--> </div> </div> <p> But now there is another problem: by default WCF will attempt to dispatch using an available SynchronizationContext. The problem with this callback is the UI thread is already blocked in an outbound call. SO for the call to dispatch we need to tell WCF not to use the SynchronizationContext – again using the CallbackBehavior attribute: </p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">[CallbackBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant, <strong>UseSynchronizationContext=<span style="color: #0000ff">false</span></strong>)]</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">class</span> Callback : IOrderPizzaCallback</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> ...</pre> <!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <!--CRLF--> </div> </div> <p> Now the issue is of course that the call is going to be processed on a non UI thread so you would have to manually marshal any UI interaction using the SynchronizationContext.Post method. </p> <p> Duplex messaging can be a useful message exchange pattern but in WCF there can be some unexpected issues. Hopefully this blog post clarifies those issues and demonstrates workarounds for them. </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=b891610a-6b78-4b54-b9a6-4ec81c82b7c0" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,847c6d5c-4fcb-4271-8be9-61833877e8d1.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,847c6d5c-4fcb-4271-8be9-61833877e8d1.aspx News of our death has been greatly exaggerated <p> <sigh> it seems that the ever increasing immediacy of social networking and blogging has some downsides. Ted Neward has posted a <a href="http://blogs.tedneward.com/CommentView,guid,dd85708f-48d8-47dc-a9c6-cc4a1287ad31.aspx#commentstart">eulogy</a> for Developmentor (who I regularly teach for). Unfortunately Ted didn’t bother checking his facts. DM are very much still in business and delivering courses (I’m teaching one the week after next and the week after that in fact! Plus several in July and September!) </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=847c6d5c-4fcb-4271-8be9-61833877e8d1" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,86b7d987-6db0-4da3-99fe-1c37a99a1715.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,86b7d987-6db0-4da3-99fe-1c37a99a1715.aspx New Screencast &ndash; Using WCF Tracing for Debugging <p> We’ve just posted a new screencast at <a href="http://rocksolidknowledge.com/">Rock Solid Knowledge</a>. In this one I walk you through enabling WCF tracing to assist in diagnosing bugs in your services using the example of a serialization failure. You can find the screen casts here </p> <p> <a href="http://rocksolidknowledge.com/ScreenCasts.mvc">http://rocksolidknowledge.com/ScreenCasts.mvc</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=86b7d987-6db0-4da3-99fe-1c37a99a1715" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,2fee98c4-abb6-455e-a738-47f286bfaf51.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,2fee98c4-abb6-455e-a738-47f286bfaf51.aspx DevWeek Interview Online <p> Every year I speak at the excellent <a href="http://www.devweek.com/">DevWeek</a> conference in London. <a href="http://geekswithblogs.net/iupdateable/Default.aspx">Eric Nelson</a>, a Microsoft Developer Evangelist in the UK is also a regular attendee. This year Eric, <a href="http://mtaulty.com/communityserver/blogs/mike_taultys_blog/default.aspx">Mike</a> and <a href="http://blogs.msdn.com/mikeormond/">Mike</a> were recording interviews with people at the conference. Eric interviewed me about Workflow 4.0 (I was delivering a post conference day on WF 4.0, Dublin and Oslo). He’s just got round to published it online </p> <p> <a href="http://geekswithblogs.net/iupdateable/archive/2009/05/20/devweek-2009-interview-with-richard-blewett-on-workflow-4.0.aspx">http://geekswithblogs.net/iupdateable/archive/2009/05/20/devweek-2009-interview-with-richard-blewett-on-workflow-4.0.aspx</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=2fee98c4-abb6-455e-a738-47f286bfaf51" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,06c841b2-52b8-473a-8168-b063b3a24b34.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,06c841b2-52b8-473a-8168-b063b3a24b34.aspx Visual Studio 2010 Beta 1 Ships <p> Soma has blogged that beta 1 has finally shipped. Lots of new stuff in here since PDC. His blog post is here </p> <p> <a href="http://blogs.msdn.com/somasegar/archive/2009/05/18/visual-studio-2010-and-net-fx-4-beta-1-ships.aspx">http://blogs.msdn.com/somasegar/archive/2009/05/18/visual-studio-2010-and-net-fx-4-beta-1-ships.aspx</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=06c841b2-52b8-473a-8168-b063b3a24b34" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,6b977408-c307-4ba1-9774-3fdeead0521c.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,6b977408-c307-4ba1-9774-3fdeead0521c.aspx New Screencasts at Rocksolidknowledge.com <p> We’ve started a library of screencasts at <a href="http://rocksolidknowledge.com/">rock solid knowledge</a>. I’ve created one on WCF Serialization and one on using SSL with Self hosted WCF services. <a href="http://andyclymer.blogspot.com/">Andy Clymer</a> has recorded one on Visual Studio Tricks and Tips and Dave Wheeler has one on character animation in Silverlight 2.0. You can find the screen casts at </p> <p> <a href="http://rocksolidknowledge.com/ScreenCasts.mvc">http://rocksolidknowledge.com/ScreenCasts.mvc</a> </p> <p> We’ll be adding to the library as time goes on so subscribe to the library RSS feed </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=6b977408-c307-4ba1-9774-3fdeead0521c" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,ac27a12b-23a9-4154-b3e1-4c1c27e26c1e.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,ac27a12b-23a9-4154-b3e1-4c1c27e26c1e.aspx What&rsquo;s new in WF 4.0 Beta 1 <p> Cliff Simpkins has just <a href="http://blogs.msdn.com/endpoint/archive/2009/05/01/the-road-to-4-wf-changes-between-beta-1-and-ctp.aspx">posted a blog entry</a> detailing some of the changes between the PDC preview of WF 4.0 and what is coming in beta 1, due shortly. </p> <p> Important information here not just about beta 1 but also about things you can expect and also things that won’t make it into RTM </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=ac27a12b-23a9-4154-b3e1-4c1c27e26c1e" /> http://blogs.mantiso.com/blog/kevin/2009/04/16/Problem-When-Upgrading-From-Rails-2-2-2-to-2-3-2 http://blogs.mantiso.com/blog/kevin/2009/04/16/Problem-When-Upgrading-From-Rails-2-2-2-to-2-3-2 Problem When Upgrading From Rails 2.2.2 to 2.3.2 <p> I've just installed the latest Active* gems to move my Rails install to 2.3.2. When I ran a console I got the following error </p> <pre> Loading development environment (Rails 2.3.2) /Library/Ruby/Gems/1.8/gems/activesupport-2.3.2/lib/active_support/dependencies.rb:443:in `load_missing_constant':NameError: uninitialized constant ApplicationController </pre> <p> I googled this and found a couple of posts on the issue but nothing obvious that I was doing. After generating a 2.3.3 app and comparing files the solution was obvious and easy. I 2.2.2 the ApplicationController class is in a file called Application.rb, in 2.3.2 this has changed to application_controller.rb. Changing the file name has fixed my problem. </p> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,2ce96651-c153-416a-a680-cced6ee34fdd.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,2ce96651-c153-416a-a680-cced6ee34fdd.aspx Extension Methods and Good Practice &ndash; or OI! Get Out of my Namespace! <p> I’ve been doing some work with the <a href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24644">WCF REST Starter Kit</a> for our website <a href="http://rocksolidknowledge.com">http://rocksolidknowledge.com</a>. Preview 2 of the start kit has a bunch of client side plumbing (the original release concentrated on the service side) </p> <p> The client side code looks something like this: </p> <p> <font size="2"><font face="Courier New"><font color="#2b91af"><font color="#2b91af">HttpClient</font></font> client = <font color="#0000ff"><font color="#0000ff">new</font></font> <font color="#2b91af"><font color="#2b91af">HttpClient</font></font>(<font color="#a31515"><font color="#a31515">"http://twitter.com"</font></font>);</font></font> </p> <p> <font size="2"><font face="Courier New"><font color="#2b91af"><font color="#2b91af">HttpResponseMessage</font></font> response = client.Get(<font color="#a31515"><font color="#a31515">"statuses/user_timeline/richardblewett.xml"</font></font>);</font></font> </p> <p> <font size="2"><font face="Courier New"><font color="#2b91af"><font color="#2b91af">Console</font></font>.WriteLine(response.Content.ReadAsString());</font></font> </p> <p> <font size="2">As compact as this is I was a bit disappointed to see that I only had a few options for processing the content: <font face="Courier New">ReadAsString</font>, <font face="Courier New">ReadAsStream</font> and <font face="Courier New">ReadAsByteArray</font>. Now seeing as they had a free hand to give you all sorts of processing options I was surprised there weren’t more. However, one of the assemblies with the start kit is called <font face="Courier New">Microsoft.Http.Extensions</font>. So I opened it up in <a href="http://www.red-gate.com/products/reflector/">Reflector</a> and lo and behold there are a whole bunch of extension methods in there – so why wasn’t I seeing them? </font> </p> <p> <font size="2">Extension methods become available to your code when their namespace is in scope (e.g. when you have a using statement for the namespace in your code). It turns out that the team put the extension methods in the namespaces appropriate to the technology they were exposing. So for example the <font face="Courier New">ReadAsXElement</font> extension method is in the <font face="Courier New">System.Xml.Linq</font> namespace and the <font face="Courier New">ReadAsXmlSerializable&lt;T&gt;</font> method is in the <font face="Courier New">System.Xml.Serialization</font> namespace.</font> </p> <p> <font size="2">Although I really like the functionality of the WCF Starter Kit, this particular practice, to me, seems bizarre. Firstly, it makes the API counter intuitive – you use the HttpClient class and then there is no hint in the library that there are a bunch of hidden extensions. Secondly, injecting your extensions into someone else’s namespace increases the likelihood of extension method collision (where two libraries define the same extension method in the same namespace). The same named extension method in difference namespaces can be disambiguated, the same named extension in the same namespace gives you no chance.</font> </p> <p> <font size="2">I think if you want to define extension methods then you should keep them in your own namespace – it makes everyone’s life simpler in the long run.</font> </p> <p> <font size="2"></font> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=2ce96651-c153-416a-a680-cced6ee34fdd" /> http://blogs.mantiso.com/blog/kevin/2009/04/02/DevWeek-2009-Demos http://blogs.mantiso.com/blog/kevin/2009/04/02/DevWeek-2009-Demos DevWeek 2009 Demos Are now available on the <a href="http://www.rocksolidknowledge.com/Conferences.mvc/">Rock Solid Knowledge</a> site. I've upload the 'So you think you now JavaScript', 'Design for Testing' and Day of 'Ruby and Rails' talks. Andy's already put up the 'Day of Patterns' and 'Patterns Dartboard' talks http://blogs.mantiso.com/blog/kevin/2009/04/01/Ruby-idioms-in-ASP-Net-MVC http://blogs.mantiso.com/blog/kevin/2009/04/01/Ruby-idioms-in-ASP-Net-MVC Ruby idioms in ASP.Net MVC <p> In Rails there is a mechanism by which you can mimic variadic methods (Ruby also supports true variadic methods) by treating the last parameter as a hash. I can write a function definition like this </p> <pre class="brush: ruby"> def pass_a_hash(s, h) puts s h.each { |key, value| puts "#{key} => #{value}"} if h.class == Hash end </pre> <p> and call it either like </p> <pre class="brush: ruby"> pass_a_hash "kevin", {:a => "b", :c => "d"} </pre> or <pre class="brush: ruby"> pass_a_hash "kevin", :a => "b", :c => "d" </pre> either way this prints <pre> kevin a => b c => d </pre> <p> The second style is much neater, it hides the use of the hash and instead makes it seem like we are using named parameters. This is used all over Rails, especially on web pages where you need to specify things such as controllers and actions. You will often see code like: </p> <pre class="brush: ruby"> &lt;%= link_to "Add", :action => :add, :controller => :students %> </pre> <p> Here we are calling the 'link_to' method passing a string and a hash of options, just like above </p> <p> Microsoft (bless 'em) have tried to mimic this in ASP.Net MVC by letting you can write code similar to the 'link_to' Rails method. On an ASP.Net view you can do something like: </p> <pre class="brush: csharp"> &lt;%= Html.RouteLink("Add", new {action = "add", controller = "students"}) %> </pre> <p> And this adds a link to the page with the text "Add" and a url something like http://server.com/students/add. This is similar to ActionLink and they both eventually call into a method called GenerateRouteLink. In the ASP.Net case the second parameter is not a hash (oh for first class hashes in C#) but an instance of an anonymous class. Using <a href="http://www.red-gate.com/products/reflector/">Reflector</a> we can see what this method does. </p> <p> Internally RouteLink creates a RoutedDictionary passing the anonymous instance as a parameter to its constructor </p> <pre class="brush: csharp"> return htmlHelper.RouteLink(linkText, new RouteValueDictionary(routeValues)); </pre> <p> The RouteValueDictionary constructor looks like this </p> <pre class="brush: csharp"> public RouteValueDictionary(object values) { this._dictionary = new Dictionary&lt;string, object>(StringComparer.OrdinalIgnoreCase); this.AddValues(values); } </pre> <p> and AddValues does this: </p> <pre class="brush: csharp"> private void AddValues(object values) { if (values != null) { foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values)) { object obj2 = descriptor.GetValue(values); this.Add(descriptor.Name, obj2); } } } public void Add(string key, object value) { this._dictionary.Add(key, value); } </pre> <p> So AddValues uses reflection to build a dictionary of name/value pairs </p> <p> Just like in Rails, when the element is rendered this dictionary is interrogated and the values used to build the URL. </p> <p> Neat, but still more ceremony than in Ruby! </p> http://blogs.mantiso.com/blog/kevin/2009/04/01/Ruby-Essence-vs-Ceremony http://blogs.mantiso.com/blog/kevin/2009/04/01/Ruby-Essence-vs-Ceremony Ruby Essence vs Ceremony <p>Last week at <a href="www.devweek.com">DevWeek</a> Tim Ewald and I tried to show some of the elegance of Ruby and I'd like to try and repeat that example here.</p> <p> We started with a Lion class in honour of the news story that week about "Christian the Lion" (hey, look it up yourselves!). The class is very simple </p> <pre class="brush: ruby"> class Lion attr_accessor :message, :name def speak @message end def to_s "#{self.name} says #{self.message}" end @@lions = {} def self.create message, name if @@lions[name] == nil @@lions[name] = Lion.new(message, name) end return @@Lions[name] end def initialize(message, name) @message = message @name = name end end </pre> <p>The bit we care about is the self.create method. The idea here is that we provide a function to only allow the creation of one lion with any given name (this was a demo so it didn't need to make sense). To do this there is a class level dictionary (a static) in which to store new lions. We only add lions to this dictionary if they are unique, otherwise we return an existing lion. The code as it is written is not very Ruby-ish, it reads more like C++, C# or Java code than Ruby and that's what I'd like to change. </p> <p> The first step is to remove the 'return' keyword. In Ruby the last statement in a method is the return value so we can change the code to look like this: </p> <pre class="brush: ruby"> def self.create message, name if @@lions[name] == nil @@lions[name] = Lion.new(message, name) end @@Lions[name] end </pre> <p> The 'if' statement isn't very idiomatic either and in Ruby this can be reduced to </p> <pre class="brush: ruby"> def self.create message, name @@lions[name] = Lion.new(message, name) if @@lions[name] == nil @@lions[name] end </pre> <p> We're still not quite there though. Ruby (like C#) has a 'null co-alescing' operator, which lets me say "if 'x' is not null, use it, else do 'y'", and I can rewrite the above 'if' using this operator (|| in Ruby). It also means I can do away with the final return statement </p> <pre class="brush: ruby"> def self.create message, name @@lions[name] || @@lions[name] = Lion.new(message, name) end </pre> <p> Which says, if @@lions[name] is not null return the value, else assign Lion.new to @@lions[name] and return that value </p> <p> One line to do what it would take four lines to do in other languages and no keywords. As my friend Stu Halloway would put it, essence over ceremony! </p> http://blogs.mantiso.com/blog/kevin/2009/03/27/Dev-Week-2009 http://blogs.mantiso.com/blog/kevin/2009/03/27/Dev-Week-2009 Dev Week 2009 <p>Just finished DevWeek 2009</p> <p>It's been another great week. Spent time with people I haven't seen for a while. I've enjoyed giving the talks and hope you have enjoyed listening to them. I always love spending time hanging out the speakers, there are so many really smart people there. Just spent a day with Tim Ewald - it always blows me away how good a presenter Tim is and how much he knows, this time on Ruby and Rails.</p> <p>Hopefully I'll be back for Software Architect in Sept/Oct and at DevWeek next year.</p> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,76bd58e0-39e7-4624-b3af-b6794d047cef.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,76bd58e0-39e7-4624-b3af-b6794d047cef.aspx Slides and demos from my Windows Workflow Session at Devweek <p> Thanks to all who attended my <a href="www.devweek.com">Devweek</a> session: A Beginners Guide to Windows Workflow. The slides and demos can be downloaded <a href="http://dotnetconsult.blob.core.windows.net/demos/WorkflowForBeginners.zip">here</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=76bd58e0-39e7-4624-b3af-b6794d047cef" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,2c0c3854-b442-4107-aee5-9c0f726eb652.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,2c0c3854-b442-4107-aee5-9c0f726eb652.aspx A Tale of Two Reader/Writer Locks <p> If you look in the System.Threading namespace you will notice something that looks slightly odd: there are a pair of classes ReaderWriterLock and ReaderWriterLockSlim. What are these for and why are there two of them? </p> <p> Whenever you have multiple threads there is a need to protect state shared between them from corruption. The simplest tool in the .NET Framework is the Monitor class (encapsulated by the lock statement in C#) that provides mutual exclusion. In other words, only one thread at a time can acquire it and anyone else trying to acquire it blocks until the first thread releases it. It situations of high update this provides a reasonable approach. However, if we had no writers we could allow everyone to access a resource without acquiring a lock. So if we had many readers and only an occasional writer, ideally we’d like all the readers to be able to access a resource at the same time and only be blocked if someone needed to write. Unfortunately a Monitor would only allow one reader in at a time so this is the role of a Reader/Writer lock – to allow many concurrent readers but only a single writer, blocking all readers. </p> <p> So we come to the next question: why are there two of them? ReaderWriterLock was introduced in version 2.0 of .NET and provided the above functionality. However, there was a problem. Imagine this scenario: we have 10 readers currently reading when a writer wants access. Obviously the writer has to let the readers finish and so waits patiently for the readers to release their read locks. However, as the readers drop to one, suddenly a brand new reader arrives – there i still a read lock being held but thats ok as it can also acquire a read lock in that situation. Now the writer is blocked on a new reader and more can continue to arrive so that the writer never gets in – this is called writer starvation. ReaderWriterLock suffers from the possibility of writer starvation. </p> <p> For version 3.5 SP1 the .NET framework team decided to address this. They introduced a new class called ReaderWriterLockSlim that provides the reader/writer lock functionality but does not suffer from writer starvation (new readers are blocked when there is a writer waiting). However, why didn’t the team just fix the original one? They say that some people depend on the feature that new readers can get a lock if a reader is already there. They didn’t want to break existing code. </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=2c0c3854-b442-4107-aee5-9c0f726eb652" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,6c02ac47-3336-47f9-b0c9-36025c58cc89.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,6c02ac47-3336-47f9-b0c9-36025c58cc89.aspx Keeping things safe wth AsyncCallback <p> The .NET Async pattern is a very neat way of running functionality asynchronously. The async pattern is where for a synchronous method DoWork be have a pair of methods BeginDoWork and EndDoWork to handle running the DoWork functionality on the threadpool. Now it is well documented that if I call the Begin method I must also call the End method to allow the async infrastructure to clean up resources it may have acquired. However, where do I call the End version? </p> <p> Consider async delegate invocation. Quite often I’d like to just fire off the async method and forget about it but I have to call EndInvoke. Fortunately lambdas make this really easy </p> <p> <font face="Courier New">Action a = DoWork;<br> a.BeginInvoke( ar =&gt; a.EndInvoke(ar) );</font> </p> <p> Now there is a nasty problem. What happens if DoWork throws an exception? The async delegate infrastructure will conveniently cache the exception and re-throw it when I call EndInvoke. However, the issue is that this is happening in an AsyncCallback delegate on a threadpool thread and so I cannot catch it easily in this construct. Why is that a problem? well since .NET 2.0 an unhandled exception on a background thread will terminate the process. This means to reliably call EndInvoke in an AsyncCallback we must put it in a try … catch. This is annoying code to reliably put in place and is easily forgotten. So I have written an extension method to wrap this functionality for you </p> <font size=4> <p> </font><font size=2><font face="Courier New"><font color=#0000ff><font color=#0000ff>public</font></font> <font color=#0000ff><font color=#0000ff>static</font></font> <font color=#0000ff><font color=#0000ff>class</font></font> <font color=#2b91af><font color=#2b91af>Extensions<br> </font></font></font></font><font face="Courier New" size=2>{<br> &nbsp; </font><font size=2><font face="Courier New"><font color=#0000ff><font color=#0000ff>public</font></font> <font color=#0000ff><font color=#0000ff>static</font></font> <font color=#2b91af><font color=#2b91af>AsyncCallback</font></font> Try(<font color=#0000ff><font color=#0000ff>this</font></font> <font color=#2b91af><font color=#2b91af>AsyncCallback</font></font> cb, <font color=#2b91af><font color=#2b91af>Action</font></font>&lt;<font color=#2b91af><font color=#2b91af>Exception</font></font>&gt; exceptionAction)<br> &nbsp; </font></font><font face="Courier New" size=2>{<br> &nbsp;&nbsp;&nbsp; </font><font size=2><font face="Courier New"><font color=#2b91af><font color=#2b91af>AsyncCallback</font></font> wrapper = <font color=#0000ff><font color=#0000ff>delegate</font></font>(<font color=#2b91af><font color=#2b91af>IAsyncResult</font></font> iar)<br> </font></font><font face="Courier New" size=2>&nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color=#0000ff><font color=#0000ff><font face="Courier New" size=2>try<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font></font><font face="Courier New" size=2>{<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font face="Courier New" size=2>cb(iar);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font face="Courier New" size=2>}<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font size=2><font face="Courier New"><font color=#0000ff><font color=#0000ff>catch</font></font> (<font color=#2b91af><font color=#2b91af>Exception</font></font> e)<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></font><font face="Courier New" size=2>{<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font face="Courier New" size=2>exceptionAction(e);<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font face="Courier New" size=2>}<br> &nbsp;&nbsp;&nbsp; </font><font face="Courier New" size=2>};<br> &nbsp;&nbsp;&nbsp; </font><font size=2><font face="Courier New"><font color=#0000ff><font color=#0000ff>return</font></font> wrapper;<br> </font></font><font face="Courier New" size=2>&nbsp; }<br> </font><font face="Courier New" size=2>}</font>> <p> <font size=2>So this code extends AsyncCallback and takes a delegate to call if an exception takes place it then wraps its own AsyncCallback around the one passed in this time putting it in a try … catch block. The usage looks like this:</font> </p> <font size=2><font color=#2b91af size=4><font color=#2b91af size=4> <p> <font face="Courier New" size=2>Action</font> </font></font><font face="Courier New"> a = DoStuff;<br> </font><font face="Courier New"><font color=#2b91af><font color=#2b91af>AsyncCallback</font></font> cb = ia =&gt; a.EndInvoke(ia);<br> </font><font face="Courier New">a.BeginInvoke(cb.Try(e =&gt; <font color=#2b91af><font color=#2b91af>Console</font></font>.WriteLine(e)), <font color=#0000ff><font color=#0000ff>null</font></font><font size=4><font size=2>);</font></font></font>> <p> <font face="Courier New"><font size=4><font face="Trebuchet MS" size=2>The only awkward thing here is having to take the lambda out of the call to BeginInvoke because the C# compiler won’t allow the dot operator on a lambda (without casting it to an AsyncCallback) but at least this wraps up some of the issues</font> </p> </font>>><img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=6c02ac47-3336-47f9-b0c9-36025c58cc89" /> http://blogs.mantiso.com/blog/kevin/2009/03/16/VSTS-Load-Web-Testing-and-Browser-Definitions http://blogs.mantiso.com/blog/kevin/2009/03/16/VSTS-Load-Web-Testing-and-Browser-Definitions VSTS Load/Web Testing and Browser Definitions <p> When you add a VSTS load test or when you configure a web test you can specify the browser(s) to use for the test. The data for each type of browser is held in files with a .browser extension in the C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\Templates\LoadTest\Browsers directory. </p> <p> You can add your own browsers to this list by copying and renaming one of these files and changing the details within the file. The files are XML so this is easy to do, they look something like this </p> <p> <pre id="browsers" class="brush: xml"> &lt;Browser Name="Netscape 6.0"> &lt;Headers> &lt;Header Name="User-Agent" Value="Mozilla/5.0 (Windows; U; Windows NT 5.0; en; rv:1.0) Netscape/6.0" /> &lt;Header Name="Accept" Value="image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*" /> &lt;Header Name="Accept-Language" Value="{{$IEAcceptLanguage}}" /> &lt;Header Name="Accept-Encoding" Value="GZIP" /> &lt;/Headers> &lt;/Browser> </pre> </p> <p> Remember to change the Name attribute on the Browser element otherwise you'll see the same browser listed twice inside visual studio. </p> <p> After making the changes you will need to re-start Visual Studio to see your new browser listed. </p> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,5a7759a2-c6c3-41f6-af58-ba4f82becc9a.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,5a7759a2-c6c3-41f6-af58-ba4f82becc9a.aspx WF4: Why do I have to pass the context to get data from an argument? <p> I talked about the new <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,707e4cb9-6111-4069-96b3-596e87f2e262.aspx">WF4 Runtime model</a> a while back. One of the things I discussed was the new data flow model of arguments and variables. However, if you are used to WF 3.5 something looks a bit odd here. Lets look at a simple activity example: </p> <p> <span style="font-size: 11px; color: black; font-family: courier new; background-color: transparent"><span style="font-size: 11px; color: blue; font-family: courier new; background-color: transparent">public</span> <span style="font-size: 11px; color: blue; font-family: courier new; background-color: transparent">class</span> WriteLineActivity : WorkflowElement<br> {<br> <span style="font-size: 11px; color: blue; font-family: courier new; background-color: transparent">&nbsp;&nbsp;&nbsp; public</span> <strong>InArgument&lt;<span style="font-size: 11px; color: blue; font-family: courier new; background-color: transparent">string</span>&gt; Text</strong> { get; set; }<br> <span style="font-size: 11px; color: blue; font-family: courier new; background-color: transparent">&nbsp;&nbsp;&nbsp; protected</span> <span style="font-size: 11px; color: blue; font-family: courier new; background-color: transparent">override</span> <span style="font-size: 11px; color: blue; font-family: courier new; background-color: transparent">void</span> Execute(ActivityExecutionContext context)<br> &nbsp;&nbsp;&nbsp; {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(<strong>Text.Get(context)</strong>);<br> &nbsp;&nbsp;&nbsp; }<br> }</span> </p> <p> <span style="font-size: 11px; color: black; font-family: courier new; background-color: transparent"><font face="Trebuchet MS" size="2">Why do I need to pass the ActivityExecutionContext when I want to get the data from the argument? This highlights a subtlety to the change in the runtime model. The activity is really just a template. A class called ActivityInstance is the thing that is actually executed, it just has a reference to the actual activity to be able to hand off to the activty’s methods (e.g. Execute). The actual argument state is stored in a construct called the LocalEnvironment. The ActivityExecutionContext gives access to&nbsp; the current ActivityInstance and that in turn holds a reference to the current LocalEnvironment. Therefore, to get from&nbsp; an activity’s Execute method to its state we have to go via the ActivityExecutionContext.<br> </font> </p> ><img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=5a7759a2-c6c3-41f6-af58-ba4f82becc9a" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,ba2f9f7f-6819-4f45-aa05-b8ded1c7ad14.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,ba2f9f7f-6819-4f45-aa05-b8ded1c7ad14.aspx BlobExplorer Released on to CodePlex <p> I’ve finally got round to pushing the code for <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,38b4889c-b9a6-4576-a944-b9286637dc14.aspx">BlobExplorer</a> to <a href="http://www.codeplex.com">CodePlex</a>. You can find the CodePlex site <a href="http://www.codeplex.com/blobexplorer">here</a>. If you want to contribute to the project, let me know at <em>richard at nospam dotnetconsult dot co dot uk</em> and I’ll add you to the contributors list. The releases will continue being pushed to blob storage <a href="http://dotnetconsult.blob.core.windows.net/tools/BlobExplorer.zip">http://dotnetconsult.blob.core.windows.net/tools/BlobExplorer.zip</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=ba2f9f7f-6819-4f45-aa05-b8ded1c7ad14" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,fb857c16-d50e-4e23-8eb8-58e981eddbd6.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,fb857c16-d50e-4e23-8eb8-58e981eddbd6.aspx Mapping from Business Objects to DTOs &ndash; Enter AutoMapper <p> A while back I did <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx">this post</a> talking about how WCF contract definitions should model the messages being passed and not use business&nbsp; objects. This inevitably&nbsp; means that you have to translate from the Data Transfer Object (DTO) in the contract to business object and back again. This can feel like a lot of overhead but it really does protect you from a lot of heartache further down the line. </p> <p> However <a href="http://www.leastprivilege.com">Dom</a> just pointed out the <a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx">AutoMapper</a> to me. This is in its early stages but looks like the kind of library that will really take away a lot of the grunt work associated with using DTOs – kudos! </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=fb857c16-d50e-4e23-8eb8-58e981eddbd6" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,56569101-55f5-476b-8272-e416edc5df9b.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,56569101-55f5-476b-8272-e416edc5df9b.aspx BlobExplorer Now Supports Blob Metadata <p> I've just dropped&nbsp;a new release of Blob Explorer for managing Windows Azure Blob Storage </p> <p> Two new features: </p> <ul> <li> Blob metadata can now be added and viewed</li> <li> There is a status bar to show that long running uploads and downloads are in progress</li> </ul> <p> As always you can get it from blob storage here </p> <p> <a href="http://dotnetconsult.blob.core.windows.net/tools/BlobExplorer.zip">http://dotnetconsult.blob.core.windows.net/tools/BlobExplorer.zip</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=56569101-55f5-476b-8272-e416edc5df9b" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0a7cd196-c36b-4afa-ab02-5e4e6829c42d.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,0a7cd196-c36b-4afa-ab02-5e4e6829c42d.aspx WCF, Messages and DataSets &hellip; Oh My! <p> Sometimes you have to wonder if this subject will ever go away … </p> <p> A few weeks ago I posted on using <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx">OO constructs in your DataContracts</a>. It’s one of those things that is understandable when .NET developers first start building message based systems. Another issue that raises its head over and over again goes along the lines of “I’m trying to send a DataSet back to my client and it just isn’t working properly”. This reminds me of the old joke: </p> <p> Patient: Doctor, doctor it hurts when I do this (patient raises his arm into a strange position over his head)<br> Doctor: Well don’t do it then </p> <p> So what is the issue with using DataSets as parameters or return types in your service operations? </p> <p> Lets start off with interoperability – or the total lack thereof. If we are talking about interoperability we have to think about what goes into the WSDL for the DataSet – after all it is a .NET type. In fact DataSets, by default serialize as XML so surely it must be ok! Here’s what a DataSet looks like in terms of XML Schema in the WSDL </p> <p> <span class="m"><font color="#0000ff">&lt;</font></span><span class="t"><font color="#990000">xs:sequence</font></span><span class="m"><font color="#0000ff">&gt;<br> </font></span><span class="b"><strong><font face="Courier New" color="#ff0000">&nbsp;</font></strong></span> <span class="m"><font color="#0000ff">&lt;</font></span><span class="t"><font color="#990000">xs:element</font></span> <span class="t"><font color="#990000">ref</font></span><span class="m"><font color="#0000ff">="</font></span><b>xs:schema</b><font color="#0000ff"><span class="m">"</span><span class="m"> /&gt;</span></font>&nbsp;<br> <span class="b"><strong><font face="Courier New" color="#ff0000">&nbsp;</font></strong></span> <span class="m"><font color="#0000ff">&lt;</font></span><span class="t"><font color="#990000">xs:any</font></span> <span class="m"><font color="#0000ff">/&gt;<br> </font></span><span class="m"><font color="#0000ff">&lt;/</font></span><span class="t"><font color="#990000">xs:sequence</font></span><span class="m"><font color="#0000ff">&gt;</font></span> </p> <p> <span class="m">In other words I’m going to send you some … XML – you work out what do with it. But hold on – if I use Add Service Reference, it *knows* its a DataSet so maybe it is ok. Well WCF cheats; just above that sequence is another piece of XML</span> </p> <p align="left"> <span class="m"><span class="m"><font color="#0000ff">&lt;</font></span><span class="t"><font color="#990000">xs:annotation</font></span><span class="m"><font color="#0000ff">&gt;<br> &nbsp;&nbsp;&nbsp; </font></span><span class="m"><font color="#0000ff">&lt;</font></span><span class="t"><font color="#990000">xs:appinfo</font></span><span class="m"><font color="#0000ff">&gt;<br> </font></span><span class="m"><font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;</font></span><span class="t"><font color="#990000">ActualType </font></span><span class="t"><font color="#990000">Name</font></span><span class="m"><font color="#0000ff">="</font></span><b>DataSet</b><span class="m"><font color="#0000ff">"</font></span><span class="t"><font color="#990000"> Namespace</font></span><span class="m"><font color="#0000ff">="</font></span><b>http://schemas.datacontract.org/2004/07/System.Data</b><span class="m"><font color="#0000ff">"</font></span><span class="ns"><font color="#ff0000"> <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns</font></span><span class="m"><font color="#0000ff">="</font></span><b class="ns"><font color="#ff0000">http://schemas.microsoft.com/2003/10/Serialization/</font></b><font color="#0000ff"><span class="m">"</span><span class="m"> /&gt;</span></font>&nbsp;<br> <span class="b"><strong><font face="Courier New" color="#ff0000">&nbsp;</font></strong></span> <span class="m"><font color="#0000ff">&lt;/</font></span><span class="t"><font color="#990000">xs:appinfo</font></span><span class="m"><font color="#0000ff">&gt;<br> </font></span><span class="m"><font color="#0000ff">&lt;/</font></span><span class="t"><font color="#990000">xs:annotation</font></span><span class="m"><font color="#0000ff">&gt;</font></span></span> </p> <p align="left"> <span class="m"><span class="m">So WCF cheats by putting an annotation only it understands into the schema so it knows to use a DataSet. If you really do want to pass back arbitrary XML as part of a message then use an XElement.</span></span> </p> <p align="left"> <span class="m"><span class="m">So how about if I have WCF on both ends of the wire? Well then you’ve picked a really inefficient way to transfer around the data. You have to remember how highly functional a DataSet actually is. Its not just the data in the tables that support that functionality, there is also : change tracking data to keep track of what rows have been added, updated and removed since the DataSet was filled; relationship data between tables; a schema&nbsp; describing itself. DataSets are there to support disconnected processing of tabular data, not as a general purpose data transfer mechanism.</span></span> </p> <p align="left"> <span class="m"><span class="m">Then you may say – “hey we’re running on an intranet – the extra data is unimportant”. So the final issue you get with a DataSet is tight coupling of the service and the consumer. Changes to the structure of the data on one side of the wire cascade to the other side to someone who may not be expecting the changes. Admittedly not all changes will be breaking ones but are you sure you know which ones will be and which ones won’t. As long as the data you actually want to pass isn’t changing why are you inflicting this instability on the other party in the message exchange. The likelihood that you will have to make unnecessary changes to, say, the client when the service changes is increased with DataSets&nbsp; </span></span> </p> <p align="left"> <span class="m"><span class="m">So what am I suggesting to do instead? Instead model the data that you do want to pass around using DataContract (or XElement if you truly want to be able to pass untyped XML). Does this mean you have to translate the data from a DataSet to this DataContract when you want to send it? Yes it does, but that code can be isolated in a single place. When you receive the data as a DataContract and want to process it as a DataSet, does this mean you have to recreate a DataSet programmatically? Yes it does, but again you can isolate this code in a single place.</span></span> </p> <p align="left"> <span class="m"><span class="m">So what does doing this actually buy you if you do that work? You get something which is potentially interoperable, that only passes the required data across the wire and that decouples the service and the consumer. </span></span><span class="m"> </p> ><img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=0a7cd196-c36b-4afa-ab02-5e4e6829c42d" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,d32be8a7-aa1b-4d2f-9e54-780cf57528a4.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,d32be8a7-aa1b-4d2f-9e54-780cf57528a4.aspx Workflow 4.0 Services and &ldquo;InvalidOperationException: DispatchOperation requires Invoker&rdquo; <p> I’ve been writing a lab on Workflow Services in 4.0 recently. Part of what I was showing was the new data orientated correlation (the same kind of mechanism that BizTalk uses for correlation). So I wanted to have two operations that were correlated to the same workflow instance based on data in the message (rather than a smuggled context id as 3.5 does it). As I was writing this lab I suddenly started getting an <font face="Courier New">InvalidOperationException</font> stating <strong><em>DispatchOperation requires Invoker</em></strong> every time I brought the .xamlx file up in a browser. It appeared that others had seen this as well but not really solved it. So I dug around looking at the XAML (workflow services can be written fully declaratively now) and the config file and could see no issues there. I asked around but no one I asked knew the reason. </p> <p> So I created a simple default Declarative Workflow Service project and that worked ok. I compared my lab workflow and the default one and it suddenly dawned on me what was wrong. The default project has just one operation on the contract and has a ServiceOperationActivity to implement it. My contract had my two operations but I had, so far, only bound one ServiceOperationActivity. So in other words I had not implemented the contract. This is obviously an issue and looking back I’m annoyed I didn’t see it sooner. </p> <p> However, the problem is that this is a change in behavior between 3.5 and 4.0. In 3.5 if I didn’t bind a ReceiveActivity to every operation I got a validation warning but I could still retrieve metadata; in 4.0 you get a fatal error. Its not hugely surprising that the behavior has changed – after all the whole infrastructure has been rewritten. </p> <p> On the whole its a good thing that implementation of the contract is enforced – although it would be nice if the validation infrastructure caught this at compile time rather than it being a runtime failure. </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=d32be8a7-aa1b-4d2f-9e54-780cf57528a4" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,98976698-78e3-478a-b671-31b6e75697c3.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,98976698-78e3-478a-b671-31b6e75697c3.aspx Dynamic hosting of WCF Services <p> A forum question was asking how to create a host that dynamically loaded up services deployed in DLLs. I told the poster to use reflection but he wasn't familiar with it so I thought I would quickly knock up a sample </p> <p> The host looks in a folder under the directory in which it is executing. The service must be annotated with a [ServiceClass] attribute (defined in a library that accompanies the host). Then you set up the config file for the service ( [ServiceBehavior(ConfigurationName="&lt;some name&gt;")] helps decouple the config from the actual implementing type nicely </p> <p> The sample is here </p> <p> <a href="http://www.dotnetconsult.co.uk/weblog2/content/binary/DynamicHost.zip">DynamicHost.zip (77.07 KB)</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=98976698-78e3-478a-b671-31b6e75697c3" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,cae2f1fe-d8aa-4d3c-baa0-c6a7c9716ede.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,cae2f1fe-d8aa-4d3c-baa0-c6a7c9716ede.aspx Fix to BlobExplorer <p> <a href="http://blogs.thinktecture.com/cweyer/">Christian</a> found a bug in <a href="http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,38b4889c-b9a6-4576-a944-b9286637dc14.aspx">BlobExplorer</a> when the blob name has pseudo directory structure in it (common prefixes) </p> <p> Fixed version is available <a href="http://dotnetconsult.blob.core.windows.net/tools/BlobExplorer.zip">here</a> </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=cae2f1fe-d8aa-4d3c-baa0-c6a7c9716ede" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,af6e6325-2e30-42e3-acb9-57e1363fa51e.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,af6e6325-2e30-42e3-acb9-57e1363fa51e.aspx WCF Sessions <p> Hanging out on the <a href="http://social.msdn.microsoft.com/Forums/en-US/wcf/threads">WCF Forums</a>, it appears one in five answers I give seem to be to do with sessions in WCF. As a result, rather than write the same thing over and over again I decided to distil my forum posts into a blog post that I can link to. </p> <p> WCF has the concept of a session. A session is simply an identifier for the proxy making the call. Where does this ID come from? Well it depends on the binding: with NetTcpBinding, the session is inherent in the transport – TCP is a connected session based transport; with WSHttpBinding session is an artifice piggybacking either WS-SecureConversation or WS-ReliableMessaging. So different bindings go via different mechanisms to achieve the concept of session. However, not all bindings support session – BasicHttpBinding, for example, has no mechanism for maintaining a session. Be aware that every mechanism for maintaining a session in WCF has issues with load balancing. The relationship between proxy and service is a machine-bound one. If you want to use load balancing you will have to use <a href="http://blogs.msdn.com/drnick/archive/2007/07/13/sticky-sessions.aspx">sticky sessions</a>. </p> <p> So what does having a session do for me? Well some parts of the infrastructure rely on sessions – callbacks for example. WCF also supports the ability to associate a specific instance of the service implementation class with a session (called PerSession instancing). Having a specific instance for the session can seem very attractive in that it allows you to make multiple calls to a service from a specific proxy instance and the service can maintain state in member variables in that service instance in behalf of the client. In fact, if the binding supports session, this is the default model for mapping service instances to requests. WCF also supports two other instancing models (controlled by the service behavior InstanceContextmode): PerCall – each request gets its own instance; Single – all calls use a single instance. </p> <p> Session has an impact beyond the service – client proxy behavior is affected by the idea of session. Say the client crashes, what happens to the session? Again this depends on the binding. NetTcpBinding is connection orientated so the service side gets torn down if the client crashes. WSHttpBinding on the othe hand rides on top of a connectionless protocol (HTTP) and so if the client crashes the service has no idea. In this situation the session will eventually time out depending on the configuration of WS-SecureConverstion or WS-ReliableMessaging – the default is 10 minutes. To tear down the session the proxy has to call back to the service to say that it is done. This means that closing the proxy in the client is crucial to efficient session management and that Close with WSHttpBinding will actually roundtrip to the service. If the service has died, Close, in this situation will throw an exception and you must call Abort to clean up the proxy correctly. </p> <p> Session also has effects that are often hidden during development. WCF has an inbuilt throttle to control concurrent operations. There are three throttles: concurrent requests (self explanatory); concurrent objects (remember that there are options as to how many service instances service requests – in reality this one is very unlikely to affect you); and most importantly for the discussion here, concurrent sessions – this defaults to 10. So if you do not clean up your proxy by default your service will support up to 10 concurrent proxies which is generally way too low for many systems. </p> <p> Sometimes your service will require the ability to maintain per client state. However, due to the complexity of dealing with sessions it is often best to avoid them (unfortunately impossible with the NetTcpBinding) and use another, applkication defined, session identifier and put the session state in a database. However, for example with callbacks, sometimes you require session in your service. In this case you should annotate your contract with the modified ServiceContract </p> <font size=2> <p> [ </font><font color=#2b91af size=2><font color=#2b91af size=2>ServiceContract</font></font><font size=2>(SessionMode=</font><font color=#2b91af size=2><font color=#2b91af size=2>SessionMode</font></font><font size=2>.Required)]</font>> <p> <font size=2>If you do not need session and you do not need to use a session orientated protocol like named pipes or tcp then I would turn off session explicitly by using the following on the contract</font> </p> <font size=2><font size=2> <p> [ </font><font color=#2b91af size=2><font color=#2b91af size=2>ServiceContract</font></font><font size=2>(SessionMode=</font><font color=#2b91af size=2><font color=#2b91af size=2>SessionMode</font></font><font size=2>.NotAllowed)]</font>> <p> <font size=2>In my experience it is rarely useful to use sessions and they introduce overhead, load balancing restrictions and complexity for the client. </p> </font>><img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=af6e6325-2e30-42e3-acb9-57e1363fa51e" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx WCF Contracts, Object Orientation and ServiceKnownType <p> I’ve recently started hanging out on the <a href="http://social.msdn.microsoft.com/Forums/en-US/wcf/threads/">MSDN WCF forum</a>. Its interesting seeing the questions that are coming up there. One fairly common one is along the lines of: </p> <p> <em>I have a service that I want to return a list of Person objects but it doesn’t seem to be working when I pass Employees and Managers in the list.</em> </p> <p> At some point someone will reply </p> <p> <em>You should annotate the contract with the ServiceKnownType attribute for each type that the Person could be.</em> </p> <p> Now in a strict sense this is true – however, I think there is a much deeper question that needs discussion. </p> <p> To understand where the basic problem is we need to take a quick detour into the architecture of WCF. WCF has two layers: the channel layer and the service model layer. </p> <p> The channel layer deals with Message objects passing them through a composable stack of channels which add or process message headers, handle mapping the Message object to and from a stream of bytes and moving those bytes from one place to another. Notice here we have no notion of ServiceContracts, etc. All messages are untyped in .NET terms are are expressed in terms of an XML Infoset. </p> <p> The service model layer sits on top of the channel layer and deals with endpoints, behaviors, dispatchers and other bits of plumbing – but the phrase “sits on top of the channel layer” is hugely important. An endpoint is made up of three elements: an address (where), a binding (how) and a contract (what). It is the contract that often causes confusion. In WCF code it takes the form of an annotated interface (can be a class but an interface is more flexible) </p> <p> <font face="Courier New" size=2>[ServiceContract]<br> interface ICalc<br> {<br> &nbsp;&nbsp;&nbsp;&nbsp; [OperationContract]<br> &nbsp;&nbsp;&nbsp;&nbsp; int Add( int x, int y);<br> }</font> </p> <p> But what do the parameters and return types really mean? What you are in fact doing here is specifying the request and response message bodies. This information will be translated into XML by the time the Message hits the channel layer. Now here we have only used simple types. The data that we generally want to move around is more complex and so we need another way to describe it – for that we use a .NET type and a serializer that translates an object into XML and back again. There are two main serializers that can be used: the long standing XmlSerializer and the DataContractSerializer that was introduced with WCF; the DataContractSerializer is the default one. You normally take a .NET class and annotate is with attributes (although .NET 3.5 SP1 removed the need to do this its generally a good idea anyway as you retain control over XML namespaces, etc) </p> <p> <font face="Courier New" size=2>[DataContract(Namespace=”urn:person”)]<br> class Person<br> {<br> &nbsp;&nbsp;&nbsp;&nbsp; public string Name{ get; set; }<br> &nbsp;&nbsp;&nbsp;&nbsp; public int Age{ get; set; }<br> }</font> </p> <p> <font face="Courier New" size=2>[ServiceContract]<br> interface IMakeFriends<br> {<br> &nbsp;&nbsp;&nbsp;&nbsp; [OperationContract]<br> &nbsp;&nbsp;&nbsp;&nbsp; void AddFriend( Person p );<br> }</font> </p> <p> So far so good. So where is the problem? Well now we’re in .NET type system world so it starts to become tempting to pass types that derive from person to the AddFriend method – after all the C# compiler doesn’t doesn’t complain. And at this point when you call the AddFriend method it doesn’t work and so you post the above question to the WCF forum. Unfortunately the way that contracts are expressed in WCF makes is very easy to forget what their purpose is: to define the messages send to the operation and being sent back from the operation. In reality you have to think <strong>“how would I express this data in XML?”</strong>. XML doesn’t support inheritance so whatever you put in the contract is going to have to have some way of mapping to XML. The data contracts used to define the messages are simply a .NET typed convenience for generating the XML for the data you want to pass – if you view them any other way you are destined for a world of pain. So think about the <em>data</em> you want to pass, not how it may happen to be represented in your business layer and design your DataContracts accordingly. </p> <p> “But wait!” you may say “I may want to pass and Employee or a Manager here and I need the data to get to the receiver”. Again it comes back to “how would I express that in XML?” as that is what will be happening at the end of the day. If you have a discrete set of types that could be passed then you have something similar to a <a href="http://www.w3schools.com/Schema/el_choice.asp">XML Schema Choice Group</a>. In this case <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.serviceknowntypeattribute.aspx">ServiceKnownType</a> is a reasonable approach (although it doesn’t use a Choice Group under the covers). Remember you will need to change the contract if new types need to be passed – as with Choice Groups. However, if you require looser semantics where an extensible number of things may be passed without wanting to change the contract then you require a different way of expressing this in XML and therefore a different way of expressing this in .NET code. Something like: </p> <font size=4> <p> </font><font face="Courier New" size=2>[<font color=#2b91af><font color=#2b91af>DataContract</font></font>]<br> </font><font color=#0000ff><font color=#0000ff><font face="Courier New" size=2>public</font></font></font><font size=2><font face="Courier New"> <font color=#0000ff><font color=#0000ff>class</font></font> <font color=#2b91af><font color=#2b91af>KeyValuePair<br> </font></font></font></font><font face="Courier New" size=2>{<br> &nbsp; </font><font face="Courier New" size=2>[<font color=#2b91af><font color=#2b91af>DataMember</font></font>]<br> &nbsp; </font><font size=2><font face="Courier New"><font color=#0000ff><font color=#0000ff>public</font></font> <font color=#0000ff><font color=#0000ff>string</font></font> Key { <font color=#0000ff><font color=#0000ff>get</font></font>; <font color=#0000ff><font color=#0000ff>set</font></font>; }<br> &nbsp; </font></font><font face="Courier New" size=2>[<font color=#2b91af><font color=#2b91af>DataMember</font></font>]<br> &nbsp; </font><font size=2><font face="Courier New"><font color=#0000ff><font color=#0000ff>public</font></font> <font color=#0000ff><font color=#0000ff>string</font></font> Value { <font color=#0000ff><font color=#0000ff>get</font></font>; <font color=#0000ff><font color=#0000ff>set</font></font>; }<br> </font></font><font face="Courier New" size=2>}</font>> <p> <font face="Courier New" size=2>[<font color=#2b91af><font color=#2b91af>DataContract</font></font>]<br> </font><font color=#0000ff><font color=#0000ff><font face="Courier New" size=2>public</font></font></font><font size=2><font face="Courier New"> <font color=#0000ff><font color=#0000ff>class</font></font> <font color=#2b91af><font color=#2b91af>FlexibleData<br> </font></font></font></font><font face="Courier New" size=2>{<br> &nbsp; </font><font face="Courier New" size=2>[<font color=#2b91af><font color=#2b91af>DataMember</font></font>]<br> &nbsp; </font><font size=2><font face="Courier New"><font color=#0000ff><font color=#0000ff>public</font></font> <font color=#0000ff><font color=#0000ff>string</font></font> Discriminator { <font color=#0000ff><font color=#0000ff>get</font></font>; <font color=#0000ff><font color=#0000ff>set</font></font>; }<br> &nbsp; </font></font><font face="Courier New" size=2>[<font color=#2b91af><font color=#2b91af>DataMember</font></font>]<br> &nbsp; </font><font size=2><font face="Courier New"><font color=#0000ff><font color=#0000ff>public</font></font> <font color=#2b91af><font color=#2b91af>List</font></font>&lt;<font color=#2b91af><font color=#2b91af>KeyValuePair</font></font>&gt; Properties { <font color=#0000ff><font color=#0000ff>get</font></font>; <font color=#0000ff><font color=#0000ff>set</font></font>; }<br> </font></font><font face="Courier New" size=2>}</font> </p> <p> In this case the receiver will be responsible for unpicking the Properties based on the Discriminator. The other thing you could do is to pass the data as an XElement and work explicitly at the XML level, with LINQ to XML this is not very onerous. Is this all really convenient to use in .NET? Well not as easy as inheritance, but then we’re actually talking about XML here not .NET. Again, <em>the .NET typed contract is simply a convenience for creating the XML message</em>. </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=a3775eb1-b441-43ad-b9f1-e4aaba404235" /> http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,22d0fd98-a1ab-46fd-8b13-7fb26df07dd7.aspx http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,22d0fd98-a1ab-46fd-8b13-7fb26df07dd7.aspx Turning off #region and red squiggly lines <p> With any development environment&nbsp;I go through a series of stages: </p> <ol> <li> Love - this thing is awesome I never realised how great life would be with these new features <li> Hate - Man why does it do these stupid things, it really detracts from the new cool features <li> Acceptance - well it has foibles but generally I get my job done faster</li> </ol> <p> I've been in 3 with VS 2008 for some time now but two things have always irked me: </p> <p> When I type a method I get error red lines appear due to syntax errors like this: </p> <p> <img src="http://www.dotnetconsult.co.uk/weblog2/content/binary/redsquigle.JPG" border=0> </p> <p> Well obviously I get an error - I haven't finished typing yet! I find these sorts of errors very distracting. </p> <p> The other issue is with implementing interfaces - I love the feature where I can specify a class implements an interface and then press Ctrl+. [Enter] and it puts a skeleton implementation in for me. What I have always found annoying though is the #region if surrounds the implementation with: </p> <p> <img src="http://www.dotnetconsult.co.uk/weblog2/content/binary/region.JPG" border=0> </p> <p> So I was looking around the C# editor options today and found I could turn both of these off. </p> <p> <img src="http://www.dotnetconsult.co.uk/weblog2/content/binary/woohoo.jpg" border=0> </p> <p> I think I may be heading back to phase 1 of my relationship with VS2008 now :-) </p> <img width="0" height="0" src="http://www.dotnetconsult.co.uk/weblog2/aggbug.ashx?id=22d0fd98-a1ab-46fd-8b13-7fb26df07dd7" /> http://blogs.mantiso.com/blog/kevin/2008/12/12/212F21AA1AF7ACD5F0A8069C5A00F850 http://blogs.mantiso.com/blog/kevin/2008/12/12/212F21AA1AF7ACD5F0A8069C5A00F850 Ruby 1.9 and Active Record <p> I'm trying to use ActiveRecord outside of Rails and with Ruby 1.9. I kept getting an error </p> <pre class="brush: ruby"> /opt/local/lib/ruby1.9/gems/1.9.1/gems /activerecord-2.2.2/lib/active_record/base.rb:394:in `&lt;class:Base>': undefined method `cattr_accessor' for ActiveRecord::Base:Class (NoMethodError) from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord- 2.2.2/lib/active_record/base.rb:391:in `&lt;module:ActiveRecord>' from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord- 2.2.2/lib/active_record/base.rb:4: in `&lt;top (required)>' from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord- 2.2.2/lib/active_record.rb:34: in `require' from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord- 2.2.2/lib/active_record.rb:34: in `&lt;top (required)>' from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord- 2.2.2/lib/activerecord.rb:1 :in `require' from /opt/local/lib/ruby1.9/gems/1.9.1/gems/activerecord- 2.2.2/lib/activerecord.rb:1: in `&lt;top (required)>' from SimpleTest.rb:2:in `require' from SimpleTest.rb:2:in `<main>' </pre> <p> so and undefined method cattr_accessor in ActiveRecord::Base. </p> <p> Trying the same code in 1.8 worked fine. After much searching I discovered that ActiveSupport had to be installed. This looked like it was installed when I installed ActiveRecord, but it possibly wasn't a complete install. </p> <p> so after a </p> <pre> sudo gem install ActiveSupprt </pre> <p> I'm good to go </p> <div class="posttagsblock"><a href="http://technorati.com/tag/Ruby" rel="tag">Ruby</a></div> http://blogs.mantiso.com/blog/kevin/2008/12/02/B64D01983CD260D66CE1935346E056D8 http://blogs.mantiso.com/blog/kevin/2008/12/02/B64D01983CD260D66CE1935346E056D8 Running the latest version of Rails <p>By this I mean running the latest Gem version not Edge. In config/environment.rb is a line that says something like</p> <pre class="brush: ruby"> RAILS_GEM_VERSION = '2.1.0' unless defined? RAILS_GEM_VERSION </pre> <p>You can either set this to a specific version or if you want to run off the latest installed (Gem) version then simply comment out the line</p> <div class="posttagsblock"><a href="http://technorati.com/tag/Rails" rel="tag">Rails</a></div> http://blogs.mantiso.com/blog/kevin/2008/11/10/B3346581008011A831343A29D045E147 http://blogs.mantiso.com/blog/kevin/2008/11/10/B3346581008011A831343A29D045E147 Rails - Routing <p> It's been a while since my last post, that's a mixture of being at PDC and battling with Rails routing so that I understand it better and so that I can bend it to my will! I've finally got something working to my liking but it's taken a while. </p> <p> Routing is a huge part of Rails and, like most things in Rails, I'm not going to be able to do it full justice in this post. </p> <p>Rails provides a flexible and convenient routing mechanism, which sounds like marketing speak but is true. If the application uses RESTful routes then much of the work is done for it, although only if you want to work exactly the way Rails expects, otherwise you have to understand the routing to get it to fit into your scheme. </p> <p> Routing information is stored in a file called routes.rb which is in the config directory. The route data 'draws' routes by mapping from resources to HTTP verbs/URLs and vice versa. This means that for a given HTTP verb (GET say) and a given URL ("/blog/foo") there is a map to a specific controller/action pair. </p> <p>When a controller is generated from a script an entry is automatically placed in /config/routes.rb. For a 'blogs' controller the entry would look like this: </p> <pre class="brush: ruby"> map.resources :blogs </pre> <p> This entry sets up a bunch of routes for the "blogs" controller in this application. There are several ways to see these routes. The generated BlogsController class will have a set of commented methods that show which URLs will be directed to which methods (shown here but shortened for convenience) </p> <pre name="code" class="brush: ruby"> # GET /blogs # GET /blogs.xml def index # GET /blogs/1 # GET /blogs/1.xml def show # GET /blogs/new # GET /blogs/new.xml def new # GET /blogs/1/edit def edit # POST /blogs # POST /blogs.xml def create # PUT /blogs/1 # PUT /blogs/1.xml def update # DELETE /blogs/1 # DELETE /blogs/1.xml def destroy </pre> <p> However this does not tell the whole story, for example these routes have names and these names can be used in your code to add references to the URLs. </p> <p>Another way to look at the roots available is to get Rails to list them. One way of doing this is to execute the <span style="white-space: pre;font-family:monospace;">rake routes</span> command: </p> <pre name="code" class="brush: ruby"> $ rake routes blogs GET /blogs {:controller=>"blogs", :action=>"index"} formatted_blogs GET /blogs.:format {:controller=>"blogs", :action=>"index"} POST /blogs {:controller=>"blogs", :action=>"create"} POST /blogs.:format {:controller=>"blogs", :action=>"create"} new_blog GET /blogs/new {:controller=>"blogs", :action=>"new"} formatted_new_blog GET /blogs/new.:format {:controller=>"blogs", :action=>"new"} edit_blog GET /blogs/:id/edit {:controller=>"blogs", :action=>"edit"} formatted_edit_blog GET /blogs/:id/edit.:format {:controller=>"blogs", :action=>"edit"} blog GET /blogs/:id {:controller=>"blogs", :action=>"show"} formatted_blog GET /blogs/:id.:format {:controller=>"blogs", :action=>"show"} PUT /blogs/:id {:controller=>"blogs", :action=>"update"} PUT /blogs/:id.:format {:controller=>"blogs", :action=>"update"} DELETE /blogs/:id {:controller=>"blogs", :action=>"destroy"} DELETE /blogs/:id.:format {:controller=>"blogs", :action=>"destroy"} </pre> <p> The format is probably screwed as you look at this but hopefully it's still easy to work out what is going on. This lists the VERB/URL mapping to Controller/action, in this case the routes are only shown for the "blogs" resource, the actual listing is much longer and contains all resources as well as the default routing behaviour. The list is fairly straightforward, it shows the name of the route (if there is one), the HTTP verb, the URL and the controller/action these map to. For example the 'blog' named route says that sending a URL of the form blog/[:id] (e.g. /blogs/1) with the HTTP GET verb results in a call to the blogs controller's show method. In this case the value '1' at the end of the URL will be available as the :id value in the params collection. Notice that not all routes are /controller/action style, but that some simply rely on /controller and the HTTP verb to work out the method to call. </p> <p> The names of the routes are very useful. For example in the above there are routes named 'blogs', 'blog' and 'new_blog' amongst others. These names can be used to display a URL for that route. As an example in views/blogs/index.html.erb there is a line like this: </p> <pre> &lt;%= link_to 'New blog', new_blog_path %> </pre> <p> that says to use the path generated from the new_blog route to get the URL to display. </p> <p> This is all well and good, and nice and easy to use and if you simply want to use the Rails conventions then you are good. However there are going to be occasions when simply using the defaults does not work. Luckily, for those cases the routing infrastructure is extensible. In the case of this blog I wanted to do two things, I wanted to support multiple blog authors, and I wanted blog IDs to be friendlier. In fact both these things are related, although I've only tackled the first issue at the moment, but the second issue is resolvable using a similar mechanism. </p> <p> These issues are to do with the way that Rails identifies