Welcome, my name is Paul Stovell. I live in Brisbane and work on Octopus Deploy, an automated deployment tool for .NET applications.
Prior to founding Octopus Deploy, I worked for an investment bank in London building WPF applications, and before that I worked for Readify, an Australian .NET consulting firm. I also worked on a number of open source projects and was an active user group presenter. I was a Microsoft MVP for WPF from 2006 to 2013.
On a recent WPF project, I spent a little time setting up our installer using WiX. Here's a useful collection of WIX configuration settings that I want to hang on to.
Every WiX project has a
Product tag. Here's an example:
<Product Id="*" Name="My Application" Language="1033" Version="1.0.0" Manufacturer="You" UpgradeCode="e0848881-1930-4d96-945b-fa8ad2813978" >
Some things to note about the various parts:
Idattribute should change each time you build the MSI - the asterisk means it will be auto-generated
Versionattribute should probably come from your CI server
UpgradeCodeis used to determine whether the product was previously installed - once you set this, don't ever change it.
Ensure the .NET Framework is installed
This snippet checks whether .NET Framework 4.0 (full, not client profile) is installed, and if not, tells the user to go and install it.
<PropertyRef Id="NETFRAMEWORK40FULL"/> <Condition Message="This application requires Microsoft .NET Framework 4.0 Runtime in order to run. Please install the .NET Framework and then run this installer again."> <![CDATA[Installed OR NETFRAMEWORK40FULL]]> </Condition>
More information on the properties is available in the WixNetFxExtension documentation.
If you are using WixUI, there are some properties you can override.
<UIRef Id="WixUI_Minimal" /> <UIRef Id="WixUI_ErrorProgressText" /> <WixVariable Id="WixUILicenseRtf" Value="Resources\License.rtf" /> <WixVariable Id="WixUIBannerBmp" Value="Resources\Banner.bmp" /> <WixVariable Id="WixUIDialogBmp" Value="Resources\Dialog.bmp" /> <WixVariable Id="WixUIExclamationIco" Value="Resources\Warning.ico" /> <WixVariable Id="WixUIInfoIco" Value="Resources\Information.ico" />
For the current build of WixUI, Banner.bmp should be 493x58, and Dialog.bmp should be 500x314.
Auto-uninstall previous versions
Suppose you release version 2.0 of your product. Here's a snipper to uninstall all previous versions upon installing 2.0:
<Upgrade Id="e0848881-1930-4d96-945b-fa8ad2813978"> <UpgradeVersion Property="PREVIOUSFOUND" Minimum="0.0.0.0" IncludeMinimum="yes" Maximum="188.8.131.52" IncludeMaximum="yes" /> </Upgrade> <InstallExecuteSequence> <RemoveExistingProducts After="InstallInitialize"/> </InstallExecuteSequence>
Note that if you release a new build (i.e.,
Product/@Id changes, but
Product/@Version doesn't) of 184.108.40.206, this snippet will also uninstall that.
It's important that
If you hope to write to the event log, you'll need to be an administrator to create the event source. The installer is the best time to do this. Here's an example:
<DirectoryRef Id="TARGETDIR"> <Component Id="RegistryEntries" Guid="8C29D953-4D25-4EE0-A7F2-A9B34C9C65EF"> <util:EventSource Name="Training Kiosk" Log="Application" EventMessageFile="[NETFRAMEWORK40FULLINSTALLROOTDIR]EventLogMessages.dll" /> </Component> </DirectoryRef>
Run the application when installer finishes
After you install your WPF application, it's nice to run it automatically. Here's how:
<Property Id="WixShellExecTarget" Value="[#YourEXEFile]" /> <CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" /> <UI> <Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchApplication">NOT Installed</Publish> </UI>
Dan Pritchett wrote a good post about the friction between innovation and consistency. The bit that resonated with me was the conclusion that if you want to achieve consistency, you have to do it by providing solutions people want to use:
The traditional role of architectural governance can be very useful though in sorting out which of the 4 scenarios exist when someone wants to introduce a new solution to a problem. Most teams have a tremendous backlog of work, so looking for ways to ensure they aren't inventing for invention's sake is useful. It is also an opportunity to mentor and mature your teams.
Ultimately, I believe the answer is consistency through meritocracy not governance. The key challenge to a meritocratic process though is communication. Your organization must have open, consistent, frequent, and quality communication between teams. Wikis and issue tracking tools are a minimum. Social networking tools like Yammer are hugely valuable and an improvement over email because they provide broader visibility and context.
By actively choosing to use your solution, people tend to take ownership over that choice. That means they work harder to ensure it's successful. After all, if it comes crashing down, they'll look silly too. By "selling" your solution to people and having them actively choose to use it, I think you're more likely to be successful.
On the other hand, when people are given a solution and forced to use it, the reaction tends to be more negative. While they might use it, they'll have no reason to ensure it is successful. In fact, when I've been forced to use certain tools in the past due to company policy, I've found myself secretly hoping they'll fail so we can switch to something better.
While I've been on the receiving end of "governance" many times, my own solutions tend to be team or project focussed, and not organizational. As my own career progresses, it will be interesting to see how my solutions are adopted. Will I gain adoption naturally through providing a good solution, or will I take the easy way out, turning into the "governance" ogre I fear? Time will tell.
Since PDC there's been some discussion about the future of Silverlight vs. HTML 5:
Via: Our strategy with Silverlight has shifted (Mary Jo Foley)
But when it comes to touting Silverlight as Microsoft’s vehicle for delivering a cross-platform runtime, “our strategy has shifted,” Muglia told me.
Silverlight will continue to be a cross-platform solution, working on a variety of operating system/browser platforms, going forward, he said. “But HTML is the only true cross platform solution for everything, including (Apple’s) iOS platform,” Muglia said.
Of course, it's all about choosing the right tool for the job. Prior to PDC, Microsoft's recommended distribution of those choices looked something like this:
Since PDC and Microsoft's promoting of HTML 5 (which is great), the recommendations feel something like this:
I think this is much more sensible.
It should be said that these graphs are only accurate for those of us outside of Microsoft. If you work for Microsoft, the distribution looks more like this:
And now that Ray Ozzie has left, that 1% for Silverlight (which was there for Live Mesh) is also gone:
From a user's point of view, OpenID works something like this:
- You browse to a site you like that uses OpenID, and click the "login" button
- You enter your OpenID
- You are redirected to the site that authenticates your OpenID.
Note: You may be asked to login with a username and password for that site if you haven't done so recently.
- You are redirected back to the original site you browsed to, and are automatically logged in
Today I got to thinking that this is quite similar to how the "reset my password" link on most websites works:
- You browse to a site you like, and click the "reset my password" button
- You enter your username or email address
- You Alt+Tab to your email client, or Ctrl+Tab to your web-based email client.
Note: You may be asked to login with a username and password for your email server if you haven't done so recently.
- You Alt/Ctrl+Tab back to the original site you browsed to, paste in the newly generated password, and are logged in
In OpenID terms, I guess this means that email is a relying party.
Which makes me wonder: if a browser plug-in could automatically receive, extract and paste replacement passwords from emails, we'd get most of the benefits of OpenID without any adoption issues. Thoughts?
I do a lot of short-term work through Readify, usually somewhere between a 2-3 day estimate or architecture review to a 3-4 month development effort. One of the highlights of that is I get to experience a lot of project kick-off's, and I get to work with some very talented and fun groups of people at our clients. The downside is that I also often have to say "goodbye" to those people.
Earlier this year I spent three months in Sydney working with an incredible team at one of our clients. We were prototyping something that could have been a real contributor to the company's long-term success. Unfortunately, due to a budget reshuffle, our project was suddenly put "on ice". Although we did get to continue the work a month later, at the time we had no idea if we'd be coming back or not. The team had worked hard and had high hopes for the prototype we were building, and feedback had been very positive, so it was disappointing to have to end it.
I didn't want to end what had been a very good three months on a bad note, so on the final afternoon we'd been allocated to "wind up" the project, I threw together a quick slide deck to celebrate the work we'd done. It went something like this:
- What our iteration plan had looked like, and how far we'd gotten through it, with dates
- For each iteration:
- A screenshot of what the application looked like at that time
- A short list of the goals we'd achieved
- Quotes from positive feedback we'd received
- A final quick demo of the working product
- An overview of each of the major areas of the product
- Caricatures of the different people who'd been involved in the project
- Some interesting output statistics, including:
- How many check-ins we'd done
- How many lines of code we'd produced
- How many work items we'd closed
- How many CI builds and deployments we'd done
- How many demos we'd given to stakeholders
- Some interesting input statistics, including:
- How many litres of coffee we'd drunk
- How many world cup soccer games we'd watched (we were lucky enough to have a TV in our team room)
- How much chocolate we'd eaten (somehow we ate through 12.6 kg)
- How many team lunches we'd had
It was still a disappointing afternoon, but by taking time to celebrate our achievements I think it helped to end on a somewhat positive note. Then of course we hit the pub.
One of the trickiest parts about putting that deck together was gathering the screenshots. It involved digging up old versions of the code or email threads, and wasn't much fun. For my current project, I've started taking screenshots every couple of days of different things. Hopefully it makes the next round of goodbyes a little easier.
If you don't want to be forced to use an SOE, don't build desktop applications.
Secondly, don't build web applications that rely on anything that isn't a web standard. That includes anything that relies on a plugin, like Silverlight.
It occurs to me that if all enterprise applications were standards compliant web applications, the only thing an employee should ever need is an up to date browser. They shouldn't need an SOE. The IT setup process for a new employee should be:
- Give them a wad of cash to buy any machine they like
- Give them a login - ideally something that supports federation without actually needing to be joined to the network. OAuth or OpenID maybe?
- Give them the URL to your corporate portal
- Give them a network cable
If there's nothing to install on their system, there's nothing to be worried about when it comes to OS upgrades and messing with your precious SOE, since you won't have one. If the OS upgrade includes a new web browser, you shouldn't have a problem, since you used standards compliant HTML and CSS.
In the "should I use HTML or Silverlight" debate, one thing that's overlooked is the impact that future browser releases will have on whether your application will still work in 5 or 10 years time. Let me play out a scenario I've been thinking about.
First, an important observation:
When new versions of Silverlight are released, Microsoft (and Novell) have to release new plugins for each of the major browsers.
Well, that's kind of obvious. Perhaps less obvious:
When Chrome, IE or Firefox re-write their plugin systems, Microsoft (or Novell) will have to release new plugins for those old Silverlight releases.
Right now the support matrix isn't too bad. Silverlight 1.0 applications won't work in Chrome, but no one ever used Silverlight 1.0, so that's OK. But how long will they be able to keep this up? If IE 10 includes a new plugin engine, I'd expect a new Silverlight plugin for Silverlight 4.0, but what about 2.0? At their current rate of release, by the time Silverlight 6 comes out, will Microsoft even be able to afford to test 6 different Silverlight releases across 3-4 different browsers?
This means that if you have a production application running Silverlight 2.0 right now, you're relying on Microsoft releasing Silverlight 2.0 plugins for every new browser, from now until your application is retired, in order for the application to work.
Of course, if they don't, that's OK. You can always upgrade your application to the latest version of Silverlight, which probably does have a plugin. Right?
Not so fast. What's cheaper? Getting developers to upgrade old technologies to new ones, or just telling users not to use that latest IE/Firefox/Chrome release? Which option will most corporate enterprise IT departments pick?
Sound familiar? It's the same problem we have with IE 6 right now. We built so many applications that only work in IE 6 that enterprises decide it's cheaper to tell users not to upgrade, to the point that IE 6 still has incredible market share.
This leads me to the conclusion:
Today's corporate Silverlight applications will produce the future equivalent of the IE 6 problem.
Being serious, I think this should matter to corporate application developers considering Silverlight when HTML would do. Since enterprises rarely do a good job of keeping their application technology stacks up to date, to have confidence we need some kind of guarantee from Microsoft that Silverlight 2.0, 3.0, 4.0 applications will be supported not just by current browsers, but by the popular browsers in five years time. I've not heard of any such guarantee so far, and I have doubts that they can.
On the HTML front, it's likely that if you had instead chosen to use standard HTML and CSS, your site will continue to work even as new browsers are released, since browsers are trending towards better standards support rather than getting worse. No serious browser vendor is going to release a browser in the next 10 years that doesn't support XHTML 1.0 or HTML 4.01. And besides, web standards only seem to change every 300 years on average.
As far as I can see, come 2015, your "Valid HTML" site stands a better chance of being used by 2015 technology than your Silverlight 4.0 application.
Edit: Nick Kramer from Microsoft has posted some background about how Silverlight compatibility works and how the team plans to support it going forward, which puts me at rest somewhat.
I just published an article on CodeProject about Magellan:
It's the first CodeProject article I've written in years - I hope it's somewhat legible. If you've been following my blog but never really given Magellan a try, I hope the article has just enough information to give you an idea of whether it would be useful to you. Also, a few 5/5 votes would be much appreciated :)
Going from Windows Forms to WPF and Silverlight, we've seen some incredible advances in the Presentation Layer in recent years. Of course, technology advances never mean longer holidays for us developers. Instead, users just expect more. Where they might have been happy to suffer through forms-over-data user interfaces, they now expect our applications to be much more proactive in managing business processes and surfacing useful information. In short, the needs of our UI's are rapidly becoming more complicated!
When the problems we're trying to solve increase in complexity, our code has a tendency to begin to increase in complexity. But it doesn't have to be that way. Programming principles like the SOLID principles, and pattern catalogs like the Gang of Four design patterns, give us some help for managing code complexity. One of my favourite books, Domain Driven Design by Eric Evans, describes solutions for managing both complex problems as well as the code. In fact, the book's subtitle is "Tackling Complexity in the Heart of Software".
Figure: As our problem domain becomes more complicated, patterns can help to act as a downward force on code complexity.
While we've had patterns for the other layers of our code for a long time, the use of patterns on the Microsoft UI stack has become an emerging trend. A category of design patterns has evolved called Separated Presentation patterns, which describe ways to structure the code that lives in the presentation layer. The goal of this article is to give you a brief overview of the major Separated Presentation patterns, as they apply to WPF.
The three patterns I'm going to cover are Model-View-ViewModel, ViewModel-first MVVM, and Model-View-Presenter.
Plain, old-fashioned code behind
Even if you don't use a separated presentation pattern, there are two kinds of objects you'll have: Views and Models. Even in the days of .NET 1.1 Windows Forms, we were using Forms (the View) and DataSets (the Model). The separated presentation patterns, which we'll look at shortly, build on top of these.
Figure: at a minimum, we want to put things on the screen (a view), and we need data to put on the screen (the model)
The View is a generic name for the Window, UserControl, Control, Page, or other major UI element that encapsulates our piece of functionality. Since we intend to eventually put some kind of UI into the monitor for a human to see and interact with, any pattern needs some kind of View.
The Model is the data objects that our UI uses - for example, an Account with Transactions, which belongs to a Customer. It may be some kind of canonical understanding of the problem domain we're dealing with, used by all of our views in differently, or they might be used just by this view. They might just be Data Transfer Objects or messages returned from a Web Service/message bus, or a DataSet, NHibernate or Entity Framework classes that we fetched from a database.
The View and Model might communicate as follows:
- Code-behind in the View can set properties or call methods on the Model
- Controls on the View can be bound to properties on the Model
- The Model can raise events, and the View can subscribe to them
Throughout this article I'll use dotted arrows to indicate an event being raised, and solid arrows to represent a method call or data binding.
This approach works fine, for a while, but since the only place to put code is code-behind, it can start to become hard to manage. The code to hide a button is next to the code to evaluate whether an account is overdue, which is next to the code that triggers an animation. Separated Presentation patterns allow us to clean up this code by adding a Third Object.
Introducing the Third Object
Each Separated Presentation pattern uses the View and Model. The third part of each pattern has a different name, but they solve the same purpose – any code that isn't highly UI specific, but is mostly concerned with behaviour or state management, goes there.
Figure: The Third Object is introduced by the Separated Presentation patterns. The difference between each pattern is how the Third Object communicates with the other two.
What might we expect to see in that third object?
- Code for creating and managing background threads
- Code for invoking a web service
- Code for filtering an in-memory collection
- Code for UI-calculated values that don't belong on the model
- Code for triggering navigation to another view
So why do we have different patterns? Because there are different ways that the third object, the View and the Model can communicate. The third object always has the same responsibilities, but the way it achieves them vary.
With WPF or Silverlight, MVVM is the simplest pattern to implement. The third object is the ViewModel, which the View is bound to, usually using the WPF DataContext property. The ViewModel also exposes Model objects, which the View also binds to.
Figure: the View is bound to the ViewModel, which raises events to notify the View about changes. The ViewModel can also manipulate and subscribe to events on the Model.
For example, imagine a screen that allowed us to search through a list of patients.
- The ViewModel would expose a SearchText string property, which would be bound to a TextBox on the View. WPF's data binding capabilities will set the SearchText property when we type in the TextBox.
- The ViewModel might expose a method, or a WPF ICommand, called Search.
- When a button is clicked, the Search command or method on the ViewModel would be invoked.
- When invoked, the Search command or method would call a web service.
- The list of patients would be added to an ObservableCollection
, which is a property exposed by the ViewModel
- The Patients list is also bound to a ListBox or DataGrid, which would show the new list of patients
Notice that most of our communication is done through properties, using observable collections or property changed events to notify the view that it has changed. This means the View becomes reactive to our ViewModel.
From a unit testing perspective, this is a joy, because our tests become very state-based – we can set a property, and assert the contents of another property. We don't need to test the view at all, because we can assume that data binding just works.
In regular MVVM, our ViewModel is "owned" by the View – the View is bound to and depends upon the ViewModel, but the ViewModel has no direct reference to the View. A downside to this is that if the ViewModel wants to trigger the View to do something, it has to do so through raising an event, and hoping that the View interprets it correctly.
ViewModel-first MVVM is a variation of MVVM whereby the ViewModel also holds a reference back to the view.
Figure: note that the View-ViewModel communication now uses method calls on both sides. The ViewModel knows about the View, and can call methods directly on it.
This means that the ViewModel can still use properties and events to notify the View of changes, but since it holds a reference, it can also call methods, such as Close, on the View.
Since this communication means both objects are dependent on each other, we often introduce an interface for the View. The View would implement the interface, giving it the smallest contract needed by the ViewModel. The ViewModel would be coded against the interface, rather than the implementation.
From a testing point of view, this variation is slightly harder, since once we introduce the interface we need to use a mocking or stubbing approach to provide a test implementation of each interface. We then turn from state-based testing to interaction-based testing.
With Model-View-Presenter, we flip MVVM on its head. Instead of the View referencing the Third Object, the Third Object references the View:
Figure: in MVP, the Presenter tells the View what to do. The View can raise events to let the presenter know something happened.
As with ViewModel-first MVVM, we use an interface for the View to provide a tighter contract between the Presenter and View.
Taking our patient search scenario again, our interaction would become:
- When we click Search, the view would raise a SearchRequested event, with the text from the TextBox included in the event arguments
- The Presenter would be subscribed to this event from the view's interface
- The Presenter would call the web service
- When the results come back, the Presenter would call a method on the view, such as ShowResults(patients), passing the results to the view.
This pattern works well for ASP.NET and Windows Forms, but since data binding in WPF or Silverlight is so powerful, it's a shame to miss out on that – MVVM does a much better job of leveraging the power of WPF. From a testing point of view, since the presenter talks to the view, we again need to use interaction-based testing and mock objects to fully test our presenter.
While the point of these patterns is to reduce the complexity of our views by separating the two major categories of code, a nice benefit we get is increased testability. With just code-behind, our only option is automated UI testing.
With the separated presentation patterns, since most of the behavioural code is in one place, we can test it without involving the view. It doesn't mean we don't do automated UI testing – I like to still have automated UI smoke tests – but it allows all of the nitty-gritty permutations to be captured as simple unit tests, keeping our automated UI test suite smaller. The ROI from testing presenters or ViewModels is so great; we may even decide automated UI testing isn't worth the hassle.
Separated Presentation patterns exist to move behavioural code out of the code-behind, so it isn't mixed up with UI technology specific concerns. The patterns may sound daunting at first, but most people are surprised by how few lines of code are needed to introduce them.
No matter which pattern you use, if any at all, you'll need the View and Model. Then it's a question of interaction patterns. I often ask clients to implement an example of both, so they can see for themselves the benefits of each.
In May I gave a rough idea of where Magellan 2.0 was heading. This weekend I decided to call it "done" and checked in the final 2.0 binaries. Let's look at what's new in Magellan 2.0.
Project Hosting and Discussion
Previously I was using my blog for Magellan documentation, and CodePlex for the source/binaries. Before 2.0, I decided to shift everything to Google Code. The source is now hosted in Google Code's Mercurial server. There's also a discussion group you can join if you have problems or questions.
I'll leave the CodePlex site and blog pages for Magellan 1.0 online, and add links to all the 2.0 content.
The easiest way to get started is to install the Visual Studio project templates, by searching for "Magellan" in the VS 2010 extensions gallery:
Once you've done that, you can use File->New Project and browse to the Magellan folder under Visual C# to create a project:
nu install magellan-framework
What are you waiting for?
Using the project templates, it should take all of about 5 minutes to create your first Magellan application. If you haven't tried Magellan before, install the template and give it a go :)