Smart Clients

New Guidance And Tools For Building Integrated Desktop Applications

Christian Thilmany and Jim Keane

This article discusses:

  • An overview of CAB and the Smart Client Software Factory
  • Architecture of an Integrated Desktop
  • Building and deploying a smart client
  • Using Modules to integrate legacy apps
This article uses the following technologies:
Visual Studio 2005, CAB, Smart Client Software Factory

Code download available at:SmartClient2006_09.exe(12394 KB)

Contents

How CAB Works
Building a Simple CAB Application
An Introduction to Smart Client Software Factory
Essential Smart Client Services
Functional Layers of the Integrated Desktop
Integrating a Legacy Web App
A Look into the Future

Alot of attention has been focused on providing information workers with Business Intelligence (BI) tools so they can make more informed decisions. Most of these enterprise BI solutions provide information from a variety of resources, typically using some form of server-side information integration. Whether it's a reporting system that summarizes data, a collaboration tool like Microsoft® SharePoint®, or a custom enterprise application integration (EAI) solution that provides business process management, the actual serving of this information is the focal point. Little thought is given to the consumption of this information.

For most activities, the information worker needs to consult several applications when making a decision: a Web browser to view a portal site, a custom app to access the EAI solution, a report viewer to read a summary of data. Over time that worker gains proficiency in his job by learning how to gather and collate data manually across application boundaries. This is typically achieved through a routine of launching Microsoft Outlook®, Word, Excel®, Internet Explorer®, and a myriad of custom applications provided by the company. This form of swivel-chair integration has dismal consequences: training time for new users is high, the system doesn't provide the right information to the right people in the right format, data error problems are introduced, and so on. Wouldn't it be more efficient to provide a secure integration and hosting substrate surrounded by a deployment model that made this form of application integration easier?

Most developers think of service-oriented architectures (SOAs) as a means of serving up information, not as a way to consume it. But how do you to handle all those islands of automation? This is where the idea of the integrated desktop comes in.

As solution architects, we aim to simplify the ever-expanding landscape of business applications and to improve the user experience, but one of the hardest objectives to meet is to integrate a solution seamleassly across multiple applications running on the desktop. Techniques such as DDE, OLE, COM, mailslots, and the like have all been used to address local application integration. But the result has been highly coupled, brittle desktop applications that are typically expensive to maintain and deploy.

The Integrated Desktop is the latest installment of a connected systems architecture that focuses on the desktop. Integrated Desktop is a loosely coupled hosting architecture and composite UI that runs on the desktop and is supported by a loosely coupled architecture on the back end. It collapses the number of applications a user must deal with and places everything under a single piece of "glass". All the technologies needed for building Integrated Desktop applications are already present in the .NET Framework. Until now, however, stitching them together has been a major challenge.

The underlying current of the Integrated Desktop strategy is service enablement. While the architecture does not absolutely require a services fabric, a strategy of building composable enterprise desktops does. The loosely coupled nature of Integrated Desktop applications is a natural fit for a service-enabled back end. Preserving the attributes of a loosely coupled architecture carries through to deployment, where these kinds of architectures often run into obstacles.

The foundation layers for the Integrated Desktop implementation from Microsoft are the new Composite UI Application Block (CAB) and the Smart Client Software Factory. Used together, these are powerful tools for solution architects who are crafting their own desktop framework and custom application. (Before moving on, familiarize yourself with the terms shown in the "Basic Terminology" sidebar.)

How CAB Works

CAB is an implementation of the patterns and concepts used for building complex smart client applications. Put simply, it provides the Windows® Forms plumbing to help you build enterprise desktop applications.

We could easily fill an entire article just discussing CAB, and there are several components that are outside the scope of this article. We'll focus here on the primary components of CAB, but we encourage you to download and explore it in detail for yourself. Start by visiting the CAB community site.

CAB is designed to support many application scenarios, such as online transaction processing (OLTP) front ends, client portals, and information worker applications. Because of its modular design and small footprint, CAB can be used not only for large-scale integrated desktops but even for simple smart clients.

CAB enables the sharing of development tasks of a single smart client interface by neatly decoupling the interface parts. Ultimately, CAB improves reuse and can easily enable such concepts as intra-application workflow. To enable reuse, a composite UI built using the CAB framework is broken up into several working parts. The driver is the shell of the application, which acts as the host executable as well as the bootstrap for loading your composite UI parts. Loaded and displayed by the shell, UI elements provide user "contact points" such as menus and other navigation components. Shells are loosely coupled to the application parts themselves, thus providing a flexible approach to UI design. The shell and the CAB services drive the car, but you have to supply the engine of the application or applications the shell will host.

Besides providing a framework for hosting reusable parts, CAB also offers a core set of smart client services for such tasks as loading modules, communicating messages, persisting state, and so on. These can be added in code or via your application's .config file. These core services include:

Module Loader and Module Enumeration Services are provider-based services for controlling reading and loading of modules listed in the configurable catalog.

Event Broker Service passes messages from part to part and sub-application to sub-application hosted by a composite UI.

Authentication Service is a provider-based service responsible for asking users for credentials, accessing certificates, and contacting back-end data providers.

State Persistence Service is a provider-based storage service that saves work item state for sharing context data and for allowing work items to be suspended and reactivated later.

To build the engine for a CAB application, you typically begin by creating a CAB module. Modules provide a deployable entry point for your individual feature set (which is sometimes referred to as a hosted application). Modules are contained within their own DLL files and are loaded at run time from the shell. Which modules are available and loaded is completely configurable and driven by an extensible program catalog. If you're familiar with the Microsoft Enterprise Library, you'll recognize the same provider model in CAB. Modules do not need to be directly referenced in the shell project in Visual Studio® and are never directly bound to the executable. Instead, they are loaded at run time by the module loader.

Inside a module's assembly you provide the work items, views, controllers, and data that are necessary to drive that feature set with the aid of CAB and the Smart Client Software Factory types such as Presenter, SmartPart, and State. These three items in particular form the Model-View-Presenter/Model-View-Controller (MVP/MVC) pattern that CAB applications are based on. Services are injected when needed by the application logic. This allows the developer to create new object instances dynamically or return objects already created within a container. For CAB, that container is the work item and it is one of the first things created by the module developer. CAB components, such as client-side services and workspaces, can be added to the container explicitly using AddNew:

_rootWorkItem.WorkItems.AddNew<WorkItemA>();

This can also be done through configuration or declaratively:

[CreateNew] public ShipNewOrderViewPresenter Presenter { set { _presenter = value; _presenter.View = this; } }

Within the scope of the container (work item), those components can also be declaratively dereferenced as needed. This provides a loosely coupled means to get access to (inject) any contained item managed by CAB, as shown here:

[ServiceDependency] public WorkItem WorkItem { set { _workItem = value; } }

A key component of CAB is Object Builder (which is also used by the new version of Enterprise Library). Providing an implementation of this dependency injection, Object Builder enables a number of useful features. It can create new concrete class instances or return existing ones when appropriate; it can select the appropriate constructor when a class exposes more than one; it can respond to attributes declared on the properties and methods, which influence the creation and naming of the new object; and it can provide a tear-down facility that can remove settings from existing objects by reversing the chain of operations.

Object Builder is a low-level utility and in most cases you won't directly interact with it. However, understanding the concept of Dependency Injection is crucial to understanding how services are plugged into your module, and this knowledge will be of great help when you're debugging. For more information on Dependency Injection and other patterns used in CAB, refer to the CAB documentation.Basic Terminology

Before diving deeper into Integrated Desktop technology, you must first understand the basic terminology.

CAB provides the framework and guidance necessary to help you build complex, loosely coupled, smart clients that provide run-time composability.

Context refers to shared data that is common to multiple applications. Context information is used to relate information from part to part, even when those parts are contained in hosted sub-applications within the composite UI.

Dependency Injection is a design pattern implemented by the patterns & practices Object Builder for dynamically injecting object implementation into the composite UI at run time. This is an implementation of a design pattern by Martin Fowler, sometimes referred to as Inversion of Control.

Event Broker is a component-to-component communication mechanism within the smart client which uses a publisher/subscriber model that allows any CAB part to communicate with other parts within the entire composite UI.

Module refers to the deployment unit for CAB applications. Modules are contained in assembly files (DLLs) and can include one or more sub-applications that will be hosted by the composite UI. A composite UI may load any number of modules.

Smart Client Software Factory is an integrated collection of guidance artifacts (reference implementations, patterns, how-to documents, Guidance Automation Toolkit packages, architecture documentation, and code assets) that leverage CAB and the Enterprise Library to develop complex smart clients.

Smart Client Service is a client-side service that provides the common plumbing for smart client parts, such as security, deployment, themes, and so on.

Smart Part (View) is a reusable composite interface that provides the view component of the model-view-controller or model-view-presenter pattern used by CAB and the Smart Client Software Factory. (The Smart Part attribute simply enables Visual Studio consumption. User controls can be used in most cases).

Theme refers to the look of the GUI elements, affecting the layout on the desktop. This is similar to ASP.NET themes, but specifically for smart clients. CAB Workspaces (or layout managers) are used to control Themes in the Smart Client Software Factory.

UI Elements are general interface controls used for shell navigation elements. Examples include menu items, toolbar items, and custom navigation components. UI elements can be associated with commands and can be dynamically controlled by any sub-application at run time.

Work Item is the CAB container used for holding references to CAB components, such as Smart Parts, events, services, shared data, workspaces, commands, and other work items. Each defined work item typically drives a specific feature set or "use case" for a sub-application.

You can divide up the module any way you want. There should be at least one work item per module, with some work item being the driver of that module. Work items, like any other application or sub-application, can be as granular or broad as you like. In a CAB application, a typical order of events looks like the following:

  1. User double-clicks the EXE that displays the shell.
  2. The shell bootstraps the desktop, loads any configured CAB services, displays its UI elements, and loads all configured modules.
  3. When loaded, each module adds a work item to its parent work item to control that sub-application and asks the work item to show any of its contents in the provided workspace.
  4. When the user selects a UI element from the menu, the associated command is fired.
  5. A command handler responds to the command by adding a child work item, which controls another sub-application and shows its views.
  6. The work item displays its view through a Smart Part.
  7. The user interacts with the view interface which, in turn, passes a controller (or presenter).
  8. The controller changes shared data (state) and communicates back to the host using the Event Broker.
  9. The Event Broker sends that relevant information (context) to other modules or parts.>

CAB modules can be self-contained or they can be part of a larger set of modules hosted by the shell. The multi-module smart clients are where CAB really shines in its flexibility and design. This flexibility comes primarily from the fact that you never have to directly reference your module assemblies in the shell project that loads them since they will be loaded at run time by CAB. In addition, individual parts of a single module can communicate with each other, as well as parts running in external modules that are contained within their own separate assemblies.

Building a Simple CAB Application

Now let's build a single-module application. I'll first explain in broad terms how you create a simple smart client. (I'll discuss a more complex integrated desktop later in this article.)

Most integrated desktops have a visible startup form, so you typically start with a Windows Form shell. To begin, inherit your class from FormShellApplication, instantiate it, and call its Run method from your application's Main method. This initializes the CAB application, loading any configured services we discussed earlier. The next steps involve overriding methods provided by FormShellApplication, such as AfterShellCreated, to populate menus and show any visible Views. (Smart Parts, which are simply user controls adorned with the SmartPartAttribute, are optional.)

To initialize your user interface when implementing AfterShellCreated, you register what CAB refers to as an extension site. This provides a UI Element manager so that any module can later add child UI Elements (such as menu items or toolbar items) at any point from any module. Finally, you begin displaying your views either when the shell loads or in response to UI Element commands that are also typically added during this initialization. Commands wire up command handlers so your code can respond to any command fired by any generic UI Element at run time; this is similar to adding normal event handlers but in a more abstract fashion.

Views can be displayed by using SmartPartPlaceHolder classes or through what CAB calls a workspace. These are simply layout containers used to display your views in a given arrangement. If you have ever worked with the Java abstract windows toolkit (AWT), you should be familiar with this concept.

Finally, to create the shell, register an interface and display a Smart Part. The sidebar "Creating a Simple Smart Client: A Step-By-Step Guide" details how you build a very simple yet modular smart client. To expose the real power of CAB, you use modules to encapsulate your parts into separate assemblies. This gives you design-time abstractions, as well as a run-time abstraction similar to what COM provides, but without all the complexity.

With modules, you can host independent feature sets that are deployed via their own assemblies. This means an organization can version, deploy, and enhance individual modules without impacting the entire Integrated Desktop. Module assembly files, which aren't directly referenced in the EXE, are loaded at run time through the module loader and enumeration services. The CAB's profile catalog and the application configuration file let you specify which modules get loaded, deployed, and wired into the shell. The sidebar "Creating a Module and Module Initializer" steps you through the process of creating a module and its initializer. The steps I've outlined describe all there is to creating a simple CAB application. But note that we have only scratched the surface here.

The "Bank Teller" QuickStart sample that installs with CAB is a ready-made single-module CAB application. It will give you an introduction to all of the key components I've summarized here.

Of course, when building a true enterprise Integrated Desktop, there's a lot more involved than just the composite UI piece. You need to address a host of complex issues like how to share information among modules, how to integrate non-CAB applications into the desktop, how to handle security, and how to control the layout.

An Introduction to Smart Client Software Factory

Aside from the core services provided by CAB, there's another class of foundation services you need when creating an enterprise-ready app. These services include facilities to help manage your desktop in such areas as deployment, security, and provisioning. You may also need services like logging, workflow, configuration, and caching to ensure that all the modules play nicely in this loosely coupled environment.

The Smart Client Software Factory can help by offering guidance and reference implementations. More than just a toolkit, the Smart Client Software Factory provides a starting set of core foundational smart client services to help you begin building enterprise-ready Integrated Desktops.

All services can be considered optional as well as extendable. The Smart Client Software Factory is built on top of CAB and Enterprise Library, and it takes advantage of existing application blocks. Figure 1 illustrates the architecture of smart client services when built with the aid of the Smart Client Software Factory.

Figure 1 Smart Client Services

Figure 1** Smart Client Services **

Because most companies require a set of common services, Microsoft has built a collection of related assets into the Smart Client Software Factory. These are highlighted by two reference implementations that map typical experiences to the services contained within the Smart Client Software Factory. Reference Implementation 1 mimics a Loan Appraisal Desktop and utilizes offline capabilities, end-user notification, and other similar features. Reference Implementation 2 mimics a Bank Officer Desktop (a multi-module version of the Bank Teller sample) to demonstrate security, deployment, and theme services.

Guidance packages also offer valuable help for building enterprise applications. They are built using the relatively new Guidance Automation Toolkit (GAT), an extension to Visual Studio 2005. Using GAT, team developers can provide startup kits (or SDKs) so other developers can add modules and other ID parts down the road. The Smart Client Software Factory includes an integral element, the Visual Studio Guidance Package for Smart Client Development. This is an integrated collection of tools, patterns, source code, and prescriptive instructions that guide ID developers throughout the CAB development lifecycle. For more information and to download GAT, go to msdn.microsoft.com/vstudio/teamsystem/Workshop/gat/default.aspx.

Essential Smart Client Services

The Integrated Desktop sits on top of the Smart Client Software Factory and CAB. It should take the form of a reusable set of CAB extensions, Smart Client Software Factory implementations, generic foundation services, and libraries that can be added in whole or in part to any existing composite UI application. This forms the Integrated Desktop Framework, which includes some essential services.

Context Services This is one the most important elements of creating an integrated desktop. It's also probably one of the most misunderstood. When working with CAB applications that consist of several modules, you usually employ some form of information sharing. For example, your CAB application may consist of a shell, a module for displaying customer information, a header module for displaying summary data, a search module, and other task-specific modules. Each of these modules may be developed, deployed, and maintained separately. CAB provides the plumbing to enable this—it provides the "how," if you will. But you still need to come up with the "what," meaning the information that will be shared among these modules. This could simply be a customer ID. The Event Broker globally communicates that context has changed and all the modules display the appropriate information at the appropriate time. The fact that you're broadcasting the customer ID states that it is the information that will be shared and this forms the premise of "Context".

Context services are used solely to broadcast and retrieve that shared information in a manner consistent with policies set forth by the enterprise desktop. You should employ a base set of context types and their corresponding schema contracts before providing any other service in your desktop. This is not unlike the "contract first" design practice used in SOA. Rather than adhering to contracts defined at Web service endpoints, you define these same contracts between the parts of the desktop itself. In fact, the same challenges found in an EAI or SOA project exist when building an Integrated Desktop application.

Deployment Services These services provide the Integrated Desktop application with its parts, by ensuring that individual modules can be deployed to the desktop at run time. One option is to build deployment services on top of the ClickOnce API. These services should provide server-side control of specific optional modules that are to be downloaded to the desktop. When the shell starts up, the authentication services provide evidence to the deployment services that specific modules are enabled for the user and thus must be downloaded to the desktop if not already present. Modules are downloaded, loaded by the module loader, and displayed to the user as needed. CAB lets you add user roles to the profile catalog. The implementer of the deployment services can easily extend the normal module loader service to take advantage of this capability since CAB will only call load in the module loader extension on any modules authorized to run given any roles that are currently attached to the running principal.

Security Services Unlike context services, security services are quite easy to understand. You can build on top of the provided authentication services you already have in CAB. This provides a starting point for using custom authentication services, and it supplies a means to add authorization logic uniformly to your Integrated Desktop application. Using services and guidance provided by CAB and the Smart Client Software Factory, you can add roles to individual modules to designate that those modules be associated with specific roles. This lets you control which modules get loaded based on who is logged in, as well as enables other facilities (such as your deployment services) to control which modules are actually deployed to the desktop.

Integration Services Deploying a single enterprise desktop would not be very useful if managed Windows Forms applications were the only candidates for integration into the smart client. There are usually numerous prewritten (legacy) applications that need to be integrated so that they can remain autonomous yet still be part of the desktop experience. These include Web applications created without .NET, ASP.NET Web applications, COM applications, and even green screens.Creating a Simple Smart Client: A Step-By-Step Guide

  1. Create a new Windows Form application.
  2. Add the following assembly references to your project:
Microsoft.Practices.CompositeUI Microsoft.Practices.CompositeUI.WinForms Microsoft.Practices.ObjectBuilder
  1. Create an application class that specifies the WorkItem (the default is RootWorkItem) to be used and the Windows Form to be displayed. To create a class called MyWorkItem, simply inherit from the CAB class called WorkItem:
public class MyFirstCABApplication : FormShellApplication<MyWorkItem, MyCABShellForm> { }
  1. Implement your application’s Main method, create the application instance, and call Run:
[STAThread] public static void Main() { new MyFirstCABApplication().Run(); }
  1. Override AfterShellCreated, call its base implementation, and initialize your interface:
protected override void AfterShellCreated() { base.AfterShellCreated(); // register extension site, in this case a File Menu ToolStripMenuItem fileItem = (ToolStripMenuItem) Shell.MainMenuStrip.Items["File"]; MyWorkItem.UIExtensionSites.RegisterSite( "File", fileItem.DropDownItems); // create and add menu items to the File Menu site ToolStripMenuItem item = new ToolStripMenuItem("Show Customer"); MyWorkItem.UIExtensionSites["File"].Add(item); // add a click event handler to the menu item called ShowCustomer MyWorkItem.Commands["ShowCustomer"].AddInvoker(item, "Click"); }
  1. Create a Smart Part. To do this, add a user control to your project and add a reference to the Microsoft.Practices.CompositeUI.SmartParts namespace. Then add the SmartPart attribute to your class:
[SmartPart] public partial class CustomerSmartPart : UserControl { ... }
  1. Add the command handler and display the Smart Part by using a DeckWorkspace:
[CommandHandler("ShowCustomer")] public void ShowCustomer(object sender, EventArgs e) { Form1 mainForm = new Form1(); CustomerSmartPart sp = MyWorkItem.Items.AddNew<CustomerSmartPart>(); mainForm.deckWorkspace1.Show(sp); // deckWorkspace1 is a DeckWorkspace control dragged onto Form1 }

Any of the CAB Workspaces can be added to the toolbox and dragged over to the design surface like any other control.

Integration services in the Smart Client Software Factory provide guidance for building some of these services into your integrated desktop. This article features one type of legacy desktop application integration—Web applications. We show you how CAB and the Smart Client Software Factory (along with its guidance packages) can help you build a Web module that can take any Web application and host it with little effort.

Functional Layers of the Integrated Desktop

An Integrated Desktop consists of three layers: foundation, platform, and application. It's critical to understand these layers, and which tiers of the architecture they affect, when developing an ID solution. Figure 2 illustrates the relationship these layers have to various levels of the Integrated Desktop architecture.

Figure 2 Architecture of the Integrated Desktop

Figure 2** Architecture of the Integrated Desktop **

Foundation Layer This consists of all the core client-side services supplied by CAB, as well as services like security and deployment that can be leveraged by any module or Smart Part. These represent the federated horizontal components of the desktop. Both CAB and the Smart Client Software Factory deliver a major piece of the foundation layer. It is this layer and its corresponding client-side services that need to be addressed up front when building an Integrated Desktop Framework.

Platform Layer This layer addresses the services that provide platform- or technology-specific elements, such as those handled by legacy services. It is made up of components that a module or Smart Part developer can use to incorporate parts that take into account the platform from which they originate. If you have several Web applications that need to be integrated into the desktop, providing reusable client-side Web application services as part of your Integrated Desktop Framework will help in hosting those apps. For example, you may want to use an existing shopping cart application that is already running in production. Services from the platform layer can be used to host this application in the desktop, allowing it to act like any other managed module. The Smart Client Software Factory provides a set of legacy services as part of this layer.

Application Layer Comprised solely of applications and reusable client-side business functionality, the application layer provides client-side services that are specific to business. This layer is made up of the modules you typically interact with, such as Search, Customer Information, and Shopping Cart.

Integrating a Legacy Web App

Hosting an existing Web application in your CAB application requires more than just adding a browser control to a Smart Part. The point of client-side integration is that all the applications (or modules) are fully integrated. This means they can communicate and share information in both directions. Until CAB was available, this capability was possible, but the solutions were prescriptive and far from reusable.

But as mentioned, you can now create a Web module to host any Web application. And you can do this without any other module knowing the difference. Existing modules never have to change the way they share information.

Now we will step through the process of building a simple Web module (such as the one shown in Figure 3), relying on the guidance provided by the Smart Client Software Factory team. We will use CAB services, as well as new Guidance packages provided by the Smart Client Software Factory.

Figure 3 Web App Hosted by a Web Module

Figure 3** Web App Hosted by a Web Module **

The first thing you need to do is either create a new Web application or augment an existing one. This example outlines the steps for creating a new ASP.NET Web app. You can also use it as a template for modifying existing Web applications. The process we'll use is slightly invasive—you must add JScript® to the application and utilize the object model to communicate with the Web application by adding code at design time.

Once we create our sample Web page, which will act as a typical Web app, we'll create a Web module. Before doing so, however, you must download the following prerequisites:

  • Guidance Automation Extensions (GAX)
  • Composite UI Application guidance package (make sure this is enabled in the current solution)
  • Composite UI Application Block
  • Simple shell application with the appropriate references to the CAB library and the Smart Client Software Factory
  • Library project with all the common code that may be reused in some other modules and application libraries

Classes like Microsoft.Practices.SmartClient.Web.WebPresenter and Microsoft.Practices.SmartClient.Web.WebView, as part of the Smart Client Software Factory, provide the base plumbing to automatically map events fired by your Web page using CAB's Event Broker. This allows any Web module to leverage the default communication mechanisms built into CAB and will automatically flow all events to and from the Web page. Microsoft.Prac-tices.SmartClient.Web.WebView inherits from a browser control and can be reused in your Web module.

Note that the guidance package is optional and only supplies some of the template code automatically in your project, such as the services supplied by the Smart Client Software Factory. As an alternative, you can download the sample Web page and Web module from this article.

Step 1: Create a Web Page We'll begin by creating a Web page that will act as our legacy Web app.

  1. Create a new Web project or add a new page to an existing Web project.
  2. Optionally, add a reference to any common library that may contain constants used by the Web application.
  3. Add an HTML button with the Text property value "Fire Context Changed Event (from JavaScript)".
  4. Add an ASP.NET Button with the Text property value "Fire Context Changed Event (from ASP.NET server)".
  5. Add an HTML textbox with the id "txtCustomerName".
  6. Add the following code in the Page_Load method of the page (this is only necessary when using ASP.NET server controls):
ClientScript.RegisterOnSubmitStatement(cstype, Common.Events. ContextChanged, BuildRaiseEvent(Common.Events.ContextChanged));
  1. Add the following private method (this too is only necessary when using ASP.NET server controls):
private string BuildRaiseEvent(string topic) { StringBuilder sb = new StringBuilder(); sb.Append("window.external.FireEvent(\""); sb.Append(topic); sb.Append("\",0);"); return sb.ToString(); }
  1. Double-click on the first button and add the following code in the onclick event:
window.external.FireEvent("ContextChangedEvent","Param1");
  1. This code fires back an event from the Web page, through the Smart Client Software Factory, to the Web browser code, and into the smart client using the Event Broker.
  2. Add the following code after the onclick event handler in the previous step:
function EventBroker_Subscribe() { window.external.SubscribeEvent("ContextChangedEvent"); window.external.SubscribeEvent("CustomerContextChangedEvent"); } function EventBroker_ContextChangedEvent() { window.alert("Context changed event: Hello from Web App"); }
  1. The Subscribe event handler allows the smart client to tell the Web page when to set up the event subscriptions (usually after the Web page loads itself in the browser control). The Web page, in turn, fires back to the host and calls SubscribeEvent (event the Web page is subscribing to). This allows all global events in CAB to flow from the smart client to the Web page whenever that event is fired. And this is caught in the EventBroker_XXX event handlers in JScript.
  2. Add this JScript function:
function EventBroker_CustomerContextChangedEvent(eventData) { document.getElementById('txtCustomerName').value = eventData.Name; }

This shows how to pass event data from the smart client to the Web page and use that data in the Web page itself.

Step 2: Create a Web Module To create a Web module, first right-click on the solution and select Add | CompositeUI | Module. In the Add New Project dialog box, specify your own module name. Now click OK, select the Shell project, and click Finish.

You'll find that a number of new items have been created. A new Web module project is added to the solution. Required references, including the CAB and Smart Client Software Factory library references, are added to the Web module project. A WorkItems folder is created inside the new project, and a ModuleInit.cs file and class are created in the project.

Step 3: Create a New WorkItem Creating a new WorkItem is just as simple. First right-click on the WorkItems folder in the module you just created and select Add | CompositeUI | WorkItem. Change the name to WebWorkItem.cs. Select the Shell project and click the Finish button.

At this point, you'll find that a WebWorkItem.cs file and class have been created. In addition, the using directives and the required references have been added for CAB and the Smart Client Software Factory.

In Load from ModuleInit class, add the following code:

WorkitemCatalog.RegisterWorkItem<WebWorkItem>();

And add the following using directive to the top of the ModuleInit.cs file:

using WebModule.WorkItems.WebWorkItem;

Step 4: Create a New View This step addresses the data interchange between the Web page and the smart client application (in this case, the Web module).

  1. Right-click on the WebWorkItem folder.
  2. Select "Add | CompositeUI | View..."
  3. Change the name to WebView and click the Finish button. This creates the IWebView interface, the WebPresenter class, and the WebView usercontrol. These implement a typical MVP pattern used throughout the Smart Client Software Factory.
  4. Go to the WebWorkItem class and add the following code:
public void ShowInView(IShellView view) { WebView webView = this.Items.AddNew<WebView>(); view.MainWorkspace.Show(webView); }
  1. This adds the WebView (a Smart Part) to the item collection of the work items Smart Part collection and displays it when the work item starts up.
  2. Open the WebView UserControl in designer mode.
  3. Add a Microsoft.Practices.SmartClient.Web.WebView control from the Smart Client Software Factory.
  4. Set the Url property of the Microsoft.Practices.SmartCli-ent.Web.WebView control to the test Web page you just created.
  5. Go to the WebWorkItem.cs file and add this using directive:
using Microsoft.Practices.SmartClient.UI.Themes;
  1. Open the WebPresenter class and add the following code:
[EventSubscription(Common.Events.ContextChanged, Thread=ThreadOption.UserInterface)] public void OnContextChange(object sender, EventArgs e) { System.Windows.Forms.MessageBox.Show( _ "Context changed: Hello from Rich UI component"); }
  1. This is fired by the Web page through the CAB Event Broker and into your WebView code.
  2. Add the following using directive:
using Microsoft.Practices.CompositeUI.EventBroker;
  1. Open the IWebView interface and add the following code:
event WebBrowserDocumentCompletedEventHandler DocumentCompleted;
  1. Open the WebPresenter class and add the code shown in Figure 4. This allows the Smart Client Software Factory to respond to the Web page loading by wiring up the subscriptions. When the Web page is loaded, a CustomerContextChangedForWebPage event is fired. It is communicated using the Event Broker to the Web page as CustomerContextChanged (in JavaScript). This is the effect of flowing context or information from the smart client to the Web page upon launching the Web module from the smart client, and it allows any Web application to display any information from the smart client in response to it loading. Note that the overrides are not necessary for the sending process and just raise the specific event when it gets loaded.
  2. Add the following using directives:
using System.Threading; using System.Security.Principal; using Microsoft.Practices.CompositeUI.Utility;
  1. Add the following code to the WebView class (the IWebView implementation):
public event WebBrowserDocumentCompletedEventHandler DocumentCompleted { add { this.webView1.DocumentCompleted += value; } remove { this.webView1.DocumentCompleted -= value; } }

Step 5 : Build and Test the Solution Place WebModule.dll in the same directory as the shell application and add the module to ProfileCatalog.xml so that it can be loaded by the CAB module loader service.

Finally, follow the same pattern you use for passing messages using Event Broker to other modules. Launch this Web module like any other Web module. All global events should now flow to the Web module from the smart client and back again.Creating a Module and Module Initializer

  1. Create a class library or control library.
  2. Add references to:
Microsoft.Practices.CompositeUI Microsoft.Practices.ObjectBuilder
  1. Add a ModuleAttribute to your project to help other modules identify it in code.
  2. Add the following to your AssemblyInfo.cs file:
[assembly: Microsoft.Practices.CompositeUI.Module("MyFirstModule")]
  1. Create a new public class in this project and inherit from Microsoft.Practices.CompositeUI.ModuleInit. Override AddServices to add CAB services at run time and override Load to display any UI.
  2. To get your module to load at run time, create an XML file called ProfileCatalog.xml that references your new module DLL file. Add this XML file to the main EXE project (the shell we just created).
  3. A typical profile catalog looks like this:
<?xml version="1.0" encoding="utf-8" ?> <SolutionProfile xmlns="https://schemas.microsoft.com/P&P/cab-profile"> <Modules> <ModuleInfo AssemblyFile="Mod1.dll"/> <ModuleInfo AssemblyFile="Mod2.dll"/> </Modules> </SolutionProfile>
  1. If you want, you can plug in your own service to use your preferred profile catalog format.
  2. Add a Load method and implement it from within your new ModuleInit class. The code that follows will create an instance of your module’s WorkItem within the context of the RootWorkItem using the AddNew method. It then calls the Run method of the new WorkItem. You retrieve the Workspace using its name and pass this Workspace to the Run method. In this example, the target is the DeckWorkspace named deckWorkspace1:
public override void Load() { base.Load(); RootWorkItem RootWorkItem = RootWorkItem.WorkItems.AddNew<RootWorkItem>(); RootWorkItem.Run(parentWorkItem.Workspaces["deckWorkspace1"]); }
  1. To get your code to run in response to your WorkItem being run, implement the Run method of your RootWorkItem class, as shown here:
public void Run(IWorkspace deckWorkspace) { IMyView view = this.Items.AddNew<MyView>(); // use any smart part deckWorkspace.Show(view); }

A Look into the Future

In my sample a small block of JavaScript talked back through the Document Object Model (DOM) to the hosting application. This is a technique that InfoPath® uses to make the HTML-based Action Pane access the DOM for the XML document.

For existing Web-based applications, this is a relatively invasive approach. It entails changing the Web app, recompiling the app, and then redeploying it. We envision a less invasive technique that allows any Smart Part to inject the requisite integration code into the DOM of the HTML page, performing the wire-up at run time rather than at compile time. Of course, some due diligence to the security impact also needs to be performed. And additional functionality must be added to the Smart Client Software Factory's Event Broker mapping techniques between Smart Client context and the HTML page elements.

The future of enterprise-ready modules is intriguing. Imagine a workflow module based on Windows Workflow Foundation that provides a clean hosting architecture for desktop-based workflow scenarios. Workflow is immediately integrated into existing applications hosted by the Integrated Desktop, providing an additional decision-enabled integration substrate and a structured task list aspect to the information worker. Could entire solutions be refactored into service islands coupled together through a set of workflow modules?

This architecture is evolving and new capabilities in the platform must be continually factored into the architecture. This longevity is one of the true tests of enterprise class solution architectures. The wave of new capabilities brought about by Windows Vista™ is definitely going to challenge how we think about solution approaches, and the Integrated Desktop is nicely positioned to take advantage of the surge.

Christian Thilmany is a Technology Architect with more than 16 years of experience in architecture, development, and consulting for a variety of Fortune 500 companies. At Microsoft, he specializes in integration, portal, and smart client patterns and technologies.

Jim Keane Jim Keane is a Technology Director based in Austin, Texas. He has been an architect in the computer industry for more than 20 years, with experience in the areas of small business, aerospace, semiconductors, insurance, and process control systems.