Breaking Changes in the Composite Web Application Block

With the initial January release of the Web Client Software Factory, and with the subsequent June update, we received a lot of feedback. Some of this feedback was good, some was not as good, and some of the feedback was feature requests. We actually took this feedback, and have made changes to both what we deliver and how patterns & practices as a whole delivers our guidance.

<WARNING Text="Begin Technical Content">

Some of the changes to the Composite Web Application Block that we made due to this feedback, resulted in a few things that have changed between versions and will require minor code changes for anyone using the earlier releases. So, what were the changes, the reasons for them, and the results for our users?

Simplify

One big piece of feedback was that patterns & practices deliverables (and WCSF) are too complicated, too big, and over-engineered. We actually reviewed our code base, and tried to simplify things where possible without effecting quality, testability, or functionality. This resulted in clean-up in a lot of places. Two things we did to simplify CWAB did cause challenges:

We merged Microsoft.Practices.ObjectBuilder.WCSFExtensions.dll into the Microsoft.Practices.CompositeWeb.dll.

This means that any project that references the old DLL will need to update its references. Also, the using statements will need to change to match the changed namespaces.

The other change made to simplify things was the re-evaluation of interfaces and where we create and use them. We did not make many changes here, but we did get rid of the ICompositionContainer interface. Anything that referenced the Composition Container via this interface will need to be updated to use the concrete class.

Thankfully, both of these changes are easy to find, as they result in compiler errors.

Dependency Injection for Pages, User Controls, and Master Pages

Lots of folks like our dependency injection solution (and a few did not). It is based on Object Builder , which is either famous or infamous, depending on your viewpoint. However, the DI we had in earlier versions only worked with Pages. We received requests to enable this for User Controls and then Master Pages.

Unfortunately, this became a bit more convoluted than we had hoped. I know that there are community solutions to this in the WCSF CodePlex forums, and that a number of people are using those solutions. Due to Microsoft's policies on outside source code, we could not use (or even look at the code for these solutions). Instead, we read the prose descriptions of these solutions to get the general idea, and then implemented our own solution. However, the solutions that are posted in the forums seem to rely upon an undocumented side effect of a property getter call. For something people post on forums, this is OK. For recommended guidance from p&p, we needed to find another solution.

Since there is no way to tie into the control creation process and replace the "new" calls (we tried. The hooks just are not there), we tried to externally hook into the Page lifecycle at a single point when the Master Page and all controls had been created, and then run DI on them. However, there is no one place (except PreRender, which is way too late in the lifecycle) that we could reliably get this to work.

After exploring a number of options, we decided the best way was for things that needed DI to be done, was for those object to basically say "Inject me now, please." We added a static helper method to the WebClientApplication class to help with this. You can call WebClientApplication.BuildItemWithCurrentContext(this) from your Page's OnPreInit method. There are also base Page, UserControl, and MasterPage classes in the Microsoft.Practices.CompositeWeb.Web.UI namespaceso you don't need to duplicate code; Just use our base classes. If you already have a custom base class for any of these, the code is simple and could be copied into your base page/control class.

What does this mean for projects upgrading to the new version of CWAB?

Basically, you will need to either copy/paste some code into your pages or change the base class for your pages to the new Page class in the CompositeWeb namespace. Then, if you want DI done on User Controls or Master Pages, change their base class as well.

One of the side effects of this change is that you can do DI on ASMX web services if you want. This makes reuse of CWAB services as web services (or JSON endpoints) very easy.

Note: I know this is now not truly doing by the book dependency injection. However, with the toolset and framework we are building on, it is the best we could do to keep things simple, reliable, and consistent.

Other Minor Changes

  • We changed the base class on a few exceptions from ApplicationException to Exception, based on feedback on the CodePlex site.
  • We moved access to the Root Container from Application[ApplicationConstants.RootContainer] to WebClientApplication.RootContainer
  • Bug fixes.
  • Some Code Cleanup.
  • More unit tests around things that are hard to test.

This is not a comprehensive list. There are going to be things I missed. However, the docs in the Blocks Bundle should cover everything necessary to upgrade from the last version.

</WARNING>

These changes will be visible in the Composite Web Client Library Bundle (not the official name) which is coming out soon. I'll post a link when it is available. Or you can check out the Web Client Bundles page.

Note: Everyone on the WCSF team has helped in pulling this content together. I'm just broadcasting it. Also, Mariano made a post about some of this a while back (when we first released the code in a weekly drop).