<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://bloggingabout.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Obiwan Jacobi</title><link>http://bloggingabout.net/blogs/marc/default.aspx</link><description>Do not underestimate the bandwidth of a truck!</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Deploy Role with caching enabled to Windows Azure</title><link>http://bloggingabout.net/blogs/marc/archive/2013/02/18/deploy-role-with-caching-enabled-to-windows-azure.aspx</link><pubDate>Mon, 18 Feb 2013 14:06:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:578336</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=578336</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2013/02/18/deploy-role-with-caching-enabled-to-windows-azure.aspx#comments</comments><description>&lt;p&gt;I am currently setting up my first Azure project. I had a skeleton Solution with a Web Role (MVC 4) and a Worker Role. &lt;/p&gt;  &lt;p&gt;To test the whole cycle I wanted to deploy early. We are using the visualstudio.com TFS, which can be coupled to Azure (or actually it’s the other way around) and a continuous deployment build template is available there (AzureContinuesDeployment.11.xaml).&lt;/p&gt;  &lt;p&gt;I was experiencing unhealthy instances and timeouts (when the build script took more than one hour to execute – due to the deployment steps) after deployment. After some searching and experimenting I came to the following conclusion.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;When you select the Caching option in the Role Properties, you MUST enter a valid Storage Account for deployment on Azure. &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;By default the configuration for that setting contains the well-known “UseDevelopmentStorage=true” value. While this is fine for running locally it absolutely will not work when deployed on Azure.&lt;/p&gt;  &lt;p&gt;The Storage Account Name and Key can be found on the Azure Portal – Storage tab. Select a Storage account there from the list. Then in the App Bar (below) there is an option Manage Keys. There you can copy the relevant values. Note that I used the primary key. Not sure if it works if you use the Secondary key.&lt;/p&gt;  &lt;p&gt;In hindsight it is logical and obvious, but it took me a good while to figure out that THAT was the problem.&lt;/p&gt;  &lt;p&gt;Hope it helps.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=578336" width="1" height="1"&gt;</description></item><item><title>Yet Another Logging Framework</title><link>http://bloggingabout.net/blogs/marc/archive/2011/10/21/yet-another-logging-framework.aspx</link><pubDate>Fri, 21 Oct 2011 11:30:27 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:576348</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=576348</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2011/10/21/yet-another-logging-framework.aspx#comments</comments><description>&lt;p&gt;This blogpost is a brain dump on a new logging framework I’m planning to write. If you have any additions or suggestions please leave them as comments.&lt;/p&gt;  &lt;p&gt;So why do we need, yet another Logging Framework. Well, because I cannot find in others what I think is important and also I want to leverage the &lt;a href="http://bloggingabout.net/blogs/marc/archive/2008/04/12/a-method-context-information-gathering-framework.aspx" target="_blank"&gt;Diagnostics Trace code&lt;/a&gt; I have already written.&lt;/p&gt;  &lt;p&gt;What scenarios should this Logging Framework be able to handle?&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Easy to use.     &lt;br /&gt;It should be easy to configure and easy to call. Any provider based mechanism (log targets) is bound to have config associated with it, but at least give good feedback on any problems that might occur. Convention over configuration and MEF might ease the problems.&lt;/li&gt;    &lt;li&gt;One liner.     &lt;br /&gt;When using it, you should only have to write one line of code. This is not always feasible but it is a good starting point. Why is this important? Because you want to make it easy on the poor developer that is using your ‘yet another logging framework’. The use of Aspects (PostSharp) can also be of use.       &lt;br /&gt;On the other hand, most applications that use a 3rd party library almost always create a façade for interacting with it. So its better to have a good API that is easy to integrate into a façade than to have an awkward API in order to force it all into one line of code.&lt;/li&gt;    &lt;li&gt;Uses the TraceContext (&lt;a href="http://www.xs4all.nl/~mjacobi/Blog/Jacobi/Jacobi.Diagnostics.zip" target="_blank"&gt;source&lt;/a&gt;) information to ‘automatically’ enrich the log entries. The TraceContext now has a method to AddContectTo an Exception, but could be extended to also AddContextTo a LogEntry.&lt;/li&gt;    &lt;li&gt;Fallback log targets.     &lt;br /&gt;Have a mechanism to fallback on log targets when they are not available. This answers the question: were do you log the exception that you cannot connect to your log target.&lt;/li&gt;    &lt;li&gt;Integrated .NET support for WCF and ASP.NET.     &lt;br /&gt;Make use of the extra information that lives in those contexts and allow that context to be easily added to the log entry. Both these contexts also support some kind of interception (think Behaviors for WCF and Modules for ASP.NET) to allow automatic logging.&lt;/li&gt;    &lt;li&gt;Log to multiple log targets at the same time – each with unique filters.     &lt;br /&gt;The default System.Diagnostics TraceListeners will already do this. Also be able to retrieve different types of logs in the code (error log, message log, security audit log etc).&lt;/li&gt;    &lt;li&gt;Use that same log framework for technical logging as well as functional auditing.     &lt;br /&gt;There is no reason why a logging framework cannot be used for (more) functional logging also, provided the they use unique ‘streams’.&lt;/li&gt;    &lt;li&gt;Different log entry formats.     &lt;br /&gt;Different log targets may require different log entry structs. Still I would prefer to use the existing diagnostics code. This means that those structures has to be serialized and deserialized. I think JSON can be of great help here.&lt;/li&gt;    &lt;li&gt;Distributed and Correlated.     &lt;br /&gt;You want to be able to correlate log (and trace) entries made by different parts of the system. This allows you to get a good impression to what happened where and why.&lt;/li&gt;    &lt;li&gt;Support debug-only log entries.     &lt;br /&gt;Conditional compilation on DEBUG. No biggie, just useful.&lt;/li&gt;    &lt;li&gt;Asynchronous logging.     &lt;br /&gt;This is tough one. You want Async logging in order to minimize performance impact on the running thread – actually this is more a tracing issue than a logging issue, assuming logging doesn’t output a whole lot of entries per second). But making it asynchronous can also mean that you lose that one vital entry just before the app crashes. More on this later.&lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Using System.Diagnostics&lt;/h3&gt;  &lt;p&gt;The idea is that we use as much of the existing logging technology as possible. That means reusing and extending the main classes of the System.Diagnostics namespace. TraceSource can be derived into LogSource and provide the basis for a log target. Each LogSource can specify a collection of TraceListeners. Custom TraceListeners can be used as well as the out of the box ones.&lt;/p&gt;  &lt;p&gt;But using these TraceListseners means that all Log information has to be squeezed through a single string (essentially – worst case). This coupled with the fact that different log types might require different log entry structures leads to one conclusion. We have to serialize the complex data into a string so that it can be output by different log targets (Sinks) and mapped to their most appropriate fields.&lt;/p&gt;  &lt;p&gt;The use of JSON would be excellent here, also because JSON is somewhat readable even in its serialized form. So you can still make sense of it even when its written to a text file. The object structure that is used will be partly fixed, we will need some known fields to extract data needed for further processing. But custom structures can also be easily serialized to JSON and on the receiving side, easily serialized into generic data containers (ExpandoObjects) for use in the viewer.&lt;/p&gt;  &lt;p&gt;Formatting this complex data into something that makes sense for the specific log target is done when reading the log, not while writing it. This not only saves a little performance hit while writing the log entry, it also allows for a more versatile viewer.&lt;/p&gt;  &lt;h3&gt;Performance&lt;/h3&gt;  &lt;p&gt;One of the obvious ways to decouple the performance costs of tracing and logging is to take the processing of the log entry onto a background thread. Only the data gathering takes place on the active thread all other operations will be done on the background thread.&lt;/p&gt;  &lt;p&gt;The trouble with this is that you can lose potentially critical log entries just before your application crashes. One possibly way to have the best of both worlds is to use the log level (Critical, Error, Warning and Info) as an indication of priority. That could mean that Critical log entries are always logged on the active thread. The other levels are processed by the background thread starting with Error, Warning and Info as least significant. &lt;/p&gt;  &lt;p&gt;We have to provide some way to identify the order of these entries (can be a simple sequence number) in order to be able to view them in the correct order. Gaps in the sequence can be detected and displayed in the viewer. This mechanism will also make it easy to merge log ‘files’ from different machine into one.&lt;/p&gt;  &lt;p&gt;If we take formatting out of the write-a-log-entry process, we might also need to revisit the Tracing code we have so far in order to make that option available in Tracing too.&lt;/p&gt;  &lt;h3&gt;Reading Log entries&lt;/h3&gt;  &lt;p&gt;For each (type of) log target a Sink is needed that knows how to put the log entry data into its storage. Think for instance Enterprise Library Logging block or Log4Net or simply the event log. A TraceListener is implemented for each target that knows how to take that one string and persist it in the most optimal way.&lt;/p&gt;  &lt;p&gt;When those (types of) targets also want to play in the log viewer, they also have to expose a Provider: an object that knows how to read log entries from its storage and provide them to the viewer. &lt;/p&gt;  &lt;p&gt;The viewer will be able to union all log entries from all providers and sort them into the temporal sequence they were written in. Merging of different (machine) sources is also possible.&lt;/p&gt;  &lt;p&gt;Of course the viewer would be able to filter and even search through the entries.&lt;/p&gt;  &lt;p&gt;I think it would be advantageous to implement an &lt;a href="http://www.odata.org/" target="_blank"&gt;OData&lt;/a&gt; REST service as a source for all the log entries. This allows easy access to the log entries for all kinds of purposes and provide a flexible basis for retrieving log entry information for different applications. Both Xml and Json formatting can be supported.&lt;/p&gt;  &lt;h3&gt;Closing remarks&lt;/h3&gt;  &lt;p&gt;I am sure that a lot more issues will present themselves once a more detailed design is made and implementation starts. But I think this WILL make a pretty nice logging framework if we can pull it off. Writing this blog post has helped me to structure my thoughts more on the subject and I hope it was a pleasant read for you, perhaps even an inspiration to tweak the logging framework you are no using.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=576348" width="1" height="1"&gt;</description></item><item><title>Seesmic Desktop Feed Reader Plugin</title><link>http://bloggingabout.net/blogs/marc/archive/2011/01/24/seesmic-desktop-feed-reader-plugin.aspx</link><pubDate>Mon, 24 Jan 2011 10:30:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:484661</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=484661</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2011/01/24/seesmic-desktop-feed-reader-plugin.aspx#comments</comments><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve released a &lt;a href="http://seesmic.com/products/desktop"&gt;Seesmic Desktop&lt;/a&gt; plugin that allows you to read syndication feeds (Rss/Atom) in a single column.&lt;/p&gt;
&lt;p&gt;It has been published on the &lt;a href="http://marketplace.seesmic.com/"&gt;Seesmic Marketplace&lt;/a&gt; and is also &lt;a href="http://seesmicfeedreader.codeplex.com/"&gt;open source&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Give it a spin and let me know what you think.&lt;/p&gt;
&lt;p&gt;Have fun,&lt;br /&gt;Marc&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=484661" width="1" height="1"&gt;</description></item><item><title>The context of anonymous methods/lambda's is lost on async proxy calls in SL3 (Updated)</title><link>http://bloggingabout.net/blogs/marc/archive/2010/06/10/the-context-of-anonymous-methods-lambda-s-is-lost-on-async-proxy-calls-in-sl3.aspx</link><pubDate>Thu, 10 Jun 2010 10:25:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:483501</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=483501</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2010/06/10/the-context-of-anonymous-methods-lambda-s-is-lost-on-async-proxy-calls-in-sl3.aspx#comments</comments><description>&lt;p&gt;&lt;b&gt;EDIT&lt;/b&gt;: This issue was caused by using cached singletons for each proxy (see comments). So the context of anonymous method works correctly, it just appeared it didn&amp;#39;t because multiple event handler (lambda&amp;#39;s) were registered to the same proxy instance.&lt;/p&gt;
&lt;p&gt;We&amp;#39;re building an SL3 application that gets its data from a WCF (Ria) Service. The application uses a standard generated proxy (SlSvcUtil.exe) and all calls are done using the familiar async pattern: call a begin method and wait for the completed event. In our SL3 application we have some layers on top of this Proxy: &lt;/p&gt;
&lt;p&gt;1) The&amp;nbsp;ServiceAgent - manages the service proxy and transparently recreates it when it is in a Faulted state. It subscribes to the completed event on the proxy and promotes this to the caller (repositories).&lt;br /&gt;2) The Repositories - exposes centralized and cached data access divided bij functional area / domain.&lt;br /&gt;3) The Model (per module) - Each module in the app implements the MVVM pattern and its model accesses the repositories and maps the data from service contracts to module-specific view entities.&lt;/p&gt;
&lt;p&gt;Because all data fetching is async we use an eventing mechanism (similar to INotifyPropertyChanged and INotifyCollectionChanged) to communicate&amp;#39;the &amp;#39;completed&amp;#39; event from the proxy upward through the application.&lt;/p&gt;
&lt;p&gt;It was in the implementation of the repositories that I first discovered that something was wrong with the context in which our &amp;#39;completed&amp;#39; events were raised. Our implementation looked something like this (pseudo code):&lt;/p&gt;
&lt;p&gt;public DataEntity GetDataEntity(Guid Id)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataEntity retVal = new DataEntity();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using(var proxy = _serviceAgent.GetProxy&amp;lt;RequestDataContract, ResponseDataContract&amp;gt;())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; proxy.RegisterCompletedHandler( (response) =&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;retVal.Property1 = Response.Property1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;retVal.Property2 = Response.Property2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;retVal.Property3 = Response.Property3;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; proxy.BeginRequest(new Request(id));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return retVal;&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;Initially this method returns an empty object that gets mapped to an empty&amp;nbsp;ViewEntity and bound to the UI. When the proxy reports the service call is completed the &amp;#39;CompletedHandler&amp;#39; is called implemented by the lambda and provides access to the response of the service call. Now the empty DataEntity is filled and these changes are propegated to the ViewEntity (think INotifyPropertyChanged) and in turn the Viewentity notifies its changes to the UI (also INotifyPropertyChanged). This works, no problem.&lt;/p&gt;
&lt;p&gt;Untill you place another call to the same repository method while the first is still &amp;#39;running&amp;#39;. Then the &amp;#39;context&amp;#39; the lambda needs to fill the retVal is lost and &amp;#39;overwritten&amp;#39; by&amp;nbsp;the second call. So it may be very well that the result of the first call is written to the retVal of the second call. You can imagine the strange behavior you&amp;#39;ll get in your app (and how long it takes to figure out what the problem is ;-).&lt;/p&gt;
&lt;p&gt;The solution that I&amp;#39;ve found is to use the userState that the proxy allows you to sent with a method call. The pseudo code will look something like this:&lt;/p&gt;
&lt;p&gt;public DataEntity GetDataEntity(Guid Id)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataEntity retVal = new DataEntity();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using(var proxy = _serviceAgent.GetProxy&amp;lt;RequestDataContract, ResponseDataContract&amp;gt;())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; proxy.RegisterCompletedHandler( (response, userState) =&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataEntity de = (DataEntity)userState;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;de.Property1 = Response.Property1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;de.Property2 = Response.Property2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;de.Property3 = Response.Property3;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; proxy.BeginRequest(new Request(id), retVal);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return retVal;&lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;Now the correct retVal is passed as userState allong with the service call to the proxy and the completed (event) handler will now have access to it when it is called and will be able to set the property values.&lt;/p&gt;
&lt;p&gt;I was very suprised that this occurred in my code and it may very well be that I&amp;#39;m doing things wrong, but I don&amp;#39;t see it. Any suggestions are welcome.&lt;/p&gt;
&lt;p&gt;Hope it helps.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=483501" width="1" height="1"&gt;</description><category domain="http://bloggingabout.net/blogs/marc/archive/tags/Code+Design/default.aspx">Code Design</category><category domain="http://bloggingabout.net/blogs/marc/archive/tags/Anonymous+Methods/default.aspx">Anonymous Methods</category><category domain="http://bloggingabout.net/blogs/marc/archive/tags/Lambda/default.aspx">Lambda</category><category domain="http://bloggingabout.net/blogs/marc/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://bloggingabout.net/blogs/marc/archive/tags/SL3/default.aspx">SL3</category></item><item><title>Services with a twist</title><link>http://bloggingabout.net/blogs/marc/archive/2010/05/21/services-with-a-twist.aspx</link><pubDate>Fri, 21 May 2010 06:52:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:483323</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=483323</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2010/05/21/services-with-a-twist.aspx#comments</comments><description>&lt;p&gt;On the project I am currently working on we have several layers of processing going on:&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;External Systems (silos)&lt;br /&gt;These are the legacy systems that contain all the information.&lt;/li&gt;
&lt;li&gt;A service layer (WCF)&lt;br /&gt;These Domain Services expose the legacy systems transparently. Talking to these services gives you no clue which legacy system is used. Sometimes its more than one.&lt;/li&gt;
&lt;li&gt;An Enterprise Service Bus (BTS2006R2/ESB)&lt;br /&gt;Positioned as messaging middle ware. For the most part completely transparent to the clients.&lt;/li&gt;
&lt;li&gt;Client / Front end applications (SL3)&lt;br /&gt;User applications that consume domain services through the ESB.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;In order to let our domain services perform optimal with the many calls that they&amp;#39;ll receive and to make them as versatile as possible, we&amp;#39;ve decided to do two additional things:&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Support Batching&lt;br /&gt;Most service methods can handle multiple requests at a time. Its like taking your normal service operation contract and putting a collection around it. This enables the client to (for instance) resolve multiple IDs in one single call / round trip. It is the classical choice between multiple calls with small messages or less calls with larger messages. The client can now choose how it wants to interact with the service.&lt;/li&gt;
&lt;li&gt;Support Prefetching&lt;br /&gt;We define a rich data model that each of these domain services work with. These services go beyond just &amp;#39;Customers&amp;#39; or just &amp;#39;Orders&amp;#39;. Because all data within a domain service is so related / connected we felt that it would be best to keep it all in one service. But you do not always want all &amp;#39;Orders&amp;#39; and all &amp;#39;OrderItems&amp;#39; and all &amp;#39;Product&amp;#39; for a &amp;#39;Customer&amp;#39;. So we allow most service operations to specify what we have called &amp;#39;Prefetch paths&amp;#39;. Basically you call the service operation and you specify what relations of the root entity that operations serves up you want also to be included in the response. So you could call GetOrders with only &amp;nbsp;the &amp;#39;OrderItems&amp;#39; prefetch key. That would result in all Orders and OrderItems for a Customer. The client once again is in control of what data is retrieved to suit its needs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;We understand that implementing services this way is somewhat non-standard (I have never seen it done before), but we feel that it provides a lot of flexibility to its clients. For a service to be reusable in a number of different contexts, we believe it should be more flexible that your normal, plain vanilla service. Nontheless, we really like some community feedback on this design and would&amp;nbsp;appreciate&amp;nbsp;any suggestions you might have.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=483323" width="1" height="1"&gt;</description><category domain="http://bloggingabout.net/blogs/marc/archive/tags/Code+Design/default.aspx">Code Design</category></item><item><title>Silverlight: Breaking the daisy chain?</title><link>http://bloggingabout.net/blogs/marc/archive/2009/10/14/silverlight-breaking-the-daisy-chain.aspx</link><pubDate>Wed, 14 Oct 2009 05:59:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:482320</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=482320</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2009/10/14/silverlight-breaking-the-daisy-chain.aspx#comments</comments><description>&lt;p&gt;This post discusses the consequences of calling asynchronous calls in Silverlight (or any other scenario that lets you pass in event handlers for completion notification).&lt;/p&gt;
&lt;p&gt;Everything is asynchronous in Silverlight. With each call you make, you pass down event handlers that are called when the operation is done. When trying to program a sequential execution flow in your Silverlight program, you&amp;#39;ll see the daisy-chain &amp;#39;pattern&amp;#39; emerge. This is where a method starts an asynchronous call, the event handler does some work and starts another asynchronous call then the next event handler performs another asynchronous call, etc. Look at your own Silverlight code and see if you can detect this pattern.&lt;/p&gt;
&lt;p&gt;You see your logic spread out over a couple of methods/event handlers. Question is: does this need fixing? From a puristic standpoint I would say yes. On the other hand I can see that a daisy chain might not be the worst you have to live with. When the logic is simple enough and following the chain is easy, it is all right to leave it at that. But what if at some point you have to branch of the chain? For instance you have a condition (if-then-else) that determines to call one asynchronous method or -if it is not true- it will call another asynchronous method. Now you have two parallel tracks the execution flow can follow down the chain. This can get messy very quickly.&lt;/p&gt;
&lt;p&gt;Another issue to remember is that the thread that is used to call your event handler and notify you of the outcome of the asynchronous call, is not necessarily the same thread that was used to create the UI. So you cannot call into the UI directly from within the event handler. You have to marshal the call using Invoke.&lt;/p&gt;
&lt;p&gt;But how do we solve this? One pattern comes to mind is the state table. Define a state for each step in the daisy chain and determine what state to go to next when an event handler is called. But this doesn&amp;#39;t do anything for the fragmentation of the code. Its just a different way of cutting it into pieces and I would argue its less obvious than the original daisy chain (its also not&amp;nbsp;entirely&amp;nbsp;what the state table was meant for).&lt;/p&gt;
&lt;p&gt;You could use anonymous methods (or lambda&amp;#39;s) to pull everything into one method, but the question is if this is more readable and maintainable than a daisy chain.&lt;/p&gt;
&lt;p&gt;Although I have not worked out the details of this idea, I was thinking of a base class that would implement some helper methods to perform asynchronous calls and provide event handlers. This should allow you to implement all your code in one method (or as many as like) and call asynchronous methods and gather their responses almost transparently. Not sure if this idea will work, though.&lt;/p&gt;
&lt;p&gt;What I would like is to code out my Silverlight code in a normal sequential flow using &amp;quot;normal&amp;quot; programming paradigms and patterns. But until someone comes up with a good solution for that, we just have to experiment with our own solutions and patterns.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=482320" width="1" height="1"&gt;</description><category domain="http://bloggingabout.net/blogs/marc/archive/tags/Research/default.aspx">Research</category></item><item><title>[Link] .NET Code Pack for Windows 7</title><link>http://bloggingabout.net/blogs/marc/archive/2009/09/10/link-net-code-pack-for-windows-7.aspx</link><pubDate>Thu, 10 Sep 2009 07:56:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:482176</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=482176</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2009/09/10/link-net-code-pack-for-windows-7.aspx#comments</comments><description>&lt;p&gt;This seems to be .NET wrapper classes and controls for the new Windows 7 features.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.msdn.microsoft.com/WindowsAPICodePack"&gt;http://code.msdn.microsoft.com/WindowsAPICodePack&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;sweeeet....&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=482176" width="1" height="1"&gt;</description></item><item><title>How to implement catch (Exception e)?</title><link>http://bloggingabout.net/blogs/marc/archive/2009/04/10/how-to-implement-catch-exception-e.aspx</link><pubDate>Fri, 10 Apr 2009 15:40:58 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:481498</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=481498</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2009/04/10/how-to-implement-catch-exception-e.aspx#comments</comments><description>&lt;p&gt;How often did you see a C# catch(Exception e) statement in code? How often did you write it yourself?&lt;/p&gt;  &lt;p&gt;I know I do it, even when I know I &lt;a href="http://blogs.msdn.com/clrteam/archive/2009/02/19/why-catch-exception-empty-catch-is-bad.aspx" target="_blank"&gt;shouldn’t&lt;/a&gt;. Why?&lt;/p&gt;  &lt;p&gt;Because its so easy! Doing it right is hard(er) or at least take much more code you have to repeat over and over again.&lt;/p&gt;  &lt;p&gt;But its not something that you’d be proud of (I’m not).&lt;/p&gt;  &lt;p&gt;So, I thought it was time to change that. But how? I definitely don’t want to rewrite a lot of code for each try-catch-finally block.&lt;/p&gt;  &lt;p&gt;First lets take a look at error handling. When do you really handle an error? Almost never I dare to say. I’ve only encountered one occasion where I really handled an exception (a dead-lock exception from SQL-Server: I waited a random amount of time a retried – three times. After that I just let the exception bubble up).&lt;/p&gt;  &lt;p&gt;What does your error handling code look like? I bet it looks something like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; try     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // real code here…      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; catch(Exception e)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Logger.LogException(e);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;I don’t see the handling part in this ;-) why do we call this error handling? BTW don’t call &lt;font face="Courier New"&gt;throw e&lt;/font&gt; in the catch block. I rewrites the call stack and you loose the original call stack.&lt;/p&gt;  &lt;p&gt;But there’s a whole range of exceptions you don’t want to catch. &lt;font face="Courier New"&gt;AccessViolationException&lt;/font&gt;? &lt;font face="Courier New"&gt;ExecutionEngineException&lt;/font&gt;?&lt;/p&gt;  &lt;p&gt;Those indicate situations you can’t fix anyway.&lt;/p&gt;  &lt;p&gt;How about &lt;font face="Courier New"&gt;InvalidCastException&lt;/font&gt; and &lt;font face="Courier New"&gt;NullReferenceException&lt;/font&gt;?&lt;/p&gt;  &lt;p&gt;Those exceptions indicate some technical error and are an indication of plain bugs. I wouldn’t want to catch those in my code (only at AppDomain level to log them).&lt;/p&gt;  &lt;p&gt;The good news is that the &lt;a href="http://msdn.microsoft.com/en-us/magazine/dd419661.aspx" target="_blank"&gt;BCL team is doing something about this in .NET 4.0&lt;/a&gt;. But even in .NET 4.0 catch(Exception e) is still not a good idea.&lt;/p&gt;  &lt;p&gt;But how do we handle exceptions the easy way (the &lt;font face="Courier New"&gt;catch(Exception)&lt;/font&gt; way) but filter on the really important exceptions? We can take the solution of the BCL team one step further. &lt;/p&gt;  &lt;p&gt;The following code is not production code but it demonstrates an idea to handle exceptions correctly once and for all.&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; public class ErrorHandler     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public delegate void TryCallback();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public delegate void ExceptionCallback(Exception e);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public delegate void FinallyCallback(bool? exception); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public ErrorHandler()     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // add &amp;quot;really&amp;quot; fatal exceptions by default.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FatalExceptions.Add(typeof(AccessViolationException));      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FatalExceptions.Add(typeof(ExecutionEngineException));      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; private List&amp;lt;Type&amp;gt; _fatalExceptions = new List&amp;lt;Type&amp;gt;();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public IList&amp;lt;Type&amp;gt; FatalExceptions      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get { return _fatalExceptions; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public bool IsFatalException(Type exceptionType)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!typeof(Exception).IsAssignableFrom(exceptionType))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new ArgumentException(&amp;quot;Specified type is not (derived from) System.Exception.&amp;quot;, &amp;quot;exceptionType&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return (_fatalExceptions.FindIndex(e =&amp;gt; e.GetType() == exceptionType) != -1);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public bool? TryCatchFinally(TryCallback @try, ExceptionCallback @catch, FinallyCallback @finally)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; bool? handleException = null; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (@try == null)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw new ArgumentNullException(&amp;quot;@try&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; @try();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; catch (Exception e)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; handleException = HandleException(ref e); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (@catch != null &amp;amp;&amp;amp; !IsFatalException(e.GetType()))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; @catch(e);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (handleException != null)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (handleException == true)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw e;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; throw;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; finally      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (@finally != null)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; @finally(handleException);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return handleException;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public bool? HandleException(ref Exception e)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; bool? result = null; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (e != null)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (IsFatalException(e.GetType()))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // throw      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; result = false;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // TODO: call EntLib exception policy &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; result = false; // for now     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return result;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The &lt;font face="Courier New"&gt;HandleException&lt;/font&gt; method is where it gets decided whether an exception is handled and how. This is also the place to integrate EntLib if you desire. The return value of the &lt;font face="Courier New"&gt;HandleException&lt;/font&gt; can be &lt;font face="Courier New"&gt;null&lt;/font&gt; (do nothing), &lt;font face="Courier New"&gt;false&lt;/font&gt; (call &lt;font face="Courier New"&gt;throw&lt;/font&gt;) or &lt;font face="Courier New"&gt;true&lt;/font&gt; – meaning the exception has been replaced (exception wrapping) and &lt;font face="Courier New"&gt;throw e&lt;/font&gt; should be called. You could elaborate the catch callback to include retries of the @try code when you actually handle an exception (like the dead lock example earlier).&lt;/p&gt;  &lt;p&gt;You could use this code as follows:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; public void MethodThatCouldGoWrong(string someParameter)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ErrorHandler errorHandler = new ErrorHandler();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; errorHandler.FatalExceptions.Add(typeof(InvalidCastException));      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; errorHandler.FatalExceptions.Add(typeof(NullReferenceException)); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; errorHandler.TryCatchFinally(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; delegate()&amp;#160; // try      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // do something here that causes an exception      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; },      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; delegate(Exception e) // catch      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // handle the exception e      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; },      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; null&amp;#160;&amp;#160;&amp;#160; // finally      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; );      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This code will &lt;strong&gt;not&lt;/strong&gt; call the catch callback on &lt;font face="Courier New"&gt;AccessViolationException&lt;/font&gt;, &lt;font face="Courier New"&gt;ExecutionEngineException&lt;/font&gt;, &lt;font face="Courier New"&gt;InvalidCastException&lt;/font&gt; and &lt;font face="Courier New"&gt;NullReferenceException&lt;/font&gt;.&lt;/p&gt;  &lt;p&gt;You probably don’t want to instantiate the &lt;font face="Courier New"&gt;ErrorHandler&lt;/font&gt; class each time you need it - you could make it static as long as you add all fatal exception during initialization of that static instance. Then its a matter of calling the TryCatchFinally method and doing your processing using anonymous delegates (I think in this case its more readable than lambdas). You can even pass null to the @catch callback if you don’t have any custom handling to perform but still get your exceptions ‘handled’.&lt;/p&gt;  &lt;p&gt;So its a start. Maybe not perfect.&lt;/p&gt;  &lt;p&gt;Thoughts?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=481498" width="1" height="1"&gt;</description><category domain="http://bloggingabout.net/blogs/marc/archive/tags/Code+Design/default.aspx">Code Design</category></item><item><title>[BAM] PivotTable names must be unique</title><link>http://bloggingabout.net/blogs/marc/archive/2008/08/05/bam-pivottable-names-must-be-unique.aspx</link><pubDate>Tue, 05 Aug 2008 10:05:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:470464</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=470464</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2008/08/05/bam-pivottable-names-must-be-unique.aspx#comments</comments><description>&lt;p&gt;More a note to self than a serious blog post (haven&amp;#39;t got the time to do screen shots and stuff).&lt;/p&gt;
&lt;p&gt;When creating BAM views in Excel, you can copy the initial PivotTable that is generated to create multiple predefined &amp;#39;views&amp;#39;. To copy the PivotTable select it (go to the edge until you get a solid arrow cursor) then Copy it (Ctrl+C), select a free cell well below the existing PivotTable and Paste (Ctrl+V). Right-click in the Pivot Table and select Table Options... to give it a name. &lt;strong&gt;This Name must be unique across the workbook&lt;/strong&gt;. Otherwise the PivotTable will not be linked to a cube when exported (although it all seems to work in excel) and your view will be missing from the Aggregations node in the BAM Portal navigation pane.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=470464" width="1" height="1"&gt;</description><category domain="http://bloggingabout.net/blogs/marc/archive/tags/BizTalk/default.aspx">BizTalk</category></item><item><title>[WPF] Data Model - View Model - View</title><link>http://bloggingabout.net/blogs/marc/archive/2008/06/29/wpf-data-model-view-model-view.aspx</link><pubDate>Sun, 29 Jun 2008 12:14:48 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:461819</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=461819</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2008/06/29/wpf-data-model-view-model-view.aspx#comments</comments><description>&lt;p&gt;This post is based on an interpretation of a pattern called View-View Model-Document or View-View Model-(Data) Model. &lt;a href="http://blogs.msdn.com/dancre/archive/2006/10/11/datamodel-view-viewmodel-pattern-series.aspx"&gt;I did not invent it&lt;/a&gt;. I just write this to have a record of what I learned when exploring the design pattern.&lt;/p&gt; &lt;p&gt;The following figure displays the WPF Application Architecture. On the right side a legend explains the meaning of the shapes used in the diagram. The Xaml shape indicates artifacts that are typically created with Xaml. The WPF shape indicates to a WPF specific type and the class shape indicates a custom class specific to the application in question.&lt;/p&gt; &lt;p&gt;&lt;img height="348" src="http://www.xs4all.nl/~mjacobi/Blog/Jacobi/DM-VM-VW/DM-VM-VW.png" width="517" alt="" /&gt; &lt;/p&gt; &lt;p&gt;The dashed lines show a Data Binding dependency with the arrow pointing toward the dependency being bound. The solid line with the arrow also displays a dependency but one that is set on the named property. A solid line with a diamond represents containment (diamond being the container). Multiplicity of this containment is indicated with the numbers at the “containee”.&lt;/p&gt; &lt;h3&gt;View Rendering&lt;/h3&gt; &lt;p&gt;The View Model is set as Content on the View. The ViewModel will provide object instances that drive the View’s content. These instances are usually Data Model types but can also be other view specific types. Through the use of Data Templates the ViewModel type and the Data Model type as well as any other types the View Model might provide are “converted into UI elements”. Each Data Template is written specifically for the object type and has knowledge of the object hierarchy within one instance.  &lt;p&gt;There are two options in how to interpret the Data Model. Some would consider the Data Model to be the collection of all application data (not necessarily counting view or UI specific data). Others would design a Data Model class to manage only one instance of one entity. A Data Model that is modeled to manage one or more collections of data can be harder than to bind against than a Data Model that manages only one entity instance. Either way can work with this architecture although it must be said that creating a Data Model that &lt;u&gt;only&lt;/u&gt; passes through the information of the entity must be avoided. &lt;p&gt;With the View Model and the Data Model in place the View can be data bound and the content is rendered in the View based on the View Model Data Template and the Data Model Data Template. &lt;p&gt;Note: A major drawback of working with Data Templates is the lack of support for Visual Designer Tools (Blend and Visual Studio). These tools will help you design views but not as a Data Template. &lt;h3&gt;Command Handling&lt;/h3&gt; &lt;p&gt;Just rendering a view is like a glass window: you can see everything but you can’t do anything with it. A user interacts with application by clicking and typing: generating events. This architecture proposes to use Commands to route these events to the application (code). WPF predefines several categories of commands that can (and should) be (re)used in your application. The Command Model manages a command and the event it represents. On one hand it references the Command it manages on the other hand does it reference the View Model. Think of the Command Model as the mini-Controller for one Command. When the Command fires the Command Manager executes its handler code against the View Model, which might cause view updates (property changed notification). &lt;p&gt;During binding in the Data Templates the Command must be set to the Command property of the UI element. Note that Command instances can be declared static. &lt;h3&gt;Unit Testing&lt;/h3&gt; &lt;p&gt;Because the objects are bound to the view (and Data Templates) there is no dependency from the View Model or Data Model to the View or its UI elements. This means that the View Model, Data Model and Command Model objects can be unit tested very easily without having to resort to UI-record &amp;amp; replaying testing tools. &lt;h3&gt;Wrapping up&lt;/h3&gt; &lt;p&gt;My first experiments with this pattern were interesting: it takes a little getting used to and frequently I had to get above the code to see the (helicopter) overview to see what I was doing and were to put the code. I realize that this post might be a bit short and cryptic. I recommend reading the blog posts of &lt;a href="http://blogs.msdn.com/dancre/archive/2006/10/11/datamodel-view-viewmodel-pattern-series.aspx"&gt;Dan Crevier&lt;/a&gt; that also includes a &lt;a href="http://blogs.msdn.com/dancre/attachment/760104.ashx"&gt;sample application&lt;/a&gt; in its last post. I think I might have deviated a little from what Dan writes but the idea remains the same: Utilize the tremendous power of WPF data binding.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=461819" width="1" height="1"&gt;</description></item><item><title>Trace Context Aspects with PostSharp</title><link>http://bloggingabout.net/blogs/marc/archive/2008/04/15/trace-context-aspects-with-postsharp.aspx</link><pubDate>Tue, 15 Apr 2008 13:47:41 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:458216</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=458216</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2008/04/15/trace-context-aspects-with-postsharp.aspx#comments</comments><description>&lt;p&gt;In my previous post I wrote about a &lt;a href="http://bloggingabout.net/blogs/marc/archive/2008/04/12/a-method-context-information-gathering-framework.aspx"&gt;method context information gathering framework&lt;/a&gt; I wrote in an attempt to increase the amount of useful information in trace output and exceptions. In this final post about the framework I will discuss the use of a static aspect weaver &lt;a href="http://www.postsharp.org/"&gt;PostSharp&lt;/a&gt;.&lt;/p&gt; &lt;h3&gt;Static Aspect Weaving&lt;/h3&gt; &lt;p&gt;I assume that you know what aspects are at least at a conceptual level. The nice thing about static aspects is that their code is injected at compile time, not at runtime. True: static aspects are not configurable, but they are completely transparent (dynamic aspects usually require the client code to create a proxy instead of the actual object).&lt;/p&gt; &lt;p&gt;I use PostSharp, a static aspect weaver, to implement a code attribute that triggers aspect code injection into the assembly. PostSharp works at IL level so it should be usable with any .NET language. While PostSharp provides a generic assembly manipulation framework, it is actually Laos that provides the aspect framework.&lt;/p&gt; &lt;p&gt;When an aspect (a code attribute) is applied to a method, PostSharp (actually Laos) rewrites the IL for that method. It basically relocates the original method IL in a new method with the same name, prefixed by a &amp;#39;~&amp;#39;. Then it inserts custom IL that performs the call sequence on your aspect object. Your aspect can be responsible for calling the actual method -using a delegate- (as it is in this example), although there are also flavors of aspects that do not require this.&lt;/p&gt; &lt;p&gt;So a typical (simplified) call stack would look something like this:&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;void MyClass.MyMethod(string param1)&lt;br /&gt;void MyAspect.OnInvocation(MethodInvocationEventArgs eventArgs)&lt;br /&gt;void delegate.DynamicInvoke(object[] parameters)&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;br /&gt;void MyClass.~MyMethod(string param1)&lt;/font&gt;&lt;/p&gt; &lt;p&gt;The stubbed MyClass.MyMethod routes execution to the aspect (OnInvocation) applied to the method and the aspect code invokes the delegate that point to the original method (or it doesn&amp;#39;t ;-) and the original method (prefixed with ~) executes.&lt;/p&gt; &lt;h3&gt;TraceContextAspect&lt;/h3&gt; &lt;p&gt;In order to eliminate the custom code you&amp;#39;d have to write to use the TraceContext in our method context information gathering framework, I&amp;#39;ve created a PostSharp/Laos aspect class that intercepts the method call as described above. So instead of making all the calls to the TraceContext yourself in the method code, you simply apply the aspect to the method:&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;[TraceContextAspect]&lt;br /&gt;public string PrintName(int numberOfTimes)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // method impl.&lt;br /&gt;}&lt;/font&gt; &lt;p&gt;The TraceContextAspect implements the OnInvocation method like so: &lt;p&gt;&lt;font face="Courier New"&gt;using (AspectTraceContext ctx = new AspectTraceContext(_methodBase))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.Initialize(eventArgs.Delegate.Target);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AddParameters(ctx, eventArgs.GetArguments());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.TraceMethodEntry();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;eventArgs.ReturnValue = eventArgs.Delegate.DynamicInvoke(eventArgs.GetArguments());&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.SetReturnValue(eventArgs.ReturnValue);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.AddContextTo(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} // maintains stack and writes method exit and flushes writer.&lt;/font&gt; &lt;p&gt;Note that I&amp;#39;ve derived a new class from TraceContext for this specific situation (AspectTraceContext) that takes a MethodBase instance as a parameter in its constructor. The MethodBase instance is handed to you by the PostSharp/Laos framework and represent the method the aspect was placed on. The bold text is the actual call to the original method. As you can see, all the custom code needed to setup the TraceContext has now moved to the OnInvocation method implementation. &lt;h3&gt;Conclusion&lt;/h3&gt; &lt;p&gt;The use of a static aspect weaver has dramatically simplified the usage of the method context information gathering framework. Tracing useful and rich information from your method has now become a breeze (as it should be ;-).&lt;/p&gt; &lt;p&gt;I hope these last 3 post has shown you how you can leverage existing technology (System.Diagnostics and PostSharp) to make the most out your own tracing framework (in this case). I also hope you will be inspired to find new applications to use static aspects in your own code. I find that static aspects can really make your life easier while at the same time not making your code (execution paths) more complicated than needed.&lt;/p&gt; &lt;p&gt;You can download the source code &lt;a href="http://www.xs4all.nl/~mjacobi/Blog/Jacobi/Jacobi.Diagnostics.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=458216" width="1" height="1"&gt;</description></item><item><title>A Method Context Information Gathering Framework</title><link>http://bloggingabout.net/blogs/marc/archive/2008/04/12/a-method-context-information-gathering-framework.aspx</link><pubDate>Sat, 12 Apr 2008 13:31:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:458194</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=458194</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2008/04/12/a-method-context-information-gathering-framework.aspx#comments</comments><description>&lt;p&gt;Do you also have that feeling when you type in your tracing code that it is too cumbersome and too much hassle to get it right? I mean really trace the information that is useful for finding faults, for instance. And when you log an exception, even when you write out all the information the exception offers, it is barely enough to really understand what went wrong?&lt;/p&gt;
&lt;p&gt;That is why I wrote this framework. This framework tries to solve one major problem (and some small one on the side): Getting the runtime information of an executing method into a trace text or an exception.&lt;br /&gt;&lt;br /&gt;Note that this post assumes you know about the main classes in &lt;a href="http://bloggingabout.net/blogs/marc/archive/2008/04/04/basic-system-diagnostics.aspx"&gt;System.Diagnostics&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;MethodContext&lt;/h3&gt;
&lt;p&gt;The MethodContext is a class that maintains all running values during the execution of a method. It is created at the beginning of the method and it is Disposed at the end of the method. It collects information about the runtime values of the method parameters, the class reference (this) if it isn&amp;#39;t a static method and its return value. This runtime method context information can be formatted into trace texts or added to an exception the code is about to throw.&lt;/p&gt;
&lt;p&gt;The MethodContext also maintains its own call stack and provides access to its calling method context.&lt;/p&gt;
&lt;p&gt;For tracing purposes a MethodContext derived class, the TraceContext, adds to this a reference to a MethodTracer and method entry and exit trace methods.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a typical usage scenario:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public string Repeat(string value, int numberOfTimes)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using(TraceContext ctx = new TraceContext())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.Initialize(this);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.AddParameter(value, &amp;quot;value&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.AddParameter(numberOfTimes, &amp;quot;numberOfTimes&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.TraceMethodEntry();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string result = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // method impl.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.ReturnValue = result;&lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; // Dispose is called on ctx, calling TraceMethodExit()&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Note that the TraceContext (MethodContext) maintains weak references to all instances.&lt;/p&gt;
&lt;h3&gt;MethodTracer&lt;/h3&gt;
&lt;p&gt;The MethodTracer instance is created for each TraceContext. The MethodTracer takes a TraceSource and an optional method-level TraceSwitch in its constructor and uses these to filter and output trace text. It implements 2 versions of the FormatTrace method; one instance and one static. The static FormatTrace method can be used by your code to trace custom texts. The TraceContext is located behind the scenes.&lt;/p&gt;
&lt;p&gt;The FormatTrace method takes an object parameter as the object to generate a trace text for (along with some other parameters). The method delegates this task to the TraceManager (discussed next) where a collection of ITraceFormatter instances is checked to see if that specific Type is supported.&lt;/p&gt;
&lt;p&gt;If the TraceSwitch allows it the formatted text is output to the TraceSource.&lt;/p&gt;
&lt;h3&gt;TraceManager&lt;/h3&gt;
&lt;p&gt;The TraceManager is a global (singleton) class that manages several cached classes. One already discussed are the TraceFormatters. These classes are able to generate trace text for a specific Type of object. TraceFormatters can use other TraceFormatters and thus composing the trace text.&lt;/p&gt;
&lt;p&gt;By convention the TraceManager will keep track of a TraceSource for each class Type that creates a TraceContext. It will also keep track of optional method TraceSwitch instances that can be configured to fine tune trace levels at method level.&lt;/p&gt;
&lt;h3&gt;Exceptions&lt;/h3&gt;
&lt;p&gt;Exceptions caught in the method that created a TraceContext can keep track of it using the LastError property on the context. When throwing exceptions you can add the context information of the TraceContext to the exception using the AddContextTo method. This method populates the Data dictionary of an exception instance with the context information. Note that only types that are serializable are added, this is because the Data dictionary doesn&amp;#39;t allow otherwise (exceptions need to be marshaled across boundaries sometimes and that involves serialization).&lt;/p&gt;
&lt;p&gt;The following code sample shows a nice way to add runtime information to an exception before propagating it to a higher level.&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;public string ReadTextFile(string path)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using(TraceContext ctx = new TraceContext())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.Initialize(this);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.AddParameter(path, &amp;quot;path&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.TraceMethodEntry();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string result = null;&lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // method impl.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch(IOException ioe)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.AddContextTo(ioe);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw;&lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ctx.ReturnValue = result;&lt;br /&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; // Dispose is called on ctx, calling TraceMethodExit()&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;The calling code will receive an exception which Data dictionary is filled with runtime method context information. A nice extension would be to be able to dump all properties of the instances present in the Data dictionary. That way you should be able to generate comprehensive error log messages.&lt;/p&gt;
&lt;h3&gt;Configuration&lt;/h3&gt;
&lt;p&gt;The following configuration shows how to set up a Console TraceListener and an EventLog TraceListener for errors, a trace source for several classes, trace switches at class level (trace source) and at method level.&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;system.diagnostics&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;sharedListeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Choose your trace output channels --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Console&amp;quot; type=&amp;quot;System.Diagnostics.ConsoleTraceListener&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; initializeData=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Only Error traces will go to the Event Log --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;ErrorEventLog&amp;quot; type=&amp;quot;System.Diagnostics.EventLogTraceListener&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; initializeData=&amp;quot;Jacobi.Diagnostics.TestApp&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filter type=&amp;quot;System.Diagnostics.EventTypeFilter&amp;quot; initializeData=&amp;quot;Error&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/add&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/sharedListeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;sources&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Configure a TraceSource for each class--&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Non-configured classes all create a default TraceSource --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;source name=&amp;quot;Jacobi.Diagnostics.TestApp&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;listeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Console&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;ErrorEventLog&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/listeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/source&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;source name=&amp;quot;Jacobi.Diagnostics.TestApp.TraceAspectTest&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;listeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Console&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;ErrorEventLog&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;remove name=&amp;quot;Default&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/listeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/source&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/sources&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;switches&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- SourceSwitch settings for classes --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- You can specify SourceSwitch settings &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; without configuring the TraceSource (&amp;lt;sources&amp;gt;) --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Jacobi.Diagnostics.TestApp&amp;quot; value=&amp;quot;Error&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Jacobi.Diagnostics.TestApp.TraceAspectTest&amp;quot; value=&amp;quot;All&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- TraceSwitch settings for Methods --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Jacobi.Diagnostics.TestApp.TraceAspectTest.WithContext&amp;quot; value=&amp;quot;Info&amp;quot; traceFlow=&amp;quot;Entry,Exit&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Jacobi.Diagnostics.TestApp.TraceAspectTest.ConcatName&amp;quot; value=&amp;quot;Verbose&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/switches&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/system.diagnostics&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/font&gt; 
&lt;p&gt;Basically this configuration is very similar to the one discussed in my previous post about &lt;a href="http://bloggingabout.net/blogs/marc/archive/2008/04/04/basic-system-diagnostics.aspx"&gt;System.Diagnostics&lt;/a&gt;.&amp;nbsp; &amp;lt;sharedListeners&amp;gt; declares all listeners, &amp;lt;sources&amp;gt; lists a TraceSource per class and &amp;lt;switches&amp;gt; configures both class-level switches and method-level switches. Notice that the method level switches extent the dot-syntax with the method name for the name of the switch and carry an extra traceFlow attribute. The traceFlow attribute allows you to filter the output of method entry and exit traces that are done by the TraceMethodEntry and TraceMethodExit methods on TraceContext.&lt;/p&gt;
&lt;p&gt;The &lt;a class="" href="http://bloggingabout.net/blogs/marc/archive/2008/04/15/trace-context-aspects-with-postsharp.aspx"&gt;next post&lt;/a&gt; will investigate a way to get rid of all the custom code you have to write to use the TraceContext. Using a static aspect weaver it is possible to have all that code removed from your method and indicate with a code attribute what methods you want to trace in a completely transparent way.&lt;/p&gt;
&lt;p&gt;Download the source code &lt;a href="http://www.xs4all.nl/~mjacobi/Blog/Jacobi/Jacobi.Diagnostics.zip"&gt;here&lt;/a&gt;. Note that this source code also contains the projects for the static aspect weaver that will be discussed in the &lt;a class="" href="http://bloggingabout.net/blogs/marc/archive/2008/04/15/trace-context-aspects-with-postsharp.aspx"&gt;next post&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=458194" width="1" height="1"&gt;</description></item><item><title>Basic System.Diagnostics</title><link>http://bloggingabout.net/blogs/marc/archive/2008/04/04/basic-system-diagnostics.aspx</link><pubDate>Fri, 04 Apr 2008 18:44:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:458144</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=458144</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2008/04/04/basic-system-diagnostics.aspx#comments</comments><description>&lt;p&gt;The .NET framework has shipped with the System.Diagnostics namespace since version 1.0. My efforts to build a method context information gathering framework on the services of System.Diagnostics has brought me a deeper understanding of its classes and configuration settings. I will talk about my method context information gathering framework in a later post, but first I thought I would get us all on the same page on System.Diagnostics.&lt;/p&gt;
&lt;p&gt;System.Diagnostics implements several classes that play a key role in outputting trace text from your application. Better understanding these classes will bring you insights in to how to extend the existing diagnostic framework in .NET or how to set up the configuration file to make full use of the out-of-the-box functionality.&lt;/p&gt;
&lt;h3&gt;TraceListener&lt;/h3&gt;
&lt;p&gt;The TraceListener class receives trace texts from the application and outputs it to a specific channel it was written for. There is a DefaultTraceListener class that outputs its text to the Win32 API OutputDebugString. But there is also an EventLogTraceListener that outputs its text to the windows event log. There is even an XmlWriterTraceListener that will output Xml to a stream. There are more listeners you can choose from and you can even write your own. Just derive your listener class from the abstract TraceListener base class and implement the abstract methods.&lt;/p&gt;
&lt;p&gt;A TraceListener also maintains an optional Filter. This allows you to fine tune the type of information that a TraceListener actually outputs. For instance, you could put an EventTypeFilter on the EventLogTraceListener to only output Error-type traces to the windows event log.&lt;/p&gt;
&lt;p&gt;TraceListener instances are held in a collection that all receive the same trace text to output. This means that the same trace text can be output on different channels (each channel is represented by a TraceListener) at the same time. This collection can live at the global/static Trace or Debug classes or at a TraceSource.&lt;/p&gt;
&lt;h3&gt;TraceSource&lt;/h3&gt;
&lt;p&gt;A TraceSource represents a configurable trace object that maintains its own set of TraceListeners. An associated TraceSwitch (discussed next) controls the trace level for this &amp;#39;scope&amp;#39;. Typically a TraceSource is configured in the .config. When the code instantiates a TraceSource with the same name it reads its settings from the .config file. This way you can control what portions of your application code will output trace text.&lt;/p&gt;
&lt;h3&gt;TraceSwitch&lt;/h3&gt;
&lt;p&gt;A TraceSwitch maintains a TraceLevel property that controls the importance of the trace texts passed to the TraceListeners. The usual Error, Warning, Info and Verbose are supported. Typical use is to configure the TraceSwitch in the .config file and when the code instantiates an instance using the same name it reads its settings from the .config file. Although you can use TraceSwitches standalone they are usually associated with a TraceSource (in config). It is also possible to write your own TraceSwitch.&lt;/p&gt;
&lt;h3&gt;Configuration Settings&lt;/h3&gt;
&lt;p&gt;A lot of System.Diagnostics functionality is driven by the .config file. Lets dive right in and look at the following configuration:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New" size="2"&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;system.diagnostics&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;sharedListeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Choose your trace output channels --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Console&amp;quot; type=&amp;quot;System.Diagnostics.ConsoleTraceListener&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; initializeData=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Only Error traces will go to the Event Log --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;ErrorEventLog&amp;quot; type=&amp;quot;System.Diagnostics.EventLogTraceListener&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; initializeData=&amp;quot;Jacobi.Diagnostics.TestApp&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;filter type=&amp;quot;System.Diagnostics.EventTypeFilter&amp;quot; initializeData=&amp;quot;Error&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/add&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/sharedListeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;sources&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Configure a TraceSource for each class--&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;source name=&amp;quot;Jacobi.Diagnostics.TestApp&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;listeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Console&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;ErrorEventLog&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/listeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/source&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;source name=&amp;quot;Jacobi.Diagnostics.TestApp.Class1&amp;quot; &amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;listeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Console&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;ErrorEventLog&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;remove name=&amp;quot;Default&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/listeners&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/source&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/sources&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;switches&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- SourceSwitch settings for classes --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Jacobi.Diagnostics.TestApp&amp;quot; value=&amp;quot;Error&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name=&amp;quot;Jacobi.Diagnostics.TestApp.Class1&amp;quot; value=&amp;quot;All&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/switches&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/system.diagnostics&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/font&gt; 
&lt;p&gt;The configuration settings live inside the &amp;lt;system.diagnostics&amp;gt; element. Then we see a &amp;lt;sharedListeners&amp;gt; section. Although it is possible to configure all TraceListener settings separately for each TraceSource, I prefer to maintain a global list of (configured) TraceListeners and refer to them from the TraceSource configuration. &amp;lt;sharedListeners&amp;gt; is that global place. Notice that the EventLogTraceListener has a &amp;lt;filter&amp;gt; defined that only allows Error-type traces to pass to the event log.&lt;/p&gt;
&lt;p&gt;The &amp;lt;sources&amp;gt; section allows you to list the configuration settings for all the TraceSources your application uses. If the configuration for an instantiated TraceSource is not found in the .config file, it is shut off by default. So if you expect to see trace output from a specific TraceSource but there isn&amp;#39;t any, 9 out of 10 times you did not configure it right (check the spelling).&lt;/p&gt;
&lt;p&gt;Each &amp;lt;source&amp;gt; declares its own collection of TraceListeners, in this case referring to one declared in &amp;lt;sharedListeners&amp;gt;. As a convention I&amp;#39;ve used the full class names as TraceSource names and TraceSwitch names. But you can also choose a courser granularity, say at component level or at sub-system level.&lt;/p&gt;
&lt;p&gt;&lt;strike&gt;You can associate a TraceSwitch with a TraceSource by using the switchName and switchType attributes on the &amp;lt;source&amp;gt; element. I&amp;#39;ve not done so in my example and that means that you have to instantiate the TraceSwitches manually in code (with the correct name).&lt;/strike&gt; You can associate a TraceSwitch with a TraceSource by either using the switchName and switchType attributes on the &amp;lt;source&amp;gt; element -or- by just declaring a switch (&amp;lt;switches&amp;gt;&amp;lt;add&amp;gt;) with the same name as the TraceSource.&lt;/p&gt;
&lt;h3&gt;Wrapping up&lt;/h3&gt;
&lt;p&gt;This quick tour around System.Diagnostics discussed the main classes that enable you to build pretty powerful tracing support into your application. With this information you could already instantiate a TraceSource for each class and configure a matching TraceSwitch. Code inside the class would simply call the TraceSource and it would work. You could configure it to allow specific (type of) information to come through while the rest is blocked, for instance. And although I would encourage anybody to at least take some time to fiddle with a simple console test application to try out these features, it is my experience that you&amp;#39;ll want more in a real application. That is why I build my method context information gathering framework. Although this framework does not add much to the tracing capabilities of System.Diagnostics, it does add a lot to the quality of information that is in the trace texts.&lt;/p&gt;
&lt;p&gt;I plan to write about my framework in a &lt;a class="" href="http://bloggingabout.net/blogs/marc/archive/2008/04/12/a-method-context-information-gathering-framework.aspx"&gt;future post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For more information on System.Diagnostics go to &lt;a href="http://msdn2.microsoft.com/en-us/library/zs6s4h68.aspx"&gt;MSDN&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=458144" width="1" height="1"&gt;</description></item><item><title>Writing a WCF POX Syndication Service</title><link>http://bloggingabout.net/blogs/marc/archive/2008/04/03/writing-a-wcf-pox-syndication-service.aspx</link><pubDate>Thu, 03 Apr 2008 19:59:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:458139</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=458139</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2008/04/03/writing-a-wcf-pox-syndication-service.aspx#comments</comments><description>&lt;p&gt;WCF has received some enhancements in the .NET 3.5 framework. It is now possible to use the WCF service framwork to write POX&amp;nbsp; services; a service that does not use SOAP, but Plain Old Xml.&lt;/p&gt;
&lt;p&gt;Also the Syndication support for WCF is new to .NET 3.5. It has builtin support to produce Rss 2.0 and Atom 1.0 feeds.&lt;/p&gt;
&lt;p&gt;The example I like to show you is an Event Log Feed Service. This service produces a Rss 2.0 feed for the Application event log Error entries. It is hosted in IIS and can be called by addressing it over the url:&lt;/p&gt;
&lt;p&gt;http://[base url]/Service.svc/GetLogEntries&lt;/p&gt;
&lt;p&gt;Notice the GetLogEntries &lt;u&gt;after&lt;/u&gt; the Service.svc. The GetLogEntries maps to the GetLogEntries method of the service and takes two optional parameters: an entryType (Error, Warning, Information) and a feedType (Rss1, Atom1).&lt;/p&gt;
&lt;p&gt;http://[base url]/Service.svc/GetLogEntries?feedType=atom1 &lt;br /&gt;http://[base url]/Service.svc/GetLogEntries?entryType=Warning&amp;amp;feedType=atom1&lt;/p&gt;
&lt;p&gt;To look at this for yourself download the source code &lt;a href="http://www.xs4all.nl/~mjacobi/Blog/WCF/EventLogFeed.zip"&gt;here&lt;/a&gt; and install the service in IIS. Make sure the service dll is in the web&amp;#39;s bin folder.&lt;/p&gt;
&lt;p&gt;The Service interface is declared using WFC&amp;#39;s ServiceContract attribute.&lt;/p&gt;
&lt;p&gt;[ServiceKnownType(typeof(Atom10FeedFormatter))] &lt;br /&gt;[ServiceKnownType(typeof(Rss20FeedFormatter))] &lt;br /&gt;[ServiceContract] &lt;br /&gt;public interface IEventFeedService &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [WebGet(UriTemplate=&amp;quot;/GetLogEntries?eventType={eventType}&amp;amp;feedType={feedType}&amp;quot;)] &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [OperationContract] &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SyndicationFeedFormatter&amp;lt;SyndicationFeed&amp;gt; GetLogEntries(string eventType, string feedType); &lt;br /&gt;}&lt;/p&gt;
&lt;p&gt;The return types are declare with using the ServiceKnownType attribute. The WebGet attribute makes it possible to call this service using the url (GET). The UriTemplate declares what possible variation are supported on the url: the method name and its optional parameters. Note that the parameter names of the method match the parameter names in the UriTemplate.&lt;/p&gt;
&lt;p&gt;The Service implementation class implements the method of the Service interface (refer to the dowload for complete source code). Creating the Syndication Feed is a matter of creating SyndicationFeedItem instances and adding them to a SyndicationFeed instance. Finally the method returns either a Rss20FeedFormatter or a Atom10FeedFormatter instance depending on the requested feed format.&lt;/p&gt;
&lt;p&gt;The Service.svc file is used by IIS to determine how to host the service.&lt;/p&gt;
&lt;p&gt;&amp;lt;%@ServiceHost Factory=&amp;quot;System.ServiceModel.Web.WebServiceHostFactory&amp;quot; Service=&amp;quot;EventLogFeedService.EventFeedService&amp;quot; %&amp;gt;&lt;/p&gt;
&lt;p&gt;Besides specifying which service class should be hosted, the file also specifies a Factory to create a WCF service Host instance. Note that this is a new class that supports the url addressing of our WebGet enabled service.&lt;/p&gt;
&lt;p&gt;Disclaimer: Exposing event log information to external sources can expose a security hole!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=458139" width="1" height="1"&gt;</description></item><item><title>7 WCF/SOA Tips</title><link>http://bloggingabout.net/blogs/marc/archive/2008/03/29/7-wcf-soa-tips.aspx</link><pubDate>Sat, 29 Mar 2008 15:48:00 GMT</pubDate><guid isPermaLink="false">813b6dfd-644e-4573-a816-eebab56ba0d0:458102</guid><dc:creator>Marc Jacobi</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://bloggingabout.net/blogs/marc/rsscomments.aspx?PostID=458102</wfw:commentRss><comments>http://bloggingabout.net/blogs/marc/archive/2008/03/29/7-wcf-soa-tips.aspx#comments</comments><description>&lt;p&gt;David Pallman gives 7 WCF and SOA tips. Not all rocket science but interesting non-theless.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div&gt;&lt;a class="" href="http://davidpallmann.spaces.live.com/blog/cns!E95EF9DC3FDB978E!257.entry" target="_blank"&gt;Service Interface Design&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;a class="" href="http://davidpallmann.spaces.live.com/blog/cns!E95EF9DC3FDB978E!258.entry" target="_blank"&gt;Service Class Design&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;a class="" href="http://davidpallmann.spaces.live.com/blog/cns!E95EF9DC3FDB978E!259.entry" target="_blank"&gt;Service Hosting&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;a class="" href="http://davidpallmann.spaces.live.com/blog/cns!E95EF9DC3FDB978E!260.entry" target="_blank"&gt;Configuration&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;a class="" href="http://davidpallmann.spaces.live.com/blog/cns!E95EF9DC3FDB978E!261.entry" target="_blank"&gt;Infrastructure&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;a class="" href="http://davidpallmann.spaces.live.com/blog/cns!E95EF9DC3FDB978E!262.entry" target="_blank"&gt;Instrumentation&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;a class="" href="http://davidpallmann.spaces.live.com/blog/cns!E95EF9DC3FDB978E!263.entry" target="_blank"&gt;Clients&lt;/a&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://bloggingabout.net/aggbug.aspx?PostID=458102" width="1" height="1"&gt;</description></item></channel></rss>