<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>CodePlex Project</title>
        <link>http://geekswithblogs.net/EltonStoneman/category/8168.aspx</link>
        <description>CodePlex Project</description>
        <language>en-GB</language>
        <copyright>EltonStoneman</copyright>
        <managingEditor>elton.stoneman@gmail.com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>The People’s Jukebox</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/09/30/the-peoples-jukebox.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For a forthcoming celebration, I've been working on a jukebox web application: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/093009_1900_ThePeoplesJ1.png" /&gt; 	&lt;/p&gt;
&lt;p&gt;The client controls the music being played on the server, so its intended for local networks where you want shared control of a central music player. If you can find a use for it, help yourself – it's on CodePlex here: &lt;a href="http://thepeoplesjukebox.codeplex.com/"&gt;The People's Jukebox&lt;/a&gt;. If nothing else it's a straightforward example of a Silverlight 2.0 client talking to WCF REST services, in what's probably a familiar domain. &lt;/p&gt;
&lt;p&gt;The user experience is meant to be zero-guidance. You can try it out on a version where the UI functions but doesn't play any music: &lt;a href="http://www.sixeyed.com/ThePeoplesJukebox.html"&gt;The People's Jukebox on sixeyed.com&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;The initial screen shows what's currently playing and has a big button for you to select a track. In the next screen you choose either to search for a specific track, browse through the collection, or have the jukebox randomly choose some options for you. From any of those routes, you select a track, confirm your choice and it gets queued: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/093009_1900_ThePeoplesJ2.png" /&gt; 	&lt;/p&gt;
&lt;p&gt;The queuing is what gives The People's Jukebox its democratic flavour – if you select a track which is already queued, you increment its vote count. When the current track finishes, the jukebox picks the next track with the most votes. When a track is selected the UI forces you to wait for a few seconds before you can continue, to discourage The People from abusing their power and making the same selection over and over again. &lt;/p&gt;
&lt;p&gt;If no one's choosing tracks, the jukebox will randomly pick one which it hasn't already played, so it should keep playing until all the songs are played, or the web server is stopped. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Usage &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Run the MSI and the jukebox Web site and services will be installed with default configuration options, using the installing user's "My Music" as the root folder to look for tracks. It will populate the track catalogue from the file system, expecting to find a conventional root/artist/album/track hierarchy: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;
    &lt;div&gt;My Music &lt;/div&gt;
    &lt;ul&gt;
        &lt;li&gt;
        &lt;div&gt;The Beatles &lt;/div&gt;
        &lt;ul&gt;
            &lt;li&gt;
            &lt;div&gt;Abbey Road &lt;/div&gt;
            &lt;ul&gt;
                &lt;li&gt;01. Come Together &lt;/li&gt;
                &lt;li&gt;etc.  &lt;/li&gt;
            &lt;/ul&gt;
            &lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Open &lt;a href="http://localhost/ThePeoplesJukebox/"&gt;http://localhost/ThePeoplesJukebox/&lt;/a&gt; and hit &lt;em&gt;Start&lt;/em&gt; - the music should start playing and you should be able to navigate around your music collection. The jukebox services log everything they do, by default to &lt;em&gt;C:\TEMP\PeoplesJukeboxService.log&lt;/em&gt;, so if nothing happens that's the place to look for clues.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt; 	&lt;/p&gt;
&lt;p&gt;The jukebox is configurable through Web.config on the services. Options are documented in comments – the installer sets up the root music directory, and the types of music files in the &lt;em&gt;fileSystemConfiguration &lt;/em&gt;element: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;!--&lt;/span&gt;&lt;span style="color: green;"&gt;Specify the root path for music files, and &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;        the types of files to load. Directory can be  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: green;"&gt;        a network path, extensions are comma-separated:&lt;/span&gt;&lt;span style="color: blue;"&gt;--&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;fileSystemCatalogueConfiguration &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;rootDirectory&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;x:\My Music&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;fileExtensions&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;*.wav,*.mp3&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: blue; font-family: Courier New; font-size: 10pt;"&gt;    /&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;rootDirectory&lt;/em&gt; can be local or a UNC path, e.g.  \\nas\music. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Track Lists &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Track lists are what drives the song selection behaviour; this is also configurable. Three types of tracklist are provided. When the jukebox finishes playing a track, it will query the tracklists in priority order until one returns a track, which will be loaded and played next: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;!--&lt;/span&gt;&lt;span style="color: green;"&gt; Tracklists to use, and the order in which they are queried.  &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;         Specify "chosenByText" to display which tracklist chose the  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: green;"&gt;         Now Playing track on the client &lt;/span&gt;&lt;span style="color: blue;"&gt;--&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;trackLists&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;trackList&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;PeoplesJukebox.Core.TrackLists.ConfiguredTrackList, PeoplesJukebox.Core&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;priority&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;1&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;trackList&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;PeoplesJukebox.Core.TrackLists.SelectedTrackList, PeoplesJukebox.Core&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;priority&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;2&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;chosenByText&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;The People&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;trackList&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;PeoplesJukebox.Core.TrackLists.RandomTrackList, PeoplesJukebox.Core&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;priority&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;3&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;trackLists&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; 	&lt;/p&gt;
&lt;p&gt;In default form, the jukebox lets you start off with some specified songs, moving onto the selections of The People, with the jukebox picking a random track if none are queued, so tracklists are queried in the following order: &lt;/p&gt;
&lt;p&gt;&lt;em&gt;1. ConfiguredTrackList&lt;/em&gt; – reads a list of specific track names from configuration, and returns them in priority order. Will not play a track that's already been played. Configuration looks like: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;trackConfiguration&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;tracks&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;track&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;trackName&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Blank Slate&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;position&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;1&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;track&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;trackName&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Love Is Noise&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;position&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;2&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;tracks&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;trackConfiguration&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; 	&lt;/p&gt;
&lt;p&gt;Intended to start the evening off with a known selection, when the configured tracks have been played, the list returns null so the jukebox moves on to the next tracklist. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;2. SelectedTrackList&lt;/em&gt; – hopefully the main provider, queues up track requests as users make a selection. Operates the voting mechanism, so tracks which are selected multiple times move up the queue. If all queued tracks have the same number of votes, they're played in the order they were first selected. Will allow tracks to be played multiple times, but not sequentially – if you choose a track that's already queued, you increase its vote count; if you choose the same track again whilst its playing, or after it has  been played, it gets queued again. Returns null if no tracks are queued. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;3. RandomTrackList&lt;/em&gt; – failsafe list, to ensure music is always playing, picks tracks at random from the catalogue. Will not play a track that's already been played. Allows the administrator to sneak in some favourites by configuring "must-have" tracks. Must-haves will be inserted between random selections, at a configured frequency: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;randomTrackListConfiguration&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;mustHaveTrackFrequency&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;5&lt;/span&gt;"&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;mustHaveTracks&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;track&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;trackName&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Black Eyed Dog&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;position&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;1&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;track&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;trackName&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;The Magic Position&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;position&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;2&lt;/span&gt;"&lt;span style="color: blue;"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;mustHaveTracks&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;  &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;randomTrackListConfiguration&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; 	&lt;/p&gt;
&lt;p&gt;- meaning every fifth track will be picked from the configured list, then the next four will be random. If no must-haves are specified, or they have all been played, the selection will be random. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Technical Details &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Much of the implementation is straightforward. WCF has in-built support for REST, so you can expose a WCF service with a RESTful endpoint like &lt;a href="http://localhost/PeoplesJukebox.Services/CatalogueService.svc/artist/2"&gt;http://localhost/PeoplesJukebox.Services/CatalogueService.svc/artist/2&lt;/a&gt; (to get the list of tracks from artist with ID=2 from the catalogue service), just by flagging the service implementation with the &lt;em&gt;WebGet&lt;/em&gt; attribute: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    [&lt;span style="color: rgb(43, 145, 175);"&gt;WebGet&lt;/span&gt;(UriTemplate = &lt;span style="color: rgb(163, 21, 21);"&gt;"artist/{artistId}"&lt;/span&gt;, ResponseFormat = &lt;span style="color: rgb(43, 145, 175);"&gt;WebMessageFormat&lt;/span&gt;.Xml)] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;public&lt;/span&gt; 			&lt;span style="color: rgb(43, 145, 175);"&gt;Artist&lt;/span&gt; GetArtist(&lt;span style="color: blue;"&gt;string&lt;/span&gt; artistId) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    {...&lt;/span&gt; 	&lt;/p&gt;
&lt;p&gt;Task-driven workflow implementation in Silverlight is also straightforward, by hosting multiple pages on the application, all of which are invisible except the current page. When the current page completes, it hides itself and loads the next page – handled through events in &lt;em&gt;Page.xaml.cs&lt;/em&gt;: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;public&lt;/span&gt; Page() &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    { &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        InitializeComponent(); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: rgb(43, 145, 175);"&gt;PageBase&lt;/span&gt; page &lt;span style="color: blue;"&gt;in&lt;/span&gt; Pages) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        { &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            page.Complete += &lt;span style="color: blue;"&gt;new&lt;/span&gt; 			&lt;span style="color: rgb(43, 145, 175);"&gt;PageBase&lt;/span&gt;.&lt;span style="color: rgb(43, 145, 175);"&gt;OnCompleteEventHandler&lt;/span&gt;(PageComplete); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            page.Cancelled += &lt;span style="color: blue;"&gt;new&lt;/span&gt; 			&lt;span style="color: rgb(43, 145, 175);"&gt;PageBase&lt;/span&gt;.&lt;span style="color: rgb(43, 145, 175);"&gt;OnCancelledEventHandler&lt;/span&gt;(PageCancelled); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;this&lt;/span&gt;.CurrentPage = &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ucStartPage; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    }&lt;/span&gt; 	&lt;/p&gt;
&lt;p&gt;Silverlight 2.0 doesn't work so well with non-GET web requests, which is why all the services are GETs where some should really be POSTs.  &lt;/p&gt;
&lt;p&gt;The only difficult part was playing music files through IIS in a background thread, while continuing to respond to web service and web site requests. If you're really interested in looking into this, you'll see the music playing component is also specified in config: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;!--&lt;/span&gt;&lt;span style="color: green;"&gt; Core configuration - which implementations to use for &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: green;"&gt;         media player and catalogue components &lt;/span&gt;&lt;span style="color: blue;"&gt;--&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;peoplesJukeboxConfiguration &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;mediaPlayer&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;PeoplesJukebox.Core.Players.FMODPlayer, PeoplesJukebox.Core&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;mediaCatalogue&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;PeoplesJukebox.Core.Catalogues.FileSystemCatalogue, PeoplesJukebox.Core&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: blue; font-family: Courier New; font-size: 10pt;"&gt;    &amp;gt;&lt;/span&gt; 	&lt;/p&gt;
&lt;p&gt;There are several (failed) implementations in the source which are not built in the solution (under ..\PeoplesJukebox\PeoplesJukebox.Core\Players). Of the five attempts, all of them had showstopper issues except the excellent &lt;a href="http://www.fmod.org/"&gt;FMOD&lt;/a&gt; library: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;em&gt;DirectX&lt;/em&gt; – using the Audio class from the managed wrapper in the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b66e14b8-8505-4b17-bf80-edb2df5abad4"&gt;DirectX SDK&lt;/a&gt;. Redistributable install is massive, which  is offputting, but more importantly the &lt;em&gt;Audio.Ending&lt;/em&gt; event didn't fire reliably, so playback would intermittently stop and never resume; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Windows Media Player&lt;/em&gt; – using the managed WMPLib wrapper in the &lt;a href="http://download.microsoft.com/download/A/7/E/A7E58606-58A3-429B-AFC0-50159DB5BC13/WMPlayer10SDK.exe"&gt;Windows Media Player SDK&lt;/a&gt;, to devolve playing responsibility to Media Player. Didn't like the extra dependency, or the alarming memory profile. Worse, the player would randomly change state to &lt;em&gt;Stopping&lt;/em&gt; in the middle of playback and not resume; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Sound&lt;/em&gt; – using .NET's native sound player in System.Media. Fine for playing WAVs, at the cost of having to manage your own threads. Main issue that WAVs are not normalized so tracks will be played at their native volume, which is likely to mean volume changes between songs. Unable to play other media types; &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.alvas.net/alvas.audio.aspx"&gt;&lt;em&gt;Alvas Audio&lt;/em&gt;&lt;/a&gt; – looked good, but highly unfriendly API. Couldn't get the thing to play at all; &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.fmod.org/"&gt;&lt;em&gt;FMOD&lt;/em&gt;&lt;/a&gt; – highly-featured C++ audio processor which does its own thread management, copes with various media types, plays reliably for extended periods and has an efficient memory model. The library is free for non-commercial use, so The People's Jukebox has the same restriction. The library is complex, but I've used it through &lt;a href="http://sourceforge.net/projects/fmodnet/"&gt;FMOD.NET&lt;/a&gt; – Rafael Nicoletti's very nice C# wrapper. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;em&gt;mediaCatalogue&lt;/em&gt; element lets you choose how the catalogue is built. Currently, only a file system catalogue is provided, but extending it (e.g. to use &lt;a href="http://www.logitechsqueezebox.com/support/download-squeezebox-server.html"&gt;SqueezeCenter – now SqueezeBox Server&lt;/a&gt;), is an option. &lt;/p&gt;
&lt;p&gt;If you download the jukebox and find any issues using it, let me know through a comment or a CodePlex bug. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=135193"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=135193" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/135193.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/09/30/the-peoples-jukebox.aspx</guid>
            <pubDate>Wed, 30 Sep 2009 19:00:38 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/135193.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/09/30/the-peoples-jukebox.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/135193.aspx</wfw:commentRss>
        </item>
        <item>
            <title>BizTalk Cache Adapter Samples</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter-samples.aspx</link>
            <description>&lt;p style="TEXT-ALIGN: center"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The sample BizTalk application provided with the &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter.aspx"&gt;BizTalk Cache Adapter&lt;/a&gt; on &lt;a href="http://biztalkcacheadapter.codeplex.com/"&gt;CodePlex&lt;/a&gt; illustrates three approaches for using the cache: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Simple Messaging – routes all messages configured for caching to the cache adapter, and sends cache-misses on to the service provider; &lt;/li&gt;
    &lt;li&gt;Orchestration – explicitly routes messages to either the cache adapter or service provider in orchestration logic; &lt;/li&gt;
    &lt;li&gt;Complex Messaging – routes messages configured for caching either to the cache adapter or to the service provider. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the samples use FILE locations for the originating request and ultimate response. The expected locations will be created in the install, with sample request files in the receive locations. Enable the relevant receive location to run the sample, then copy the request file to the receive location again to re-run it – from the second run onwards, the responses should be the cached versions. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Installation&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;To use the samples, you'll need to install and configure a cache provider, the cache adapter, cache adapter sample, sample service, and the cache viewer (if you want to see the contents of the cache). &lt;/p&gt;
&lt;p&gt;Both the Cache Adapter and Sample BizTalk MSIs use PowerShell scripts for their post-processing steps. If you want to install from the MSIs, you'll need to have PowerShell installed and set up to enable script execution (&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;Set-ExecutionPolicy RemoteSigned&lt;/span&gt; is fine). &lt;/p&gt;
&lt;p&gt;1. Cache Provider. &lt;/p&gt;
&lt;p&gt;Download and install &lt;a href="http://www.alachisoft.com/ncache/ncache_express.html"&gt;NCache Express&lt;/a&gt; (this is a free edition, you'll have a product key emailed to you), and configure a cache instance for the samples by modifying the configuration file (config.ncconf – by default in C:\Program Files\NCache Express\config): &lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cache-config&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;name&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;Sixeyed.CacheAdapter.NCacheExpressProvider.Tests&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;inproc&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cleanup&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;interval&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;1sec&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;log&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;trace-errors&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;trace-debug&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;enabled&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;storage&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;cache-size&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;5mb&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;eviction-policy&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;default-priority&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;normal&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;eviction-ratio&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;10%&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;eviction-enabled&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;perf-counters&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;enabled&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cache-config&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;
&lt;p&gt;This creates a single-node cache on the local machine, limited to 5Mb of system memory. Start the cache by running the startcache tool (C:\Program Files\NCache Express\bin\tools): &lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;startcache Sixeyed.CacheAdapter.NCacheExpressProvider.Tests &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;- and verify it's there with listcaches. You should see the cache listed as Running: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach1.png" /&gt; &lt;/p&gt;
&lt;p&gt;2. Cache Adapter. &lt;/p&gt;
&lt;p&gt;Sixeyed.CacheAdapter.msi is the BizTalk MSI which installs the adapter and artifacts. Import the application into BizTalk and run the installer. Verify the Sixeyed.CacheAdapter application is listed, and add the adapter in the Administration Console through &lt;em&gt;Platform Settings...Adapters...New&lt;/em&gt;. &lt;/p&gt;
&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;em&gt;Note: the installer adds the necessary adapter files to the GAC and sets up the registry keys. If you don't use the MSI, manual installation steps are: add the files from the Binaries release to a local directory and to the GAC; modify run the .REG command to specify assembly paths and import the .REG file; add the BizTalk artifact resources to your own application. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;2. Cache Adapter Sample. &lt;/p&gt;
&lt;p&gt;Sixeyed.CacheAdapterSample.msi is the BizTalk MSI which installs the sample application and artifacts, and configures the ports. Import the application into BizTalk and run the installer. Verify the Sixeyed.CacheAdapterSample application is listed, and that the message types are configured in SSO (check the contents of SSO application &lt;strong&gt;Sixeyed.CacheAdapter&lt;/strong&gt;). &lt;/p&gt;
&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;em&gt;Note: the installer creates FILE send and receive locations, copies sample messages, and sets up SSO configuration for the cached message types. If you don't use the MSI, manual installation should follow the steps in: Source\Sixeyed.CacheAdapterSample\Deployment\Sixeyed.CacheAdapterSample.Install.ps1. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;4. Sample Service. &lt;/p&gt;
&lt;p&gt;Sixeyed.CacheAdapterSample.Service.msi installs a WCF service for the samples to call. Verify the service has deployed correctly by navigating to &lt;a href="http://localhost/Sixeyed.CacheAdapterSample/SampleService.svc?wsdl"&gt;http://localhost/Sixeyed.CacheAdapterSample/SampleService.svc?wsdl&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;5. Cache Viewer. &lt;/p&gt;
&lt;p&gt;Sixeyed.CacheAdapter.CacheViewer.msi installs a Winforms app for viewing cache contents. Run the application and configure it to use the running cache instance, by navigating to the NCacheExpressProvider assembly and selecting the NCacheExpressProvider: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach2.png" /&gt; &lt;/p&gt;
&lt;p&gt;- and specifying the ID of the cache instance: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach3.png" /&gt; &lt;/p&gt;
&lt;p&gt;(This is the same management UI used for configuring cache adapter ports in the BizTalk Administration Console. For the samples the Cache Id is &lt;strong&gt;Sixeyed.CacheAdapter.NCacheExpressProvider.Tests&lt;/strong&gt;). &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Simple Messaging&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;Enable the receive location &lt;strong&gt;ReceiveRequest_SimpleMessaging.FILE&lt;/strong&gt; and you should see the following workflow: &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Message is picked up by the receive location, which is using the CacheXMLReceive pipeline. This checks the cache configuration in SSO, where the message type is configured for caching, so context property &lt;em&gt;IsMessageCacheEnabled&lt;/em&gt; is set to true; &lt;/li&gt;
    &lt;li&gt;Send port SimpleMessaging_GetCache picks up the message and sends it to the cache adapter, using the request message to build a cache key, and checking for a response existing in the cache. There is no cached response, so the message returned from the cache adapter is the original request message, with context property &lt;em&gt;IsCached&lt;/em&gt; set to false; &lt;/li&gt;
    &lt;li&gt;Send port SimpleMessaging_SendServiceRequest picks up the message and sends it to the service; &lt;/li&gt;
    &lt;li&gt;Send port SimpleMessaging_PutCache picks up the service response and adds it to the cache, using the cache key from the original request; &lt;/li&gt;
    &lt;li&gt;Send port SimpleMessaging_SendServiceResponse picks up the service response and copies it to the output directory. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Check the cache viewer and you will see a byte array cached with a GUID key: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach4.png" /&gt; &lt;/p&gt;
&lt;p&gt;The GUID is the hash of the request message, and the byte array is the response message. Subsequent drops of the same request into the Requests folder will find the cached response at step 2, and the response will be the cached message. &lt;/p&gt;
&lt;p&gt;This workflow is suitable for any simple messaging solution, where static ports are used and where the original request and ultimate response can be auctioned by different ports. Configuration of the cache instance is contained in the send ports. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Orchestration &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The orchestration sample follows the same workflow as the Simple Messaging sample, and uses the same CacheXMLReceive pipeline to add the caching properties to the incoming message. The orchestration sample makes the cache access with explicit send and receives, and configuration of the cache instance is still contained in the send ports. &lt;/p&gt;
&lt;p&gt;Enable the receive location ReceiveRequest_Orchestration.FILE to run the sample. This is suitable for solutions where finer grained control is needed over the caching mechanism, and an orchestration is a viable option. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Complex Messaging &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Both the simple implementations use the cache adapter as a passthrough when there is no matching response in the cache – the incoming message is returned by the cache adapter, and a send port picks it up and routes it on the service. This is not suitable for more complex solutions: &lt;/p&gt;
&lt;ul style="MARGIN-LEFT: 37pt"&gt;
    &lt;li&gt;where the service is invoked through a dynamic port, as the outbound transport and location set on the original message are not reset by the cache adapter on the passed-through message; &lt;/li&gt;
    &lt;li&gt;where the originating receive is from a request-response port, as the interchange will accept the passed-through message as a response, and not return the actual service request. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For these scenarios, the cache checking can be moved forward into the originating receive, so the cache adapter is only called if the response is known to exist in the cache. Added complexity here is that the receive pipeline needs to have the cache instance configuration, along with the send ports. This is shown in the Complex Messaging sample – run by enabling the receive location ReceiveRequest_ComplexMessaging.FILE: &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;
    &lt;div&gt;Message is picked up by the receive location, which is using a custom pipeline – CheckCacheReceive. This consists of the SetMessageCacheProperties component which checks SSO to see if the message type is configured for caching, followed by the CheckIsCached component which checks is the message response is actually in the cache, and sets the &lt;em&gt;IsCached&lt;/em&gt; property: &lt;/div&gt;
    &lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach5.png" /&gt; &lt;/p&gt;
    &lt;p style="MARGIN-LEFT: 18pt"&gt;Note that the cache instance is configured in the pipeline. Using a custom pipeline means you can configure the instance using the Cache Adapter UI in Visual Studio, which is easier and applies validation. While you could use a generic pipeline and modify the configuration per-instance on receive locations, that means manually hacking the XML; &lt;/p&gt;
    &lt;ol&gt;
        &lt;li&gt;If the message response is cached, send port ComplexMessaging_GetCache picks up the message and sends it to the cache adapter. The adapter is configured in the same way as other samples, and uses the same logic – but in this case the response is known to be cached, so it will be returned and the request message should never be passed-through; &lt;/li&gt;
        &lt;li&gt;If the message response is not cached, send port ComplexMessaging_SendServiceRequest calls the service provider passing the original request message; &lt;/li&gt;
        &lt;li&gt;Send port ComplexMessaging_PutCache picks up the service response and adds it to the cache, using the cache key from the original request; &lt;/li&gt;
        &lt;li&gt;Send port ComplexMessaging _SendServiceResponse picks up the service response and copies it to the output directory. &lt;/li&gt;
    &lt;/ol&gt;
    &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is a risk in this scenario that the object will exist in cache at the point of checking, but been removed by the time the cache is actually read. In this case the response from step 2 will be a passthrough of the original request – in the sample, this means the originating request will be copied to the output directory. Suspending the message may be a better option, but depending on the solution you may be able to cope with this differently. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132543"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132543" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/132543.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter-samples.aspx</guid>
            <pubDate>Tue, 02 Jun 2009 03:11:26 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/132543.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter-samples.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/132543.aspx</wfw:commentRss>
        </item>
        <item>
            <title>BizTalk Cache Adapter</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter.aspx</link>
            <description>&lt;p style="TEXT-ALIGN: center"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In a recent project we had a requirement for a configurable cache, residing on a BizTalk host and storing responses from WCF services which the BizTalk app had brokered. Producing this as a generic cache adapter was the preferred option, but project timescales didn't allow for it – instead I've written the adapter as an open source component which is available on CodePlex: &lt;a href="http://biztalkcacheadapter.codeplex.com/"&gt;BizTalkCacheAdapter&lt;/a&gt;, and which we're now making use of in the project. &lt;/p&gt;
&lt;p&gt;It's a simple design suitable for any situation where BizTalk is brokering services to consumers. The incoming request from the consumer is hashed to generate a cache key, and the response is stored in the cache against the request key. When future requests exactly match, they will receive the cached response; if the response doesn't exist in the cache, the service provider is invoked and the response is added to the cache. The adapter is independent of the cache store being used – currently the only option provided is &lt;a href="http://www.alachisoft.com/ncache/ncache_express.html"&gt;NCache Express&lt;/a&gt;, but extending it to use &lt;a href="http://www.danga.com/memcached/"&gt;memcached&lt;/a&gt; or &lt;a href="http://msdn.microsoft.com/en-us/data/cc655792.aspx"&gt;Velocity&lt;/a&gt; will be straightforward. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Overview &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The adapter uses context properties to store cache configuration, so it's suitable for orchestration or messaging solutions. Alongside the adapter on CodePlex is a sample project which demonstrates the approaches. The workflow is the same in both cases: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2108_BizTalkCach1.png" /&gt; &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;The consumer sends a service request via the CacheXMLReceive pipeline, which checks if the message type is configured for caching, and promotes the &lt;em&gt;IsMessageCacheEnabled&lt;/em&gt; property; &lt;/li&gt;
    &lt;li&gt;If caching is enabled, a two-way message is sent to the cache adapter. This is a GET request, so the adapter checks the cache using the &lt;em&gt;MessageCacheKey&lt;/em&gt; context property – if the context property is not available, the adapter writes it by hashing the contents of the service request in the message body; &lt;/li&gt;
    &lt;li&gt;The response from the cache adapter promotes the &lt;em&gt;IsCached&lt;/em&gt; property, which identifies whether the response is in cache – if so, the body of the response message will be the cached service response, if not the body is the original service request which can be passed on to the service; &lt;/li&gt;
    &lt;li&gt;If &lt;em&gt;IsCached&lt;/em&gt; is false, the service is invoked and a one-way message containing the response is sent to the cache adapter. This is a PUT request, so the adapter adds the message body to the cache using the &lt;em&gt;MessageCacheKey&lt;/em&gt;; &lt;/li&gt;
    &lt;li&gt;The service response (either cached or from the provider) is returned to the consumer. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the messaging solution, the same workflow is carried out using subscriptions to the promoted cache configuration properties, and the various send ports. This workflow may not be suitable for more complex messaging solutions, where services are invoked through dynamic send ports – there is an alternative workflow which I'll cover in a &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter-samples.aspx"&gt;separate post.&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The only real complexity in the adapter is in putting the service response into the cache – the outgoing service request message has the cache configuration properties promoted, but the incoming response does not. In orchestration solutions this isn't a problem, as the cache properties can be stored as state in the orchestration instance. In messaging solutions, the cache properties are retained by temporarily adding them to the cache, keyed by the interchange ID of the service instance, and removing them when the response is added to the cache. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Configuration &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The cache adapter can be used with messages of any type, but with XML messages it can employ different cache configurations for different message types - e.g. a service to get current tax rates may configured to live for several days in the cache, while a service to get current exchange rates may use the same cache store, but be configured to expire after an hour. The &lt;strong&gt;CacheReceive&lt;/strong&gt; and &lt;strong&gt;CacheReceiveXml&lt;/strong&gt; pipelines contain properties for configuring the cache – it can be enabled/disabled for all messages, or (for the XML pipeline) only for configured message types: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2108_BizTalkCach2.png" /&gt; &lt;/p&gt;
&lt;p&gt;Message-level configuration uses an SSO application store, which holds a &lt;strong&gt;MessageCacheConfigurationCollection&lt;/strong&gt; object in XML: &lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfigurationCollection&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;xmlns&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;http://schemas.sixeyed.com/CacheAdapter/2009&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfigurations&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfiguration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;http://schemas.sixeyed.com/CacheAdapterSample/2009#GetServerDateTime&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfiguration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfiguration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;http://schemas.xyz.com/2009#GetXYZ&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cacheLifespan&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;PT10M&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cacheLifespan&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfiguration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;... &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Caching is enabled for a message if: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;
    &lt;div&gt;&lt;em&gt;IsCacheEnabled&lt;/em&gt; is true on the pipeline AND&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt; &lt;/span&gt;&lt;/div&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;em&gt;IsMessageTypeConfigurationEnabled&lt;/em&gt; is false on the pipeline OR&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt; &lt;/span&gt;&lt;/li&gt;
        &lt;li&gt;
        &lt;div&gt;&lt;em&gt;IsMessageTypeConfigurationEnabled&lt;/em&gt; is true on the pipeline AND&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt; &lt;/span&gt;&lt;/div&gt;
        &lt;ul&gt;
            &lt;li&gt;the incoming message type has an entry in the &lt;strong&gt;MessageCacheConfigurationCollection&lt;/strong&gt; in SSO.&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt; &lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The lifespan of the object put into cache will be either the &lt;em&gt;cacheLifespan&lt;/em&gt; specified in the &lt;strong&gt;MessageCacheConfiguration&lt;/strong&gt; in SSO, or the &lt;em&gt;defaultLifespan&lt;/em&gt; specified in the cache send port: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2108_BizTalkCach3.png" /&gt; &lt;/p&gt;
&lt;p&gt;(The point at which the object is removed from cache will depend on the provider, some will remove it when its lifespan expires, others only when its lifespan expires and the cache is full or the cleanup schedule runs). &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Installation &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For version 1.0.0.0, the CodePlex project comes with three project releases, which can be used independently or together: &lt;/p&gt;
&lt;ul style="MARGIN-LEFT: 38pt"&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapter.msi&lt;/strong&gt; - a BizTalk application MSI which can be imported and installed to your BizTalk server(s). The application contains the configuration schema and pipelines, so it can be used as-is, or the relevant artifacts can be moved to your own application; &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapter.Binaries.zip&lt;/strong&gt; – a ZIP file of the adapter binaries you can deploy manually. Use instead of the CacheAdapter MSI, if you don't want to deploy the whole BizTalk application; &lt;/li&gt;
    &lt;li&gt;
    &lt;div&gt;&lt;strong&gt;Sixeyed.CacheAdapter.CacheViewer.msi&lt;/strong&gt; – a Windows forms application which lets you view the contents of a cache store (the app uses the configuration components from the adapter management assembly, so it is also cache-provider agnostic):  &lt;/div&gt;
    &lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2108_BizTalkCach4.png" /&gt; &lt;/p&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;- a documentation release: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapter.chm&lt;/strong&gt; – documents the .NET assemblies of the adapter &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;- and two sample releases which should be deployed together: &lt;/p&gt;
&lt;ul style="MARGIN-LEFT: 38pt"&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapterSample.msi&lt;/strong&gt; – a BizTalk application MSI which has sample usage of the cache adapter, demonstrating orchestration and messaging approaches; &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapterSample.Service.msi&lt;/strong&gt; – a WCF MSI which provides a service which the BizTalk app can cache. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pre-requisite for the initial release is the non-commercial &lt;a href="http://www.alachisoft.com/ncache/ncache_express.html"&gt;NCache Express&lt;/a&gt; to use as the cache provider. &lt;/p&gt;
&lt;p&gt;To add the sample message-level cache configuration to SSO, the &lt;a href="http://ssoconfigtool.codeplex.com/"&gt;SSO Config Tool&lt;/a&gt; can import the provided .ssoconfig file into SSO. &lt;/p&gt;
&lt;p&gt;I'll update the project to add a memcached provider, and write an updated post when it's available - and the same when Velocity is released. One advantage in having multiple providers would be in evaluating their performance against your expected caching load, so I'll look at extending the sample solution and adding some &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c8af583f-7044-48db-b7b9-969072df1689&amp;amp;DisplayLang=en"&gt;LoadGen&lt;/a&gt; scripts. &lt;/p&gt;
&lt;p&gt;And as &lt;a href="http://geekswithblogs.net/michaelstephenson/Default.aspx"&gt;Michael Stephenson&lt;/a&gt; commented, a nice alternative would be to move the caching up to the WCF layer as a behavior, so WCF requests would check the cache first. Two options for this – it can either be a client behaviour using a local cache store (which could be more performant and would have less impact on server resources, but requires the cache provider to be deployed client-side), or as an operation behaviour using a shared server-side cache (which could be more performant, depending on the type of messages being cached, would impact on server and network resource, but would make the caching transparent to consumers). The complexity is on caching the response message if not already cached – the cache key from the original message will have been lost, so there needs to be a different approach for maintaining state to correlate the WCF service request and response. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132542"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132542" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/132542.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter.aspx</guid>
            <pubDate>Tue, 02 Jun 2009 03:08:31 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/132542.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/132542.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Visualizing SOA’s Return on Investment</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/03/26/visualizing-soas-return-on-investment.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is the rather grand title of a WebCast I've recorded recently which tries to illustrate where the return on investment comes after moving to a SOA strategy. The video is on Digital Forum:  &lt;a href="http://www.digitalforumtv.com/#/Community/852"&gt;Visualizing SOA ROI&lt;/a&gt; , and the Open Source proof of concept it references is on CodePlex: &lt;a href="http://www.codeplex.com/ESBSimpleSamples"&gt;ESBSimpleSamples&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;In the WebCast I start with a blank Visual Studio solution and create a new Web app which consumes an existing service. All in it takes 3 lines of code and around 3 minutes of development (most of it spent correcting typos), and it doesn't require me to have any understanding of the underlying SOA infrastructure – in this case, Microsoft's ESB Guidance package sitting on BizTalk Server 2006 R2. Equally important, assuming the service we consume is in production, the testing and deployment effort needed for the new project is minimal. &lt;/p&gt;
&lt;p&gt;This is a rework of a presentation I did with a client where I wanted to show how quick and easy it is to use their SOA implementation. I had reservations of showing a code demonstration to an audience which included IT heads (IT Director and Solution Architects) and project management, but it was surprisingly well received, so I've reproduced it using services and components which are publicly available. &lt;/p&gt;
&lt;p&gt;Direct links to the references in the WebCast are here: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;ESB Guidance: &lt;a href="http://www.codeplex.com/esb"&gt;http://www.codeplex.com/esb&lt;/a&gt; 		&lt;/li&gt;
    &lt;li&gt;UK SOA/BPM User Group presentation: &lt;a href="http://sbug.org.uk/media/p/129.aspx"&gt;http://sbug.org.uk/media/p/129.aspx&lt;/a&gt; 		&lt;/li&gt;
    &lt;li&gt;Blog posts on ESB Guidance: &lt;a href="http://geekswithblogs.net/EltonStoneman/category/7947.aspx"&gt;http://geekswithblogs.net/EltonStoneman/category/7947.aspx&lt;/a&gt; 		&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=130437"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=130437" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/130437.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/03/26/visualizing-soas-return-on-investment.aspx</guid>
            <pubDate>Thu, 26 Mar 2009 18:36:18 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/130437.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/03/26/visualizing-soas-return-on-investment.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/130437.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Sixeyed.Guidance.CodeGeneration: Technical Walkthrough</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/03/09/sixeyed.guidance.codegeneration-technical-walkthrough.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2009/03/07/code-generation-guidance-package.aspx"&gt;Code Generation Guidance Package&lt;/a&gt; on &lt;a href="http://www.codeplex.com/GAXCodeGeneration"&gt;CodePlex&lt;/a&gt; was designed to be extensible and reusable. There are three main C# projects, which isolate logic for code generation, and the UI and GAX components.  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sixeyed.CodeGeneration&lt;/em&gt; 	&lt;/p&gt;
&lt;p&gt;This is the core project, defining how metadata is represented and retrieved, and defining configuration for code generation runs. Metadata is defined in terms of: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;A metadata source, which contains the logic for connecting to the source &lt;/li&gt;
    &lt;li&gt;A metadata provider, which uses the source to provide a list of available items, and to populate requested items &lt;/li&gt;
    &lt;li&gt;Metadata items, which are a representation of the metadata, typically using an appropriate .NET framework class &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Code generation and UI logic always works on the interfaces which define these components, and the relationships between them: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030909_1806_SixeyedGuid1.png" /&gt; 	&lt;/p&gt;
&lt;p&gt;In the &lt;em&gt;Add Generated Items&lt;/em&gt; recipe, the available source types, sources and providers are populated from the collection of &lt;strong&gt;IMetadataSource&lt;/strong&gt; objects held in the static &lt;strong&gt;SourceContainer&lt;/strong&gt; class (additional sources can be added to the container at runtime using the &lt;em&gt;SourceAssemblyConfiguration&lt;/em&gt; recipe argument – described in &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2009/03/08/sixeyed.guidance.codegeneration-sample-package.aspx"&gt;Sixeyed.Guidance.CodeGeneration Sample Package&lt;/a&gt;). When a provider is selected, &lt;em&gt;GetItemNames&lt;/em&gt; is called to populate the list of available metadata items. When the selected items are iterated over in a code generation run, &lt;em&gt;GetItem&lt;/em&gt; is called and the populated &lt;strong&gt;IMetadataItem&lt;/strong&gt; is loaded as a property for the T4 template. The metadata item exposes the provider, and the provider exposes the source so the template can connect directly to the metadata if it needs to. &lt;/p&gt;
&lt;p&gt;Each metadata interface has an abstract base class which implements it and contains core logic. For a given source, there may be an additional base class which abstracts logic common to that type of source. In &lt;strong&gt;Sixeyed.CodeGeneration.Metadata.Database.Source&lt;/strong&gt;, &lt;strong&gt;DatabaseSource&lt;/strong&gt; contains logic for accessing ADO.NET data sources in terms of &lt;strong&gt;IDbConnection&lt;/strong&gt; and &lt;strong&gt;IDbCommand&lt;/strong&gt; objects; &lt;strong&gt;SqlServerSource&lt;/strong&gt; contains overriding logic to specify &lt;strong&gt;SqlConnection&lt;/strong&gt; and &lt;strong&gt;SqlCommand&lt;/strong&gt; usage – any additional database sources would do the same. Similarly for the SOAP metadata source, the logic for accessing WSDL is abstracted into a base class which may be used by other sources (e.g. a WCF specific source): &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030909_1806_SixeyedGuid2.png" /&gt; 	&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IMetadataProvider&lt;/strong&gt; contains logic for accessing the source and retrieving a list of available items, and for populating a named item. The majority of logic is in the generic base class, so provider classes are quite simple. Simpler still are metadata item classes, which inherit the generic &lt;strong&gt;ItemBase&lt;/strong&gt; class, specifying the underlying type of the item (&lt;strong&gt;XmlSchema&lt;/strong&gt; in this case), without requiring any additional code. &lt;/p&gt;
&lt;p&gt;Logic for populating template properties and executing T4 templates is located in the Guidance project rather than the code generation project, as it is dependent on the specific T4 engine being used.  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sixeyed.CodeGeneration.UI&lt;/em&gt; 	&lt;/p&gt;
&lt;p&gt;The UI project contains generic user controls which represent metadata selections, and expose various events to notify of selection changes. The Guidance package Wizard uses these components rather than defining its own UI – the controls from this assembly allow code generation to be configured and invoked from a different UI host. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sixeyed.Guidance.CodeGeneration &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This project defines the GAX package and links together the code generation and UI components. The Guidance package is quite straightforward – it contains a single class &lt;strong&gt;AddGeneratedItems&lt;/strong&gt; for the action of generating items from metadata and adding them to the selected project. The action expects &lt;em&gt;SourceConfiguration&lt;/em&gt;, &lt;em&gt;SelectedItems&lt;/em&gt; and &lt;em&gt;TemplateConfiguration&lt;/em&gt; arguments; it connects to the source, iterates over the selected items and executes the template for each item. &lt;/p&gt;
&lt;p&gt;To collect the argument values, there are custom wizard pages and value providers for each, allowing a recipe to provide ready-configured settings, or build a UI to gather them from the user: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.Guidance.CodeGeneration.CustomWizardPages&lt;/strong&gt;. The custom Wizard pages use the static &lt;strong&gt;Metadata &lt;/strong&gt;class to share state for the configured metadata source and provider. They override &lt;em&gt;IsDataValid&lt;/em&gt; to determine if the page has collected enough information for the Wizard to proceed and the base class provides &lt;em&gt;EnableNextStep&lt;/em&gt; which will advance the Wizard by enabling the Next or Finish button as appropriate. The base class will read the &lt;em&gt;SourceAssemblyConfiguration&lt;/em&gt; recipe argument if provided, and use it to add any extra metadata assemblies at runtime. &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.Guidance.CodeGeneration.ValueProviders&lt;/strong&gt;. The value provider classes are straightforward, reading optional arguments from the recipe and populating the relevant metadata settings. Custom recipes can specify value providers to load settings instead of Wizard pages, so the Wizard UI can be restricted. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;TODOs &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There are a couple of minor changes I'd like to make to the current codebase: &lt;/p&gt;
&lt;ul style="margin-left: 38pt;"&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.Guidance.CodeGeneration.CustomWizardPages.SelectTemplate &lt;/strong&gt;defines its own UI, which should be moved to a user control in the UI project; &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CodeGeneration.Generation.MemberName&lt;/strong&gt; contains methods for providing valid field and property names, but the Pascal and camel-case conversion is very basic; &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CodeGeneration.UI.SourceUri&lt;/strong&gt; has some ugly hard-coding to decide which UI dialog it should show for different types of URI. It should be configurable, but I'm not happy moving it to an attribute of &lt;strong&gt;IMetadataSource&lt;/strong&gt;, as that brings the UI into the core project.  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And some additional metadata sources which I'll add at a future point – a Clipboard source providing access to clipboard data through text or XML providers, and a BizTalk source which will use the ExplorerOM for providers supplying application, group and instance information as metadata. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129942"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129942" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/129942.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/03/09/sixeyed.guidance.codegeneration-technical-walkthrough.aspx</guid>
            <pubDate>Mon, 09 Mar 2009 23:05:28 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/129942.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/03/09/sixeyed.guidance.codegeneration-technical-walkthrough.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/129942.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Sixeyed.Guidance.CodeGeneration Sample Package</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/03/08/sixeyed.guidance.codegeneration-sample-package.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The basic &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2009/03/07/code-generation-guidance-package.aspx"&gt;Code Generation Guidance Package&lt;/a&gt; on &lt;a href="http://www.codeplex.com/GAXCodeGeneration"&gt;CodePlex&lt;/a&gt; comes with an additional sample Guidance package. This sample is intended to demonstrate how the functionality of the base package can be customised to create a project-specific Guidance package, where you can easily add tailored code generation recipes to your package. In the basic package are the Wizard steps necessary to configure ad-hoc code generation, but there are also ValueProviders which can read configuration from recipes without requiring the whole user interface. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Installation &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You'll need to modify the hard-coded paths and URIs in the sample package, so it doesn't come with an installed release. If you open the &lt;strong&gt;Sixeyed.Guidance.CodeGenerationSample&lt;/strong&gt; solution you'll see that it references the base &lt;strong&gt;Sixeyed.Guidance.CodeGeneration&lt;/strong&gt; and &lt;strong&gt;Sixeyed.CodeGeneration&lt;/strong&gt; assemblies. The sample contains a set of T4 templates in the &lt;em&gt;\Templates\Text&lt;/em&gt; directory, the XML configuration for the package and the XML includes for individual recipes. There's no additional code in the sample project, all the required functionality is in the referenced base package. &lt;/p&gt;
&lt;p&gt;Together with the GAX project, there's a database project which you can use to create a SQL Server database suitable for the data-bound recipes to run against. To install, run the &lt;em&gt;CreateDatabase&lt;/em&gt; script and then execute the SSIS package to populate data from the included Excel workbook (this is only necessary if you want to run the recipes as-is, otherwise you can modify the XML to use your own database). &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sample T4 Templates&lt;/em&gt; 	&lt;/p&gt;
&lt;p&gt;There are T4 templates for each of the metadata providers in the base package. The scripts named &lt;em&gt;_Simple.tt&lt;/em&gt; are straightforward and begin with the name of the expected provider; to run them, you can use &lt;em&gt;Add Generated Items&lt;/em&gt; from the base package, select the relevant metadata and point to the template. To demonstrate more useful code generation, there are two more substantial templates: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;em&gt;ConfigurationSection.cs.tt&lt;/em&gt; – use the File source and the Text provider on this template. If you select &lt;em&gt;Configuration.txt&lt;/em&gt; (from the database project) as the source, the recipe will generate a typed configuration class, which has a static property to access the current config settings. The template can be easily extended to add a Default value for optional settings, and the same text file can be used to drive a different T4 template to generate the actual configuration settings; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;StoredProcedure.cs.tt&lt;/em&gt; – use the SQL Server database source and the Stored Procedure provider. Select a procedure and the recipe will generate a DAL class to execute the stored procedure. This class won't compile, as it inherits from a base class which isn't provided, but it demonstrates one approach for DAL generation. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Sample Recipes&lt;/em&gt; 	&lt;/p&gt;
&lt;p&gt;The included recipes demonstrate configuring one or more settings for code generation so that the Wizard can be tailored or avoided altogether. &lt;em&gt;Generate Stored Procedure&lt;/em&gt; shows this best, configuring the metadata provider using the &lt;strong&gt;SourceConfigurationValueProvider&lt;/strong&gt;: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;Argument&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;SourceConfiguration&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Sixeyed.CodeGeneration.Metadata.SourceConfiguration, Sixeyed.CodeGeneration&lt;/span&gt;"&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ValueProvider&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;SourceConfigurationValueProvider&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;SourceTypeName&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Database&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;SourceName&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;SqlServer Database&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;SourceUri&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Data Source=x\y;Integrated Security=True;Initial Catalog=Scratchpad;&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;ProviderName&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Stored Procedure Provider&lt;/span&gt;"&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ValueProvider&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;Argument&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;These settings are the equivalent of the first Wizard page, selecting the metadata source. It specifies the source type and source name, the URI for the source (in this case, the Scratchpad database included with the sample), and the metadata provider name. Having the &lt;em&gt;SourceConfiguration&lt;/em&gt; argument pre-populated means the first Wizard page will be skipped. The recipe also specifies the T4 template to use with the &lt;strong&gt;TemplateConfigurationValueProvider&lt;/strong&gt;: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;Argument&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;TemplateConfiguration&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Sixeyed.CodeGeneration.Generation.TemplateConfiguration, Sixeyed.CodeGeneration&lt;/span&gt;"&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ValueProvider&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;TemplateConfigurationValueProvider&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 108pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: red;"&gt;   TemplatePath&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;x:\y\z\Templates\Text\StoredProcedure.cs.tt&lt;/span&gt;"&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ValueProvider&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;Argument&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; 	&lt;/p&gt;
&lt;p&gt;Only the template path is specified here, but other settings (target namespace, class name etc.) can also be provided. Having the &lt;em&gt;TemplateConfiguration&lt;/em&gt; argument populated means the third Wizard page will not be shown. Running this recipe gives you a Wizard form which only contains the second page, for selecting metadata items, pre-populated with the list which has already been loaded from the configured database: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030809_1747_SixeyedGuid1.png" /&gt; 	&lt;/p&gt;
&lt;p&gt;- note that the other pages are not available, so the user is constrained to using the configured source and T4 template. &lt;/p&gt;
&lt;p&gt;Other recipes demonstrate configuring all or part of the settings needed for code generation. &lt;em&gt;Generate Simple&lt;/em&gt; runs a template which requires no metadata, so it connects to the metadata source, runs the template and adds the project output with no user intervention. &lt;em&gt;Additional Source&lt;/em&gt; demonstrates how you can extend the base code generation guidance package with additional metadata  sources and providers of your own, without rebuilding the base package. Specify the &lt;em&gt;SourceAssemblyConfiguration&lt;/em&gt; argument: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;Argument&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;SourceAssemblyConfiguration&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Sixeyed.CodeGeneration.Metadata.SourceAssemblyConfiguration, Sixeyed.CodeGeneration&lt;/span&gt;"&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ValueProvider&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;Type&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;SourceAssemblyConfigurationValueProvider&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;AssemblyList&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Sixeyed.CodeGeneration.Tests&lt;/span&gt;"&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;      &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ValueProvider&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;Argument&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; 	&lt;/p&gt;
&lt;p&gt;- and the .NET assemblies named in &lt;em&gt;AssemblyList&lt;/em&gt; (semi-colon separated) will be interrogated at run-time to identify &lt;strong&gt;IMetadataSource&lt;/strong&gt; and &lt;strong&gt;IMetadataProvider&lt;/strong&gt; implementations (there'll be more detail on those interfaces in a coming post). Any available classes will be added to the list of sources and providers shown in &lt;em&gt;Add Generated Items&lt;/em&gt;, and can also be used in &lt;em&gt;SourceConfiguration&lt;/em&gt; argument values. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Usage &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By providing custom recipes, you can tailor your own Guidance packages which contain recipes for generating classes or other artifacts based on established patterns. This gives the project team an easy way of ensuring consistency for common coding problems in the domain – configuration sections and stored procedure wrappers are simple examples. Note that the URIs and paths are hard-coded. The code generation guidance package will attempt to find a T4 template if the path is not fully stated, but it won't always succeed (there's an issue with returning the running &lt;strong&gt;GuidancePackage&lt;/strong&gt; instance that I haven't tracked down). In a typical project though, templates would be in SCM and source URIs would be consistent among developers, so fully-qualified hard-coded text shouldn't be a problem. &lt;/p&gt;
&lt;p&gt;I'll be extending the sample package to include other templates that may be useful starting points for common code generation tasks – enums to represent reference data, unit tests for .NET and BizTalk artifacts, MSBuild scripts and anything else that occurs. If you have any templates of your own which would fit in a standard library, let me know and I'll add you as a CodePlex contributor. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129921"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129921" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/129921.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/03/08/sixeyed.guidance.codegeneration-sample-package.aspx</guid>
            <pubDate>Sun, 08 Mar 2009 22:46:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/129921.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/03/08/sixeyed.guidance.codegeneration-sample-package.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/129921.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Code Generation Guidance Package</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/03/07/code-generation-guidance-package.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I've been working on a Guidance package which lets you use Visual Studio as a front end to generate items from T4 templates. Using a recipe wizard you choose your metadata from a Web service, database or file system source, and the template is rendered against each of the metadata objects you select. It's on CodePlex here: &lt;a href="http://www.codeplex.com/GAXCodeGeneration"&gt;Code Generation Guidance Package&lt;/a&gt;, and comes in two flavours. The basic Guidance package has a single recipe "Add generated items" – when you run it, you specify a metadata provider, select the items to use for metadata and the T4 template to render against the items.  &lt;/p&gt;
&lt;p&gt;The second package is a sample which extends the functionality of the main Guidance package with custom recipes. This demonstrates how you can define recipes for pre-configured generation types, so the user does not need to complete all the wizard pages – one example specifies a database connection string and a T4 template for generating stored procedure wrappers; to add a new DAL class, the user runs the recipe and just selects which stored procedure(s) they want generated.  &lt;/p&gt;
&lt;p&gt;Neither package comes with any Visual Studio solution or project templates, and they do not need to be used to create the original solution. Any existing project can make use of the code generation features by enabling the package(s) through &lt;em&gt;Tools…Guidance Package Manager&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;In this post I'll give an overview of using the basic &lt;strong&gt;Sixeyed.Guidance.CodeGeneration &lt;/strong&gt;package, and in future posts I'll add some technical detail and give a walkthrough of the sample project. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Add Generated Items &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Run the Add generated items recipe from the Guidance Package Manager, or from the context menu of any project in Solution Explorer. The wizard loads to collect settings - in the first page you select the metadata source type, configure the source and select the metadata provider: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030709_1952_CodeGenerat1.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;During generation, the provider will load each of the selected metadata items and provide them as a property which can be accessed in the T4 template. For instance if you use the SQL Server Stored Procedure provider, your T4 script will have a populated SqlCommand object available to use. &lt;/p&gt;
&lt;p&gt;Provided with the basic Guidance package are the following Sources and Providers: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;
    &lt;div&gt;File System &lt;/div&gt;
    &lt;ul&gt;
        &lt;li&gt;
        &lt;div&gt;File source – for using one or more files as metadata &lt;/div&gt;
        &lt;ul&gt;
            &lt;li&gt;XML File provider – for using XML file contents, exposed to the template as an XmlDocument instance &lt;/li&gt;
            &lt;li&gt;Text File provider – for using text file contents, exposed as a string &lt;/li&gt;
            &lt;li&gt;Assembly File provider – for using a .NET assembly, exposed as an Assembly instance &lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;
        &lt;div&gt;Directory source – for using a list of directory contents as metadata &lt;/div&gt;
        &lt;ul&gt;
            &lt;li&gt;File List provider – for using a list of file names, exposed as a List&amp;lt;string&amp;gt; instance &lt;/li&gt;
            &lt;li&gt;Directory provider – for using a directory, exposed as a DirectoryInfo instance &lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;div&gt;Database &lt;/div&gt;
    &lt;ul&gt;
        &lt;li&gt;
        &lt;div&gt;SQL Server Database &lt;/div&gt;
        &lt;ul&gt;
            &lt;li&gt;Query Result provider – for executing a SQL query and exposing the results in a populated DataSet &lt;/li&gt;
            &lt;li&gt;Table provider – for using a table as metadata, exposed as an empty DataTable with the correct structure &lt;/li&gt;
            &lt;li&gt;Stored Procedure provider – for using stored procedures, exposed as a populated SqlCommand object &lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;
    &lt;div&gt;WSDL &lt;/div&gt;
    &lt;ul&gt;
        &lt;li&gt;
        &lt;div&gt;SOAP source &lt;/div&gt;
        &lt;ul&gt;
            &lt;li&gt;Web Method provider – for using a Web service method, exposed as a MethodInfo object &lt;/li&gt;
            &lt;li&gt;Schema provider – for using the WSDL of the service, exposed as an XmlSchema object &lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you select a provider, it will load a list of all available metadata items, and you select which items you want to run the T4 template against: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030709_1952_CodeGenerat2.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;The item selection is always a simple list displaying the item name – this will be the name of the file, table, Web method etc (an exception is the QueryResult provider which uses this page to capture the SQL query to be executed). &lt;/p&gt;
&lt;p&gt;In the final screen, select the T4 template to use: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030709_1952_CodeGenerat3.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;The file dialog will default to the "Templates" folder of the Guidance package, but you can navigate to any T4 file. If you want to override the output settings from the T4 file, specifying a different target filename, namespace extension or class name you can do it in the additional properties in this step: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030709_1952_CodeGenerat4.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;Finish the wizard and the recipe will iterate over each of the selected items, populating a representation of the metadata and passing it to the T4 template property.  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;T4 Template Properties &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In order to access metadata item information and create the output, your T4 script needs to specify two properties which will be populated using the Guidance PropertyProcessor engine: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&amp;lt;#@ property processor="PropertyProcessor" name="MetadataItem" #&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&amp;lt;#@ property processor="PropertyProcessor" name="TemplateConfiguration" #&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;The &lt;em&gt;MetadataItem&lt;/em&gt; property is an object implementing &lt;strong&gt;Sixeyed.CodeGeneration.Metadata.Interfaces.IMetadataItem&lt;/strong&gt;: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030709_1952_CodeGenerat5.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;The underlying &lt;em&gt;Item&lt;/em&gt; property gives you access to the populated metadata item – the object type will depend on the provider, and will be specified in the &lt;em&gt;ItemType&lt;/em&gt; property. The &lt;em&gt;Key&lt;/em&gt; for the item (the name shown in the Select Items wizard page) is available, as is the metadata &lt;em&gt;Provider&lt;/em&gt; which can be used to navigate up to the source. &lt;/p&gt;
&lt;p&gt;The &lt;em&gt;TemplateConfiguration&lt;/em&gt; property allows you to control the output of the template, setting default values for the target file name etc. (which can be overridden in the Select Template wizard page). It's an object of type &lt;strong&gt;Sixeyed.CodeGeneration.Generation.TemplateConfiguration&lt;/strong&gt;: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030709_1952_CodeGenerat6.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Sample Templates &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The CodeGeneration.Sample Guidance package contains a sample template for each of the metadata providers, demonstrating the type of object they expose and how it can be used. The scripts don't do much other than demonstrate usage, but there are fully-fledged scripts for generating wrappers for SQL Server stored procedures, and configuration sections from text files. The full script for the Table provider sample makes straightforward use of the underlying DataTable object: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;template&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; language=&lt;/span&gt;"&lt;span style="color: blue;"&gt;C#&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; processor=&lt;/span&gt;"&lt;span style="color: blue;"&gt;PropertyProcessor&lt;/span&gt;"&lt;span style="color: red;"&gt; name=&lt;/span&gt;"&lt;span style="color: blue;"&gt;MetadataItem&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; processor=&lt;/span&gt;"&lt;span style="color: blue;"&gt;PropertyProcessor&lt;/span&gt;"&lt;span style="color: red;"&gt; name=&lt;/span&gt;"&lt;span style="color: blue;"&gt;TemplateConfiguration&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;assembly&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; name=&lt;/span&gt;"&lt;span style="color: blue;"&gt;System.dll&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;assembly&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; name=&lt;/span&gt;"&lt;span style="color: blue;"&gt;System.Data.dll&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;assembly&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; name=&lt;/span&gt;"&lt;span style="color: blue;"&gt;System.Xml.dll&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;assembly&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; name=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Sixeyed.CodeGeneration.dll&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;import&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; namespace=&lt;/span&gt;"&lt;span style="color: blue;"&gt;System.Data&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#@&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: brown;"&gt;&lt;strong&gt;import&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: red;"&gt; namespace=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Sixeyed.CodeGeneration.Generation&lt;/span&gt;"&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#&lt;/span&gt;&lt;span style="color: midnightblue; background-color: silver;"&gt; PrepareOutput(); &lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: gray; font-family: Courier New; font-size: 10pt;"&gt;/* &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: gray;"&gt;Table&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: gray;"&gt;name&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: gray;"&gt;(from&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: gray;"&gt;metadata):&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#=&lt;/span&gt;&lt;span style="color: midnightblue; background-color: silver;"&gt; MetadataItem.Key &lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: gray;"&gt;Table&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: gray;"&gt;name&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: gray;"&gt;(from&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: gray;"&gt;table):&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#=&lt;/span&gt;&lt;span style="color: midnightblue; background-color: silver;"&gt; dataTable.TableName &lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: gray; font-family: Courier New; font-size: 10pt;"&gt;Columns: &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#&lt;/span&gt;&lt;span style="color: midnightblue; background-color: silver;"&gt; foreach (DataColumn column in dataTable.Columns) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;{ &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: midnightblue; background-color: silver;"&gt;    &lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt;&lt;/span&gt;&lt;span style="color: gray;"&gt;Column&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: gray;"&gt;Name:&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#=&lt;/span&gt;&lt;span style="color: midnightblue; background-color: silver;"&gt; column.ColumnName &lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: red;"&gt;      &lt;/span&gt;&lt;span style="color: gray;"&gt;Data&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="color: gray;"&gt;Type:&lt;/span&gt;&lt;span style="color: red;"&gt; 			&lt;/span&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#=&lt;/span&gt;&lt;span style="color: midnightblue; background-color: silver;"&gt; column.DataType &lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="background-color: yellow;"&gt;&amp;lt;#&lt;/span&gt;&lt;span style="color: midnightblue; background-color: silver;"&gt;} &lt;/span&gt;&lt;span style="background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: gray; font-family: Courier New; font-size: 10pt;"&gt;*/ &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt; background-color: yellow;"&gt;&amp;lt;#+ &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;private DataTable dataTable &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;{ &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;    get{ return MetadataItem.Item as DataTable; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;private void PrepareOutput() &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;{ &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;    TemplateConfiguration.ClassName = string.Format("Table_{0}", MemberName.ToPascalCase(MetadataItem.Key, true)); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;    TemplateConfiguration.FileExtension = "cs"; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: midnightblue; font-family: Courier New; font-size: 10pt; background-color: silver;"&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt; background-color: yellow;"&gt;#&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;(If you don't already have it, the &lt;a href="http://www.visualt4.com/downloads.html"&gt;T4 Editor Community Edition&lt;/a&gt; from Clarius makes editing templates much easier). &lt;/p&gt;
&lt;p&gt;The directives specify the expected properties, and import the relevant reference assemblies and namespaces. The script provides the &lt;em&gt;dataTable&lt;/em&gt; property to easily access the metadata item as a typed DataTable object. In the &lt;em&gt;PrepareOutput&lt;/em&gt; method (called at the start of the template), the script sets up the target class name and file extension. In this case a target filename is not specified, so the engine will use the class name and file extension for the filename. Note there are some helper methods in &lt;strong&gt;Sixeyed.CodeGeneration.Generation.MemberName&lt;/strong&gt; for preparing valid member names. &lt;/p&gt;
&lt;p&gt;Selecting a single table called Manufacturers for this script generates and adds a file called Table_Manufacturers.cs to the selected project, containing the following output: &lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;/* &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;Table name (from metadata): Manufacturers &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;Table name (from table): Manufacturers &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;Columns: &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;Column Name: ManufacturerId &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;      Data Type: System.Int16 &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;Column Name: ManufacturerName &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;      Data Type: System.String &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;Column Name: AvailableFromDate &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;      Data Type: System.DateTime &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;Column Name: AvailableToDate &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;      Data Type: System.DateTime &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;*/ &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Usage &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For ad-hoc code generation, this basic Guidance package lets you specify metadata to execute against a T4 template. For commonly used scripts and standard patterns you can build a custom Guidance package which contains your solution structure, and specific recipes for generating known types of item – for DAL classes, entities, configuration sections, proxies or anything else that is based on external metadata. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129906"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129906" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/129906.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/03/07/code-generation-guidance-package.aspx</guid>
            <pubDate>Sun, 08 Mar 2009 01:51:14 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/129906.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/03/07/code-generation-guidance-package.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/129906.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Using the WCF SQL Adapter in .NET: Calling Stored Procedures</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/03/02/using-the-wcf-sql-adapter-in-.net-calling-stored-procedures.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The Adapter Pack 2.0 for BizTalk has been &lt;a href="http://blogs.msdn.com/adapters/archive/2009/02/20/adapter-pack-2-0-beta-released.aspx"&gt;released in public beta recently&lt;/a&gt;, and among the WCF Line Of Business adapters it contains the WCF SQL adapter. This exposes SQL Server connections as WCF service endpoints, and lets you connect to a SQL Server source using the standard ServiceModel stack. The adapter pack will be released under the BizTalk brand, but the adapters themselves are not limited to BizTalk – the WCF SQL adapter can be used natively in .NET code. &lt;/p&gt;
&lt;p&gt;This is a brief walkthrough covering the SQL Adapter for executing stored procedures, and I'll be covering SQL statements in a subsequent post. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Installation &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Installation of the Adapter Pack is straightforward – you'll need .NET 3.5 Service Pack 1 with the latest hotfixes applied, and you'll need to install the WCF LOB Adapter SDK and then the BizTalk Adapter Pack 2.0 Evaluation (the beta version is limited to 120-day use). Note, you do not need to have BizTalk installed, and the tooling to support the WCF LOB adapters runs under Visual Studio 2008 as well as 2005. Help files for all the adapters are included, and although in pre-release form they are detailed and thorough. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Walkthrough: Consuming a Stored Procedure&lt;/em&gt; 	&lt;/p&gt;
&lt;p&gt;The Adapter Pack adds a new context menu to code projects in Visual Studio – &lt;em&gt;Add Adapter Service Reference&lt;/em&gt;. Run this and you're given a generic form for configuring your WCF LOB adapter. Choose &lt;strong&gt;sqlBinding&lt;/strong&gt; to set up a WCF SQL connection: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030209_1842_UsingtheWCF1.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;Click Configure and you specify the connection configuration that will be used to build the binding. In the case of the WCF SQL adapter, you need to specify: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Client Credential Type (Windows for integrated authentication); &lt;/li&gt;
    &lt;li&gt;Server (database server name); &lt;/li&gt;
    &lt;li&gt;Instance (SQL instance name, if configured); &lt;/li&gt;
    &lt;li&gt;Initial catalog (the database to connect to). &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will build you a URI of the form: &lt;strong&gt;mssql://&amp;lt;server&amp;gt;/&amp;lt;instance&amp;gt;/&amp;lt;initialCatalog&amp;gt;?&lt;/strong&gt; – with the ending question mark used to separate the core connection details from any configuration options. &lt;/p&gt;
&lt;p&gt;Click Connect and you have the option to generate a Client binding, for making outbound requests to SQL Server (executing SQL statements, stored procedures etc.), or a Service binding which will react to inbound calls from SQL Server (for Query Notification or polling). Choose Client and the category view will be populated with a hierarchy of database objects which can be generated as WCF client proxies: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030209_1842_UsingtheWCF2.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Generated Code &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For stored procedure calls, the adapter can create generic proxies for weakly-typed calls returning populated DataSets, or strongly-typed calls which will generate entities representing the return from the call. In this case I've selected a Strongly-Typed Stored Procedure called GetManufacturer; add the selection and with the default options the adapter generates two items: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;App.config – containing the WCF binding configuration; &lt;/li&gt;
    &lt;li&gt;SqlAdapterBindingClient.cs – containing the generated entity types and proxy classes. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The full binding configuration for the SQL adapter looks like this: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;system.serviceModel&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;bindings&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;sqlBinding&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;                &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;binding&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;SqlAdapterBinding&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;closeTimeout&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;00:01:00&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;openTimeout&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;00:01:00&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;receiveTimeout&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;00:10:00&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;sendTimeout&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;00:01:00&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;maxConnectionPoolSize&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;100&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;encrypt&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;false&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;workstationId&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;""&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;useAmbientTransaction&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;true&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;batchSize&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;20&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;polledDataAvailableStatement&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;""&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;pollingStatement&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;pollingIntervalInSeconds&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;30&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;pollWhileDataFound&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;false&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;notificationStatement&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;notifyOnListenerStart&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;true&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;enableBizTalkCompatibilityMode&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;true&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;chunkSize&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;4194304&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;inboundOperationType&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;Polling&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;useDatabaseNameInXsdNamespace&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;false&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;allowIdentityInsert&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;false&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;enablePerformanceCounters&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;false&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;xmlStoredProcedureRootNodeName&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;""&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;xmlStoredProcedureRootNodeNamespace&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;""&lt;span style="color: blue;"&gt; /&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;            &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;sqlBinding&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;        &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;bindings&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;client&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;endpoint&lt;/span&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;address&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;mssql://x/y/z?&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;binding&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;sqlBinding&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;bindingConfiguration&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;SqlAdapterBinding&lt;/span&gt;"&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;contract&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;TypedProcedures_dbo&lt;/span&gt;" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;name&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;"&lt;span style="color: blue;"&gt;SqlAdapterBinding_TypedProcedures_dbo&lt;/span&gt;"&lt;span style="color: blue;"&gt; /&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;        &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;client&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;system.serviceModel&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;- note that the binding contains some familiar WCF settings (sendTimeout, receiveTimeout), but the majority are SQL Server specific connection options. The client element specifies the contract as &lt;strong&gt;TypedProcedures_dbo&lt;/strong&gt;, the ServiceContract interface generated by the adapter, which has a single OperationContract defined: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;GetManufacturerResponse&lt;/span&gt; GetManufacturer(&lt;span style="color: rgb(43, 145, 175);"&gt;GetManufacturerRequest&lt;/span&gt; request); &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The proxy code for the client is all generated, so to invoke the stored procedure in your own code it's a familiar case of instantiating the client and calling the service, and of course you have full IntelliSense on the entity representing the resultset: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030209_1842_UsingtheWCF3.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;It's the content of the generated code that's interesting. The service, request, response and entity objects here are contained in 166 lines of generated code. The entity object is just a plain DTO-style class which implements &lt;strong&gt;IExtensibleDataObject&lt;/strong&gt; to allow access to any returned data that hasn't been mapped, and has a DataContract attribute with the schema name representing the stored procedure. The mapping between the entity properties and the returned columns is done with standard System.Runtime.Serialization attributes, so the ManufacturerId column is represented as: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        [System.Runtime.Serialization.&lt;span style="color: rgb(43, 145, 175);"&gt;DataMemberAttribute&lt;/span&gt;()] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;public&lt;/span&gt; System.&lt;span style="color: rgb(43, 145, 175);"&gt;Nullable&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;short&lt;/span&gt;&amp;gt; ManufacturerId { &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;get&lt;/span&gt; { &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;return&lt;/span&gt; 			&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ManufacturerIdField; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;set&lt;/span&gt; { &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt; 			&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ManufacturerIdField = &lt;span style="color: blue;"&gt;value&lt;/span&gt;; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;            } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;- note that this is an optional field in the database table, so it's generated as nullable in the entity. No other flags or code are used to map data, so the WCF SQL adapter is effectively deserializing the resultset from the stored procedure call straight into the DataContract. &lt;/p&gt;
&lt;p&gt;The generated code works well and is cleanly produced, but it has a few quirks you may not be happy with. A typed client class is generated for each individual procedure, whereas you might want them grouped into a single class which represents the full suite; and the class names are a bit cumbersome ("StoredProcedureResultSet0", "TypedProcedures_dboClient"). However, the code needed to actually connect to SQL through WCF and map the response is so simple that it's a straightforward task to generate your own code from custom templates. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Potential Usage &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After an initial look, the WCF SQL adapter seems to be an attractive option for generating and powering the data access layer of a .NET application, entirely apart from its primary purpose as a BizTalk adapter. It repositions data access as a service call and uses the standard WCF mechanisms of ServiceContract and DataContract for information exchange. Assuming other data providers follow suit, or other WCF-database adapters follow from the community, it's a nice way of isolating your application from the physical database, so swapping to MySQL or Oracle could become a simple matter of changing your WCF binding. &lt;/p&gt;
&lt;p&gt;It'll be interesting to see the licensing of the WCF LOB adapters from Microsoft. Currently the availability of a comprehensive suite of adapters is being positioned as one of the attractions of BizTalk as the Integration Server, compared to WF+WCF+Dublin as the Application Server. With the WCF SQL adapter there's a lot of potential take-up as a simpler alternative to the ADO.NET Entity Framework, so if it requires a BizTalk license, there will be room for an open source alternative. &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129794"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129794" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/129794.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/03/02/using-the-wcf-sql-adapter-in-.net-calling-stored-procedures.aspx</guid>
            <pubDate>Tue, 03 Mar 2009 00:42:45 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/129794.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/03/02/using-the-wcf-sql-adapter-in-.net-calling-stored-procedures.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/129794.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Introducing: BizTalkCop</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2008/11/14/introducing-biztalkcop.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To make good on a rash comment around the lack of standards-enforcement for BizTalk, I've put together a set of FxCop rules which allow you to run static analysis over BizTalk solutions. It covers all aspects by running rules against compiled artifact assemblies and configured BizTalk applications. It's on CodePlex here: &lt;a href="http://www.codeplex.com/BizTalkCop"&gt;BizTalkCop&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;The first release(1.0) contains a full ruleset for validating BizTalk application artifact names, based on &lt;a href="http://www.traceofthought.net/misc/BizTalk%20Naming%20Conventions.htm"&gt;Scott Colestock's naming conventions&lt;/a&gt;. By default the rules are more strict in places, but they're configurable so you can modify them to suit your own standards. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Usage &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Currently BizTalk projects don't integrate fully with static analysis in VS 2005, so you'll need the separate FxCop UI – latest version is &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9aeaa970-f281-4fb0-aba1-d59d7ed09772&amp;amp;DisplayLang=en"&gt;FxCop 1.36&lt;/a&gt;. Once you've installed FxCop, run the BizTalkCop installer and it will add &lt;em&gt;BizTalkCop.Rules.dll&lt;/em&gt; and &lt;em&gt;BizTalkCop.Rules.chm&lt;/em&gt; to the FxCop rules folder (default: Program Files\Microsoft FxCop 1.36\Rules). Open FxCop and there are three steps to configure your BizTalk project: &lt;/p&gt;
&lt;p&gt;1. Add Targets &lt;/p&gt;
&lt;p&gt;Add the compiled BizTalk assemblies you want to check to the FxCop project. For compiled artifacts, BizTalkCop covers orchestrations, maps, schemas and pipelines so you can add any assemblies that contain these: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/111408_1034_Introducing1.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;2. Select Rules &lt;/p&gt;
&lt;p&gt;If you've used the default installation, then the BizTalkCop rule set should be listed in the Rules tab (if not you'll need to navigate to add it). Check BizTalkCop and uncheck all the others: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/111408_1034_Introducing2.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;3. Set up Application Configuration &lt;/p&gt;
&lt;p&gt;In order to validate the configured BizTalk Application, you'll need to specify the location of your management database, and the name of the Applications to check. Open the &lt;em&gt;ApplicationConfig&lt;/em&gt; rule properties (this is a dummy rule which is only there to capture BizTalk Server config), and modify the Settings to specify your server, and the Applications to run over (semi-colon separated if more than one) – you only need to do this once, and all Application rules will use these settings: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/111408_1034_Introducing3.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;When you run FxCop it'll list all the rule failures, some of which may have multiple issues (e.g. ReceiveLocationNamesShouldIndicateTransport will flag an issue for every configured location that doesn't have its transport type as a suffix). There should be no locks on targets, so you can change the artifacts and recompile, or edit application config with FxCop open, and then re-run it. &lt;/p&gt;
&lt;p&gt;Most rules are configurable, so you can modify the prefixes and suffixes to suit your standards, or ignore any rules you don't care for. Save the project as a .FxCop file and you can integrate this into your build process using the &lt;a href="http://msbuildtasks.tigris.org/"&gt;MSBuild Community Tasks.&lt;/a&gt; 	&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Development&lt;/strong&gt; 	&lt;/p&gt;
&lt;p&gt;There's potential for rules to cover a lot more than the "Naming" category. Certain of the recommendations in the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=98ecf11a-9a8e-4939-8cef-2bc5536dc792&amp;amp;DisplayLang=en"&gt;BizTalk Performance Optimization Guide&lt;/a&gt; are candidates for a "Performance" category,  and there are a few gotchas that could be avoided with warnings from a "Design" category. I'm not planning to add these for a while, but if you want to get involved let me know and I'll add you as a contributor. &lt;/p&gt;
&lt;p&gt;FxCop runs over compiled assemblies, so introducing it to BizTalk meant for a few workarounds. If you want to extend BizTalkCop by adding new rules, there are a set of base classes which will help: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;em&gt;RuleBase&lt;/em&gt; – general base class for rules using normal introspection over classes; contains methods for determining if targets are maps, schemas etc; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;ConfiguredRuleBase &lt;/em&gt;– base class for rules which have default setting values which can be overridden in the project file; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;ApplicationRuleBase&lt;/em&gt; – base class for rules analysing BizTalk Applications; wraps the Explorer OM (so not good for 64-bit) to get the current config; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;OrchestrationRuleBase&lt;/em&gt; – base class for analysing Orchestrations; typically the compiled code is too dense for analysis, so the base class exposes methods for accessing the shape and OM configuration. This is stored as XML in the compiled class, and the base class provides XPath helpers to access it. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code for running the rule is quite straightforward, although tracking down the XML elements to check can be fiddly for orchestration rules (if you can find any schemas for the shape or OM XML, let me know and I'll modify it all to use entity classes). The source code contains a sample BizTalk project which fails all known rules, so you can add to this to check your own rules run as expected. &lt;/p&gt;
&lt;p&gt;Quite possibly the CSD have something like this in place for the VS 2008 integration coming in BizTalk Server 2009. If not, it should be a trivial job to migrate these rules to run under VS, and in any case the ability to separate them out for running in the build should be useful. &lt;/p&gt;
&lt;p&gt;I've run the rules over a few solutions and they've been accurate, but if you come across any issues, log them on CodePlex and I'll have a look. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=127018"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=127018" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/127018.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2008/11/14/introducing-biztalkcop.aspx</guid>
            <pubDate>Fri, 14 Nov 2008 16:36:06 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/127018.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2008/11/14/introducing-biztalkcop.aspx#feedback</comments>
            <slash:comments>10</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/127018.aspx</wfw:commentRss>
        </item>
        <item>
            <title>SSO Config Tool</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2008/06/29/sso-config-tool.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The Enterprise Single Sign On database can function as a centralized configuration store, as well as an identity store, which is available to all BizTalk instances in a group, and also to custom .Net apps. For a clear explanation of the benefits and drawbacks of the EntSSO approach (and the alternative options), see Michael Stephenson's post &lt;a href="http://geekswithblogs.net/michaelstephenson/archive/2008/05/25/122381.aspx"&gt;Where do I store my custom configuration for a BizTalk solution&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Here I'll look at overcoming some of the practical issues in developing, deploying and maintaining config in an EntSSO store using  another tool I've been using for a while and have recently put onto CodePlex: &lt;a href="http://www.codeplex.com/SSOConfigTool"&gt;SSO Config Tool&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;The original purpose was to codegen a strongly-typed configuration model that abstracted away the EntSSO store, and made read-only config values available from a static class for expressions: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/062908_1841_SSOConfigTo1.png" /&gt; 	&lt;/p&gt;
&lt;p&gt;- or .Net code: &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: green; font-family: Courier New; font-size: 10pt;"&gt;//extract the UDDI config settings: &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;string&lt;/span&gt; uddiUrl = &lt;span style="color: teal;"&gt;ConsolidatedGyroscope_App1Config&lt;/span&gt;.UDDIServerUrl; &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;&lt;span style="color: blue;"&gt;uint&lt;/span&gt; uddiTimeout = &lt;span style="color: teal;"&gt;ConsolidatedGyroscope_App1Config&lt;/span&gt;.UDDICacheTimeout; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So it does that (if you're looking for an app which just lets you manage SSO stores, have a look at &lt;a href="http://seroter.wordpress.com/2007/09/21/biztalk-sso-configuration-data-storage-tool/"&gt;Richard Seroter's Config Application Manager&lt;/a&gt;), and it also gives you: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;a console app to generate the config, and to import/export between EntSSO and an XML config file &lt;/li&gt;
    &lt;li&gt;MSBuild task versions of the console functionality  &lt;/li&gt;
    &lt;li&gt; a UI version of the console functionality, which also lets you maintain config settings: &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/062908_1841_SSOConfigTo2.png" /&gt; 	&lt;/p&gt;
&lt;p&gt;There are a couple of things worth noting here.  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Application Settings &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;These are all mandatory. The Groups specify who has access to read and update the config store settings. Groups must exist at the time you try and save the app to EntSSO, and they cannot be built-in groups or the "Everyone" group (not that you would…). The BizTalk groups are sensible options, so they're the default for the UI. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fields&lt;/em&gt; 	&lt;/p&gt;
&lt;p&gt;Field types are limited (by EntSSO) to one of the following built-in types: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;String &lt;/li&gt;
    &lt;li&gt;Int32 &lt;/li&gt;
    &lt;li&gt;UInt32 &lt;/li&gt;
    &lt;li&gt;Boolean &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The type you select will be emitted as the type of the property in the generated config model. Values are validated against the given type. The Masked option is a little misleading – all entries in EntSSO are encrypted, but if the field is defined as Masked in the config store then you can only retrieve it if you access EntSSO with a specific flag. The generated config model gives itself this permission, so the Masked value has no effect if you only use the config model. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;XML &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A custom schema is used so I can capture the expected field data type (rather than inferring it) – so it's similar but not compatible with the structure used by &lt;strong&gt;ssomanage&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Generated Code&lt;/em&gt; 	&lt;/p&gt;
&lt;p&gt;The config model produced by SSOConfigTool uses a couple of helper classes in the SSOConfig namespace. When you generate the model, you can either generate the source code (so you'll have to add the SSOConfig assembly to your app as well as adding the C# class), or a compiled assembly (which contains the configuration model in your selected namespace, and the helper classes in SSOConfig, so you can use it on its own). The API (Microsoft.BizTalk.Interop.SSOClient) should be in the GAC. &lt;/p&gt;
&lt;p&gt;Structure is quite basic – there's an &lt;strong&gt;SSOApplication&lt;/strong&gt; class that represents the config store for an application, and the business of wrapping the EntSSO API is done in &lt;strong&gt;SSOHelper&lt;/strong&gt;. The config class uses &lt;strong&gt;SSOApplication&lt;/strong&gt; behind the scenes to get field values,  and exposes them as the correct type. The class also exposes a CacheSSOAccess property which determines whether values are fetched from EntSSO on each call, or lazy loaded – it defaults to being lazy loaded (this is a static class so be aware of the thread implications if you're changing this value). &lt;/p&gt;
&lt;p&gt;Some quirks with the EntSSO API are documented here: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://blogs.msdn.com/kevin_michael_schultz/archive/2006/12/14/eat-my-rough-draft-punk.aspx"&gt;http://blogs.msdn.com/kevin_michael_schultz/archive/2006/12/14/eat-my-rough-draft-punk.aspx&lt;/a&gt; 		&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://suneetnangia.spaces.live.com/Blog/cns!AF14D545C10A3693!300.entry"&gt;http://suneetnangia.spaces.live.com/Blog/cns!AF14D545C10A3693!300.entry&lt;/a&gt; 		&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the config tool, the implication is that it creates a dummy field in the config app, but you won't see it unless you look in SSODB. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Usage &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I've mainly used the UI to create the app in the EntSSO store, then used the MSBuild tasks to extract the app as XML and generate code from it. Alternatively you can use the build tasks to create the SSO store and/or generate code from a saved config file. The sample MSBuild files in the project show these uses. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Work Outstanding &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Only a couple of things – firstly the SSO Config Tool (in its various guises) expects the EntSSO store to be available locally, so currently it doesn't allow you to run it from one machine to update SSO on another. The other one is more of an annoying niggle – if you try to open an SSO app from the UI, you'll probably find the dropdown list of available apps empty. This is down to &lt;strong&gt;ISSOMapper.GetApplications&lt;/strong&gt; always returning an empty list, so until I work out why it thinks the user isn't entitled to view them, you'll need to type in the name of the app. Think of it as a security measure. &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=123462"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=123462" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/123462.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2008/06/29/sso-config-tool.aspx</guid>
            <pubDate>Mon, 30 Jun 2008 00:41:30 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/123462.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2008/06/29/sso-config-tool.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/123462.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>