<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-2285278671879033267</atom:id><lastBuildDate>Fri, 03 Apr 2026 19:26:52 +0000</lastBuildDate><category>xpo</category><category>devexpress</category><category>eco</category><category>ravendb</category><category>vistadb</category><category>postsharp</category><category>production</category><category>resharper</category><category>visualstudio</category><category>windowsvista</category><category>cloud</category><category>nservicebus</category><category>winforms</category><category>xml</category><title>Atlantic Breeze</title><description>A .Net view onto the Atlantic</description><link>http://kearon.blogspot.com/</link><managingEditor>noreply@blogger.com (Sean Kearon)</managingEditor><generator>Blogger</generator><openSearch:totalResults>41</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-1448996683657910394</guid><pubDate>Fri, 15 Jun 2018 16:06:00 +0000</pubDate><atom:updated>2020-12-28T09:42:59.716+00:00</atom:updated><title>Using Rebus Service Bus from F# with DotNet Core</title><description>&lt;p&gt;&lt;b&gt;UPDATE December 2020&lt;/b&gt;&lt;/p&gt;&lt;p&gt;There is an improved and updated version of this article here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://seankearon.me/posts/2020/12/rebus-sagas-fsharp/&quot;&gt;https://seankearon.me/posts/2020/12/rebus-sagas-fsharp/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This post is about how to use Rebus from F# using DotNet Core.&amp;nbsp; Code for the below is &lt;a href=&quot;https://github.com/seankearon/rebus-fsharp&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;h1&gt;What is Rebus?&lt;/h1&gt;&lt;p&gt;Rebus is a free, open-source service bus written in .NET.&amp;nbsp; Source code is in &lt;a href=&quot;https://github.com/rebus-org/Rebus&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt; and, whilst it’s absolutely free to use, there are also professional support services provided by &lt;a href=&quot;https://rebus.fm/&quot; target=&quot;_blank&quot;&gt;rebus.fm&lt;/a&gt; if you need them.&amp;nbsp; It is very similar to other .NET service busses like &lt;a href=&quot;https://particular.net/nservicebus&quot; target=&quot;_blank&quot;&gt;NServiceBus&lt;/a&gt; (commercial) or &lt;a href=&quot;http://masstransit-project.com/&quot; target=&quot;_blank&quot;&gt;MassTransit&lt;/a&gt; (free).&lt;/p&gt;&lt;h1&gt;Why not Functions as a Service?&lt;/h1&gt;&lt;p&gt;You can use something like Azure Functions or AWS Lambda and easily knock up a simple message-based architecture.&amp;nbsp; &lt;/p&gt;&lt;p&gt;Azure Functions give you a lot of integration points and management tooling out of the box and you can &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/azure-functions/functions-runtime-install&quot; target=&quot;_blank&quot;&gt;install on your own box&lt;/a&gt; so you don’t even need to be tied to the cloud.&amp;nbsp; They’ve even got &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-install&quot; target=&quot;_blank&quot;&gt;durability and orchestration&lt;/a&gt; now.&lt;/p&gt;&lt;p&gt;It’s all super cool and could well be all you need for most scenarios.&amp;nbsp; Services busses, like Rebus, NServiceBus or MassTransit have a whole lot of additional things that are not available out of the box with FaaS today, such as:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Publish/Subscribe (with more than one subscriber!)&lt;/li&gt;&lt;li&gt;Support for complex workflows (&lt;a href=&quot;https://github.com/rebus-org/Rebus/wiki/Coordinating-stuff-that-happens-over-time&quot; target=&quot;_blank&quot;&gt;sagas&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Can be used in anywhere: web apps, desktop apps, services, the cloud…&lt;/li&gt;&lt;li&gt;Groovy stuff like &lt;a href=&quot;https://github.com/rebus-org/Rebus/wiki/Timeouts&quot; target=&quot;_blank&quot;&gt;deferred messages&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That’s not a full list and I’m not saying FaaS &amp;gt; Service Bus or FaaS &amp;lt; Service Bus.&amp;nbsp; My reasons for choosing Rebus here are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;I’ve been using it for years and trust it.&lt;/li&gt;&lt;li&gt;I’m already deploying a .NET Core Web API and want to host my bus in that.&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;A Service Bus Inside a .NET Core Web API?&lt;/h1&gt;&lt;p&gt;Really?&amp;nbsp; WTF???&amp;nbsp; I’ve been handling complex, long-running workflows inside an Azure Web App for a couple of years now (read my previous article &lt;a href=&quot;http://kearon.blogspot.com/2016/06/running-rebus-service-bus-in-azure-web.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;).&amp;nbsp; That implementation is using Rebus with C# on .NET 4.x and has been running like a dream for years.&amp;nbsp; As it’s in an Azure Web App, you can scale it up or down flicking a switch.&amp;nbsp; I love it because it’s so simple!&amp;nbsp; &lt;/p&gt;&lt;p&gt;So, given that I am writing a web API, I thought I’d use Rebus inside that.&amp;nbsp; My API is written using F#, .NET Core and &lt;a href=&quot;https://github.com/giraffe-fsharp/Giraffe#giraffe&quot; target=&quot;_blank&quot;&gt;Giraffe&lt;/a&gt;.&amp;nbsp; I’ve never seen anything about Rebus with F# before, but F# is just .NET and has &lt;a href=&quot;https://fsharpforfunandprofit.com/posts/completeness-seamless-dotnet-interop/&quot; target=&quot;_blank&quot;&gt;excellent interoperability with C#&lt;/a&gt;.&amp;nbsp; &lt;/p&gt;&lt;p&gt;By the way, I’m using F# because it’s expressive, concise and is a beautiful language for modelling domains.&amp;nbsp; Read more from the venerable &lt;a href=&quot;https://twitter.com/ScottWlaschin&quot; target=&quot;_blank&quot;&gt;Scott Wlaschin&lt;/a&gt; here:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fsharpforfunandprofit.com/ddd/&quot; title=&quot;https://fsharpforfunandprofit.com/ddd/&quot;&gt;https://fsharpforfunandprofit.com/ddd/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://fsharpforfunandprofit.com/posts/no-uml-diagrams/&quot; title=&quot;https://fsharpforfunandprofit.com/posts/no-uml-diagrams/&quot;&gt;https://fsharpforfunandprofit.com/posts/no-uml-diagrams/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Scott’s book, &lt;a href=&quot;https://pragprog.com/book/swdddf/domain-modeling-made-functional&quot; target=&quot;_blank&quot;&gt;Domain Modelling Made Functional&lt;/a&gt; is also an excellent read.&amp;nbsp; If you’re coming to F# from C# then I recommend&amp;nbsp; &lt;a href=&quot;https://www.manning.com/books/get-programming-with-f-sharp&quot; target=&quot;_blank&quot;&gt;Get Programming with F#&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/isaac_abraham&quot; target=&quot;_blank&quot;&gt;Isaac Abraham&lt;/a&gt; as well as &lt;a href=&quot;https://fsharpforfunandprofit.com&quot; target=&quot;_blank&quot;&gt;Scott’s website&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Anyway, let’s get started!&lt;/p&gt;&lt;h1&gt;Create .NET Core API with Giraffe&lt;/h1&gt;&lt;p&gt;Instructions on how to set up a Giraffe app using &lt;font face=&quot;Courier New&quot;&gt;dotnet new&lt;/font&gt; are in Giraffe’s docs &lt;a href=&quot;https://github.com/giraffe-fsharp/Giraffe#getting-started&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&amp;nbsp; The command line I used was: &lt;font face=&quot;Courier New&quot;&gt;dotnet new giraffe –lang F# –V none&lt;/font&gt;.&lt;/p&gt;&lt;p&gt;This will give you a basic, functional .NET Core web API project.&amp;nbsp; To that, add the following Rebus Nuget packages: &lt;font face=&quot;Courier New&quot;&gt;Rebus &amp;amp; Rebus.ServiceProvider&lt;/font&gt;.&lt;/p&gt;&lt;p&gt;After that, you should be able to run your API and get a response from &lt;font face=&quot;Courier New&quot;&gt;~/api/hello&lt;/font&gt;.&amp;nbsp; Here’s the routing configuration at this stage.&amp;nbsp; Cool, eh?&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5W3r6F3ZtQwqzOITnHUtj-880V_nX5525_LVJSZSIwHks_mUjB18mecttZA_Thb3BMZj6FEFY3kkfF6oaATS_xqkccQaNJb4jTRE5Blk-3U_dx_psXiZSllnMnz07Kd4crk-T9cWcLX7O/s1600-h/image3&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;205&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhATSElH0rMRyFU1Tyx9eeuKBdh1VwHa4Pb7Qhyphenhyphen-dC6SSoNPxFDbIbpcz3RASn3kCsiv4-NQXM2FtPe2LrwwBYrlgvSx7SfIllAKo2SQnvEMwLxT7eX9Wn3pE3LoEwNZwzl7_VD0W4Jw6lu/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;h1&gt;Configure Rebus&lt;/h1&gt;&lt;p&gt;We’re loosely following Rebus’ .NET Core configuration that you can find in their GitHub &lt;a href=&quot;https://github.com/rebus-org/Rebus.ServiceProvider&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&amp;nbsp; Instead of using Rebus’ in-memory transport as in the previous link, I’m going to use the file system transport.&amp;nbsp; This is a great transport to use when hacking on Rebus as you can see your messages as files, and failed messages will be dropped into the “error queue”, which is a folder named “error”.&amp;nbsp; By default, Rebus serialises messages to JSON with Base64 encoding of the message body, so they’re pretty easy to read. Error messages are added to the message as headers.&amp;nbsp; Sweet!&lt;/p&gt;&lt;h2&gt;Create a Message&lt;/h2&gt;&lt;p&gt;Firstly, we need a message that we will send to Rebus.&amp;nbsp; In Rebus, messages are modelled using .NET classes.&amp;nbsp; Our message is going to be a very simple command to tell the bus to say hello.&amp;nbsp; Here is is:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3zvWAxyiCFsHPKeJejVPnKji93ejaCbkhlHGKpcPt6oblKKrRdCvO169BvOPaPbvJuB9XjBeLLXqMUcHp8ChZph1UaCN8ne6P-ewQwuLzLp-ImWmiypo93LWkZQ0-FtwoJjxTp9FAHCie/s1600-h/image7&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;141&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDraVzf2-S4_isnwSv0atyoGjNW-AjRFZRP8sdfDqf_JlVerZzmVB1Tk_sUc_KUrqvD4wrclTG3XxQ7jWhZITBAaTkfcl1vzavJyYF_vaiK8NYBhwnzNaAMuvX_0HsjUH1x2H3XN6npRZ_/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;So, this is an &lt;a href=&quot;https://fsharpforfunandprofit.com/posts/records/&quot; target=&quot;_blank&quot;&gt;F# record&lt;/a&gt; type that holds a single string field called &lt;font face=&quot;Courier New&quot;&gt;Name&lt;/font&gt;.&amp;nbsp; The &lt;font face=&quot;Courier New&quot;&gt;CLIMutable&lt;/font&gt; attribute tells the compiler to generate IL that’s more friendly for the .NET serialisers – read about that on Mark Seeman’s blog &lt;a href=&quot;http://blog.ploeh.dk/2013/10/15/easy-aspnet-web-api-dtos-with-f-climutable-records/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;h2&gt;Create a Message Handler&lt;/h2&gt;&lt;p&gt;Next, we need something to handle those messages.&amp;nbsp; In Rebus, that’s a class that implements &lt;font face=&quot;Courier New&quot;&gt;IHandleMessates&amp;lt;MyMessageType&amp;gt;&lt;/font&gt;, these are then registered into the bus.&amp;nbsp; Rebus gives you &lt;a href=&quot;https://github.com/rebus-org/Rebus/wiki/Handler-pipeline&quot; target=&quot;_blank&quot;&gt;fine-grained control&lt;/a&gt; over these are handled, but we only need a very simple handler.&amp;nbsp; Here is what the interface looks like &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKcZJZwf9WZbzzboiWtZfZ6T4dOhYBF8iGzl-PMFFhlAsMVSBLOncZKzEdwId67234NWIpzcwoUjbzQia8LDt3bw2QkcQIAYko9rMMJT6N8bUL7NC6qDaUyljp_K1oCvSajvnpyn0ERyiX/s1600-h/image11&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;179&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjosvBASjVnYrjhFEiQCZvSJCLnfdIrySy6yqrR1BcRuHG02Nm7DTSxHY0SbxIEOMNbA45h8UGLIasytKWmfK-_ct31RKqCMxUNJj6JLJJbavH_d8-zE4I-0D6t028skI-9W7fwZj5dzBmz/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Here’s what our F# implementation to handle our messages of type &lt;font face=&quot;Courier New&quot;&gt;Commands.SayHello&lt;/font&gt; looks like:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJeYRecQF4y5gVUi7UdHcgl4iXRd6_jLqeY4tFWqFvh1GR4z5Rw007JKK6iuuIELVVfPiKNiOmSqbW8LEgZv-z1BtVKA8LlglUrzd4-0yTB92ncLisJLbutBKFAleXeFHHHN0FA6BeBRdY/s1600-h/image15&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;110&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiFB7sr-c92ohPKhElC1PWQHhsf6V3KqVTdx9zIU6FmhTmVdqGun4zqfrKzpSI8O1LbA7hZtQVUotme-BlRYYxQrff6J2eGvdrPQnGThZmWt-2iyvXqiTos7ZjIMDGUm0XC7Q6sayV7VGg/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This is a class in F# with a default constructor that implements the &lt;font face=&quot;Courier New&quot;&gt;IHandleMessages&amp;lt;Commands.SayHello&amp;gt;&lt;/font&gt; interface.&amp;nbsp; (A good place to start reading about classes is &lt;a href=&quot;https://fsharpforfunandprofit.com/posts/overview-of-types-in-fsharp/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.)&amp;nbsp; &lt;/p&gt;&lt;p&gt;Rebus, being written in C# uses System.Threading.Tasks.Task for concurrency.&amp;nbsp; F# has it’s own support for concurrency using &lt;font face=&quot;Courier New&quot;&gt;Async&lt;/font&gt; workflow, and &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/asynchronous-and-concurrent-programming/async#for-the-cvb-programmer-looking-into-f&quot; target=&quot;_blank&quot;&gt;these are not the same things&lt;/a&gt;.&amp;nbsp; You can, however, convert between the two models.&amp;nbsp; &lt;/p&gt;&lt;p&gt;It’s worth noting that Giraffe works with &lt;font face=&quot;Courier New&quot;&gt;Task/Task&amp;lt;T&amp;gt;&lt;/font&gt; and not F#’s &lt;font face=&quot;Courier New&quot;&gt;Async&lt;/font&gt;. It does this to avoid having to always convert. &lt;/p&gt;&lt;p&gt;If you look at the code above, we are using F#’s Async and then piping that to &lt;font face=&quot;Courier New&quot;&gt;RunAsRebusTask&lt;/font&gt; to convert back to a &lt;font face=&quot;Courier New&quot;&gt;Task&lt;/font&gt;.&amp;nbsp; Here’s how I’m doing that (using code from &lt;a href=&quot;https://fslang.uservoice.com/forums/245727-f-language/suggestions/6092853-async-waittask-for-non-generic-task&quot; target=&quot;_blank&quot;&gt;Veikko Eeva&#39;s comment here&lt;/a&gt;): &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaDqSkLgcfKfeIsbsTJ86EGNN5sjSytzIzu4khytbWnyA0-SUhN71K3fPb2cHP78gsHp6W95SfbPJtcFtr0KVQeYokmm8ymKsbdmX1r825fL6URoZGZQij6tQXFZ4T9yVy6zeIqcHuI1m2/s1600-h/image19&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;84&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvuzmkYLcua7OPt9FLcw3YqsRTEMv_NaMQ-c385oThppKsWqrGyfBjOgqFdmTLlJQyl8_NJdLGL_78Zg0MZtd9dFcxVE2O9bdg06ZxgleV9m64Iv78Cw8mWv-lgQjT2AvEi_5VYP1Ht7GB/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Configure and Start the Bus&lt;/h2&gt;&lt;p&gt;Lastly, we need to configure and start Rebus’ bus.&amp;nbsp; We do that like this:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeTxzQVc4eHWY1yKYVVi1d_bHiz4BvKm1hhSbv60Kaa9blkLn7Jx9yE5qmK-mgQ3_1NLyjIq92TjjCf_tIvA8yAAltqrZxx449QEFsLGdxtIvSKCjzYThdhjwWmgeYyCf7V_hDmHx2ArRW/s1600-h/image23&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;180&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjANbizRb7eYb4OpR-uMtJiCsba4QeZDOibwZjeWLlN6LDKOR4HpLm4N6EElGCK1UsmkVQqIoqvujqSQ9uU6glW1ipUKksZTxL50O2Fsc5ecDsWBf6hJ5KheIiaCB1pZdPkt7zr1avVjsbn/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This is nearly identical to the C# equivalent.&amp;nbsp; The two notable changes are when we pipe output to ignore, which is needed because &lt;a href=&quot;https://fsharpforfunandprofit.com/troubleshooting-fsharp/#fs0020-with-expressions-that-are-not-the-last-expression-in-the-block&quot; target=&quot;_blank&quot;&gt;only the last expression in a block can return a value in F#&lt;/a&gt;, and the use of the different F# lambda syntax &lt;font face=&quot;Courier New&quot;&gt;fun x –&amp;gt; ….&lt;/font&gt;. &lt;/p&gt;&lt;p&gt;By default, Rebus will retry handling a message 5 times before it fails.&amp;nbsp; If you’re hacking on Rebus, you may want only one exception in your message.&amp;nbsp; You can configure the number of retries like you see on line 47 (again, a slightly different syntax to what you’d use in C#)&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf7mSwNphGkifv1f6AvCqlLEWQDq24EiGe2t-9I9O4ef8g-3Gd9G1wEMxwQl9WH4hMjB0ZOUZSEMDyar-jdefeB3UWlCas1IdokybE08xHmA9l905cC_mCmZa2By6WnhHMsIv8p99VOmnE/s1600-h/image27&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;192&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS8PAHk06R1phO5XP5rDoxDEACyV1aUn3Ru6O7_M7Dl4pBLp688Do5qPpAoUFKm1pYj5mmA_lMdVUx8ZrCR_EctG-v9pxlwLiup3teEU0HqRmLGaHlccAni2vlUpRBsQALq7VAlR0AajDj/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Then just hook that method up in your .NET Core service configuration as follows&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-WEcecJoq92VpbJwluZBc2e0fqPnrIUCxwUy5KjxxclVmxERH6p_so_GoGw65a5WzpxGtSR6XRVlra2sIECdK2cgFZcKJC4r98aiLjCUv7dqwBX_RzUqVfHMU7RnHHnDEoFDab0zkanzg/s1600-h/image31&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;139&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRPxoZC68F3FJtN44jiwSzjROGiUxIgi-R4jiIAnwE_aO9negnLik_bavirMH1mFvOX2POhDMQtjbtJ24yRbe9QfG9w1OHRFRUtQagogOmDli3qsN0tNeZqRqmbEBwqEU7edD5yirolaWd/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;h1&gt;Send a Message to the Bus&lt;/h1&gt;&lt;p&gt;All good, we’ve got our Rebus bus running and waiting to handle messages.&amp;nbsp; We just need to send it a message.&lt;/p&gt;&lt;p&gt;In my &lt;a href=&quot;http://kearon.blogspot.com/2016/06/running-rebus-service-bus-in-azure-web.html&quot; target=&quot;_blank&quot;&gt;last article&lt;/a&gt;, I used a timer inside the web app to send a message.&amp;nbsp; This was because I wanted to be able to leave it running for a day or so and come back to see that the bus had stayed running over that time.&amp;nbsp; This time, I’m going to send a message to the bus as a result of a POST call to the API.&lt;/p&gt;&lt;h2&gt;Set the Routing&lt;/h2&gt;&lt;p&gt;Change the routing section to add a POST call, like this:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7uDB1I2-8g9Y6dsrXWnBFtPjpZ4b-5oEF_ovbyVltMaBvoakEqwd6wsD4P3l20W26I8v6axkAvGKyRS899rvgtO0cV5xQFzPE5yimDUT_UmLN1g3_u7EXPS6MsStpL-ehVM1aPkUPgZyL/s1600-h/image%255B4%255D&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;276&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBvJuj9z4LPRk4_pOKghfvgpPfh2MsSXKRAv7ZZKoQF02jTImPtMuSRwH5259x4H7FoOC9oyZ5oA8XqJBpG2DDanju5bSdCPek6H71gCPUsU05UVWdNxTikebON8vyXH1A85nPPglKrB_S/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Note that there is no “fish” between the route and the handler when you use &lt;font face=&quot;Courier New&quot;&gt;routef&lt;/font&gt;.&lt;/p&gt;&lt;h2&gt;Create an HTTP Handler&lt;/h2&gt;&lt;p&gt;We’re using Giraffe’s &lt;a href=&quot;https://github.com/giraffe-fsharp/Giraffe/blob/master/DOCUMENTATION.md#routef&quot; target=&quot;_blank&quot;&gt;routef&lt;/a&gt;&lt;font face=&quot;Courier New&quot;&gt;&lt;/font&gt; function to configure a route that passes off to &lt;font face=&quot;Courier New&quot;&gt;sayHello&lt;/font&gt;. The implementation of which looks like this:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2nNN16Ntdn42fLfOQg0aEdpc5AR-Ux2PpckrwtOfVLf2AQvkPIEWtgwnciOF7ZWBsNk_KWSnqpYv7GIgHmLoav9RGuWHEepTVk45aqyR8Zk9hWB5xAbxAyI8FvvIo9jzqETH-Ze9icXxj/s1600-h/image39&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;188&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihvzMPXweWaFNMJFHoVl_BLRrMoiFgu4rlCWuYRe4DT3b57bx3RhC5mJDMr4DfG-g6Z3d7PsjdNe8nPGnfMuHcp7WxmyJNHjRUlbIwu5llfkvtMWe5ebsp6dusK867ehNb-vjF0-MF3ni4/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This function receives the string parameter passed from the routing and returns an &lt;font face=&quot;Courier New&quot;&gt;HttpHandler&lt;/font&gt;.&amp;nbsp; You can see it uses &lt;font face=&quot;Courier New&quot;&gt;task { … }&lt;/font&gt; starting on line 23, which is Giraffe’s Task implementation mentioned earlier.&lt;/p&gt;&lt;p&gt;Line 25 does the business and sends a new message to the bus.&amp;nbsp; We then return OK with a message saying the world is good.&lt;/p&gt;&lt;p&gt;On line 24 you can see that it uses an extension method on the &lt;font face=&quot;Courier New&quot;&gt;ctx&lt;/font&gt; parameter (which is of type &lt;font face=&quot;Courier New&quot;&gt;HttpContext&lt;/font&gt;).&amp;nbsp; This is how you retrieve registered services from inside your HTTP handlers.&amp;nbsp; If you’re coming from a C# background you may be expecting to see some sort of dependency injection.&amp;nbsp; Dependencies are more explicit in a functional language – here they come from being passed in as a parameter.&amp;nbsp; Read more about dependency management in functional programming &lt;a href=&quot;https://fsharpforfunandprofit.com/posts/dependency-injection-1/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&amp;nbsp; In an OO codebase, line 24 would be called a Service Locator and lots of people would get very hot and bothered if they saw that.&amp;nbsp; Don’t worry, it’s fine.&amp;nbsp; The world isn’t going to end and your codebase will stay nice and maintainable!&lt;/p&gt;&lt;h1&gt;All Done – Run it!&lt;/h1&gt;&lt;p&gt;Run the project, and then post to our API and you get back a 200 OK with a nice message:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9L380opwVaBynb-aF3c_f_qXV9IFrtX0TQa_X9pGYwBNjM60DMkAaMY3EfuC9yabbPe_qqXWnM7zDISIq5wbc8pfea89IJ1gF14XKSNygQP-BkV44uzmldDvLovt2-0qAKLQ4-WdUVJnn/s1600-h/SNAGHTMLa018c87%255B4%255D&quot;&gt;&lt;img alt=&quot;SNAGHTMLa018c87&quot; border=&quot;0&quot; height=&quot;230&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjazwfXcvlFSh2C-Ca04l7DHMuWYMdNlVJzKSivE242DqUPfAG_kKUhifCLTyLvGwgZ1aDovznmNgn6-Diz-F7zwYq7eQnc5CVhTvWXuRYJJAal_Rd1tn22qPum8HEQOfCOR5MRK-xyOW4Z/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;SNAGHTMLa018c87&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If you look in the console output from the app, you’ll see that our message has been handled by our message handler, which has printed out a nice message for us:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4HsW_PbVmyZ-4Ba4gby1S5fTcsZtqspiR7FAmYzGOs8c1nbTxSpZnuy8dN7j21FUb2C9RiWmEqBwjGgYv4DZ_aHgJn28HLv_5ajATHnpQkFXudlN_rJLJrdtHgu7BdIrftgPI19AEcXtc/s1600-h/image%255B14%255D&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; height=&quot;258&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhG3zMHJu0KWPyW-fWZ2S98fz_GinJmQQMR_hADE56-LIo-rMcgzdZ5judAe1chv50nGyab1ocoO6vQ9-GdEehipFpa2nM5duXvJmRS6dItJVOwdbPQrw2Y2QNhXeATuihuTf1u9cZsnbH/?imgmax=800&quot; style=&quot;background-image: none; display: inline;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;And there you have it – an F# implementation of a Rebus service bus running inside a Giraffe .NET Core Web API app!&lt;/p&gt;&lt;h1&gt;Closing Thoughts&lt;/h1&gt;&lt;p&gt;You can easily adapt the code above to run in other hosts, such as a console app, a service or a desktop app.&amp;nbsp; &lt;/p&gt;&lt;p&gt;Remember that you’re not limited to using the file system to transport your messages..&amp;nbsp; Rebus provides a whole load of transports that you can use, ranging from RabbitMQ, Azure Storage Queues to databases like RavenDB, Postgres and SQL Server.&amp;nbsp; You can see a list of what’s supported in .NET Core on &lt;a href=&quot;https://github.com/rebus-org/Rebus/issues/358&quot; target=&quot;_blank&quot;&gt;this thread&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you’re going to host in an Azure Web App, don’t forget to set the app to be “always-on”, as shown at the end of my &lt;a href=&quot;http://kearon.blogspot.com/2016/06/running-rebus-service-bus-in-azure-web.html&quot; target=&quot;_blank&quot;&gt;previous article&lt;/a&gt;.&amp;nbsp; You can also read a little about how to scale your bus in there too.&lt;/p&gt;&lt;p&gt;Code for the above is &lt;a href=&quot;https://github.com/seankearon/rebus-fsharp&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</description><link>http://kearon.blogspot.com/2018/06/using-rebus-service-bus-from-f-with.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhATSElH0rMRyFU1Tyx9eeuKBdh1VwHa4Pb7Qhyphenhyphen-dC6SSoNPxFDbIbpcz3RASn3kCsiv4-NQXM2FtPe2LrwwBYrlgvSx7SfIllAKo2SQnvEMwLxT7eX9Wn3pE3LoEwNZwzl7_VD0W4Jw6lu/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-6960108972673185401</guid><pubDate>Wed, 23 Aug 2017 17:54:00 +0000</pubDate><atom:updated>2017-08-24T07:07:25.173+01:00</atom:updated><title>Creating a new Fable React/Redux project</title><description>&lt;h2&gt;React and Redux&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://facebook.github.io/react/&quot; target=&quot;_blank&quot;&gt;React&lt;/a&gt; is Facebook’s JavaScript library for building user interfaces.&amp;nbsp; It’s a joy to develop with and has a “learn once, write anywhere” philosophy that allows you to use your React skills to build not just JS based UI, but also Node-based server-side apps and mobile apps using &lt;a href=&quot;https://facebook.github.io/react-native/&quot; target=&quot;_blank&quot;&gt;React Native&lt;/a&gt;.&lt;p&gt;&lt;a href=&quot;http://redux.js.org/&quot; target=&quot;_blank&quot;&gt;Redux&lt;/a&gt; is a predictable state container for JavaScript apps that is commonly used with React apps.&amp;nbsp; It brings a whole pile more awesome to the table with things like time travelling debugging.&amp;nbsp; There’s a bunch of free tutorial videos linked from the project’s home page.&lt;p&gt;All in all, the developer experience for using React is very joyful.&amp;nbsp; The only downside is that setting things up can be difficult.&amp;nbsp; I think this comment applies to a lot of the JavaScript world at the moment, but this is recognised and there is a lot of effort to make getting started easier.&amp;nbsp; For example, check out the &lt;a href=&quot;https://github.com/facebookincubator/create-react-app&quot; target=&quot;_blank&quot;&gt;create-react-app&lt;/a&gt; project.&lt;p&gt;I’ve got to say thanks here to &lt;a href=&quot;https://twitter.com/NickLanng&quot; target=&quot;_blank&quot;&gt;@nicklanng&lt;/a&gt; for introducing me to the joys of React and Redux – your lunchtime lightning talk changed my dev-life, mate! :)&lt;h2&gt;Fable&lt;/h2&gt;&lt;p&gt;The &lt;a href=&quot;http://fable.io/&quot; target=&quot;_blank&quot;&gt;Fable Compiler&lt;/a&gt; compiles F# into JavaScript.&amp;nbsp; It’s tag line is:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;The compiler that emits JavaScript you can be proud of!&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Or, in the words of &lt;a href=&quot;http://tomasp.net/&quot; target=&quot;_blank&quot;&gt;Tomas Petricek&lt;/a&gt;, &lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;JavaScript you can take home to meet your mother.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;You’ve gotta love that description!&lt;/p&gt;&lt;p&gt;So, basically you can write beautiful, type safe, immutable F# code and Fable will translate it into JavaScript for you.&amp;nbsp; That’s another level of awesome and I encourage you to take a look at the &lt;a href=&quot;http://fable.io/samples.html&quot; target=&quot;_blank&quot;&gt;amazing samples&lt;/a&gt; to see what can be done with Fable.&amp;nbsp; You can even set a breakpoint in Chrome and you’ll see the F# code in the Chrome dev tools!&amp;nbsp; Oh my…&lt;p&gt;Whilst things like TypeScript and Facebook Flow are very good to help you write complex JavaScript apps, having the F# compiler behind takes that support to a whole new level.&amp;nbsp; &lt;p&gt;Why not &lt;a href=&quot;http://elm-lang.org/&quot; target=&quot;_blank&quot;&gt;Elm&lt;/a&gt;?&amp;nbsp; Elm also brings the benefits of a functional type-checked language to web development. and it’s certainly an awesome language.&amp;nbsp; For me, the choice of Fable comes down to the fact that it can keep growing my F# skills whilst doing web development (&lt;a href=&quot;https://www.goodreads.com/quotes/520768-the-used-key-is-always-bright&quot; target=&quot;_blank&quot;&gt;the used key is the brightest&lt;/a&gt;, right?), and I can also leverage the wonderful “learn once, write many” approach of React to write native mobile apps.&amp;nbsp; (Sure, there’s some talk about using &lt;a href=&quot;http://ohanhi.com/elm-native-ui.html&quot; target=&quot;_blank&quot;&gt;Elm with React Native&lt;/a&gt; if that floats your boat.)&lt;p&gt;You even stop at breakpoints in Chrome in your F# code - tell me that that’s not just &lt;em&gt;totally amazing&lt;/em&gt;!&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkBlI3AjFA0DJro2paFunkULY78U95QCINZz7vNYh3fwi2zsTI3bXXGheCXx5RNBVT4E3LMLWGSYqLRKap2jBNSiE2sbS0GwDSpPW9fhWnw_GZk5JhywfdBeSjA35wtPT6ja8D_EAOul2f/s1600-h/image%255B2%255D&quot;&gt;&lt;img width=&quot;244&quot; height=&quot;115&quot; title=&quot;image&quot; style=&quot;margin: 0px; display: inline; background-image: none;&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVq-d40xAkWu-Yj9uXr-otanzOvDDNs3W_MRIBhCSOpO_Tu2RxlHiHyfb2mSarMpI4yvjKvccNz1-57iWf1alNM039ovX_HPNuZnkMo0Ceylz0QkDbkMxlAoyuLRNNLdD10T24vIYIFqYq/?imgmax=800&quot; border=&quot;0&quot;&gt;&lt;/a&gt;&lt;h2&gt;But…&lt;/h2&gt;&lt;p&gt;But setting up a Fable React/Redux project isn’t the easiest thing to do, particularly when you’re starting out.&amp;nbsp; So, if you’d like to take Fable with React and Redux out for a spin, but didn’t know where to get started, read on.&lt;h2&gt;Getting Started&lt;/h2&gt;&lt;p&gt;Firstly, head over to Fable’s page about getting set up and install all the shizzle you’ll need (.Net Core, Yarn, etc.).&amp;nbsp; You can find that here:&lt;/p&gt;&lt;p&gt;&lt;a title=&quot;http://fable.io/pages/getting-started.html&quot; href=&quot;http://fable.io/pages/getting-started.html&quot;&gt;http://fable.io/pages/getting-started.html&lt;/a&gt;&amp;nbsp;&lt;p&gt;Then follow the steps below to create your first Fable React/Redux project and start hacking:&lt;h2&gt;1 – Create a Project&lt;/h2&gt;&lt;p&gt;We’re going to create a project called “fableredux”.&amp;nbsp; If you want, change that to something else, but make sure you use your name throughout the rest of the instructions.&amp;nbsp; (You’ll be working mainly in your console.)&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;dotnet new fable -n fableredux&lt;br&gt;cd fableredux&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;2 - React and Redux&lt;/h2&gt;&lt;p&gt;Install the NPM modules we’ll need:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;yarn add react react-dom fable-core fable-react redux&lt;br&gt;yarn install (might not be needed)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;3 - Configure webpack&lt;/h2&gt;&lt;p&gt;Locate the file &lt;font face=&quot;Consolas&quot;&gt;webpack.config.js&lt;/font&gt;.&amp;nbsp; We’re going to add the externals section to tell webpack about the external dependencies.&amp;nbsp; If the section is already present, just add the entries for react and redux, as below:&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; devServer: {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; contentBase: resolve(&#39;./public&#39;),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; port: 8080&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;/font&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // This section needs React and Redux&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; externals: {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;react&quot;: &quot;React&quot;,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;redux&quot;: &quot;Redux&quot;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module: {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;4 - Update References&lt;/h2&gt;&lt;p&gt;The Fable sample app loads the React and Redux JS dependencies from disk in in it’s index.html file.&amp;nbsp; We’ll stick with that approach.&lt;p&gt;Copy index.html and the supporting files in the &lt;font face=&quot;Consolas&quot;&gt;\lib&lt;/font&gt; folder from the Fable Redux sample and replace the files in the project’s &lt;font face=&quot;Consolas&quot;&gt;\public&lt;/font&gt; folder.&amp;nbsp; You can get those from here:&lt;p&gt;&lt;a href=&quot;https://github.com/fable-compiler/samples-browser/tree/master/public/redux-todomvc/&quot;&gt;https://github.com/fable-compiler/samples-browser/tree/master/public/redux-todomvc/&lt;/a&gt;&lt;h2&gt;5 - Add Fable.React&lt;/h2&gt;&lt;p&gt;Use &lt;a href=&quot;https://fsprojects.github.io/Paket/&quot; target=&quot;_blank&quot;&gt;Paket&lt;/a&gt; to add the Fable.React Nuget package to the project (assumes Paket is on the path).&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;paket add fable.react&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Also, make sure there is an entry for &lt;font face=&quot;Consolas&quot;&gt;Fable.React&lt;/font&gt; in &lt;font face=&quot;Consolas&quot;&gt;src\paket.references&lt;/font&gt;.&amp;nbsp; Add it if it doesn’t already exist.&lt;h2&gt;6 – Add Some Fable Code&lt;/h2&gt;&lt;p&gt;Let’s get the Fable F# code in now.&amp;nbsp; Replace the contents of &lt;font face=&quot;Consolas&quot;&gt;App.fs&lt;/font&gt; with the contents of the &lt;font face=&quot;Consolas&quot;&gt;App.fs&lt;/font&gt; from the Redux-ToDoMVC from the Fable samples.&amp;nbsp; You can get that here:&lt;p&gt;&lt;a href=&quot;https://github.com/fable-compiler/samples-browser/blob/master/src/redux-todomvc/App.fs&quot;&gt;https://github.com/fable-compiler/samples-browser/blob/master/src/redux-todomvc/App.fs&lt;/a&gt;&lt;p&gt;Make sure to change the line that says:&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;module ReduxTodoMVC&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;To the following (or whatever you named your project at the start):&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;module fableredux&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;7 - Restore and Build&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;cd src&lt;br&gt;dotnet restore&lt;br&gt;dotnet build&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;You should see a message that the build has succeeded.&lt;h2&gt;8 - Run it!&lt;/h2&gt;&lt;p&gt;Now you’re ready to run the project (sometimes I needed to close and re-open my console here as it complained about not finding an executable matching dotnet-fable.&amp;nbsp; YMMV!):&lt;blockquote&gt;&lt;p&gt;&lt;font face=&quot;Consolas&quot;&gt;dotnet fable yarn-start&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Then open &lt;a href=&quot;http://localhost:8080&quot;&gt;http://localhost:8080&lt;/a&gt; and enjoy!&lt;h2&gt;Getting Help&lt;/h2&gt;&lt;p&gt;The Fable community is awesome so drop by their Gitter room (and thanks to &lt;a href=&quot;https://github.com/rkosafo&quot; target=&quot;_blank&quot;&gt;@rkosafo&lt;/a&gt; for assistance getting me over some bumps along the way!):&lt;p&gt;&lt;a title=&quot;https://gitter.im/fable-compiler/Fable&quot; href=&quot;https://gitter.im/fable-compiler/Fable&quot;&gt;https://gitter.im/fable-compiler/Fable&lt;/a&gt;</description><link>http://kearon.blogspot.com/2017/08/creating-new-fable-reactredux-project.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVq-d40xAkWu-Yj9uXr-otanzOvDDNs3W_MRIBhCSOpO_Tu2RxlHiHyfb2mSarMpI4yvjKvccNz1-57iWf1alNM039ovX_HPNuZnkMo0Ceylz0QkDbkMxlAoyuLRNNLdD10T24vIYIFqYq/s72-c?imgmax=800" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-2071857201630310758</guid><pubDate>Sun, 19 Jun 2016 07:47:00 +0000</pubDate><atom:updated>2017-06-25T10:57:46.483+01:00</atom:updated><title>Running Rebus Service Bus in an Azure Web App</title><description>&lt;h2 id=&quot;whats-all-this&quot;&gt;What’s all this?&lt;/h2&gt;

&lt;p&gt;Rebus is a lean service bus running in .NET that is also free and open source.  It’s created and is maintained by Mogens Heller Grabe, and it even has stickers!  It’s a whole pile of awesome and I warn you that it may change the way you build software forever.  You can find more delights in the Rebus wiki.  Mogens also wrote an article about using Rebus in a web application, which you can find here:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mookid.dk/oncode/archives/4008&quot;&gt;http://mookid.dk/oncode/archives/4008&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rebus is similar to other .NET Service Buses, like NServiceBus, MassTransit and EasyNetQ.  You can also host these buses in Azure web apps (note that NServiceBus is commercial and EasyNetQ only supports RabbitMQ for message transport and does not support long running processes (sagas)).&lt;/p&gt;

&lt;p&gt;Azure Web Apps are fully managed service in Azure that lets you easily deploy, run and scale your apps, APIs and websites.  They are beautifully simple things to work with and to manage.  They really do just work!&lt;/p&gt;

&lt;p&gt;Rebus is typically run as a Windows service on a server or VM.  Can I really run a server-side service in an Azure Web App, I hear you ask?  Yes you can, and that’s just what we’re going to do!&lt;/p&gt;



&lt;h3 id=&quot;is-there-code&quot;&gt;Is there code?&lt;/h3&gt;

&lt;p&gt;Yes there is!  You can get it from here:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/seankearon/rebus-in-azure-wep-app&quot;&gt;https://github.com/seankearon/rebus-in-azure-wep-app&lt;/a&gt;&lt;/p&gt;



&lt;h2 id=&quot;choose-your-toppings&quot;&gt;Choose your toppings&lt;/h2&gt;

&lt;p&gt;A quick read through the Rebus docs shows that it supports a whole bunch of message transports, types and storage mechanisms and it has support for most of the current IoC containers.  I’m going to use Autofac as our DI container and Azure Service Bus as our message transport medium.  I’ll also be using Visual Studio 2015 with Web API 2 (because Rebus doesn’t support ASP.Net Core at time of writing).&lt;/p&gt;



&lt;h3 id=&quot;why-autofac&quot;&gt;Why Autofac?&lt;/h3&gt;

&lt;p&gt;You don’t need a DI container when working with Rebus as it has one baked right in.  I always use Autofac (because it rocks) and I’m going to use to show a how little configuration you need once you’re set up.&lt;/p&gt;



&lt;h3 id=&quot;why-azure-service-bus&quot;&gt;Why Azure Service Bus?&lt;/h3&gt;

&lt;p&gt;Like other message queues, Azure Service Bus has built in pub/sub mechanisms and can do lots of wonderful things for you at huge scale.  We’re just going to be using it as a message queue for and let Rebus will deal with all the message handling, subscriptions, orchestration and all that malarkey.&lt;/p&gt;



&lt;h3 id=&quot;why-azure-web-apps&quot;&gt;Why Azure Web Apps?&lt;/h3&gt;

&lt;p&gt;These beasties are super easy to develop, debug, deploy, manage and scale.  You can scale your service to huge capacity using Azure, or keep it pared down to a minimum (free!).  The Azure infrastructure takes care of all the maintenance patching for you and will make sure your service is restarted if it stops.  In my view, this is probably one of the best developer experiences around!&lt;/p&gt;

&lt;p&gt;Guess this has to be SBaaS: Service Bus as a Service!&lt;/p&gt;



&lt;h2 id=&quot;create-the-web-api-project&quot;&gt;Create the Web API project&lt;/h2&gt;

&lt;p&gt;Start by creating a new ASP.NET Web API project: &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/Q69x2M7.png&quot; alt=&quot;1&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Select the Empty project template and add references for Web API:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/2ySJEus.png&quot; alt=&quot;2&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;You should end up with something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/RQXELhp.png&quot; alt=&quot;3&quot; title=&quot;&quot;&gt;&lt;/p&gt;



&lt;h2 id=&quot;add-rebus-and-autofac-packages&quot;&gt;Add Rebus and Autofac packages&lt;/h2&gt;

&lt;p&gt;Install the packages by opening the Nuget Package Manager Console and running this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;install-package Rebus.Autofac&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;install-package Rebus.AzureServiceBus&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will bring in both Rebus and Autofac along with the Rebus package for interop with Autofac and Azure Service Bus.  Then run the following command to add the package that allows Autofac to work with ASP.Net Web API 2:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;install-package Autofac.WebApi2&lt;/code&gt;&lt;/p&gt;



&lt;h2 id=&quot;configure-the-autofac-container&quot;&gt;Configure the Autofac container&lt;/h2&gt;

&lt;p&gt;I’m going to use Autofac to start up the Rebus bus when the app starts.  Start by creating the following a configuration class for Autofac:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/JAj7jGh.png&quot; alt=&quot;4&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;This sets up the Autofac container and then registers it with ASP.Net Web API on line 21.  You know – if you’re just going to use Rebus and you’re not going to inject dependencies into any controllers, then won’t need that line.&lt;/p&gt;

&lt;p&gt;Take a look at line 15.  This tells Autofac to {scan the assembly](&lt;a href=&quot;http://docs.autofac.org/en/latest/register/scanning.html&quot;&gt;http://docs.autofac.org/en/latest/register/scanning.html&lt;/a&gt;) and register all Autofac modules it finds.  I’m using that as I’m going to be putting the rest of my container configuration into a module which we’ll see later.&lt;/p&gt;

&lt;p&gt;Line 19 is where we pass the Autofac container into our Rebus configuration, which we’ll see later.  The last thing is to call the configuration when the app starts up:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/WU2vwBJ.png&quot; alt=&quot;5&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;That’s all the Autofac configuration needed.  Let’s configure Rebus next.&lt;/p&gt;



&lt;h2 id=&quot;configure-the-rebus-bus&quot;&gt;Configure the Rebus bus&lt;/h2&gt;

&lt;p&gt;The following class is responsible for the bus configuration:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/HSNu0U7.png&quot; alt=&quot;6&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;The container parameter on line 12 is an Autofac container passed in from the Autofac configuration earlier.  On line 14 we pass that container into the Rebus Autofac adapter which will make Rebus use our Autofac container and will also register Rebus’ types into our container so we can use them later.  &lt;br&gt;
Read more in the Rebus docs &lt;a href=&quot;https://github.com/rebus-org/Rebus/wiki/Container-adapters&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You’ll need to add a connection string for your Azure Service Bus – or you can remove lines 18 – 21 and uncomment line 21 to use your file system as the message transport to run locally. &lt;/p&gt;

&lt;p&gt;Line 22 tells Rebus where to send messages that you give it.  Read more about that in the docs &lt;a href=&quot;https://github.com/rebus-org/Rebus/wiki/Routing&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The lines 25 and 26 start a timer to give us a simple heartbeat so we can see that the bus is running when it’s in Azure.&lt;/p&gt;



&lt;h2 id=&quot;registering-handlers-and-getting-the-heart-beating&quot;&gt;Registering handlers and getting the heart beating&lt;/h2&gt;

&lt;p&gt;Our heartbeat is going to work by having a simple timer running that publishes a message to the bus every few seconds.  Then we have a handler that receives that message and updates a simple counter to increase the heart beat count.  This is going to show us the magic of our bus running in the Azure Web App.&lt;/p&gt;

&lt;p&gt;So, the next part is to set up the and also register any and all Rebus message handlers into our Autofac container.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/YwoXJHc.png&quot; alt=&quot;7&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Lines 15 to 17 registers all the Rebus message handlers in this assembly by using Autofac’s assembly scanning.  A message handler is a class than received a message from the bus and does things with it. &lt;/p&gt;

&lt;p&gt;Rebus has a lot of rich support for controlling how and when this happens – see the &lt;a href=&quot;https://github.com/rebus-org/Rebus/wiki/Handler-pipeline&quot;&gt;docs&lt;/a&gt; for more.&lt;/p&gt;

&lt;p&gt;Starting on line 20 we add a simple timer that sends a message to the bus every few seconds.  I’m using &lt;a href=&quot;http://docs.autofac.org/en/latest/advanced/keyed-services.html&quot;&gt;Autofac’s named registration&lt;/a&gt; so that I know which timer I’m getting back from the container when I start it up.&lt;/p&gt;



&lt;h3 id=&quot;the-message&quot;&gt;The message&lt;/h3&gt;

&lt;p&gt;In Rebus, messages are just simple &lt;code&gt;POCO&lt;/code&gt; types.  I am using this one for our heartbeat:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/mjtZrM2.png&quot; alt=&quot;8&quot; title=&quot;&quot;&gt;&lt;/p&gt;



&lt;h3 id=&quot;the-handler&quot;&gt;The handler&lt;/h3&gt;

&lt;p&gt;The Rebus message handler is the class that receives the message.  Again, it’s just a very simple class which looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/02GCYwi.png&quot; alt=&quot;9&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;All it does is to tell the heart to beat!  It’s worth noting in case you are new to Rebus – you can have more than one handler for this message type and Rebus will take care of getting the message to all your handlers.&lt;/p&gt;



&lt;h3 id=&quot;the-heart&quot;&gt;The heart&lt;/h3&gt;

&lt;p&gt;The heart is just a static class that keeps a count of not many times it has beaten and tells us when it was last refreshed.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/P4nEUoA.png&quot; alt=&quot;10&quot; title=&quot;&quot;&gt;&lt;/p&gt;



&lt;h3 id=&quot;the-controller&quot;&gt;The controller&lt;/h3&gt;

&lt;p&gt;Just so that we can see the heartbeat, we’re going to add a simple Web API controller to allow access to the internal state.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/pv2YABw.png&quot; alt=&quot;11&quot; title=&quot;&quot;&gt;&lt;/p&gt;



&lt;h2 id=&quot;bring-it-to-life&quot;&gt;Bring it to life&lt;/h2&gt;

&lt;p&gt;Run the project in Visual Studio and it will open a browser.  Navigate to &lt;code&gt;/heartbeat&lt;/code&gt; and you’ll see something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/SxNI5te.png&quot; alt=&quot;12&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Refresh the browser and you’ll see the number of heart beats increases every 5 seconds, which means our Rebus bus is sending and receiving messages.  Woohoo – happy days!&lt;/p&gt;

&lt;p&gt;An easy way to see the message content (which is &lt;code&gt;JSON&lt;/code&gt; serialised by default), swap the Rebus transport to use the file transport in your &lt;code&gt;RebusConfig&lt;/code&gt; class:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/KlVKiec.png&quot; alt=&quot;13&quot; title=&quot;&quot;&gt;&lt;/p&gt;



&lt;h3 id=&quot;getting-an-error&quot;&gt;Getting an error?&lt;/h3&gt;

&lt;p&gt;You might get an error about not being to resolve the &lt;code&gt;AzureServiceBusTransport&lt;/code&gt;.  That will be because you haven’t set up the connection string in &lt;code&gt;RebusConfig&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/eJKoONy.png&quot; alt=&quot;14&quot; title=&quot;&quot;&gt;&lt;/p&gt;



&lt;h2 id=&quot;whats-all-this-doing&quot;&gt;What’s all this doing?&lt;/h2&gt;

&lt;p&gt;Let’s review how all this is working. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have an ASP.NET Web API app that configures an Autofac container when it starts up.&lt;/li&gt;
&lt;li&gt;The Autofac container scans the assembly for Autofac modules and it finds a module that does two things.&lt;/li&gt;
&lt;li&gt;The Autofac module it finds scans the current assembly and then registers all the Rebus handlers that it finds in that assembly.&lt;/li&gt;
&lt;li&gt;The Autofac module then registers a timer that is configured in the module to send heart beat messages to the bus every few seconds.&lt;/li&gt;
&lt;li&gt;The Autofac container is then built and passed into our Rebus configuration.&lt;/li&gt;
&lt;li&gt;The Rebus configuration sets up a Rebus bus that uses Azure Service Bus as its message transport. &lt;/li&gt;
&lt;li&gt;The Rebus configuration then starts the Rebus bus and makes it available from inside the Autofac container.&lt;/li&gt;
&lt;li&gt;Then Rebus configuration resolves our timer from the Autofac container and starts it.&lt;/li&gt;
&lt;li&gt;It’s worth noting here that when the timer starts inside the Autofac container, it resolves the Rebus bus directly from the Autofac container.&lt;/li&gt;
&lt;li&gt;The timer send a message to the Rebus bus, which puts it into the Azure Service Bus queue.&lt;/li&gt;
&lt;li&gt;The Rebus bus is monitoring the Azure Service Bus queue and it detects the message, opens it and passes it to the handler that we’ve built to handle those messages.&lt;/li&gt;
&lt;li&gt;The message handler then tells the heart to beat.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 id=&quot;deploy-to-azure-web-apps&quot;&gt;Deploy to Azure Web Apps&lt;/h2&gt;

&lt;p&gt;The last part is to publish all this goodness to an Azure Web App.  There are plenty of ways to publish an Azure Web App, including publishing from Git.  I’m just going to use Visual Studio for that. &lt;/p&gt;

&lt;p&gt;Right click the solution and choose Publish:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/X1FVYcr.png&quot; alt=&quot;15&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;You might need to sign into your Microsoft Account at this point.  Select the Azure App Service target:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/B5evp6h.png&quot; alt=&quot;16&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Select an App Service, or click New to create one:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/BO2GAlF.png&quot; alt=&quot;17&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Enter the details and click Create:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/cKFnujP.png&quot; alt=&quot;18&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Then click Publish in the next screen to publish to Azure:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/gG80Q7S.png&quot; alt=&quot;19&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;You’ll see something like this (with links for how to set up Git deploy if you’re interested!):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/5nUbm6R.png&quot; alt=&quot;20&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Navigate to /heartbeat to see Rebus running in an Azure Web App:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/48YnZBk.png&quot; alt=&quot;21&quot; title=&quot;&quot;&gt;&lt;/p&gt;



&lt;h3 id=&quot;getting-an-error-1&quot;&gt;Getting an error?&lt;/h3&gt;

&lt;p&gt;Did you set the Azure Service Bus connection string? &lt;br&gt;
Scaling out and keeping it running&lt;/p&gt;

&lt;p&gt;If your use case is to have a service bus running in the cloud, then you’ll most likely want it to stay on.  Azure Service Bus will unload an app if it’s idle for a period of time, but you can configure it to keep the app on at all times. &lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/y0n7QJj.png&quot; alt=&quot;22&quot; title=&quot;&quot;&gt;&lt;/p&gt;

&lt;p&gt;Note that you always on is not available in the free Azure plan, you need Basic or Standard mode for this.  You can read more about that here:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://azure.microsoft.com/en-gb/documentation/articles/web-sites-configure/&quot;&gt;https://azure.microsoft.com/en-gb/documentation/articles/web-sites-configure/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As for scaling, it’s super easy to scale to giddy heights.  Read more here:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://azure.microsoft.com/en-gb/documentation/articles/web-sites-scale/&quot;&gt;https://azure.microsoft.com/en-gb/documentation/articles/web-sites-scale/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description><link>http://kearon.blogspot.com/2016/06/running-rebus-service-bus-in-azure-web.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-2789743898820298191</guid><pubDate>Sat, 15 Aug 2015 09:44:00 +0000</pubDate><atom:updated>2015-08-15T10:46:54.784+01:00</atom:updated><title>Using PowerShell as the Visual Studio Developer Command Prompt</title><description>&lt;h2 style=&quot;border-bottom-color: rgb(46, 61, 84); font-family: Arial, sans-serif; font-size: 20px; font-weight: normal; line-height: 1.5; margin: 0px;&quot;&gt;
Overview&lt;/h2&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
The&amp;nbsp;&lt;a data-mce-href=&quot;https://msdn.microsoft.com/en-us/library/ms229859(v=vs.110).aspx&quot; href=&quot;https://msdn.microsoft.com/en-us/library/ms229859(v=vs.110).aspx&quot; style=&quot;color: rgb(50, 108, 166) !important; text-decoration: none;&quot;&gt;Visual Studio Developer Command Prompt&lt;/a&gt;&amp;nbsp;is a command window that loads up a bunch of useful environmental enhancements when it starts. &amp;nbsp;This let&#39;s you access things like&amp;nbsp;&lt;a data-mce-href=&quot;https://msdn.microsoft.com/en-us/library/k5b5tt23(v=vs.110).aspx&quot; href=&quot;https://msdn.microsoft.com/en-us/library/k5b5tt23(v=vs.110).aspx&quot; style=&quot;color: rgb(50, 108, 166) !important; text-decoration: none;&quot;&gt;sn.exe&lt;/a&gt;&amp;nbsp;from your command window. &amp;nbsp;However, it loads up in cmd.exe and I prefer using PowerShell &#39;cos it&#39;s proper useful! &amp;nbsp;This article shows one way making PowerShell act like the Developer Command Prompt.&lt;/div&gt;
&lt;h1 style=&quot;border-bottom-color: rgb(46, 61, 84); font-family: Arial, sans-serif; font-size: 24px; font-weight: normal; line-height: 1.25; margin: 30px 0px 0px;&quot;&gt;
Adjust your PowerShell Profile&lt;/h1&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
When PowerShell loads it looks for a profile file under your user profile and loads that if found. &amp;nbsp;By default, the profile file is:&lt;/div&gt;
&lt;pre style=&quot;color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px;&quot;&gt;&lt;documents&gt;\WindowsPowerShell\Microsoft.PowerShell_profile.ps1&lt;/documents&gt;&lt;/pre&gt;
&lt;pre style=&quot;color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif;&quot;&gt;Note that you can access your documents folder path from PowerShell like so:&lt;/span&gt;&lt;/pre&gt;
&lt;pre style=&quot;color: #333333; font-size: 14px; line-height: 20px; tab-size: 4; white-space: pre-wrap;&quot;&gt;$([environment]::getfolderpath(&quot;mydocuments&quot;)&lt;/pre&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
If that file isn&#39;t there, create it, add the following code and save it:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;script src=&quot;https://gist.github.com/seankearon/a7562ab10b37cf29c68f.js&quot;&gt;&lt;/script&gt;

&lt;br /&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
Adjust the environment in the last line above according to your VS installation.&lt;/div&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
&lt;span style=&quot;font-size: 24px; line-height: 1.25;&quot;&gt;Load in PowerShell&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
Open up a new PowerShell window (existing windows will not have loaded the profile we&#39;ve just saved). &amp;nbsp;Type sn and &lt;enter&gt; to show that you don&#39;t have access to sn.exe:&lt;/enter&gt;&lt;/div&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
&lt;img class=&quot;confluence-embedded-image&quot; data-base-url=&quot;https://newvoicemedia.atlassian.net/wiki&quot; data-image-height=&quot;225&quot; data-image-src=&quot;/wiki/download/attachments/69141840/1.png?version=1&amp;amp;modificationDate=1422030287897&amp;amp;api=v2&quot; data-image-width=&quot;877&quot; data-linked-resource-container-id=&quot;69141840&quot; data-linked-resource-container-version=&quot;1&quot; data-linked-resource-content-type=&quot;image/png&quot; data-linked-resource-default-alias=&quot;1.png&quot; data-linked-resource-id=&quot;69141838&quot; data-linked-resource-type=&quot;attachment&quot; data-linked-resource-version=&quot;1&quot; data-location=&quot;Development Wiki &amp;gt; 2015/01/23 &amp;gt; Using PowerShell as the Visual Studio Developer Command Prompt &amp;gt; 1.png&quot; data-mce-src=&quot;https://newvoicemedia.atlassian.net/wiki/download/attachments/69141840/1.png?version=1&amp;amp;modificationDate=1422030287897&amp;amp;api=v2&quot; data-unresolved-comment-count=&quot;0&quot; src=&quot;https://newvoicemedia.atlassian.net/wiki/download/attachments/69141840/1.png?version=1&amp;amp;modificationDate=1422030287897&amp;amp;api=v2&quot; style=&quot;margin-left: 2px; margin-right: 2px; max-width: calc(100% - 4px); vertical-align: text-bottom;&quot; title=&quot;Development Wiki &amp;gt; 2015/01/23 &amp;gt; Using PowerShell as the Visual Studio Developer Command Prompt &amp;gt; 1.png&quot; /&gt;&lt;/div&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
Then type As-VSPrompt and hit &lt;enter&gt;. &amp;nbsp;This will load up the Developer Command Prompt profile. &amp;nbsp;Type sn and &lt;enter&gt; again and you see sn.exe reporting for duty:&lt;/enter&gt;&lt;/enter&gt;&lt;/div&gt;
&lt;div style=&quot;color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; word-wrap: break-word;&quot;&gt;
&lt;img class=&quot;confluence-embedded-image&quot; data-base-url=&quot;https://newvoicemedia.atlassian.net/wiki&quot; data-image-height=&quot;225&quot; data-image-src=&quot;/wiki/download/attachments/69141840/2.png?version=1&amp;amp;modificationDate=1422030287953&amp;amp;api=v2&quot; data-image-width=&quot;877&quot; data-linked-resource-container-id=&quot;69141840&quot; data-linked-resource-container-version=&quot;1&quot; data-linked-resource-content-type=&quot;image/png&quot; data-linked-resource-default-alias=&quot;2.png&quot; data-linked-resource-id=&quot;69141839&quot; data-linked-resource-type=&quot;attachment&quot; data-linked-resource-version=&quot;1&quot; data-location=&quot;Development Wiki &amp;gt; 2015/01/23 &amp;gt; Using PowerShell as the Visual Studio Developer Command Prompt &amp;gt; 2.png&quot; data-mce-src=&quot;https://newvoicemedia.atlassian.net/wiki/download/attachments/69141840/2.png?version=1&amp;amp;modificationDate=1422030287953&amp;amp;api=v2&quot; data-unresolved-comment-count=&quot;0&quot; src=&quot;https://newvoicemedia.atlassian.net/wiki/download/attachments/69141840/2.png?version=1&amp;amp;modificationDate=1422030287953&amp;amp;api=v2&quot; style=&quot;margin-left: 2px; margin-right: 2px; max-width: calc(100% - 4px); vertical-align: text-bottom;&quot; title=&quot;Development Wiki &amp;gt; 2015/01/23 &amp;gt; Using PowerShell as the Visual Studio Developer Command Prompt &amp;gt; 2.png&quot; /&gt;&lt;/div&gt;
</description><link>http://kearon.blogspot.com/2015/08/using-powershell-as-visual-studio.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-4669685922131861465</guid><pubDate>Sun, 25 Jan 2015 10:24:00 +0000</pubDate><atom:updated>2015-01-25T10:24:45.859+00:00</atom:updated><title>Installing a Service using Topshelf with OctopusDeploy</title><description>I was using&amp;nbsp;&lt;a href=&quot;http://octopusdeploy.com/&quot;&gt;OctopusDeploy&lt;/a&gt;&amp;nbsp;to install a&amp;nbsp;&lt;a href=&quot;https://github.com/rebus-org/Rebus&quot;&gt;Rebus&lt;/a&gt;&amp;nbsp;service endpoint as a Windows Service from a console application created using &lt;a href=&quot;http://topshelf-project.com/&quot;&gt;Topshelf&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Octopus has &lt;a href=&quot;http://docs.octopusdeploy.com/display/OD/Windows+Services&quot;&gt;built-in support for Windows Services&lt;/a&gt;&amp;nbsp;that uses sc.exe under the hood. &amp;nbsp;I&#39;d used this many times previously without hitch, but for some reason the install seemed to start before the service was fully removed. &amp;nbsp;As Topshelf can do all the service set up, I decided to try using that instead.&lt;br /&gt;
&lt;br /&gt;
My deployment step in Octopus was configured to use the &lt;a href=&quot;http://docs.octopusdeploy.com/display/OD/PowerShell+scripts&quot;&gt;standalone PowerShell scripts&lt;/a&gt;. &amp;nbsp;Installing using Topshelf is simple - just call the&amp;nbsp;executable&amp;nbsp;using the commandline &lt;i&gt;install&amp;nbsp;--autostart&lt;/i&gt;. &amp;nbsp;Removing a Topshelf service is just as simple - call the&amp;nbsp;executable&amp;nbsp;using the &lt;i&gt;uninstall&lt;/i&gt; commandline. &lt;br /&gt;
&lt;br /&gt;
The only hard part is finding the executable path for the service so that you can remove the service before re-deploying. &amp;nbsp;PowerShell doesn&#39;t have built-in support for this at time of writing, but you can do that pretty easily using WMI. &amp;nbsp;The following&amp;nbsp;function is based on &lt;a href=&quot;http://stackoverflow.com/a/24449854/2608&quot;&gt;David Martin&#39;s SO answer&lt;/a&gt;&amp;nbsp;and finds the&amp;nbsp;executable&amp;nbsp;path from the service name:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJlaFB71GnZ3lNoftuJjATeGhYM1cP2VZDOLR2c0C4Ic9_1M4LPQYNfElIUoK0mv-3GnE35i-JviZNAe27N2Wymn8qLOfuUVaOHUpuFOADOhTacAAvzMcDTmr_Refkizwf-EHuULCvzydr/s1600/1.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJlaFB71GnZ3lNoftuJjATeGhYM1cP2VZDOLR2c0C4Ic9_1M4LPQYNfElIUoK0mv-3GnE35i-JviZNAe27N2Wymn8qLOfuUVaOHUpuFOADOhTacAAvzMcDTmr_Refkizwf-EHuULCvzydr/s1600/1.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
From that point, it&#39;s pretty easy to remove the service using Topshelf:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrMS25Mo9k-XuBkK-QRh0tudtn4uywGRPa6WrlLB676yydAjlw9mOSPSHIrvZ5uCn4pi_fCmBW6TJ9gWoEwSIH1FtwMOeMQHgrHOARmnNGh1NKUcb7v4fqn6gzIYbkJ8fYoxVvSFe1PDYw/s1600/2.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrMS25Mo9k-XuBkK-QRh0tudtn4uywGRPa6WrlLB676yydAjlw9mOSPSHIrvZ5uCn4pi_fCmBW6TJ9gWoEwSIH1FtwMOeMQHgrHOARmnNGh1NKUcb7v4fqn6gzIYbkJ8fYoxVvSFe1PDYw/s1600/2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
An alternative approach would be to use a known installation location each time and derive the executable path using Octopus&#39; powerful&amp;nbsp;&lt;a href=&quot;http://docs.octopusdeploy.com/display/OD/System+variables&quot;&gt;variables&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;References&lt;/b&gt;&lt;br /&gt;
The code for the pre-deployment and &amp;nbsp;post-deployment tasks can be found in &lt;a href=&quot;https://gist.github.com/seankearon/a0ac3b310cdf9ff74284&quot;&gt;this gist&lt;/a&gt;. &lt;br /&gt;
The full Topshelf command line reference is &lt;a href=&quot;http://docs.topshelf-project.com/en/latest/overview/commandline.html&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;</description><link>http://kearon.blogspot.com/2015/01/installing-service-using-topshelf-with.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJlaFB71GnZ3lNoftuJjATeGhYM1cP2VZDOLR2c0C4Ic9_1M4LPQYNfElIUoK0mv-3GnE35i-JviZNAe27N2Wymn8qLOfuUVaOHUpuFOADOhTacAAvzMcDTmr_Refkizwf-EHuULCvzydr/s72-c/1.png" height="72" width="72"/><thr:total>6</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-2863806702145241048</guid><pubDate>Fri, 31 Oct 2014 19:56:00 +0000</pubDate><atom:updated>2015-03-14T09:43:12.880+00:00</atom:updated><title>Using IIS URL Rewrite</title><description>This article is about creating IIS URL Rewrite Rules using Powershell. The Powershell functions that we use apply generally to reading and writing to .NET configuration file (web.config, app.config, etc.), and so can be applied to tasks like updating connection strings.  &lt;br /&gt;
The functions used are:  &lt;br /&gt;
&lt;blockquote&gt;
&lt;a href=&quot;http://technet.microsoft.com/en-us/library/ee790590.aspx&quot;&gt;Get-WebConfigurationProperty&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://technet.microsoft.com/en-us/library/ee807834.aspx&quot;&gt;Add-WebConfigurationProperty&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://technet.microsoft.com/en-us/library/ee807821.aspx&quot;&gt;Set-WebConfigurationProperty&lt;/a&gt; &lt;/blockquote&gt;
&lt;br /&gt;
Although these are powerful, being well documented is not their strongest feature! There are also a couple of simple pitfalls with the URL Rewrite Rules, which I’ll point out. Note that for the following to work, you’ll need to have the &lt;a href=&quot;http://www.iis.net/learn/extensions/url-rewrite-module/using-url-rewrite-module-20&quot;&gt;IIS URL Rewrite extension&lt;/a&gt; installed in IIS. You can install this using the &lt;a href=&quot;http://www.microsoft.com/web/downloads/platform.aspx&quot;&gt;Web Platform Installer&lt;/a&gt;, or using &lt;a href=&quot;https://chocolatey.org/packages/UrlRewrite&quot;&gt;Chocolatey&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
Files for this article can be found &lt;a href=&quot;http://1drv.ms/1G3gHiU&quot;&gt;here&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;
&lt;h1&gt;
The test website&lt;/h1&gt;
So we can test our rewrite rules we’ll use a simple website structured as follows:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMbxxGeBYmAqx7sU4gsTaSEoCmLEniyFL1JyOOne3orPvAywS3OLs8jzMkMMrA0aWlqXOL9_p7tt-0LhDLQzNCg7G7gwImkMEtaX3WIDW9Xm-3PHjgH3sTKzY9dvCv2yNB7WQh4nXXDMjo/s1600-h/image%25255B23%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF-Zl0sBuodyfJQe9PcmDOd3DTjLO3VHcqo755-QjPeXM1g9SGuy8CaDQUtElX4q_NYqQyWBBi4vaaYQBzCXvPGc4b94PSQ-qRmk7H6VGMbGoNeUkpqpfBK3tMnSIfLymV0FEyhDfz3ryp/?imgmax=800&quot; height=&quot;404&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;701&quot; /&gt;&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
Each leaf folder has two HTML files, 1.html and 2.html and there’s a page of links at the root:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs576g5tBPJsJ4Ypu9YCUnDooLhx0ob-BX77y0_fqbnG5uBV84J2xYrnFCgMQmaGQaxQ9BjM3tPh68otpZI9azx_yFlScI68yD648LMYQPm9iCXO7k-kd_UAmx5Xudbc0HSzP-a8oREpWT/s1600-h/clip_image002%25255B5%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image002&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1FuiKmzO6_t9rOxchaVLYXSeoIake8rhAsYtu9L0VuSsox7Mi2HrmYFvcHXJdBETEEmzaB_jKI7v9_0HWkmDfZNfqfiSeOldD2YuN0o_jy63LNxqOWMjI5ap_bdRDTxOHlKAIRuSANOJA/?imgmax=800&quot; height=&quot;440&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image002&quot; width=&quot;433&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
To help test the rewrite rules, the HTML files indicate where they are in the structure:&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfW9BfbURUWgYljOWV2aISMpvI7xO5PN4MnlaS4iA1b-YCLMEFjbigzhSl63lbM3sVJ0J_Od7gw5oj9dgZMCmPdZJsWqeOoal5zxyD7FWH5N-Rhq8cizS1Lzsql2V3hJ6NL8sgyqv3gh_i/s1600-h/clip_image003%25255B5%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image003&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHgE6CAW1RiTq-4z7LDOJ5r8whCAd4gAqcRyebK-Z4a-7xP_YKGdPVL3QLmmQ5MXIwsh10hRPnUZukNbRDSMcIlgWgiTYN9P5_gtsCpiEzB9XQexkEQAYWjfu4dp_Z0JO-CkTznYjX2lGH/?imgmax=800&quot; height=&quot;146&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image003&quot; width=&quot;431&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;h1&gt;
Introduction to rewrite rules&lt;/h1&gt;
The rules can be maintained in the IIS Manager by double clicking URL Rewrite in features view:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKIhDlLRqzOD4NG8w00zL4AAq9YpGcbaE6uhGXD6jzXKoyOx5yyhAQ_jpVIX84d3mPU0LTJUBOWRtkHF_kVZRCUTS4-XoeruTG4BvRLoa5uZIJnIXbxb77FnHGpJxc-x97BG9uF4u6JEx4/s1600-h/clip_image004%25255B5%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image004&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKSIwC-GkOlSjPdc_9eUwEl28cgmPZI3uZzTk6n_oRgYGsXoPBog3h7XyzevKYFaL39D8l9NzwfuPUHbhEj-uy33qCBHBzGZPswLaDzT3RPsGIbQhVPaeG5PaH2CJjLJpmli7WsnUZBFyI/?imgmax=800&quot; height=&quot;698&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image004&quot; width=&quot;735&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
There is a rich GUI that lets you maintain the rules and which does validation against your input:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_5kfncixveUmQnmvflo0uVxM0jfOw14xRFzdYyA76i-75lGhQsDgse_PJcZZpRP-iSAc8RIWOqW1K3Hh6Tqyr2XNAQbhPeX6WdMHA5Jd0gxEmu60c5yxQALRBo0BV8G80GfAgS-5klnjB/s1600-h/clip_image005%25255B6%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image005&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqyWPgCDOMv4l3BYKKsfjeEOV3PF5kIdZQCKQktQ9Hfe6ZjI9P-kxEurIDD-Wk57vw-1iAmLQDqycXAPK5E0uMXjfbpSjK3klgAm8esfVVYkdw9_RrwJ6EU4rGtZ6iOmLTGJw2h9RIBkMm/?imgmax=800&quot; height=&quot;1296&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image005&quot; width=&quot;768&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
The above rule redirects any URL section matching “1.html” to “2.html”. You’ll see this in the site’s config file:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJRMx9mywx1GYGraMyNDyo-stqIyvyTdiPz3QyAtisZGIohaH1fQe4uWcYmQHBs2izsdifjmUiyrtYmp6HXCqcMmKLc1KuNu5bxSUO_xvutKB1B-oSYzE6WtyLZLO9z7KAjg4vsJJOdGIf/s1600-h/clip_image006%25255B5%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image006&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5juP34-57PlnfmhZkvpJRfsbiqSgoQ4sZaa-4iugXCR304Mz1KJa4hKc3Mz3xPpOEitWBT5gnU0_kYJxqg95VMrKiP5nM_dVzTNKzbSMR55BtqdPSvTSLdUHNlfvonH4dPE_G4ZjFENlj/?imgmax=800&quot; height=&quot;237&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image006&quot; width=&quot;547&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
The rules are stored in the config file. The config file that’s changed depends on whether you apply the rules at the level of the virtual directory, website or the server. If the rules apply at the server level they are stored in the main IIS config file here:  &lt;br /&gt;
&lt;blockquote&gt;
%windir%\system32\inetsrv\config\applicationHost.config &lt;/blockquote&gt;
After this rule has been applied, recycle the app pool or reset IIS and then when accessing &lt;a href=&quot;http://localhost/simple-rewrite/1.html&quot;&gt;http://localhost/simple-rewrite/1.html&lt;/a&gt; you’ll be taken to &lt;a href=&quot;http://localhost/simple-rewrite/2.html&quot;&gt;http://localhost/simple-rewrite/2.html&lt;/a&gt;.  &lt;br /&gt;
&lt;h1&gt;
Using Powershell &lt;/h1&gt;
Firstly, make sure you have the WebAdministration module loaded:  &lt;br /&gt;
&lt;blockquote&gt;
&lt;b&gt;Import-Module&lt;/b&gt; WebAdministration &lt;/blockquote&gt;
To create the above rule using Powershell, run the following script (see CreateRule1.ps1):  &lt;br /&gt;
&lt;blockquote&gt;
&lt;b&gt;Add-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-&lt;/i&gt;pspath &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-&lt;/i&gt;filter &#39;/system.webserver/rewrite/rules&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-&lt;/i&gt;name &quot;.&quot; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-&lt;/i&gt;value @{name=&#39;Rule 1&#39;; patternSyntax=&#39;ECMAScript&#39;; stopProcessing=&#39;True&#39;}  &lt;br /&gt;
&lt;b&gt;Set-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;-pspath &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;-filter &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1&quot;]/match&#39; &lt;b&gt;`&lt;/b&gt;-name url &lt;b&gt;`&lt;/b&gt;-value &#39;1.html&#39;  &lt;br /&gt;
&lt;b&gt;Set-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;-pspath &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;-filter &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1&quot;]/action&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-&lt;/i&gt;name . &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-&lt;/i&gt;value @{ type=&quot;Redirect&quot;; url=&#39;2.html&#39;; redirectType=&quot;SeeOther&quot; } &lt;br /&gt;
&lt;br /&gt;&lt;/blockquote&gt;
The pspath parameter is the website path in the format used by the WebAdministration module. The filter parameter is the XPath to select the element we’re interested in. Here it’s under rules/rule and has a name attribute with the value “Rule 1”.  &lt;br /&gt;
&lt;br /&gt;
To remove the rule, run the following script (see RemoveRule1.ps1):  &lt;br /&gt;
&lt;blockquote&gt;
&lt;b&gt;Clear-WebConfiguration&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;-pspath &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;-filter &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1&quot;]&#39; &lt;/blockquote&gt;
&lt;br /&gt;
Note that &lt;b&gt;Clear-WebConfiguration&lt;/b&gt; removes the rule using the name selector and will raise an error if the rule is not found. W If you want to test whether the rule exists, use &lt;b&gt;Clear-WebConfiguration &lt;/b&gt;as follows:  &lt;br /&gt;
&lt;blockquote&gt;
$existing = &lt;b&gt;Get-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-pspath&lt;/i&gt; &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-filter&lt;/i&gt; &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1&quot;]&#39; &lt;i&gt;-name&lt;/i&gt; *  &lt;br /&gt;
if ($existing) { &lt;br /&gt;
&lt;b&gt;Clear-WebConfiguration&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-pspath&lt;/i&gt; &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-filter&lt;/i&gt; &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1&quot;]&#39;&lt;br /&gt;
} &lt;/blockquote&gt;
&lt;h1&gt;
Rule processing order and redirect exclusions&lt;/h1&gt;
The rules are processed in the order they appear in IIS Manager and the config file. A rule can be set to stop processing of subsequent rules. These two combine to make an effective way to create an exception to a redirect. Say you wanted to redirect all “1.html” URLs to “2.html” except for “~b/c/1.html”. To achieve this add in the following rule above the more general redirect:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsMj6tCNHvvLTeBvsm8boz8quPlXaLZ3bFMthOJA4vgPZn5aqgpQLzdRY70Bpp4CtdWaCuLw1kbs-MgLgqjsuAZD_ho3pXSe7TjCW2jWYtDB4sWZ1DRnfvJAaBfIYi9Y3UTobqdB0Cd8xq/s1600-h/clip_image007%25255B4%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image007&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrTIRSsipbweROa9odr2Lvp70pgLw8cE2EaDRYQlwnk0fNAd0W10JmkdviLKU7pa2dKVLFip8WfpDRQucc_15eYW0JpPLH1o7TUwGSM1tOHcFvwaSJVYTguAnUL1W2usE9I3YXhDeODeYG/?imgmax=800&quot; height=&quot;553&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image007&quot; width=&quot;682&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
Your configuration will look something like:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9xEyKwqgj0QfKgBhEpuEfQCc4fpNnXh5QrzRDPltfuvOhgoyDFt5c_b7AhjboORS_6OryOP8pAKOADRETpeTxwtAqflhaPKOwAd_FY70tl71mjgPyh5e0BQbruNsXj0nt9RAdUQ6kra0Q/s1600-h/clip_image008%25255B4%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image008&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNQNGqDY3bm7UdAVK8XekdxpCRX9iYJVNQmrmFD_0ShbRd3zcFr8bVW3fLnUZnzKds1IqVTdyAZvBiZuCNqUxF50LFKtSqkx-3LBkGisaS9-6fFDK_fzjh58C_UfBUDXB48OXDBBe_vIMH/?imgmax=800&quot; height=&quot;309&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image008&quot; width=&quot;560&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;h1&gt;
Using rule conditions&lt;/h1&gt;
Let’s say you want a rule that applies to POSTs to a particular URL but which only contain certain parameters in the query string. Such as a POST to:  &lt;br /&gt;
~/b/2.html?paramA=Z  &lt;br /&gt;
&lt;br /&gt;
Let’s say we want to detect parameter values of X, Y or Z. You can do this using rule conditions. The completed rule looks like this in IIS Manager:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQlmgi6pxy86SKdPKaOCYEigAnhtQ2h0rShV2Rn0hrVRcGALku8GcS9e1lkh19G-J9D4cGCXNEBBr_4NA7CunMATFRTpwGQgaPiP7jgijGhdMMPWjKxYH2o7sJQLkxz9AdomDU3QEYQ-cU/s1600-h/clip_image009%25255B4%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image009&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaBznHiQuY3_B3D7x87qDthHD1QABJ16lXNy8F-XC_CLqepVHP0VDDe5CgbGvrj5DbtUW_KNZwkRjyhrWo6U8-vHgJH9fVnB6Ti2coxlpzGSTXmumTT_vtrs8kQTH7ARjtiguihvXGY6dp/?imgmax=800&quot; height=&quot;840&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image009&quot; width=&quot;682&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
In the configuration, this rule looks like:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXENPsMgbliV4y3BD3WIdmgMErRPgrocnsGV02SMELKWLDjdjiDtzswR5nsZlzcjHqd9vq0Wd_J-uUDMcszazznlKTAwZ94hLPo70VyBG2F0rx4peMC88jCfqZwKF_Z5Ivywv7D7DaCX2m/s1600-h/clip_image010%25255B4%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image010&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2oX67nKjLOcLadgNsy14NdTGXr2yyaBXoYdjADV4ESK4afmp2fa2_UED-1RerTVNKn3L4MZWag5YO75sU-VeajaC5DHkba7F7vJMa9s6o4M2ia7TV8oUnHoLLKjQko2sSp9vfTMAcWryX/?imgmax=800&quot; height=&quot;132&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image010&quot; width=&quot;528&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
And can be scripted as follows:  &lt;br /&gt;
&lt;blockquote&gt;
&lt;b&gt;Add-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-pspath&lt;/i&gt; &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; ` &lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;i&gt;-filter&lt;/i&gt; &#39;/system.webserver/rewrite/rules&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-name&lt;/i&gt; &quot;.&quot; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-value&lt;/i&gt; @{name=&#39;Rule 1 Post Exception&#39;; patternSyntax=&#39;ECMAScript&#39;; stopProcessing=&#39;True&#39;}  &lt;br /&gt;
&lt;b&gt;Set-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;-pspath &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; ` &lt;br /&gt;
-filter &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1 Post Exception&quot;]/match&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-name&lt;/i&gt; url &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-value&lt;/i&gt; &quot;b/2.html&quot;  &lt;br /&gt;
&lt;b&gt;Add-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;-pspath &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; ` &lt;b&gt;&lt;br /&gt;&lt;/b&gt;-filter &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1 Post Exception&quot;]/conditions&#39; &lt;b&gt;`&lt;/b&gt;-name &quot;.&quot; &lt;b&gt;`&lt;/b&gt;-value @{input=&quot;{REQUEST_METHOD}&quot;; pattern=&#39;POST&#39;}  &lt;br /&gt;
&lt;b&gt;Add-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;-pspath &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; ` &lt;b&gt;&lt;br /&gt;&lt;/b&gt;-filter &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1 Post Exception&quot;]/conditions&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-name&lt;/i&gt; &quot;.&quot; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-value&lt;/i&gt; @{input=&quot;{QUERY_STRING}&quot;; pattern=&#39;paramA=(X|Y|Z)&#39;} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/blockquote&gt;
&lt;h1&gt;
Notes and gotchas&lt;/h1&gt;
&lt;h3&gt;
Rules are relative to the site root&lt;/h3&gt;
Once you realize that the redirect URLs are relative to the site root, it’s all very obvious. Gaining that realisation can take some time! So for the example site above, the following rule will do nothing:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoErxfM5zYwNAoYs19W37PDarFr1-j-jImj5Nq7g4ep2cktgDUfXAxjYTvBzmoB5aNrjrsjX-QEXPYfi436KLA_fV43EdxTQLcY20JBc233VcIKAPVtk_vdzg9RqeUT19lPBJspZi2_MmN/s1600-h/clip_image011%25255B4%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image011&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd6EJeStcb3eCuMOTV3Vr-MDA7TsP0RlnliE8NJs6FqJnptTLTdMbOkxYWesL4p4MgKpoy6QsriAjj5LP_lqrZBVOZqxoChMDMI0IMyHTpjSICnGSq7apge0Pbr0N4ur3x8DjjpvtnWHFz/?imgmax=800&quot; height=&quot;788&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image011&quot; width=&quot;716&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
IIS Manager has code completion for conditions&lt;/h3&gt;
When you add a condition in IIS Manager, you get code completion after typing the first “{“ (such as in the POST exception rule above):  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-X6a1WaL-5okXdRdfjsUJKqo4TkMYGtzCmOFuk7bl45-dM5afW-pipxWxYkH6KEQV8mjESM9CDuXticU2nNyh2_1pN_yy0VfuHxNxqZcYPz-n5f4pcJMAnbAG2G9YJkftSpFUyhiz0wAA/s1600-h/clip_image012%25255B4%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image012&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgleF9tlyX5pOhh7Yxvdh3sc8aXwGVSrlvtQnPGQZpda1nCAi1GkROQlom9O3jPU5fNQxYCXZLnAvFwneZsDw0Fip9kCbir5tWh5Sd31DMQmjkiv8kX2lK5aLunSSAeFXZiqwhkcGBvDcnU/?imgmax=800&quot; height=&quot;329&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image012&quot; width=&quot;495&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Files get locked and browsers cache pages&lt;/h3&gt;
When you’re developing the rules config file is being touched by TIIS, IIS Manager, Notepad++, Powershell and goodness know what else. Your super-modern browser is being super-modern helpful and caching the HTML pages. Sometimes you just need to recycle the app pool to see the updated rule. Other times, you need to do an IIS reset, clear your browser cache and restart your tool windows.  &lt;br /&gt;
&lt;h3&gt;
Default values are not written&lt;/h3&gt;
When the rule’s action type is None and it stops processing of other rules, the configuration written by the IIS Manager GUI is like this:  &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWgpc0uJItBVTI8CoT562V8es3r2yniUDsgMP7BssATLMpGNbpEUnBx8wwENL7sFhDQtWKRKStjBAYW2JeZZnD8OcoVlyOzLPg-rjYx_g4LCMdX4CDE7L6ptY4cZEs81U3kngD7c5ZBQIj/s1600-h/clip_image013%25255B5%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image013&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyz4rm4Wyf5RnKVmV9hHTtVNJkx02Srw2YkLLdo76rJj4ow8ibmByKqKgLK4cweiYCVAd9vjFhaWhAK9uRg8jpeITJrIbY8K4Zhr9PMFDOf0VXZ3cAKnP8YMYuJowfklMJYiiq3wB108_t/?imgmax=800&quot; height=&quot;79&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image013&quot; width=&quot;439&quot; /&gt;&lt;/a&gt;  &lt;br /&gt;
&lt;br /&gt;
Following the same pattern for creating the rule in a script, you can run something like this (see CreateExceptionRule.ps1):  &lt;br /&gt;
&lt;blockquote&gt;
&lt;b&gt;Add-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-pspath&lt;/i&gt; &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-filter&lt;/i&gt; &#39;/system.webserver/rewrite/rules&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-name&lt;/i&gt; &quot;.&quot; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-value&lt;/i&gt; @{name=&#39;Rule 1 Exception&#39;; patternSyntax=&#39;ECMAScript&#39;; stopProcessing=&#39;True&#39;}  &lt;br /&gt;
&lt;b&gt;Set-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-pspath&lt;/i&gt; &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-filter&lt;/i&gt; &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1 Exception&quot;]/match&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-name&lt;/i&gt; url &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-value&lt;/i&gt; &#39;b/c/1.html&#39;  &lt;br /&gt;
&lt;b&gt;Set-WebConfigurationProperty&lt;/b&gt; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-pspath&lt;/i&gt; &#39;IIS:\Sites\Default Web Site\simple-rewrite&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-filter&lt;/i&gt; &#39;/system.webserver/rewrite/rules/rule[@name=&quot;Rule 1 Exception&quot;]/action&#39; &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-name&lt;/i&gt; . &lt;b&gt;`&lt;/b&gt;&lt;i&gt;-value&lt;/i&gt; @{ type=&quot;None&quot; } &lt;br /&gt;
&lt;br /&gt;&lt;/blockquote&gt;
The above script writes the following to the configuration file.  &lt;br /&gt;
&amp;nbsp; &lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCajc6phrca-H4nsqqXklZCYFIGytUGKweTYKgUZkm5M3nyHNAVK3lKwbc02sXQpYpyB-CTL1iSvDPG5lPSQXSZ-Xg7yiIbiGr_ZKnI60OJczdc7YJ21lb5qa7tajDvOjMY1hGd1jIc9TZ/s1600-h/image%25255B22%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb6x4tFubUU1nadu5QVCQ_7mAA7BwWTmRittuwOMI7S1UOiJ5mVqWaWWZRH6CY0f8m1FS4MNHYovtbSRg_ByY6dTRosOEoiEa_9OES12LxzaSfNPl9tWa0IuQ7WPMN34B4F7ihtXQFeMbc/?imgmax=800&quot; height=&quot;63&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;434&quot; /&gt;&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
Note that the action element is not written. It seems that the Powershell command knows that &amp;lt;action type=”None”&amp;gt; is the default and doesn’t bother to write it, but the IIS Manager GUI writes it anyway. If you didn’t know that you may spend a lot of time trying to work out why your Powershell isn’t doing what you think it should!        &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://kearon.blogspot.com/2014/10/using-iis-url-rewrite.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF-Zl0sBuodyfJQe9PcmDOd3DTjLO3VHcqo755-QjPeXM1g9SGuy8CaDQUtElX4q_NYqQyWBBi4vaaYQBzCXvPGc4b94PSQ-qRmk7H6VGMbGoNeUkpqpfBK3tMnSIfLymV0FEyhDfz3ryp/s72-c?imgmax=800" height="72" width="72"/><thr:total>14</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-2089630177192713082</guid><pubDate>Sat, 11 Oct 2014 08:37:00 +0000</pubDate><atom:updated>2015-01-29T10:20:53.227+00:00</atom:updated><title>Simple UI testing with Nightwatch.js</title><description>This week I was introduced to &lt;a href=&quot;http://nightwatchjs.org/&quot;&gt;Nightwatch.js&lt;/a&gt; by my colleague &lt;a href=&quot;https://github.com/Matthew-Davey&quot;&gt;Matt Davey&lt;/a&gt;.&amp;nbsp; Nightwatch provides a clear and simple syntax for writing your UI tests and uses &lt;a href=&quot;http://nodejs.org/&quot;&gt;NodeJS&lt;/a&gt; and &lt;a href=&quot;http://www.seleniumhq.org/&quot;&gt;Selenium&lt;/a&gt; to run the tests.&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
Having played with &lt;a href=&quot;http://lefthandedgoat.github.io/canopy/&quot;&gt;Canopy&lt;/a&gt; for UI testing, the high readability of the test syntax impressed me from the start.&amp;nbsp; We used it to nail down a reproduction of a bug we were working in our test environment.&lt;br /&gt;
&lt;h1&gt;
Test scenario&lt;/h1&gt;
Our test did something like this&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Logs into a site using known credentials.&lt;/li&gt;
&lt;li&gt;Clicks through to a place in the UI.&lt;/li&gt;
&lt;li&gt;Changes and saves a value.&lt;/li&gt;
&lt;li&gt;Asserts that the new value is being displayed in another area of the UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
The test syntax&lt;/h1&gt;
The test syntax looks like this: &lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6vfQO8swQYfiDoM-5eIpfYI3UGEW4uPymbAiBqONBgjIrlO4uQpNzHRbnjg7geol39F_dub8aB4K-asULKc4lFS3bvjhE5ZUK1WqpYPF09rMW_Y_yejzspLkIpMZzWFQm2sdqwZVv02Q0/s1600-h/image%25255B3%25255D.png&quot;&gt;&lt;img alt=&quot;image&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjhsMwZYzh2C0YsyN6zWBW_U8LXQUKBG1KpmCp_sdz1oj7KHYA0fjXQaIithI_uAiEcCXxNiYZvdAidD22yN3_h_lkSloiIdnBJ8ICsjAfgehI2sRv62j7HcqjGe8ewRG613v8FRR4KZlo/?imgmax=800&quot; height=&quot;396&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;image&quot; width=&quot;644&quot; /&gt;&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
The syntax is clean, easy to read and all in a one file. One of the CSS selectors is pretty evil, but you can get that from the browser’s context menu in the inspector (which I learnt this week too!): &lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvbJbEAD8YCYhL5ORBQSK6iF1UM4VX0YBxkLVJ0FYtmwDDD0m_WF2z85n2p91W7hhoW1GE7HSPLxb5Y0JWvV9bVvRyHdMv0LKN7Tk7Oodar200TytoOOH199nWNr10mxppfsSg5rSo8262/s1600-h/clip_image001%25255B5%25255D.png&quot;&gt;&lt;img alt=&quot;clip_image001&quot; border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP6Eaav7shENm0XS-ZIHa3Z4ANhT7Pkrx8GN22qoevlHmzaoGU56ga9Xq2rhkTGcGjacO2wBQbn73d9JgROgpwrIKdmXjcQ0EhL1cZpIcaPofDIbScjMltk5zhskSEs2QkF-XaI0oa3mPR/?imgmax=800&quot; height=&quot;152&quot; style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;&quot; title=&quot;clip_image001&quot; width=&quot;244&quot; /&gt;&lt;/a&gt; &lt;br /&gt;
&lt;h1&gt;
Setting up the test runner&lt;/h1&gt;
Setting up to run the test is very simple to do on any development or test machine. You the components are: &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;NodeJS&lt;/li&gt;
&lt;li&gt;NPM&lt;/li&gt;
&lt;li&gt;Nightwatch&lt;/li&gt;
&lt;li&gt;A Selenium Server&lt;/li&gt;
&lt;/ul&gt;
You can install Java, NodeJS and Nightwatch using &lt;a href=&quot;http://www.chocolatey.org/&quot;&gt;Chocolatey&lt;/a&gt; by opening a command window and running: &lt;br /&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;choco install javaruntime&lt;br /&gt;choco install nodejs.install&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;npm install -g NightWatch&lt;/span&gt; &lt;br /&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
Note that Chocolatey seems to install the Node packages under Chocolatey&#39;s folders, and NPM then places the Nightwatch module into the &lt;span style=&quot;font-family: Courier New;&quot;&gt;nodejs.commandline &lt;/span&gt;folder under \tools.&amp;nbsp; In there is a batch called Nightwatch.cmd in there that we need to access. So, we need to add the following to our path: &lt;br /&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;C:\ProgramData\chocolatey\lib\ nodejs.commandline.X.Y.Z\tools&lt;/span&gt; &lt;br /&gt;
&lt;br /&gt;
(where X.Y.Z is the NodeJS version we’ve installed.) &lt;br /&gt;
&lt;br /&gt;
Then we need to start up a Selenium server.&amp;nbsp; It would be nice to use &lt;a href=&quot;http://chocolatey.org/packages?q=seleniumserver&quot;&gt;Chocolatey&lt;/a&gt; here too, but the version of Selenium from the package at time of writing is too old.&amp;nbsp; So, download the latest Selenium driver (JAR) from &lt;a href=&quot;http://docs.seleniumhq.org/download/&quot;&gt;here&lt;/a&gt; (which is &lt;a href=&quot;http://selenium-release.storage.googleapis.com/2.43/selenium-server-standalone-2.43.1.jar&quot;&gt;2.43&lt;/a&gt; at time of writing).  &lt;br /&gt;
&lt;br /&gt;
Rename the Selenium JAR file to &lt;span style=&quot;font-family: Courier New;&quot;&gt;selenium-server-standalone.jar&lt;/span&gt; and save it to &lt;span style=&quot;font-family: Courier New;&quot;&gt;C:\selenium\&lt;/span&gt;. Then start up a Selenium Server for opening a new command window (as admin) and typing:  &lt;br /&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;java -jar &quot;C:\selenium\selenium-server-standalone.jar&quot;&lt;/span&gt; &lt;br /&gt;
&lt;br /&gt;
That’s the setup done, now let’s run the test. &lt;br /&gt;
&lt;h1&gt;
Running the test&lt;/h1&gt;
Save your test (similar to the code above) to a file, let’s say &lt;span style=&quot;font-family: Courier New;&quot;&gt;repro.js&lt;/span&gt;, into a folder.&amp;nbsp; Create a sub-folder called “&lt;span style=&quot;font-family: Courier New;&quot;&gt;examples\custom-commands&lt;/span&gt;” (which Nightwatch wants to find, not sure why!).&lt;br /&gt;
Then open another command window and change to the folder containing the test file and run the following:  &lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New;&quot;&gt;nightwatch --test repro.js&lt;/span&gt; &lt;br /&gt;
&lt;br /&gt;
Job done!</description><link>http://kearon.blogspot.com/2014/10/simple-ui-testing-with-nightwatchjs.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjhsMwZYzh2C0YsyN6zWBW_U8LXQUKBG1KpmCp_sdz1oj7KHYA0fjXQaIithI_uAiEcCXxNiYZvdAidD22yN3_h_lkSloiIdnBJ8ICsjAfgehI2sRv62j7HcqjGe8ewRG613v8FRR4KZlo/s72-c?imgmax=800" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-2034374102429512335</guid><pubDate>Mon, 11 Aug 2014 09:49:00 +0000</pubDate><atom:updated>2014-08-11T12:51:20.967+01:00</atom:updated><title>Testing TypeScript with Jasmine in Visual Studio</title><description>&lt;p&gt;This post is about setting up testing for &lt;a href=&quot;http://typescript.io/&quot;&gt;TypeScript&lt;/a&gt; with &lt;a href=&quot;http://jasmine.github.io/&quot;&gt;Jasmine&lt;/a&gt; in Visual Studio, but it should be pretty much the same using &lt;a href=&quot;http://qunitjs.com/&quot;&gt;QUnit&lt;/a&gt;.&amp;nbsp; &lt;/p&gt; &lt;p&gt;To set this up, start a new MVC project and let’s get Knockout and Jasmine installed into the project, along with their TypeScript definitions:&lt;/p&gt;&lt;pre class=&quot;brush: powershell; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;Install-Package knockoutjs&lt;br /&gt;Install-Package knockout.typescript.DefinitelyTyped&lt;br /&gt;Install-Package JasmineTest&lt;br /&gt;Install-Package jasmine.typescript.DefinitelyTyped&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;We’re using the Jasmine Nuget package called JasmineTest.&amp;nbsp; There is a similar one on Nuget called Jasmine-JS, the difference being that JasmineTest will add a controller and view to let you run your tests.&amp;nbsp; We’ll be using that in a second to let us debug the tests.&amp;nbsp; Now run and browse to ~/jasmine/run and you’ll see this:&lt;br&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijX_0gyQbU0S-YDZGRnl1Wns957Hy2i4Y4WAzWbCM60VelXwsMatRL025uOOUwiTmIoBOQIU2JXb9mPyE2Y6zY2-aOuMJVCHR8GKnO019o0Rmoe_il-dHLEw2sGmEnpQEsvmr3itRZ43Ju/s1600-h/image%25255B47%25255D.png&quot;&gt;&lt;br&gt;&lt;img title=&quot;image&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOYxf7P_zKTrGT8g5cgt8c61Q1ckFqWWkj4pOx4HT4LDob5sqmvPP_RDW8LYyUzZf8kpMeTZV5nr-f9XQjTE4Iu9yfiu_dltsBk1vKHb1S6v4MWo4QdkdvqaP05c-WqhPk829bIfR5vUKv/?imgmax=800&quot; width=&quot;619&quot; height=&quot;323&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This is the view added by the JasmineTest package.&amp;nbsp; It is an HTML page (SpecRunner.cshtml)&amp;nbsp; and has the references for the example Jasmine specs that ship with Jasmine.&amp;nbsp; We are going to be using to let us debug out tests.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8pUiBx5xrJ-yqk3uSgFSe53XiVSoL87Z3vRsGNem7aWCAfAA8s1bVOV8C2hd8LOdy9v_vcQWSAO4EdlzOSx_uJpSDCcnlKSDVesqBdbv9NDcyHdUCqjK8uLh7IYiz4HnvyVc8hpr_UXd9/s1600-h/image%25255B28%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpkpnWgBHbORxAn1u2gz7P8dMW51VuKQ5IaovCKNVBsaUZi6USvKvj-GXmendUhdt_MzU3YUxUD-gbySSkjSDJxJ236LijlTZIAKtTgbWCzZ5VhV5Tlq7JJCwdumQoBhd86EpFBgJVt3Ap/?imgmax=800&quot; width=&quot;644&quot; height=&quot;433&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So, let’s write some tests.&amp;nbsp; For simplicity we’re going to put the model and the tests into the same file.&amp;nbsp; So we add a TypeScript file called Tests.ts to your /Scripts folder and add the following lines to that file, giving this:&lt;/p&gt;&lt;pre class=&quot;brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: true; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimo59RsaebaPh6PHboSCbw5ibEDi9EC1CYSlwkl7fH4TNLioDTK7JVLJ0E1YW5PJXOe2PWgHv-FLtin_cwb03FC8jnGZVP7G82Whfy1gFslTJuLoUuE_miqueIAROAFIrUbgs_MIzGm230/s1600-h/image%25255B13%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOzSToSgM_F4Z_1BdPcUmsvwuqAfdDagyPgXdDRvWRBSxWO0hE8DP1J7wsJjv3ZRrZo65ANWF144eKiZypIcfmNu3Sl69Bb4N_LYiF_SfEnpbUIfyydTwUiZ84YMihvnFYQYEYIzDyrpwv/?imgmax=800&quot; width=&quot;508&quot; height=&quot;292&quot;&gt;&lt;/a&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h1&gt;Running tests with ReSharper&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;If you have &lt;a href=&quot;http://www.jetbrains.com/resharper/&quot;&gt;ReSharper&lt;/a&gt; installed, then the R# Test Runner will recognise the Jasmine test and allow you to run them.&amp;nbsp; To set this up for a smooth experience, first install &lt;a href=&quot;http://chocolatey.org/packages/PhantomJS&quot;&gt;PhantomJS&lt;/a&gt; and set the path to &lt;font face=&quot;Courier New&quot;&gt;phantomjs.exe&lt;/font&gt; in Resharper | Options | Tools | Unit Testing | JavaScript Tests.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;R# will need to find the .JS files for the .TS references.&amp;nbsp; R# will look for and use a file that is named the same as the &lt;a href=&quot;https://github.com/borisyankov/DefinitelyTyped&quot;&gt;Definitely Typed&lt;/a&gt; TS file, but ending with .JS.&amp;nbsp; For us, this means copying &lt;font face=&quot;Courier New&quot;&gt;knockout-3.1.0.js&lt;/font&gt; from &lt;font face=&quot;Courier New&quot;&gt;/Scripts &lt;/font&gt;to &lt;font face=&quot;Courier New&quot;&gt;/Scripts/typings/knockout&lt;/font&gt; and renaming it to &lt;font face=&quot;Courier New&quot;&gt;knockout.d.js&lt;/font&gt;:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS0bKT-yAwUh9e1-TAtQH0U3ECRFx3Av641b9Kmo7vgS4vXCDlfg7cvEikNvN3Y8dxPNM3pkeEt6FLzgFAT-UenjDqXe1wWGgaUm9rK_s7MpTCEz9fuT75x6Tl8V57o1BFWa8aYE7oy7k1/s1600-h/image%25255B33%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHgjZV-Hed9BJLf6vFp6EA63OjEthzkMf_XpBN_zLXDCB5ryUWbUAASRhNlM1Fi9flyrHhjfMfXRk22FZHrDVcK7wfybhaU__o86deN0n4oH9M2yMPftBGjd_OkCWRIDNMV05_PMcCR17-/?imgmax=800&quot; width=&quot;411&quot; height=&quot;751&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;After that you can just run the tests as you would in C#:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgND8ROt5ND-_yTCKfOItCtuNQoDD3tAytwfBIgUsd0Yy7QpFnqgBjimGEsknlTXzkPILo9VYYs3th8UFoTNOeOK18GkhPZwCbwsXLOUpw9c4DpgIVfvzd3KTc48wUwxUQdYaEed3kTjSpa/s1600-h/image%25255B37%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRID14Cuuz_cd8MSv9vvdgQSPSco6PxkYQgfIGuIOhna5NndMFAH2OIWS8M-EWwRuxd-Y0M3MdoWnwYTSDyF74WhhJ-BkKgdM1VybhICmkVNWb-7csxMWabBasp9FYUhn3OQsFysSWkx0G/?imgmax=800&quot; width=&quot;619&quot; height=&quot;591&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;Running tests with Chutzpah&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;You can also use the &lt;a href=&quot;http://chutzpah.codeplex.com/&quot;&gt;Chutzpah&lt;/a&gt; test runner to run Jasmine tests in Visual Studio.&amp;nbsp; You can install that from Tools | Extensions and Updates here:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio867bXerUTn-D6ViJ05NE9d_RxyDpB7z8QClA2rLjz8yD6n5UmzFAOsExSkhheM_mRI3UOsBKvHajcQnnhyphenhyphenvd0Wl3eb9933WsZJhGaZWHmYxFxVCsEtLVKbil4xSomJxNRXqh5CNA6xvQ/s1600-h/image%25255B42%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP2JY-H30p_xYVh-HYYBhdUc2gAuR3VgDASzuSrUsi7oEnn1FsyNUH9oa_VPgXjuaQzm9lkMWyw_Cx59gbAotrb63X5gKH7fioSoXujipb-w-whyphenhyphen-faUFIG0Xwycx0oIDPkUggB3GdvJtz/?imgmax=800&quot; width=&quot;644&quot; height=&quot;294&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Once installed, you just right click the TypeScript file that contains the tests and select the item Run JS Tests.&amp;nbsp; This puts the test results into the Visual Studio Output window by default, but there is a Visual Studio extension that gives &lt;a href=&quot;http://visualstudiogallery.msdn.microsoft.com/f8741f04-bae4-4900-81c7-7c9bfb9ed1fe&quot;&gt;integration with the Visual Studio Test Explorer&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;If you go ahead and run the tests as shown above you’ll get an error.&amp;nbsp; This is because Chutzpah resolves referenced JS files differently to R#.&amp;nbsp; For this to run, we need to add a reference to the JS file in the TS test for Chutzpah to pick up.&amp;nbsp; This is documented &lt;a href=&quot;http://chutzpah.codeplex.com/wikipage?title=Chutzpah%20File%20References&amp;amp;referringTitle=Documentation&quot;&gt;here&lt;/a&gt; and looks like this:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;font face=&quot;Courier New&quot;&gt;/// &amp;lt;chutzpah_reference path=&quot;knockout-3.1.0.js&quot; /&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1&gt;Debugging tests in Visual Studio&lt;/h1&gt;&lt;br /&gt;&lt;p&gt;As far as I can tell, there is currently no support from either R# or Chutzpah for debugging TS tests from either test runner in the IDE.&amp;nbsp; However, we can do that by going back to our &lt;font face=&quot;Courier New&quot;&gt;SpecRunner.cshtml&lt;/font&gt; that was installed with the JasmineTest Nuget package.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Just add the JS references along with a reference to our test file to the HTML shipped with the package:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyCPVRFy-mdIxCx8OE-5Mhbn-fe51GN2wE6VpdHyNz8j5t0Gv95heXjYw0t5rcUKXq-wAJaOHOwvO_n656xiN9n47hoOSCSHv6Ft4FfaXSQCTTWWMIO7M9bR4FYbmdFNn8BYCZDiGuK5jJ/s1600-h/image%25255B46%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRMRbLSpW_duIKV9_5PK7a2X7CtDhHwP01vhFUte0677svWHR3Rt1u4YeLfunpNLuw84l5h4WPlDrXMkbkaU-hHG_J4kq57FiJ7tvx6PLKBXCAfP6bGuoDQv_mWNlNoLSI-45c3uE2crr3/?imgmax=800&quot; width=&quot;718&quot; height=&quot;449&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Note that we are referencing &lt;font face=&quot;Courier New&quot;&gt;Tests.js&lt;/font&gt; instead of the TS file.&amp;nbsp; Then place a break point in the test in the TS file, run a browse to ~/Jasmine/Run:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLY2lOVwmiGrLW9vks_zcRRv3Bp8YX3rY7ypw059op6AQ7nSq-1l_Ct2B53GWaasgiLWdt_LnrxiqBtIf9tyrG6hrnGo6xKRbNDC2jqp9vw1c0uYUzpUITNf_cSV9iewC7aE2JKPZLPCkV/s1600-h/image%25255B51%25255D.png&quot;&gt;&lt;img title=&quot;image&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfLmj1LuPuTUOQTzQrawu0cDQ_5NljxopfNSmYjSPt3Xf7Nndv8zcV_e7oyu0vY_ggrASsO9-45nKcKkTvKfaPPC5KWH1AMO6XuSHBTFwQTqDDAeQQxPSntm3yySI55dspc5ZV49P3hnic/?imgmax=800&quot; width=&quot;487&quot; height=&quot;315&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Job done!&amp;nbsp; Source code is here: &lt;a title=&quot;https://bitbucket.org/seankearon/typescript-testing-in-studio&quot; href=&quot;https://bitbucket.org/seankearon/typescript-testing-in-studio&quot;&gt;https://bitbucket.org/seankearon/typescript-testing-in-studio&lt;/a&gt;&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2014/08/testing-typescript-with-jasmine-in.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOYxf7P_zKTrGT8g5cgt8c61Q1ckFqWWkj4pOx4HT4LDob5sqmvPP_RDW8LYyUzZf8kpMeTZV5nr-f9XQjTE4Iu9yfiu_dltsBk1vKHb1S6v4MWo4QdkdvqaP05c-WqhPk829bIfR5vUKv/s72-c?imgmax=800" height="72" width="72"/><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-6956058217160641433</guid><pubDate>Fri, 29 Mar 2013 12:21:00 +0000</pubDate><atom:updated>2015-11-10T17:20:46.092+00:00</atom:updated><title>Does Windows Azure comply with UK/EU Data Privacy Law?</title><description>&lt;h2&gt;
Update, November 2016&lt;/h2&gt;
&lt;div&gt;
Times have changed and the content of my article from 2013 may no longer be correct due to a recent ruling by the European Court of Justice. &amp;nbsp;Read more here:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;http://uk.businessinsider.com/european-court-of-justice-safe-harbor-ruling-2015-10&quot;&gt;http://uk.businessinsider.com/european-court-of-justice-safe-harbor-ruling-2015-10&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
TL;DR&lt;/h2&gt;
&lt;em&gt;Yes, it does.&amp;nbsp; The Information Commissioner’s Office in the UK considers that Windows Azure provides adequate protection for the rights of individuals with regard to their data that is held on Windows Azure.&amp;nbsp; &lt;/em&gt;&lt;br /&gt;
&lt;em&gt;Given that you have the other relevant measures in place to comply with the Data Protection Act, this means that you go ahead and use Windows Azure to store your customers’ personal information.&amp;nbsp; As Microsoft comply with the EU/US Safe Harbor Framework, the data can be considered to remain solely within the EU geographic region.&lt;/em&gt;&lt;br /&gt;
&lt;h2&gt;
Background&lt;/h2&gt;
As developers we often need to store information about individuals, such as their name and email address.&amp;nbsp; When people share this information with us, they expect that we will treat the information properly and respect their privacy.&amp;nbsp; &lt;br /&gt;
In the UK, the &lt;a href=&quot;http://en.wikipedia.org/wiki/Data_Protection_Act_1998&quot; target=&quot;_blank&quot;&gt;Data Protection Act&lt;/a&gt; provides a legal framework to define how companies capture and process information about individuals.&amp;nbsp; For instance, they may choose to let you send them an email newsletter, but tell you that they do not want to receive then from other companies that you work with.&lt;br /&gt;
In the UK, the &lt;a href=&quot;https://www.google.com/url?sa=t&amp;amp;rct=j&amp;amp;q=&amp;amp;esrc=s&amp;amp;source=web&amp;amp;cd=1&amp;amp;cad=rja&amp;amp;ved=0CDUQFjAA&amp;amp;url=http%3A%2F%2Fwww.ico.gov.uk%2F&amp;amp;ei=RG5VUfr9I4m1PLe-gJgM&amp;amp;usg=AFQjCNHi_2ACuYeQOVxNvgzlAcHhFz9EeA&amp;amp;sig2=otRHBeoZqQoMZvUdL6RBug&amp;amp;bvm=bv.44442042,d.ZWU&quot; target=&quot;_blank&quot;&gt;Information Commissioner’s Office&lt;/a&gt; (ICO) is the body responsible for upholding information rights and privacy for individuals.&amp;nbsp; The ICO can and do fine companies who do not treat individuals information properly.&amp;nbsp; These fines are &lt;a href=&quot;http://www.ico.org.uk/news/latest_news/2013/ico-news-release-2013&quot; target=&quot;_blank&quot;&gt;quite&lt;/a&gt; &lt;a href=&quot;http://www.dma.org.uk/news/ico-fines-glasgow-firm-%C2%A390000-nuisance-calls&quot; target=&quot;_blank&quot;&gt;large&lt;/a&gt; &lt;a href=&quot;http://www.v3.co.uk/v3-uk/news/2244230/ico-fines-nursing-and-midwifery-council-gbp150-000-for-lost-dvds&quot; target=&quot;_blank&quot;&gt;too&lt;/a&gt;!&lt;br /&gt;
&lt;h2&gt;
To the Cloud&lt;/h2&gt;
As developers we increasingly want to be able to use hosted cloud services to build our web sites and internet enabled applications.&amp;nbsp; There are a number of choices out there that include large offerings such as &lt;a href=&quot;http://www.windowsazure.com/&quot; target=&quot;_blank&quot;&gt;Windows Azure&lt;/a&gt; and &lt;a href=&quot;http://aws.amazon.com/&quot; target=&quot;_blank&quot;&gt;Amazon Web Services&lt;/a&gt;, but also more targeted offerings such as &lt;a href=&quot;https://www.mongohq.com/&quot; target=&quot;_blank&quot;&gt;MongoHQ&lt;/a&gt;.&lt;br /&gt;
If we store any information about an individual (in the UK the law relates to living individuals), then any cloud service that we use as developers must ensure that the data about the individuals is protected.&lt;br /&gt;
&lt;h2&gt;
Keep it local&lt;/h2&gt;
Other member states of the European Union have similar data protection laws and there is a &lt;a href=&quot;http://ec.europa.eu/justice/data-protection/&quot; target=&quot;_blank&quot;&gt;common legal framework&lt;/a&gt; to protect the rights of individuals in the EU.&lt;br /&gt;
To be able to benefit from the protection that this legal framework gives, the individual’s data has to remain physically within the EU.&amp;nbsp; If the data were to be held in another country outside of the EU, then the laws of that country would apply to that data.&amp;nbsp; For example, the US has a &lt;a href=&quot;http://en.wikipedia.org/wiki/Data_Protection_Directive#Comparison_with_US_data_protection_law&quot; target=&quot;_blank&quot;&gt;very different approach&lt;/a&gt; to the protection of individuals data than we do in the EU.&lt;br /&gt;
&lt;h2&gt;
Back to the Cloud&lt;/h2&gt;
Let’s look at how Amazon AWS and Microsoft Azure - two popular US cloud providers - handle this. &lt;br /&gt;
Amazon make the statement that any data hosted in one of their EU regions will remain within that region.&amp;nbsp; You can read that &lt;a href=&quot;http://aws.amazon.com/s3/faqs/#Can_I_comply_with_EU_data_privacy_regulations_using_Amazon_S3&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&amp;nbsp; Okay, not much detail in that, but it sounds fine.&lt;br /&gt;
Azure talk a little more about this than Amazon and you can read about that &lt;a href=&quot;http://www.windowsazure.com/en-us/support/trust-center/privacy&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&amp;nbsp; If you are eagle eyed, then you will notice that data in Azure EU regions will generally remain in the EU, but may be shipped to the US for disaster recovery purposes.&lt;br /&gt;
Oh dear, that sounds like it breaks the condition that data has to remain physically within the EU.&lt;br /&gt;
&lt;h2&gt;
Can I use Azure then?&lt;/h2&gt;
Yes, you can.&amp;nbsp; The reasons for this - also stated on &lt;a href=&quot;http://www.windowsazure.com/en-us/support/trust-center/privacy&quot; target=&quot;_blank&quot;&gt;Azure Trust Centre Privacy&lt;/a&gt; page – is that Microsoft are certified as complying with the EU/US &lt;a href=&quot;http://export.gov/safeharbor/&quot; target=&quot;_blank&quot;&gt;Safe Harbor Framework&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;
This is a legal framework between the EU and the US Department of Commerce that essentially provides EU compliant data protection for data that is moved to the US under the Safe Harbor Framework.&amp;nbsp; The ICO deem that the Safe Harbor Framework provides adequate protection for the rights of the individual whose data may be transferred to the US by Microsoft.&amp;nbsp; You can read about that &lt;a href=&quot;http://www.ico.org.uk/for_organisations/data_protection/the_guide/principle_8&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;
That’s simple then – why the doubt?&lt;/h2&gt;
So, if it’s that easy, why am I writing this article in the first place?&amp;nbsp; Well, I’ve been looking at Azure for a while now and wanting to use it for some of my applications.&amp;nbsp; The advice I had received in the past was basically that once the data was in the US, other US laws, such as the Patriot Act, could override the Safe Harbor Framework and remove the legal protections provided by the Safe Harbor Framework.&amp;nbsp; &lt;br /&gt;
If that was the case, then I would need treat it as if it were being shipped outside of the EU and under the jurisdiction of different data protection laws.&amp;nbsp; Not something that my customers would want to hear!&amp;nbsp; Also, the reason why I’d been using Amazon AWS.&lt;br /&gt;
I recently spun up a build server on an Azure VM and I absolutely loved the experience of using Azure.&amp;nbsp; I was thinking what a shame it was that I couldn’t use it more and so I got in touch with the venerable &lt;a href=&quot;http://www.hanselman.com/&quot; target=&quot;_blank&quot;&gt;Mr Hanselman&lt;/a&gt;, Microsoft developer evangelist extraordinaire, to say “please can we use Azure in Europe?” (I had previously tried other routes, but without getting any answers).&lt;br /&gt;
&lt;a href=&quot;http://www.hanselman.com/blog/&quot; target=&quot;_blank&quot;&gt;Scott&lt;/a&gt; kindly took my question back to the Azure team and then came back with a bunch of challenges for me.&amp;nbsp; The summary of those being that all I needed was already on the &lt;a href=&quot;http://www.windowsazure.com/en-us/support/trust-center/privacy/&quot; target=&quot;_blank&quot;&gt;Azure Trust Centre Privacy page&lt;/a&gt;.&amp;nbsp; And, he was quite right too!&amp;nbsp; &lt;br /&gt;
I got onto the phone to the ICO and asked them about it, and they confirmed that this provided “adequate protection for the rights of individuals” and that there are exceptions to data protection law to allow circumstances such as the Courts or the Police to have access as part of their investigations – both in the EU as well as the US – and that I could now just focus on complying with the Data Protection Act requirements.&amp;nbsp; &lt;br /&gt;
Awesome – my future is now on Azure!&lt;br /&gt;
&lt;h2&gt;
A note of caution&lt;/h2&gt;
It’s worth remembering that the location of the data is just one part of the process of protecting your customers’ data.&amp;nbsp; You need to make sure that you comply with all other aspects of the relevant data protection laws.&amp;nbsp; &lt;br /&gt;
Generally, the more sensitive the information and the more people about whom you hold that sort of information, the less likely you will be able to host it externally.&lt;br /&gt;
In the UK, if you’re not sure about how to go about things, contact the &lt;a href=&quot;http://www.ico.org.uk/&quot; target=&quot;_blank&quot;&gt;ICO&lt;/a&gt; for advice – they’re very helpful people!</description><link>http://kearon.blogspot.com/2013/03/does-windows-azure-comply-with-ukeu.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-701394281535428538</guid><pubDate>Wed, 23 May 2012 17:04:00 +0000</pubDate><atom:updated>2012-05-23T18:18:52.523+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ravendb</category><title>Embedded RavenDB Indexes with Obfuscation</title><description>&lt;p&gt;I ran into an issue today with using &lt;a href=&quot;http://ravendb.net&quot; target=&quot;_blank&quot;&gt;RavenDB&lt;/a&gt; from an obfuscated assembly.&amp;nbsp; RavenDB started giving some nasty looking errors like:&lt;/p&gt; &lt;p&gt;System.InvalidOperationException: Could not understand query: &lt;br&gt;-- line 2 col 43: invalid NewExpression&lt;/p&gt; &lt;p&gt;After bashing my head against this for too long, I had run out of ideas and so I posted the problem on the &lt;a href=&quot;https://groups.google.com/d/topic/ravendb/IsVxNXnSK6w/discussion&quot; target=&quot;_blank&quot;&gt;RavenDB group&lt;/a&gt;.&amp;nbsp; One of the really good things about RavenDB is the amazing support from both the Hibernating Rhinos team and the community on this group.&amp;nbsp; So, pretty soon it was problem solved!&lt;/p&gt; &lt;p&gt;The problem: the obfuscation was renaming the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb397696.aspx&quot; target=&quot;_blank&quot;&gt;anonymous types&lt;/a&gt; that are used when &lt;a href=&quot;http://ayende.com/blog/4668/ravendb-defining-indexes&quot; target=&quot;_blank&quot;&gt;defining indexes from code in RavenDB&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The solution: either put your types into a non-obfuscated assembly or tell the obfuscator to stop renaming anonymous types.&amp;nbsp; Let’s look at the second option a bit more.&lt;/p&gt; &lt;p&gt;Okay, so how do you detect an anonymous type?&amp;nbsp; One way is to look at their names.&amp;nbsp; The compiler gives anonymous types names and puts the text “AnonymousType” into the name. For example:&lt;/p&gt;&lt;pre class=&quot;csharpcode&quot;&gt;&lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; { Name = &lt;span class=&quot;str&quot;&gt;&quot;Sean&quot;&lt;/span&gt;}.GetType().Name // Gives: &amp;lt;&amp;gt;f__AnonymousType0`1&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Simple enough, &lt;strong&gt;but there is a caveat&lt;/strong&gt;:&amp;nbsp; the naming of anonymous types is an implementation detail and &lt;a href=&quot;http://stackoverflow.com/questions/10724112/does-the-always-compiler-include-the-text-anonymoustype-in-the-names-of-anonym&quot; target=&quot;_blank&quot;&gt;may vary with different compiler implementations&lt;/a&gt;.&amp;nbsp; You cannot rely in this working with different compilers.&amp;nbsp; &lt;/p&gt;&lt;br /&gt;&lt;p&gt;So, with that in mind, let’s look at a solution…&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Different obfuscators allow you to add obfuscation rules in various ways.&amp;nbsp; In &lt;a href=&quot;https://github.com/seankearon/raven-obfuscation&quot; target=&quot;_blank&quot;&gt;this repo&lt;/a&gt; there is an example of using &lt;a href=&quot;http://www.foss.kharkov.ua/g1/projects/eazfuscator/dotnet/Default.aspx&quot; target=&quot;_blank&quot;&gt;Eazfuscator&lt;/a&gt; with a RavenDB index.&amp;nbsp; (Note that you will need to install Eazfuscator to be able to run the code.)&amp;nbsp; All that is needed is to use an assembly scoped &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.reflection.obfuscationattribute.aspx&quot; target=&quot;_blank&quot;&gt;ObfuscationAttribute&lt;/a&gt; to prevent renaming of any type whose name contains the text “AnonymousType”:&lt;/p&gt;&lt;pre class=&quot;csharpcode&quot;&gt;[assembly: Obfuscation(Feature = &lt;span class=&quot;str&quot;&gt;&quot;Apply to type *AnonymousType*: renaming&quot;&lt;/span&gt;, Exclude = &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;, ApplyToMembers = &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;)]&lt;/pre&gt;&lt;br /&gt;&lt;style type=&quot;text/css&quot;&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, &quot;Courier New&quot;, courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Bingo, everything works as it should again…happy days!&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2012/05/embedded-ravendb-indexes-with.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-850356039358818119</guid><pubDate>Sat, 21 Apr 2012 08:32:00 +0000</pubDate><atom:updated>2012-04-27T09:09:53.099+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ravendb</category><title>RavenDB Magic – Modelling Polymorphic Collections</title><description>I&#39;m starting to port my main application over to&amp;nbsp;&lt;a href=&quot;http://ravendb.net/&quot; target=&quot;_blank&quot;&gt;RavenDB&lt;/a&gt;. &amp;nbsp;A driving design principle for RavenDB is to reduce friction for the developer and the main reason I’m choosing RavenDB is to &lt;b&gt;make my life easier&lt;/b&gt;. &amp;nbsp;Here&#39;s one example of that...&lt;br /&gt;
&lt;br /&gt;
Let’s say that you’ve got a model with a marker interface and some types implementing that interface.&amp;nbsp; Something like this:&lt;br /&gt;
&lt;pre class=&quot;csharpcode&quot;&gt;   &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;interface&lt;/span&gt; ILookup { }

   &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; IntegerLookup : ILookup
   {
      &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;int&lt;/span&gt; Number { get; set; }
   }
   
   &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; StringLookup : ILookup
   {
      &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; Text { get; set; }
   }&lt;/pre&gt;
Then you have a type that holds a collection of the interface:&lt;br /&gt;
&lt;pre class=&quot;csharpcode&quot;&gt;   &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; Container
   {
      &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; ILookup[] Lookups { get; set; }
   }&lt;/pre&gt;
All good so far, and now you want to store this in a database.&amp;nbsp; Not quite so simple!&amp;nbsp; If you’re using a relational database, whether through an &lt;a href=&quot;http://en.wikipedia.org/wiki/Object-relational_mapping&quot; target=&quot;_blank&quot;&gt;ORM&lt;/a&gt; or another means, you will have to do quite a bit more work to get your objects into the database and back.&lt;br /&gt;
&lt;br /&gt;
However, if you’re using &lt;a href=&quot;http://ravendb.net/&quot; target=&quot;_blank&quot;&gt;RavenDB&lt;/a&gt;&amp;nbsp;then your work is done!&amp;nbsp; Well, nearly - all you need to do is to add an Id property to your container to tell RavenDB to store it as a root:&lt;br /&gt;
&lt;pre class=&quot;csharpcode&quot;&gt;   &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; Container
   {
      &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; Id { get; set; }
      &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; ILookup[] Lookups { get; set; }
   }&lt;/pre&gt;
&lt;pre class=&quot;csharpcode&quot;&gt;&lt;/pre&gt;
That’s it – the rest is pure Raven magic!&amp;nbsp; Here’s a test showing how Raven it handles it:&lt;br /&gt;
&lt;pre class=&quot;csharpcode&quot;&gt;   [Test]
   &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;void&lt;/span&gt; can_store_polymorphic_collection()
   {
      &lt;span class=&quot;kwrd&quot;&gt;using&lt;/span&gt; (var store = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; EmbeddableDocumentStore
      {
         DataDirectory = &lt;span class=&quot;str&quot;&gt;&quot;Data&quot;&lt;/span&gt;,
         RunInMemory = &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;
      })

      {
         store.Initialize();

         var holder = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; Container
               {
                  Lookups = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; ILookup[]
                              {
                                 &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; StringLookup {Text = &lt;span class=&quot;str&quot;&gt;&quot;Hello&quot;&lt;/span&gt;},
                                 &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; IntegerLookup {Number = 123}
                              }
               };&lt;/pre&gt;
&lt;pre class=&quot;csharpcode&quot;&gt;         &lt;span class=&quot;kwrd&quot;&gt;using&lt;/span&gt; (var session = store.OpenSession())
         {
            session.Store(holder);
            session.SaveChanges();
         }

         &lt;span class=&quot;kwrd&quot;&gt;using&lt;/span&gt; (var session = store.OpenSession())
         {
            var h = session.Load&amp;lt;Container&amp;gt;(holder.Id);

            Assert.That(h.Lookups
               .OfType&amp;lt;StringLookup&amp;gt;().Single().Text == &lt;span class=&quot;str&quot;&gt;&quot;Hello&quot;&lt;/span&gt;);
            Assert.That(h.Lookups
               .OfType&amp;lt;IntegerLookup&amp;gt;().Single().Number == 123);
         }
      }
   }&lt;/pre&gt;
You just new up an instance of Container, add in a couple of ILookup instances, then save it.&amp;nbsp; When I load it back up, it’s all there just as you need it to be.&amp;nbsp; Now, that is seriously impressive!</description><link>http://kearon.blogspot.com/2012/04/ravendb-magic-modelling-polymorphic.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-6400886466514876665</guid><pubDate>Thu, 28 Jul 2011 20:17:00 +0000</pubDate><atom:updated>2012-04-21T09:35:04.525+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">nservicebus</category><category domain="http://www.blogger.com/atom/ns#">ravendb</category><title>RavenDB &amp;amp; NServiceBus -</title><description>The upcoming version 3.0 of everyone’s favourite service bus, &lt;a href=&quot;http://www.nservicebus.com/&quot; target=&quot;_blank&quot;&gt;NServiceBus&lt;/a&gt;, will now use &lt;a href=&quot;http://ravendb.net/&quot; target=&quot;_blank&quot;&gt;RavenDB&lt;/a&gt; for saga persistence.&amp;nbsp; This makes it even easier to work with sagas in NSB.&lt;br /&gt;
Very cool!&amp;nbsp; Even better than that, it looks like RavenDB will be available for NServiceBus Express users too.&amp;nbsp; You can read Udi’s comment &lt;a href=&quot;http://www.udidahan.com/2011/07/22/nservicebus-and-ravendb-better-together/comment-page-1/#comment-38024&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
Big thanks to Ayende and Udi for getting these two elegant technologies together like this.&amp;nbsp;</description><link>http://kearon.blogspot.com/2011/07/ravendb-nservicebus.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-7501879205779358317</guid><pubDate>Sun, 27 Feb 2011 21:07:00 +0000</pubDate><atom:updated>2011-05-22T09:54:10.054+01:00</atom:updated><title>Mocking DbContext Entity Framework 4 Code First CTP5 with NSubstitute</title><description>Take an Entity Framework 4 Code First model, something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div id=&quot;codeSnippetWrapper&quot;&gt;&lt;div id=&quot;codeSnippet&quot; style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum1&quot; style=&quot;color: #606060;&quot;&gt;   1:&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;class&lt;/span&gt; Customer&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum2&quot; style=&quot;color: #606060;&quot;&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum3&quot; style=&quot;color: #606060;&quot;&gt;   3:&lt;/span&gt;    &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;int&lt;/span&gt; Id { get; set; }&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum4&quot; style=&quot;color: #606060;&quot;&gt;   4:&lt;/span&gt;    &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;string&lt;/span&gt; Name { get; set; }&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum5&quot; style=&quot;color: #606060;&quot;&gt;   5:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum6&quot; style=&quot;color: #606060;&quot;&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum7&quot; style=&quot;color: #606060;&quot;&gt;   7:&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;class&lt;/span&gt; CustomerContext : DbContext, ICustomerContext&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum8&quot; style=&quot;color: #606060;&quot;&gt;   8:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum9&quot; style=&quot;color: #606060;&quot;&gt;   9:&lt;/span&gt;    &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; DbSet&amp;lt;Customer&amp;gt; Customers { get; set; }&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum11&quot; style=&quot;color: #606060;&quot;&gt;  11:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
&lt;style type=&quot;text/css&quot;&gt;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, &quot;Courier New&quot;, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;br /&gt;
I now want to write some tests and I&#39;m going to mock the DbContext using &lt;a href=&quot;http://http//nsubstitute.github.com/&quot; target=&quot;_blank&quot;&gt;NSubstitute&lt;/a&gt;. &amp;nbsp;I first try something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div id=&quot;codeSnippetWrapper&quot;&gt;&lt;div id=&quot;codeSnippet&quot; style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum1&quot; style=&quot;color: #606060;&quot;&gt;   1:&lt;/span&gt; [Test]&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum2&quot; style=&quot;color: #606060;&quot;&gt;   2:&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;void&lt;/span&gt; can_mock_customer_context()&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum3&quot; style=&quot;color: #606060;&quot;&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum4&quot; style=&quot;color: #606060;&quot;&gt;   4:&lt;/span&gt;    var context = Substitute.For&amp;lt;CustomerContext&amp;gt;();&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum5&quot; style=&quot;color: #606060;&quot;&gt;   5:&lt;/span&gt;    context.Customers.Returns(&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum6&quot; style=&quot;color: #606060;&quot;&gt;   6:&lt;/span&gt;       &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; DbSet&amp;lt;Customer&amp;gt;(&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum7&quot; style=&quot;color: #606060;&quot;&gt;   7:&lt;/span&gt;          &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt;[]&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum8&quot; style=&quot;color: #606060;&quot;&gt;   8:&lt;/span&gt;          {&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum9&quot; style=&quot;color: #606060;&quot;&gt;   9:&lt;/span&gt;             &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; Customer {Name = &lt;span style=&quot;color: #006080;&quot;&gt;&quot;Sean&quot;&lt;/span&gt;}&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum10&quot; style=&quot;color: #606060;&quot;&gt;  10:&lt;/span&gt;          })&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum11&quot; style=&quot;color: #606060;&quot;&gt;  11:&lt;/span&gt;       );&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum12&quot; style=&quot;color: #606060;&quot;&gt;  12:&lt;/span&gt;    Assert.AreEqual(1, context.Customers.Count());&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum13&quot; style=&quot;color: #606060;&quot;&gt;  13:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
The problem is that the DbSet constructor is internal (as of EF4 Code First CTP5). &amp;nbsp;So, let&#39;s abstract our DB access to a simple interface and replace DbSet&amp;lt;T&amp;gt; with the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb351562.aspx&quot; target=&quot;_blank&quot;&gt;IQueryable&amp;lt;T&amp;gt;&lt;/a&gt; interface,&amp;nbsp;ending up with the below:&lt;br /&gt;
&lt;br /&gt;
&lt;div id=&quot;codeSnippetWrapper&quot;&gt;&lt;div id=&quot;codeSnippet&quot; style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum1&quot; style=&quot;color: #606060;&quot;&gt;   1:&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;interface&lt;/span&gt; ICustomerContext&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum2&quot; style=&quot;color: #606060;&quot;&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum3&quot; style=&quot;color: #606060;&quot;&gt;   3:&lt;/span&gt;    IQueryable&amp;lt;Customer&amp;gt; Customers { get; set; }&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum4&quot; style=&quot;color: #606060;&quot;&gt;   4:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
This interface can be implemented like so:&lt;br /&gt;
&lt;br /&gt;
&lt;div id=&quot;codeSnippetWrapper&quot;&gt;&lt;div id=&quot;codeSnippet&quot; style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum1&quot; style=&quot;color: #606060;&quot;&gt;   1:&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;class&lt;/span&gt; CustomerContext : DbContext, ICustomerContext&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum2&quot; style=&quot;color: #606060;&quot;&gt;   2:&lt;/span&gt;   {&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum3&quot; style=&quot;color: #606060;&quot;&gt;   3:&lt;/span&gt;      &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; DbSet&amp;lt;Customer&amp;gt; Customers { get; set; }&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum4&quot; style=&quot;color: #606060;&quot;&gt;   4:&lt;/span&gt;      IQueryable&amp;lt;Customer&amp;gt; ICustomerContext.Customers { get { &lt;span style=&quot;color: blue;&quot;&gt;return&lt;/span&gt; Customers; } }&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum5&quot; style=&quot;color: #606060;&quot;&gt;   5:&lt;/span&gt;   }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
Now all we need to do is to use an implementation of &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb351562.aspx&quot; target=&quot;_blank&quot;&gt;IQueryable&amp;lt;T&amp;gt;&lt;/a&gt; in our mock. &amp;nbsp;I&#39;m going to use&amp;nbsp;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/cc190116.aspx&quot; target=&quot;_blank&quot;&gt;EnumerableQuery&amp;lt;T&amp;gt;&lt;/a&gt; which gives me the following test that now passes:&lt;br /&gt;
&lt;br /&gt;
&lt;div id=&quot;codeSnippetWrapper&quot;&gt;&lt;div id=&quot;codeSnippet&quot; style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum1&quot; style=&quot;color: #606060;&quot;&gt;   1:&lt;/span&gt; [Test]&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum2&quot; style=&quot;color: #606060;&quot;&gt;   2:&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: blue;&quot;&gt;void&lt;/span&gt; can_mock_customer_context()&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum3&quot; style=&quot;color: #606060;&quot;&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum4&quot; style=&quot;color: #606060;&quot;&gt;   4:&lt;/span&gt;    var context = Substitute.For&amp;lt;ICustomerContext&amp;gt;();&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum5&quot; style=&quot;color: #606060;&quot;&gt;   5:&lt;/span&gt;    context.Customers.Returns(&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum6&quot; style=&quot;color: #606060;&quot;&gt;   6:&lt;/span&gt;       &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; EnumerableQuery&amp;lt;Customer&amp;gt;(&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum7&quot; style=&quot;color: #606060;&quot;&gt;   7:&lt;/span&gt;          &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt;[]&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum8&quot; style=&quot;color: #606060;&quot;&gt;   8:&lt;/span&gt;          {&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum9&quot; style=&quot;color: #606060;&quot;&gt;   9:&lt;/span&gt;             &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; Customer {Name = &lt;span style=&quot;color: #006080;&quot;&gt;&quot;Sean&quot;&lt;/span&gt;}&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum10&quot; style=&quot;color: #606060;&quot;&gt;  10:&lt;/span&gt;          })&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum11&quot; style=&quot;color: #606060;&quot;&gt;  11:&lt;/span&gt;       );&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum12&quot; style=&quot;color: #606060;&quot;&gt;  12:&lt;/span&gt;    Assert.AreEqual(1, context.Customers.Count());&lt;/pre&gt;&lt;pre style=&quot;background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum13&quot; style=&quot;color: #606060;&quot;&gt;  13:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style=&quot;background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: &#39;Courier New&#39;, courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;&quot;&gt;&lt;span id=&quot;lnum14&quot; style=&quot;color: #606060;&quot;&gt;  14:&lt;/span&gt;    }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
I&#39;m new to&amp;nbsp;&lt;a href=&quot;http://http//nsubstitute.github.com/&quot;&gt;NSubstitute&lt;/a&gt;&amp;nbsp;but it seem to be the lowest friction mocking library out there. &amp;nbsp;Just perfect for use with Entity Framework 4 Code First - certainly the lowest friction ORM there is today!&lt;br /&gt;
&lt;br /&gt;
Note that we could have used the&amp;nbsp;&lt;a href=&quot;http://martinfowler.com/eaaCatalog/repository.html&quot;&gt;repository pattern&lt;/a&gt;&amp;nbsp;to wrap the DbContext&amp;nbsp;instead of a simple interface, the approach is almost identical.&lt;br /&gt;
&lt;br /&gt;
Update: Ro Miller has an alternative approach using fakes that does a better job of surfacing IDbSet&lt;t&gt;. &amp;nbsp;Check it out here:&amp;nbsp;&lt;a href=&quot;http://romiller.com/2010/09/07/ef-ctp4-tips-tricks-testing-with-fake-dbcontext/&quot;&gt;http://romiller.com/2010/09/07/ef-ctp4-tips-tricks-testing-with-fake-dbcontext/&lt;/a&gt;.&lt;/t&gt;</description><link>http://kearon.blogspot.com/2011/02/mocking-entity-framework-4-code-first.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>5</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-4525629588746665978</guid><pubDate>Thu, 17 Feb 2011 20:05:00 +0000</pubDate><atom:updated>2011-02-17T20:07:05.160+00:00</atom:updated><title>Package Manager With Source Download</title><description>&lt;p&gt;I was skinning up some code and I used my &lt;a href=&quot;http://nuget.codeplex.com/&quot; target=&quot;_blank&quot;&gt;package&lt;/a&gt; &lt;a href=&quot;http://www.openwrap.org/&quot; target=&quot;_blank&quot;&gt;manager&lt;/a&gt; of choice to add &lt;a href=&quot;http://nlog-project.org/&quot; target=&quot;_blank&quot;&gt;NLog&lt;/a&gt; to the project.&amp;nbsp; All good, very easy and away I coded.&lt;/p&gt; &lt;p&gt;The project required a single DLL as an output.&amp;nbsp; So, I thought hey – I’ll use Paul Stovell’s &lt;a href=&quot;http://www.paulstovell.com/tape&quot; target=&quot;_blank&quot;&gt;Tape&lt;/a&gt; to save using &lt;a href=&quot;http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx&quot; target=&quot;_blank&quot;&gt;ILMerge&lt;/a&gt; in the build.&amp;nbsp; Good plan, but after 5 minutes browsing the NLog source on GitHub it realised I was not sure how to find the version I needed.&amp;nbsp; That’s fine, ILMerge is pretty easy to use so I used the build to save the day.&lt;/p&gt; &lt;p&gt;On the same day (today) I read &lt;a href=&quot;http://blogs.jetbrains.com/dotnet/2011/02/resharper-6-bundles-decompiler-free-standalone-tool-to-follow&quot; target=&quot;_blank&quot;&gt;this post&lt;/a&gt; about ReSharper 6 features and suddenly realised how powerful it would be for package managers to be able to give me the source, not just binaries.&amp;nbsp; Now that’s a killer feature and would be even better if the source came with a single file option so I didn’t even have to run &lt;a href=&quot;http://www.paulstovell.com/tape&quot; target=&quot;_blank&quot;&gt;Tape&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Oh, please, soon…&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2011/02/package-manager-with-source-download.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-836136502342039711</guid><pubDate>Thu, 03 Feb 2011 01:19:00 +0000</pubDate><atom:updated>2011-02-03T08:25:36.985+00:00</atom:updated><title>A Better Deal</title><description>Red Gate are now going to charge for &lt;a href=&quot;http://www.lutzroeder.com/&quot;&gt;Lutz Roeder’s&lt;/a&gt; &lt;a href=&quot;http://en.wikipedia.org/wiki/.NET_Reflector&quot;&gt;Reflector&lt;/a&gt;.&amp;nbsp; This tool has been free for it&#39;s life – more years than I care to remember.&amp;nbsp; Its as much part of a software developer’s toolkit as a hammer is part of a builder’s toolkit.&lt;br /&gt;
&lt;br /&gt;
I have dealt with Red Gate as part of a very small company and as part of a very large company.&amp;nbsp; I am sorry to say that each time I have come away feeling less than happy. &amp;nbsp;Any company that sends be a maintenance bill at the end of year one that &lt;em&gt;exceeds&lt;/em&gt; &lt;em&gt;my original purchase price &lt;/em&gt;isn&#39;t going to make me happy to deal with them!&lt;br /&gt;
&lt;br /&gt;
Reading Red Gates’ &lt;a href=&quot;http://www.neildavidson.com/dontjustrollthedice.html&quot;&gt;pricing strategy&lt;/a&gt;, written by their co-founder, Neil Davidson, I struggle to believe their other CEO, Simon Galbraith, when he says how sorry he is &lt;a href=&quot;http://www.youtube.com/watch?v=TKnEjiSGZLA&quot;&gt;about charging for Reflector&lt;/a&gt;.&amp;nbsp; I just kept thinking that they just want my cash - like the other times I’ve dealt with them.&lt;br /&gt;
&lt;br /&gt;
Maybe Galbraith and Davidson should go and listen to &lt;a href=&quot;http://sethgodin.typepad.com/seths_blog/2010/08/the-right-price-the-first-time.html&quot;&gt;Seth Godin’s pricing advice&lt;/a&gt;.&amp;nbsp; Maybe then I’d want to buy stuff from them!&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
35USD is good value for Reflector and I may have to buy a copy.&amp;nbsp; I’d really just rather buy from another company and get a better deal.</description><link>http://kearon.blogspot.com/2011/02/better-deal.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-2545162448055848762</guid><pubDate>Sat, 23 Oct 2010 14:12:00 +0000</pubDate><atom:updated>2010-10-24T07:54:58.570+01:00</atom:updated><title>Install the Full .Net 4 Framework with Tarma Installer</title><description>&lt;p&gt;If you haven’t seen &lt;a href=&quot;http://www.tarma.com/&quot; target=&quot;_blank&quot;&gt;Tarma InstallMate&lt;/a&gt; before, the you need to check this little beauty out.&amp;nbsp; It’s a fully featured installer that&amp;nbsp; have been using it in production for just under a year now and the end-user setup installer just drops out of the end of my build process – sweet!&lt;/p&gt; &lt;p&gt;There’s one thing that is very different with Tarma and all the other installers out there – Tarma doesn’t charge stupid rip-off money like all the other suppliers seem to like to do.&amp;nbsp; You can get their top-of-the-range product for under $90USD per developer.&amp;nbsp; Couple that with totally superb support, rock solid performance and a really rich feature set, Tarma’s a total winner!&lt;/p&gt; &lt;p&gt;Out of the box, Tarma has support for a number of prerequisites like .Net Framework, Access runtimes and Windows Installer.&amp;nbsp; However, it doesn’t differentiate between the Full and Client Profiles for .Net 4 – if the Client Profile is detected then it will not install the full framework and I need to get the full framework onto my user’s machine.&amp;nbsp; &lt;/p&gt; &lt;h4&gt;Detecting the Installed Framework Version&lt;/h4&gt; &lt;p&gt;To detect which version of the .Net Framework 4 has been installed, you need to check the presence of the following registry keys.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client&lt;br&gt;HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;More details on that &lt;a href=&quot;http://blogs.msdn.com/b/heaths/archive/2010/05/04/detection-keys-for-net-framework-4-0-and-visual-studio-2010.aspx&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;We can set up Tarma to do that easily, like this:&lt;/p&gt; &lt;h4&gt;Read Registry Key into a Variable&lt;/h4&gt; &lt;p&gt;Go to Symbolic Variables and add a new variable called IsFullDotnet4.&amp;nbsp; Then use Tarma’s support for &lt;a href=&quot;http://www.installmate.com/support/im7/using/symbols/index.htm&quot; target=&quot;_blank&quot;&gt;symbolic expressions&lt;/a&gt; to read whether the registry key exists by setting the new variable’s value to this: &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&amp;lt;$rkaccess(&amp;lt;HKLM&amp;gt;\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full)&amp;gt; &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;It should now look like this:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1ODoTqZi3A_sQ-WgWubbbXacgtDfDf9_Z1nbjMyoq1gF6JF5-tXbb3oN-fxRH_3SbM39muu0SxdS3BtRYL9dHgvJK4v3E3CzSWDUR6Jw4cxhloIx-oyKyUyChw1YNbWdDcwuvFTQszwzD/s1600-h/SNAGHTML6641ea8%5B3%5D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;SNAGHTML6641ea8&quot; border=&quot;0&quot; alt=&quot;SNAGHTML6641ea8&quot; src=&quot;http://lh3.ggpht.com/_tA36DMxmDew/TMLtSZJ7FoI/AAAAAAAAAqE/DbC8wdID4Ks/SNAGHTML6641ea8_thumb.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;160&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;Adjust Prerequisites Condition&lt;/h4&gt; &lt;p&gt;Go to the prerequisites section and adjust the condition to install the .Net 4 Runtime by setting the condition to this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;NOT IsFullDotnet4&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;It should look something like this:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw3hOHnmpo-U5-HVJIiKfhRkXWsXGWtWSKfhmOlRJ8h8YnX-dTOh6hEc5yFvJqBSSbQty9HYOwifViCDqIpleLDhZcNFYOns31BFz6MEMJGxIHxy0ohUUAcKjkV2Edy1iG-KKzPP9ViiE4/s1600-h/SNAGHTML7d171%5B3%5D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;SNAGHTML7d171&quot; border=&quot;0&quot; alt=&quot;SNAGHTML7d171&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXiFsh3NspJXMf0M-I6CZ-HjI14gSLIoe7fM08MURNI7y5lG-bce9zZ0fpRk2feb5CAtcILAo7ehTU-8qjhGXeJhTmFgbX-LRwQyJopDuLCKEEkBQN3k0NtsQvGfpBW2LH03GhUz9e9bWf/?imgmax=800&quot; width=&quot;244&quot; height=&quot;170&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;That’s all you need – Tarma will now upgrade .Net 4 Client Profile installations to the Full version.&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2010/10/install-full-net-4-framework-with-tarma.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_tA36DMxmDew/TMLtSZJ7FoI/AAAAAAAAAqE/DbC8wdID4Ks/s72-c/SNAGHTML6641ea8_thumb.png?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-8529205708774705378</guid><pubDate>Mon, 04 Oct 2010 18:45:00 +0000</pubDate><atom:updated>2010-10-04T19:51:38.293+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">xpo</category><title>Replacing Strings in XPObject.SetPropertyValue with Lambdas</title><description>&lt;p&gt;I came across a post on &lt;a href=&quot;http://alfware.com.au/index.php&quot; target=&quot;_blank&quot;&gt;Aussie Alf&lt;/a&gt;’s blog today about removing magic strings from the persistent property setters in the &lt;a href=&quot;http://www.devexpress.com/Products/NET/ORM/&quot; target=&quot;_blank&quot;&gt;XPO ORM&lt;/a&gt; from &lt;a href=&quot;http://www.devexpress.com&quot; target=&quot;_blank&quot;&gt;DevExpress&lt;/a&gt;.&amp;nbsp; &lt;/p&gt; &lt;p&gt;The Aussie Alf blog is written by Michael Proctor who is a member of the DevExpress community &lt;a href=&quot;http://www.dxsquad.com/&quot; target=&quot;_blank&quot;&gt;DXSquad&lt;/a&gt;, specialising in XPO.&amp;nbsp; The blog is a superb resource for any XPO developers and really worth reading.&amp;nbsp; Michael is also a very active member on the DevExpress forums and may well come to your help with an XPO issue there.&lt;/p&gt; &lt;p&gt;XPO uses a classic INotifyPropertyChanged pattern and passes a string of the changed property name into SetPropertyValue method.&amp;nbsp; You can see this below:&amp;nbsp;&amp;nbsp; &lt;/p&gt;  &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:3676b23d-2c9f-47aa-8585-86d0e06a63cc&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt; &lt;div style=&quot;border: #000080 1px solid; color: #000; font-family: &#39;Courier New&#39;, Courier, Monospace; font-size: 10pt&quot;&gt; &lt;div style=&quot;background: #ddd; max-height: 300px; overflow: auto&quot;&gt; &lt;ol style=&quot;background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px; white-space: nowrap&quot;&gt; &lt;li&gt;&lt;span style=&quot;color:#0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#2b91af&quot;&gt;Customer&lt;/span&gt; : &lt;span style=&quot;color:#2b91af&quot;&gt;XPObject&lt;/span&gt;&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;{&lt;/li&gt; &lt;li&gt;   &lt;span style=&quot;color:#0000ff&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;string&lt;/span&gt; _number;&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;   &lt;span style=&quot;color:#0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;string&lt;/span&gt; Number&lt;/li&gt; &lt;li&gt;   {&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;      &lt;span style=&quot;color:#0000ff&quot;&gt;get&lt;/span&gt; { &lt;span style=&quot;color:#0000ff&quot;&gt;return&lt;/span&gt; _number; }&lt;/li&gt; &lt;li&gt;      &lt;span style=&quot;color:#0000ff&quot;&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style=&quot;color:#a31515&quot;&gt;&amp;quot;Number&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color:#0000ff&quot;&gt;ref&lt;/span&gt; _number, &lt;span style=&quot;color:#0000ff&quot;&gt;value&lt;/span&gt;); }&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;   }&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;The problem with this approach is that the compiler can’t determine whether the string is correct or not, leaving you open to potential runtime errors.&amp;nbsp; Michael’s solution to this to generate a helper class that can be used in the property setter and he has a Visual Studio plugin that generates and refreshes the helper class for you based on your domain model.&amp;nbsp; &lt;/p&gt; &lt;p&gt;This is a great approach to the problem and you can read more about it on the homepage for Michael’s plugin, &lt;a href=&quot;http://code.google.com/p/dxcorecommunityplugins/wiki/XPO_EasyFields&quot; target=&quot;_blank&quot;&gt;XPO_EasyFields&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Michael’s &lt;a href=&quot;http://code.google.com/p/dxcorecommunityplugins/wiki/XPO_EasyFields&quot; target=&quot;_blank&quot;&gt;XPO_EasyFields&lt;/a&gt; plugin uses the free &lt;a href=&quot;http://www.devexpress.com/Products/Visual_Studio_Add-in/DXCore/&quot; target=&quot;_blank&quot;&gt;DXCore&lt;/a&gt; Visual Studio plugin from DevExpress.&amp;nbsp; Personally, I use Resharper and don’t have DXCore installed, so I thought I would share my approach to removing the magic strings - I use a helper class and lambdas to do this.&amp;nbsp; It looks like this:&lt;/p&gt; &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:ea84ff22-5aba-4b53-a87c-e99d5e2883e8&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt; &lt;div style=&quot;border: #000080 1px solid; color: #000; font-family: &#39;Courier New&#39;, Courier, Monospace; font-size: 10pt&quot;&gt; &lt;div style=&quot;background: #ddd; max-height: 300px; overflow: auto&quot;&gt; &lt;ol style=&quot;background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px; white-space: nowrap&quot;&gt; &lt;li&gt;&lt;span style=&quot;color:#0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#2b91af&quot;&gt;Customer&lt;/span&gt; : &lt;span style=&quot;color:#2b91af&quot;&gt;XPObject&lt;/span&gt;&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;{&lt;/li&gt; &lt;li&gt;   &lt;span style=&quot;color:#0000ff&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;string&lt;/span&gt; _number;&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;   &lt;span style=&quot;color:#0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;string&lt;/span&gt; Number&lt;/li&gt; &lt;li&gt;   {&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;      &lt;span style=&quot;color:#0000ff&quot;&gt;get&lt;/span&gt; { &lt;span style=&quot;color:#0000ff&quot;&gt;return&lt;/span&gt; _number; }&lt;/li&gt; &lt;li&gt;      &lt;span style=&quot;color:#0000ff&quot;&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style=&quot;color:#2b91af&quot;&gt;Property&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#2b91af&quot;&gt;Customer&lt;/span&gt;&amp;gt;.Name(x =&amp;gt; x.Number), &lt;span style=&quot;color:#0000ff&quot;&gt;ref&lt;/span&gt; _number, &lt;span style=&quot;color:#0000ff&quot;&gt;value&lt;/span&gt;); }&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;   }&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;p&gt;This relies on the use of a generic Property class and a helper method that gleans the property name from a Linq Expression.&amp;nbsp; The property class looks like this:&lt;/p&gt;  &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c33bc3cb-ae65-47e7-82a6-0f1ed5c27a99&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt; &lt;div style=&quot;border: #000080 1px solid; color: #000; font-family: &#39;Courier New&#39;, Courier, Monospace; font-size: 10pt&quot;&gt; &lt;div style=&quot;background: #ddd; max-height: 300px; overflow: auto&quot;&gt; &lt;ol style=&quot;background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px; white-space: nowrap&quot;&gt; &lt;li&gt;&lt;span style=&quot;color:#0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#2b91af&quot;&gt;Property&lt;/span&gt;&amp;lt;T&amp;gt;&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;{&lt;/li&gt; &lt;li&gt;   &lt;span style=&quot;color:#0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;string&lt;/span&gt; Name(&lt;span style=&quot;color:#2b91af&quot;&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#2b91af&quot;&gt;Func&lt;/span&gt;&amp;lt;T, &lt;span style=&quot;color:#0000ff&quot;&gt;object&lt;/span&gt;&amp;gt;&amp;gt; expression)&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;   {&lt;/li&gt; &lt;li&gt;      &lt;span style=&quot;color:#0000ff&quot;&gt;if&lt;/span&gt; (expression == &lt;span style=&quot;color:#0000ff&quot;&gt;null&lt;/span&gt;) &lt;span style=&quot;color:#0000ff&quot;&gt;throw&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af&quot;&gt;ArgumentNullException&lt;/span&gt;(&lt;span style=&quot;color:#a31515&quot;&gt;&amp;quot;expression&amp;quot;&lt;/span&gt;);&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;      &lt;span style=&quot;color:#0000ff&quot;&gt;if&lt;/span&gt; (expression.Body &lt;span style=&quot;color:#0000ff&quot;&gt;is&lt;/span&gt; &lt;span style=&quot;color:#2b91af&quot;&gt;MemberExpression&lt;/span&gt;) &lt;span style=&quot;color:#0000ff&quot;&gt;return&lt;/span&gt; ((&lt;span style=&quot;color:#2b91af&quot;&gt;MemberExpression&lt;/span&gt;)expression.Body).Member.Name;&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;      &lt;span style=&quot;color:#0000ff&quot;&gt;if&lt;/span&gt; (expression.Body &lt;span style=&quot;color:#0000ff&quot;&gt;is&lt;/span&gt; &lt;span style=&quot;color:#2b91af&quot;&gt;UnaryExpression&lt;/span&gt; &amp;amp;&amp;amp; ((&lt;span style=&quot;color:#2b91af&quot;&gt;UnaryExpression&lt;/span&gt;)expression.Body).Operand &lt;span style=&quot;color:#0000ff&quot;&gt;is&lt;/span&gt; &lt;span style=&quot;color:#2b91af&quot;&gt;MemberExpression&lt;/span&gt;)&lt;/li&gt; &lt;li&gt;      {&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;         &lt;span style=&quot;color:#0000ff&quot;&gt;return&lt;/span&gt; ((&lt;span style=&quot;color:#2b91af&quot;&gt;MemberExpression&lt;/span&gt;)((&lt;span style=&quot;color:#2b91af&quot;&gt;UnaryExpression&lt;/span&gt;)expression.Body).Operand).Member.Name;&lt;/li&gt; &lt;li&gt;      }&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;      &lt;span style=&quot;color:#0000ff&quot;&gt;throw&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#2b91af&quot;&gt;ArgumentException&lt;/span&gt;(&lt;span style=&quot;color:#0000ff&quot;&gt;string&lt;/span&gt;.Format(&lt;span style=&quot;color:#a31515&quot;&gt;&amp;quot;Could not get property name from expression of type &amp;#39;{0}&amp;#39;&amp;quot;&lt;/span&gt;,&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;                                                expression.GetType()));&lt;/li&gt; &lt;li&gt;   }&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;The magic comes from translating the little lambda expression x =&amp;gt; x.Name to a string.&amp;nbsp; If I remember right, I originally based this on some code from Jeremy Miller, but there are various implementations out there.&amp;nbsp; Here’s and elegant one from &lt;a href=&quot;http://www.paulstovell.com/strong-property-names&quot; target=&quot;_blank&quot;&gt;Paul Stovell&lt;/a&gt; that’s focused purely on INotifyPropertyChanged.&amp;nbsp; &lt;/p&gt; &lt;p&gt;As Paul mentions in the above link, it’s worth noting that there is a performance hit when using this approach.&amp;nbsp; Michael’s approach of generating the code does not have any performance hit.&amp;nbsp; You may need to consider the performance issue if you have very high rates of properties being set.&amp;nbsp; &lt;/p&gt; &lt;p&gt;I did some simple performance tests that show a 10-15x overhead with my approach compared to Michael’s.&amp;nbsp; However, this only becomes relevant with a very large number of property sets.&amp;nbsp; For my usage scenarios the added quality benefit outweighs the performance hit, but you will need to carefully consider your scenario.&lt;/p&gt; &lt;p&gt;Lastly, to take this further, and get an even tighter syntax, I add this helper method to my persistent classes:&lt;/p&gt;  &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:38984329-ccd0-499c-bef0-dfdbec7eb12b&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt; &lt;div style=&quot;border: #000080 1px solid; color: #000; font-family: &#39;Courier New&#39;, Courier, Monospace; font-size: 10pt&quot;&gt; &lt;div style=&quot;background: #ddd; max-height: 300px; overflow: auto&quot;&gt; &lt;ol style=&quot;background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px; white-space: nowrap&quot;&gt; &lt;li&gt;&lt;span style=&quot;color:#0000ff&quot;&gt;protected&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;void&lt;/span&gt; Set&amp;lt;T&amp;gt;(&lt;span style=&quot;color:#2b91af&quot;&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#2b91af&quot;&gt;Func&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#2b91af&quot;&gt;Customer&lt;/span&gt;, &lt;span style=&quot;color:#0000ff&quot;&gt;object&lt;/span&gt;&amp;gt;&amp;gt; property, &lt;span style=&quot;color:#0000ff&quot;&gt;ref&lt;/span&gt; T holder, T value)&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;{&lt;/li&gt; &lt;li&gt;   SetPropertyValue(&lt;span style=&quot;color:#2b91af&quot;&gt;Property&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#2b91af&quot;&gt;Customer&lt;/span&gt;&amp;gt;.Name(property), &lt;span style=&quot;color:#0000ff&quot;&gt;ref&lt;/span&gt; holder, value);&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;This allows the setter to be even more compact:&lt;/p&gt;  &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:f0f82388-fdef-48f2-ac30-c96b713ec48e&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt; &lt;div style=&quot;border: #000080 1px solid; color: #000; font-family: &#39;Courier New&#39;, Courier, Monospace; font-size: 10pt&quot;&gt; &lt;div style=&quot;background: #ddd; max-height: 300px; overflow: auto&quot;&gt; &lt;ol style=&quot;background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px; white-space: nowrap&quot;&gt; &lt;li&gt;&lt;span style=&quot;color:#0000ff&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;string&lt;/span&gt; _number;&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;&lt;span style=&quot;color:#0000ff&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#0000ff&quot;&gt;string&lt;/span&gt; Number&lt;/li&gt; &lt;li&gt;{&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;   &lt;span style=&quot;color:#0000ff&quot;&gt;get&lt;/span&gt; { &lt;span style=&quot;color:#0000ff&quot;&gt;return&lt;/span&gt; _number; }&lt;/li&gt; &lt;li&gt;   &lt;span style=&quot;color:#0000ff&quot;&gt;set&lt;/span&gt; { Set(x =&amp;gt; x.Number, &lt;span style=&quot;color:#0000ff&quot;&gt;ref&lt;/span&gt; _number, &lt;span style=&quot;color:#0000ff&quot;&gt;value&lt;/span&gt;); }&lt;/li&gt; &lt;li style=&quot;background: #f3f3f3&quot;&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;The downside is that you need the helper method in each class.&amp;nbsp; Down to taste that really, but I always go for the tighter syntax wherever possible!&amp;nbsp; &lt;/p&gt; &lt;p&gt;You can get the code from &lt;a href=&quot;https://bitbucket.org/seankearon/xpo-replace-strings-with-lambdas&quot; target=&quot;_blank&quot;&gt;bitbucket&lt;/a&gt; and browse the salient parts &lt;a href=&quot;https://bitbucket.org/seankearon/xpo-replace-strings-with-lambdas/src/tip/XPOWithLamdbas/Customer.cs&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2010/10/replacing-strings-in.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-5267946429540948021</guid><pubDate>Thu, 21 Jan 2010 23:11:00 +0000</pubDate><atom:updated>2010-04-16T16:20:28.141+01:00</atom:updated><title>Sometimes It Just Works</title><description>&lt;p&gt;Some things in life that just do what they say they will do and when this happens you get blown away.&amp;#160; &lt;/p&gt;  &lt;p&gt;VMware Workstation says it lets you use Visual Studio to debug an application that is running on a virtual machine.&amp;#160; I used this recently and was blown away by how easy it was to set up and by how amazingly useful it was.&lt;/p&gt;  &lt;p&gt;The story is that I released a new build for informal testing, but it could not be installed.&amp;#160; I installed it onto a clean XP VM (yeah, I should have done that already…) and got the error myself.&amp;#160; However, there was no error information coming back from the application as the failure was happening before the logging layer was instantiated. &lt;/p&gt;  &lt;p&gt;I was stuck.&amp;#160; I could reproduce, but had no other information to help.&amp;#160; Then I remembered that VMware Workstation had the facility to debug apps running on VMs.&amp;#160; So, I followed the instructions (yes, I was desperate enough to read the VMware help file!!) and set up a VM for remote debugging.&amp;#160; This was pretty swift to achieve and I then started a debugging session on the VM from Visual Studio.&amp;#160; &lt;/p&gt;  &lt;p&gt;Almost immediately I could see what was happening: it was my bad – I’d just forgotten to include a third-party assembly with the build.&amp;#160; My dev box was happily loading it from the GAC and so I couldn’t see I’d missed anything.&lt;/p&gt;  &lt;p&gt;VMware Workstation just did what it said it would do.&amp;#160; in doing so, it got me out of a sticky situation.&amp;#160; Also, it says it has the ability to record and replay a debugging session…maybe next time, eh?&lt;/p&gt;  &lt;p&gt;In the meantime, and whilst loving the things that go right, here’s a shot of the error from VS debugging on the VM:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/_tA36DMxmDew/S1jfJHKtKGI/AAAAAAAAAYc/Hv3dbAbmMRA/s1600-h/image%5B2%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://lh5.ggpht.com/_tA36DMxmDew/S1jfJt1CgsI/AAAAAAAAAYg/f_Vqj8v-cY0/image_thumb.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;97&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2010/01/sometimes-it-just-works-right.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_tA36DMxmDew/S1jfJt1CgsI/AAAAAAAAAYg/f_Vqj8v-cY0/s72-c/image_thumb.png?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-2351309664810123365</guid><pubDate>Thu, 07 Jan 2010 19:24:00 +0000</pubDate><atom:updated>2010-01-07T19:52:43.473+00:00</atom:updated><title>Friendly OS Name from WMI</title><description>&lt;p&gt;When you want to find out what operating system your application is running on, &lt;font face=&quot;Courier New&quot;&gt;System.Environment.OSVersion&lt;/font&gt; is not very readable.&amp;#160; You can get a nice friendly name using WMI like this:&lt;/p&gt; &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;style type=&quot;text/css&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, &quot;Courier New&quot;, courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;  &lt;pre&gt;&lt;pre style=&quot;background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px&quot;&gt;  1: &lt;span style=&quot;color: #0000ff&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; GetOSName()&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px&quot;&gt;  2: {&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px&quot;&gt;  3:    &lt;span style=&quot;color: #0000ff&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #0000ff&quot;&gt;string&lt;/span&gt; query = &amp;quot;&lt;span style=&quot;color: #8b0000&quot;&gt;SELECT * FROM Win32_OperatingSystem&lt;/span&gt;&amp;quot;;&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px&quot;&gt;  4:    var searcher = &lt;span style=&quot;color: #0000ff&quot;&gt;new&lt;/span&gt; ManagementObjectSearcher(query);&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px&quot;&gt;  5:    var results = from x &lt;span style=&quot;color: #0000ff&quot;&gt;in&lt;/span&gt; searcher.Get().OfType&amp;lt;ManagementObject&amp;gt;()&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px&quot;&gt;  6:            select x.GetPropertyValue(&amp;quot;&lt;span style=&quot;color: #8b0000&quot;&gt;Caption&lt;/span&gt;&amp;quot;);&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px&quot;&gt;  7:    &lt;span style=&quot;color: #0000ff&quot;&gt;return&lt;/span&gt; results.Any() ? results.First().ToString() : &amp;quot;&lt;span style=&quot;color: #8b0000&quot;&gt;Unknown&lt;/span&gt;&amp;quot;;&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px&quot;&gt;  8: }&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This will give you something like &amp;quot;Microsoft® Windows Server® 2008 Enterprise &amp;quot;.&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2010/01/getting-friendly-os-name-from-wmi.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-6163736458281143256</guid><pubDate>Sat, 18 Apr 2009 08:10:00 +0000</pubDate><atom:updated>2009-04-18T09:10:31.023+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">cloud</category><category domain="http://www.blogger.com/atom/ns#">production</category><title>Cloud Computing – SMD Services</title><description>&lt;p&gt;Rinat Abdullin has recently put up an interesting post about &lt;a href=&quot;http://abdullin.com/journal/2009/4/11/cloud-computing-could-windows-azure-catch-up-with-amazon.html#comments&quot; target=&quot;_blank&quot;&gt;cloud computing&lt;/a&gt;, along with another post as a &lt;a href=&quot;http://abdullin.com/journal/2009/4/14/why-is-cloud-computing-important-for-us.html&quot; target=&quot;_blank&quot;&gt;response&lt;/a&gt; to a &lt;a href=&quot;http://abdullin.com/journal/2009/4/11/cloud-computing-could-windows-azure-catch-up-with-amazon.html#comments&quot; target=&quot;_blank&quot;&gt;comment&lt;/a&gt; of mine.&amp;#160; Rinat pointed out the benefits cloud scenarios bring when there is a need for distributed computing resources, highlighting Amazon’s &lt;a href=&quot;http://aws.amazon.com/elasticmapreduce/&quot; target=&quot;_blank&quot;&gt;recent announcement&lt;/a&gt; along with Microsoft’s offerings in &lt;a href=&quot;http://research.microsoft.com/en-us/projects/Dryad/&quot; target=&quot;_blank&quot;&gt;that&lt;/a&gt; &lt;a href=&quot;http://research.microsoft.com/en-us/projects/dryadlinq/default.aspx&quot; target=&quot;_blank&quot;&gt;space&lt;/a&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;I agree with Rinat that distributed computing scenarios are clearly winners for cloud computing.&amp;#160; However, my view is that one of the critical success factors for the success of cloud computing will be developer adoption.&amp;#160; If you have developers using your product it will succeed (as a cloud platform), if you don’t then…well, you get it!&amp;#160; My view is that the larger organisations who already have their own infrastructure will certainly adopt cloud resources, but it will not be these organisation that will drive the adoption of cloud technologies.&amp;#160; It will be the small to medium enterprises (SME) for whom the effort to host themselves is a large compared to their overall effort to stay in business.&lt;/p&gt;  &lt;p&gt;What is going to drive SME uptake – having software that delivers business advantage.&amp;#160; How does this get to them – by developers producing it for them.&amp;#160; Making your cloud platform accessible and usable for developers will drive wider adoption.&lt;/p&gt;  &lt;p&gt;In Rinat’s &lt;a href=&quot;http://abdullin.com/journal/2009/4/14/why-is-cloud-computing-important-for-us.html&quot; target=&quot;_blank&quot;&gt;second&lt;/a&gt; post he mentions a scenario where if he had had a cloud platform like &lt;a href=&quot;http://www.microsoft.com/azure/default.mspx&quot; target=&quot;_blank&quot;&gt;Azure&lt;/a&gt; available, cost could have been saved.&amp;#160; He also outlines the basis for how cloud computing will reduce the overall costs of the adoption of a the provided in the cloud – the larger data centres selling their idle CPU cycles.&amp;#160; &lt;/p&gt;  &lt;p&gt;He then points out that there is fast evolving market for hosted developer environments where you can easily and cheaply access version control, wiki, issue tracker services, etc.&amp;#160; In an earlier post I mentioned one such provider, &lt;a href=&quot;http://kearon.blogspot.com/2008/06/praise-subversion-hosting-at-wushnet.html&quot; target=&quot;_blank&quot;&gt;WUSH&lt;/a&gt;, with whom I have had a positive experience throughout the last year in the smaller scale development work I do out of normal working hours.&amp;#160; &lt;/p&gt;  &lt;p&gt;It is this area – developer services – that I see as the key to making cloud computing ubiquitous.&amp;#160; If you can provide developers with full-lifecycle support from your platform they will come in their droves.&amp;#160; By full lifecycle, I mean support for planning, production, test and live all in an integrated set of cloud services.&lt;/p&gt;  &lt;p&gt;As mentioned, there we see some support for planning and some aspects of production already out there (search for “&lt;a href=&quot;http://www.google.co.uk/search?rlz=1C1CHMR_en-GBGB306GB306&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&amp;amp;q=hosted+subversion&quot; target=&quot;_blank&quot;&gt;hosted subversion&lt;/a&gt;”, take a look at &lt;a href=&quot;http://www.google.co.uk/search?rlz=1C1CHMR_en-GBGB306GB306&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8&amp;amp;q=hosted+subversion&quot; target=&quot;_blank&quot;&gt;Scrumy&lt;/a&gt; or &lt;a href=&quot;http://www.manymoon.com&quot; target=&quot;_blank&quot;&gt;Manymoon&lt;/a&gt;, etc.), and you can but cost efficient test and live&amp;#160; environments (by renting your own server).&amp;#160; But to get other aspects running, like a build or &lt;a href=&quot;http://www.martinfowler.com/articles/continuousIntegration.html&quot; target=&quot;_blank&quot;&gt;CI&lt;/a&gt; environment, involves setting it up yourself on a server you have rented yourself.&amp;#160; However, doing that would not be using &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_as_a_service&quot; target=&quot;_blank&quot;&gt;SaaS&lt;/a&gt; beyond having a server hosted in the cloud.&amp;#160; Unfortunately, I know of no decently priced build service that for commercial projects.&lt;/p&gt;  &lt;p&gt;What do I want to see?&amp;#160; In the short term, I’m missing a &lt;strike&gt;sensibly&lt;/strike&gt; cheaply priced build services for commercial projects (see James Kovac’s recent &lt;a href=&quot;http://www.jameskovacs.com/blog/AnnouncingTeamCityCodeBettercom.aspx&quot; target=&quot;_blank&quot;&gt;announcement&lt;/a&gt; of their new &lt;a href=&quot;http://www.jetbrains.com/teamcity/&quot; target=&quot;_blank&quot;&gt;Team City&lt;/a&gt; service for OS projects).&amp;#160; In the longer term I want to be able to have a fully hosted CI environment that prices me by disk and CPU usage.&amp;#160; &lt;/p&gt;  &lt;p&gt;The ultimate goal: Microsoft to host &lt;a href=&quot;http://msdn.microsoft.com/en-us/teamsystem/dd408382.aspx&quot; target=&quot;_blank&quot;&gt;TFS&lt;/a&gt; and reduce the cost of adoption for SMDs (small to medium developers :) ) to the &lt;a href=&quot;http://msdn.microsoft.com/en-us/teamsystem/default.aspx&quot; target=&quot;_blank&quot;&gt;Team System&lt;/a&gt; versions of Visual Studio.&lt;/p&gt;  &lt;p&gt;In the meantime, will I be using the current set of cloud services?&amp;#160; Absolutely, both in my production processes as an SMD and for services that my clients will use.&amp;#160; And, I am doing this for the the reasons &lt;a href=&quot;http://abdullin.com/&quot; target=&quot;_blank&quot;&gt;Rinat&lt;/a&gt; has outlined!&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2009/04/cloud-computing-smd-services.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-4973450791296211341</guid><pubDate>Mon, 15 Dec 2008 20:15:00 +0000</pubDate><atom:updated>2009-04-18T08:01:57.061+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">visualstudio</category><title>Double Click to Open Visual Studio Solutions in Vista/2008</title><description>&lt;p&gt;For a while I have been running Visual Studio under Vista (x32) and now I’m using &lt;a href=&quot;http://www.win2008workstation.com/wordpress/&quot; target=&quot;_blank&quot;&gt;Workstation 2008&lt;/a&gt; (very happily too!).&amp;#160;&amp;#160; I have UAC on, but have a policy setting to automatically elevate without showing a prompt.&amp;#160; (I absolutely can’t live with the dialogs…see &lt;a href=&quot;http://kearon.blogspot.com/2008/06/uac-time-is-marked.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://kearon.blogspot.com/2008/06/uac-peace-at-last.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; for more info).&lt;/p&gt;  &lt;p&gt;I have also Visual Studio set to run as administrator, and that’s where the problem starts: I have not been able to open solution files by double clicking them.&amp;#160; &lt;/p&gt;  &lt;p&gt;I am very grateful to “Sajeev Prasad / Arun Arcot” response to &lt;a href=&quot;http://www.pluralsight.com/community/blogs/matt/archive/2007/05/21/47446.aspx&quot; target=&quot;_blank&quot;&gt;this post&lt;/a&gt; for the solution.&lt;/p&gt;  &lt;p&gt;Basically, set both IDE and the loader (%programfiles%\Common Files\Microsoft Shared\MSEnv\VSLauncher.exe) to run as administrator and you can then double click to open solutions.&lt;/p&gt;  &lt;p&gt;Thanks Sajeev and Arun!&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2008/12/double-click-to-open-visual-studio.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-5852325940942319358</guid><pubDate>Mon, 15 Dec 2008 01:17:00 +0000</pubDate><atom:updated>2008-12-15T01:20:47.520+00:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">resharper</category><title>ReSharper Plugins</title><description>&lt;p&gt;I’ve been using ReSharper since it’s first EAP release (late 2003 or early 2004, if I am right) and quite simply would not want to code without it. &lt;/p&gt;  &lt;p&gt;ReSharper is a platform that can be easily extended and it is worth noting that there are a number of excellent plugins available that to make your ReSharper experience even better. &lt;/p&gt;  &lt;p&gt;I mentioned &lt;a href=&quot;http://kearon.blogspot.com/2008/12/joyful-reflections-resharper-scout.html&quot; target=&quot;_blank&quot;&gt;Scout&lt;/a&gt; in an earlier post, but there are plugins for NHibernate, Gallio, xUnit and also for stuff like helping extract resources for internationalisation. &lt;/p&gt;  &lt;p&gt;Check &lt;a href=&quot;http://www.jetbrains.com/resharper/plugins/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; for more details.&lt;/p&gt;</description><link>http://kearon.blogspot.com/2008/12/resharper-plugins.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-4280979360067297038</guid><pubDate>Mon, 15 Dec 2008 00:44:00 +0000</pubDate><atom:updated>2008-12-15T00:49:53.422+00:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">xml</category><title>XML Editor - Liquid XML Studio</title><description>&lt;p&gt;I’ve just started using a great XML editor: &lt;a href=&quot;http://www.liquid-technologies.com/Product_XmlStudio.aspx&quot; target=&quot;_blank&quot;&gt;Liquid XML Studio&lt;/a&gt;.&amp;#160; I used it when creating some XSDs the other day.&amp;#160; It’s really easy to use, and has a great graphical interface too.&amp;#160; &lt;/p&gt;  &lt;p&gt;The thing I really really like is the feature to generate an instance of the schema.&amp;#160; The only other tool I’m aware of that does this is the BizTalk schema editor – but that’s a bit more of a heavyweight tool than I usually need!&lt;/p&gt;  &lt;p&gt;It also has Visual Studio integration (with the visual editor), XPath expression builder, documentation generation and a web service browser.&amp;#160; It’s not cheap, but there is a free feature limited &lt;a href=&quot;http://www.liquid-technologies.com/Product_XmlStudio_Features.aspx&quot; target=&quot;_blank&quot;&gt;Community Edition&lt;/a&gt;.&amp;#160; There’s also the high end &lt;a href=&quot;http://www.liquid-technologies.com/Product_XmlDataBinding.aspx&quot; target=&quot;_blank&quot;&gt;Developer Edition&lt;/a&gt; that adds a load of muscle for people working with more complex schemas, such as the &lt;a href=&quot;http://www.oasis-open.org/home/index.php&quot; target=&quot;_blank&quot;&gt;OASIS&lt;/a&gt; schemas.&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2008/12/xml-editor-liquid-xml-studio.html</link><author>noreply@blogger.com (Sean Kearon)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-6957976025569437110</guid><pubDate>Mon, 15 Dec 2008 00:21:00 +0000</pubDate><atom:updated>2008-12-15T00:28:01.495+00:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">resharper</category><title>Joyful Reflections - ReSharper Scout</title><description>&lt;p&gt;I’ve just found an excellent &lt;a href=&quot;http://www.jetbrains.com/resharper/&quot; target=&quot;_blank&quot;&gt;ReSharper&lt;/a&gt; plugin called &lt;a href=&quot;http://code.google.com/p/scoutplugin/&quot; target=&quot;_blank&quot;&gt;Scout&lt;/a&gt;.&amp;#160; This lovely little beast will open &lt;a href=&quot;http://www.red-gate.com/products/reflector/&quot; target=&quot;_blank&quot;&gt;Reflector&lt;/a&gt; when you choose Go to Declaration.&amp;#160; The thing I really love is that Scout also takes care of loading the appropriate assembly in Reflector.&amp;#160; I previously had to load the assembly in Reflector before I could browse it, which took time.&amp;#160; Scout makes this process seamless.&lt;/p&gt;  &lt;p&gt;All you have to do is right click and select Go to Declaration:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipmvGFecDblhCcp-SFMkjo3BDRou_JMoWit-nLrEvFVf3-vlgNyKt8w9fImbPbUDSlEdbDtyTbLRW141d3YkkDjeIzenfLra34UH5BKoXgaehPGKGIuLoMS-XU2Xytq9A_boynNNJzg1eO/s1600-h/changed%5B2%5D.png&quot;&gt;&lt;img title=&quot;Selecting the &amp;quot;Go to Declaration&amp;quot; menu item&quot; style=&quot;border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px&quot; height=&quot;217&quot; alt=&quot;Selecting the &amp;quot;Go to Declaration&amp;quot; menu item&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2V0AyU1G0BZ5Ys7IaqrK1zJvYeimp6RgJ-GJMz-rZsiM-2P6vDOouNJ0ORTk3IproVNUVU4E0v1hJ66B6OSu79G-PPe3FZ4MYZS5dTGBTdheJz45Ao_tFgCYclZrH2Jko5yRB-4fSAwqZ/?imgmax=800&quot; width=&quot;244&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Then you get taken to the item in Reflector and the correct assembly is loaded:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikpEfkLsS8Hctp-D_NX93n1vPaKvEUsaarIX0FaHbbe58eAZrzH-m5jL7B831ez4rPKv8rrG31sfXgGzAwuq6UUlZAfUckif8lcoMM04y3Cyxkjud1TvecipEFrFoSyxKZ2WFDtqqoHMEd/s1600-h/reflector%5B2%5D.png&quot;&gt;&lt;img title=&quot;reflector&quot; style=&quot;border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px&quot; height=&quot;138&quot; alt=&quot;reflector&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwSrmlKszBATdhFYKEEtkVq_HG15aWuizq0NlNMyu3sK6HII4dY_BUfrKaYXdoM7ThnbA3f32RGVPRD5Lh0kgiLkmutshtcnpkJB3B9JyGTMbtaVFOCvbxgroLnpVlvIJ3yr_W_Lcpo8MY/?imgmax=800&quot; width=&quot;244&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Scout will also take you to the &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx&quot; target=&quot;_blank&quot;&gt;Dotnet source code&lt;/a&gt; – but I haven’t got around to that yet!&amp;#160; You can find lots of other ReSharper plugin goodness &lt;a href=&quot;http://www.jetbrains.com/resharper/plugins/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;  </description><link>http://kearon.blogspot.com/2008/12/joyful-reflections-resharper-scout.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2V0AyU1G0BZ5Ys7IaqrK1zJvYeimp6RgJ-GJMz-rZsiM-2P6vDOouNJ0ORTk3IproVNUVU4E0v1hJ66B6OSu79G-PPe3FZ4MYZS5dTGBTdheJz45Ao_tFgCYclZrH2Jko5yRB-4fSAwqZ/s72-c?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2285278671879033267.post-6512962686300383946</guid><pubDate>Sat, 29 Nov 2008 07:12:00 +0000</pubDate><atom:updated>2008-11-30T16:20:24.284+00:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">devexpress</category><category domain="http://www.blogger.com/atom/ns#">xpo</category><title>Update on XPO and One-Way Associations</title><description>&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzeziDy2pAJyd_PyS78MrnZpImT5ksLA0UlxZQdt6O2QMdfHgopVjQoR8fLv3oS5IgGMCjFAX9lg4sYIpAXrhmUjSYegFf4K3Y-w9JKykJ6ua3o3sGGGAHrMhx1wHyfpaHFex7uq28VJ26/s1600-h/stop.gif&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzeziDy2pAJyd_PyS78MrnZpImT5ksLA0UlxZQdt6O2QMdfHgopVjQoR8fLv3oS5IgGMCjFAX9lg4sYIpAXrhmUjSYegFf4K3Y-w9JKykJ6ua3o3sGGGAHrMhx1wHyfpaHFex7uq28VJ26/s200/stop.gif&quot; /&gt;&lt;/a&gt;I stated in a &lt;a href=&quot;http://kearon.blogspot.com/2008/11/express-persistent-objects-xpo-to.html&quot;&gt;previous post&lt;/a&gt; that XPO would be supporting one-way multi associations.&amp;nbsp; Unfortunately, this is now not the case.&amp;nbsp; At the time I wrote the previous post, &lt;a href=&quot;http://www.devexpress.com/&quot;&gt;Developer Express&lt;/a&gt; had marked my request as accepted, but have now changed that to rejected.&lt;br /&gt;
&lt;br /&gt;
The guys at Developer Express support say that having a two-way association in your object model is fundamental to XPO multiple associations and, as my request was only to simplify code, the feature is now not to be implemented.&amp;nbsp; The bottom line from them was:&lt;br /&gt;
&lt;blockquote&gt;&quot;To sum it up, we think that the current design of one-to-many associations in XPO is reliable and transparent. We are not going to change it, unless we have strong arguments for doing so.&quot;&lt;/blockquote&gt;Well, although it&#39;s a shame that it&#39;s not going to be implemented, you can&#39;t argue than that!&lt;br /&gt;
&lt;br /&gt;
You can find the request thread &lt;a href=&quot;http://www.devexpress.com/Support/Center/p/S130253.aspx&quot;&gt;here&lt;/a&gt; (but may need to register).&amp;nbsp; If you still want to keep your XPO code clean, you can use some IL enhancement with PostSharp - details &lt;a href=&quot;http://kearon.blogspot.com/2008/10/using-postsharp-to-allow-one-way.html&quot;&gt;here&lt;/a&gt;.</description><link>http://kearon.blogspot.com/2008/11/update-on-xpo-and-one-way-associations.html</link><author>noreply@blogger.com (Sean Kearon)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzeziDy2pAJyd_PyS78MrnZpImT5ksLA0UlxZQdt6O2QMdfHgopVjQoR8fLv3oS5IgGMCjFAX9lg4sYIpAXrhmUjSYegFf4K3Y-w9JKykJ6ua3o3sGGGAHrMhx1wHyfpaHFex7uq28VJ26/s72-c/stop.gif" height="72" width="72"/><thr:total>0</thr:total></item></channel></rss>