February 28th, 2008
Good news people: WCSF 2.0 was finally shipped.
There were a lots of changes since the June 2007 release (WCSF 1.1). Many of you may have already downloaded the bundles that were released in October through December.
The big change since the October 2007 releases (apart from having all the content that was shipped as separate bundles in a single deliverable) is that this release targets Visual Studio 2008 and .NET Framework 3.5 natively. There are also some changes that enhance the performance of the Composite Web Application Block, and some other minor changes and bug fixes.
There are already some great posts about this release that contain detailed information of this new release, so instead of writing it myself, I’d better link you to them:
October 9th, 2007
I’m proud to announce that the Composite Web Client Libraries Bundle (including Composite Web Application Block and associated libraries) and the Automation Bundle (a.k.a the Web Client Software Factory Guidance Package) has just been released.
Both releases are updates to what was previously packed in one deliverable as the Web Client Software Factory – June 2007 release,
This release of the Composite Web Client Automation Bundle has additional recipes as well as modifications and bug fixes to some existing recipes. PageFlow recipes have been removed, but don’t worry too much, as they will be released as a separate automation bundle. This will allow you to take only the assets you really want to use on your web applications.
The Composite Web Application Library Bundle adds support for creating responsive composite Web applications using Microsoft’s ASP.NET AJAX and AJAX Control Toolkit.
Be sure to download these bits, as they are a must for developing web client applications on the .NET Framework. Don’t miss the other bundles from the team while you’re on it on the codeplex site.
Coming soon: a Reference Implementation that puts all these pieces together, so stay tuned!
September 16th, 2007
There is a new Knowledge Database to organize all of the content that is already out there on the Internet about Web Client Software Factory.
The KB is very well categorized, and easy to access. If you’re a WCSF user, you should definitively check it out, as you’ll find solutions to many common problems and little pearls that are worth reading. They promise to update it periodically, so be sure to bookmark it.
July 9th, 2007
That’s right, the second weekly drop is available on Codeplex for you to download.
We’ve decided to try a new approach to injecting dependencies to web pages. Instead of letting the application build up every page automatically for you, you have to specify with code that you want the page to be built up. Why? So you can build user controls, master pages and web services in the same consistent and high-performant way.
But what about other approaches already on the web? we’ve considered them, but we wanted to try this approach too. One advantage over the ones we saw, is that this also works with dynamically created UserControls, which will probably be an important part of WCSF vNext when we focus in UI Composability. You can read more on this in Juan’s post, or better yet, download the code here.
Please, play around with the code, and tell us what you think. Your feedback is very valuable. Remember that we are on a very early stage, so your feedback can make a huge difference.
With the Web Client Softare Factory you can easily use dependency injection for object creation and obtaining required resources. For example, the factory demonstrates how to use view/presenter pairs with an application (module) controller. As the user interacts with a Web page, the presenter notifies the controller, where the business logic and flow decisions reside. This means a presenter requires a reference to a controller instance. With the WCSF, the presenter can use the CreateNewAttribute to have the controller object injected into the presenter (the presenter does not create the controller):
public ApproveCustomerViewPresenter([CreateNew] CustomersController controller)
controller = controller;
However, the CreateNewAttribute requires that you specify a concrete type. Wouldn’t it be great if we could request an implementation of an interface, and make WCSF behave like a simple factory?
For example, imagine that we want to tell the ObjectBuilder to inject a concrete implementation of the interface IMyInterface, but we don’t really care which implementation to use. In fact, we want to let some other part of the code (e.g. in another module, or in the configuration file) determine the concrete implementation to use. In essence, we want the developer experience to be similar to the code required when you request a service:
public CustomersController([ServiceDependency] INavigationService navigationService)
navigationService = navigationService;
While we want the developer experience to be similar, we want the behavior to be different. We want the ability to have a new object created and obtain a reference to that object.
Those with experience in CAB or SCSF might consider implementing this with a TypeMappingPolicy. Actually, that was the first thing I intended to do, as I was inspired by this forum thread. Unfortunately, it turns out we can’t use the TypeMappingPolicy without modifying the way WCSF builds objects. When objects are created by WCSF, it assigns a random GUID as a temporary id for the object being built. It does not let you specify a custom id, and therefore the builder cannot find the appropriate TypeMappingPolicy required to provide a new concrete type of the object being requested.
Introduce a new attribute, InterfaceDependencyAttribute, to provide this functionality. With this attribute, your code requests an object instance that implements a particular interface:
public ModuleController([InterfaceDependency] IMyInterface myInterface)
We want this to attribute to behave in the same way as the [CreateNew] attribute, but instead obtain a concrete implementation of an interface.
What if there are multiple implementations of an interface, and a developer wants to request a particular one? The attribute allows you to specify the key of a particular implementation:
public ModuleController([InterfaceDependency] IMyInterface myInterface, [InterfaceDependency(Key="Other")] IMyInterface myOtherInterface)
To support this, you must add a mapping when you register particular types. This way ObjectBuilder will know which concrete type to inject. For example in the ShellModuleInitializer you could add the following method:
private void AddRegisteredTypes(IInterfaceMappingService interfaceMappingService)
interfaceMappingService.RegisterType(typeof(MyOtherConcreteObject), typeof(IMyInterface), “Other”);
And in the Load method, add the InterfaceMappingService to the root WorkItem.
To make this even easier (and not require developers to write this code in each application) we could extend WCSF a little. All we need to do is add a few classes to our solution, and register IInterfaceMappingService as a global service before trying to build any object using the InterfaceDependency attribute. This could be done in a custom application class, and make global.asax inherit from this class:
public class CustomWebClientApplication : WebClientApplication
protected override void AddRequiredServices()
You could even add another attribute to decorate your concrete classes, and let ObjectBuilder register them automatically to the IInterfaceMappingService. (This is not done in the provided source code.) Another improvement could be to register the concrete types in the web.config file, and implement a class that reads them and configures them automatically.
Comparison between CreateNew and InterfaceDependency attributes
Don’t confuse this InterfaceDependency with ServiceDependency. The ServiceDependency attribute is specific to CWAB services (which are stored in the services container), and not for the creation of objects. The InterfaceDependency attribute is closer to (but a little more complex than) the CreateNew attribute. The difference is that with the InterfaceDependency attribute you do not specify which concrete class to instantiate.
The following table compares both attributes:
|Allows creation of a concrete type (replacement of new operator)||Allows creation of a concrete type that implements a specific interface|
|Very simple use, simply add the attribute above a concrete type||Two step use: register the type in a catalog (InterfaceMappingService), decorate a parameter/property with [InterfaceDependency]|
|The object is built with ObjectBuilder and all the strategies will run over it.||The object is built with ObjectBuilder and all the strategies will run over it.|
|The object won’t be added to any container||The object won’t be added to any container|
|The lifetime of the object is the page request (not singleton)||The lifetime of the object is the page request (not singleton)|
|The specified concrete type will be injected||Allows multiple implementation of the same interface and the injection of a particular using a string identifier|
- You can get the source code of the CompositeWeb.Extensions project by downloading the CompositeWeb.Extensions.zip file below. The solution contains the source code of the required services and parameter, plus a sample application that uses this approach
- If you face problems building the solution, make sure the references to the Composite Web Application Block and ObjectBuilder assemblies are correct.
- Important: The code is provided “as is” without warranty of any kind.
April 4th, 2007
One of the requested features for the Web Client Software Factory has been the possibility to register global services through the Web.Config file. By registering the services through configuration there is no need to rebuild any module when you want to switch the concrete implementation of a service.
This is what we wanted to be able to write in the Web.Config:
<module name=”Shell” assemblyName=”MyApplication.Modules.Shell” virtualPath=”~/”/>
<service registerAs=”MyInterfaces.IMyService, MyInterfaces” type=”MyImplementations.MyService, MyImplementations”/>
Ezquiel Jadib and me have been working on this request, and to see what we came up with, check Ezquiel’s blog post: http://staff.southworks.net/blogs/ejadib/archive/2007/03/30/WCSF_3A00_-Registering-services-through-configuration.aspx