Daniel Cazzulino's Blog :

Shadowfax (RSS)

100% Managed Wizard Framework from Patterns & Practices

The Shadowfax Visual Studio Wizards are built on top of a managed framework for constructing wizards automatically from configuration files. When the source code for the wizards is released, you'll see that there's minimum code in them, mostly for those parts of the wizard that actually need to modify information on the current solution, called Commands. The whole wizard UI is built from the configuration file.

So let's see this XML format to see what's possible with the framework.

Configuration

Wizard definition file has the following main sections:

 

- <wizard>

--  <typeDefinitions> ?

--  <step> +

 

<wizard>

Root element of config. Contains the following attributes:

 

Attribute

Description

title

A title shown in the initial wizard page.

description

Full description of what the wizard does, shown in initial page.

type

Full type name of class inheriting from Wizard or reference to a TypeDefinition. If not specified, defaults to the built-in provided form. Optional.

prompt

An arbitrary text to show the user to confirm execution of the wizard. May warn about pre-requisites.

 

Title and description are shown as follows:

 

 

A custom form can be developed and plugged using the Type attribute.

State is kept in a simple IDictionary.

 

<typeDefinitions>

This element contains any number of <typeDefinition> child elements, to create aliases to repeated types being used in the file, having the following attributes:

 

Attribute

Description

name

A alias to assign to this type.

type

The full type name.

 

At any place in the configuration file, all attributes expecting a type can either specify a fully qualified type name, or an alias referring to these type definitions.

 

<step>

This element defines each visual step that will be available in the wizard. Steps are visualized through the Next | Previous buttons in the wizard form. It has the following attributes:

 

Attribute

Description

title

The title of the step.

description

A description of what this step does.

tip

A tip to show to the user about the current step. Optional.

type

Full type name of class inheriting from Step or reference to a TypeDefinition. If not specified, defaults to the built-in provided step. Optional.

dependsOn

An expression that determines whether the step should be shown or skipped.

 

They are laid out as follows:

 

dependsOn

Some steps may only be executed under certain conditions. For example, a step may collect additional values if a previous step has a certain value, or if an option (such as a radio button) was selected.

This attribute allows for such conditional execution through a reduced conditional (i.e. "if") expression with the following format:

 

([not] ArgumentName [ ( = | < | > | >= | <= | != ) VALUE ] [ ( and | or ) ])*

 

That is, an argument name, optionally preceded by the "not" negation, optionally followed by a value comparison (currently only string value comparisons supported) and any number of "and" or "or" operators chaining multiple argument checks. Operators are not case sensitive.

Semantics for an argument name in the expression is the same as for XPath boolean function: if the argument is not defined or it is null, it evaluates to false. If it's present and its not a boolean, it evaluates to true, unless it's a string and its length is zero. Otherwise, the actual boolean value.

 

Examples:

 

Transport = 'WebServiceTransport'    

 

Depends on a specific string value in an argument

 

MessageQueueTransport or MSMQDispatchingTransport

 

Depends on any of the two arguments to be specified, and if any of them is, to evaluate to true according to the rules for boolean evaluation.

 

WebServiceName

 

Depends on the argument to exist and actually have a value, subject to the rules for boolean evaluation.

 

A step contains the definition of arguments to collect from the user. Arguments can optionally be arranged in option groups (exclusive boolean arguments, i.e. a RadioButton group) or regular groups, with a title such as the one shown in the previous screenshot. Also, the step may contain one or more commands to be executed before moving to the next step (or upon finishing the wizard). Full definition is as follows:

 

- <step>

--  <optionGroup> *
---   <argument> *

--  <group> *
---   <argument> *

--  <argument> *

--  <execute> *

 

<optionGroup>

This group renders as a set of RadioButtons for each child argument, which are always of type Boolean. It has only one attribute:

 

Attribute

Description

title

The title of the group.

 

Its child <argument> element is a reduced version of the full argument element explained below. It can only contain the following attributes: label, tooltip, help, storeIn, selected (determines the initial state of the radio button). See explanation below for the full <argument> element.

<group>

Like we said, this is only a visual arrangement for arguments. It has only one attribute:

 

Attribute

Description

title

The title of the group.

 

Both kinds of groups render at the top of the form, before all non-grouped arguments.

<argument>

This is the element that defines the way arguments are collected from the user. It has many attributes that control the behavior and appearance of the Value Editor control:

 

Attribute

Description

label

A label to show next to the argument input box.

tooltip

Brief hint to the user about the purpose of this argument. Optional.

help

Complete help for the argument. Optional.

type

Full type name of argument or a reference to a TypeDefinition Defaults to string. Optional.

converter

Full type name of a class that can convert values to and from representations other than the argument type or a reference to a TypeDefinition. Defaults to converter associated with the argument type. Optional.

editor

Full type name of a class that provides UI editing of the argument or a reference to a TypeDefinition. Defaults to editor associated with the argument type. Optional.

storeIn

Key to use to store the value.

usage

Enumeration values: Required, Optional. Defaults to Required. It's optional.

defaultValue

A value to use as the default when the wizard starts. Either the argument must be of type string, or a converter must be able to transform it  to the argument type.

defaultExpression

An expression that can be a state key name (stored by another argument) optionally followed by property or field accesses on it. This is useful for setting a value's default to a previously collected argument.

 

Help causes an icon to appear next to the input box, and clicking on it causes a new window to show the full help for it.

converter and editor work together to provide the collection strategy. The former provides conversion to/from string (usually) representations of the value. For example, an argument of type Int32 is converted from the string used as a default value or the one entered by the user. Converter can also provide a list of values that are valid. For example, the .NET built-in converter for enums displays an ordered list of valid enum values. This value relies on the .NET TypeConverter base class.

The Editor can provide a UI for editing the value, such as the .NET built-in ColorEditor or CollectionEditor or custom ones such as a ClassBrowserEditor or a ProjectSelectionEditor. This value relies on the .NET UITypeEditor base class.

 

Collectively, they make for the following argument collection UI:

 

 

Editors and converters build upon the .NET System.ComponentModel features. Therefore, we offer instant availability of all .NET converters and editors. Plus, the documentation and expertise in building them for custom components and controls can be leveraged for the wizard construction process.

 

To really understand the power of this feature, let's just see a couple more screenshots. Let's say a wizard configuration file has the following argument definition (taken from the Add New Service wizard):

 

<argument label="Service folder" storeIn="ServiceFolder"

          editor="FolderEditor" defaultValue="BusinessLayer"

          tooltip="Parent folder to place the new service folder into." />

 

Note the editor attribute. It points to an alias in the typeDefinitions section that defines a type inheriting from UITypeEditor, which happens to be a dropdown editor that shows all the projects and folders in the current solution (implemented as a Windows Forms User Control). This is the UI rendered and the editor shown after the user clicked the down arrow:

 

 

And the following shows a similar argument specifying another editor that loads the list of handlers in the current configuration file:

 

 

A converter that shows a list of values is even more easy to develop, although it provides only simple dropdown capabilities.

 

Finally use attribute determines whether the value associated with the argument can be left unassigned or not. This will affect whether the Next button will be enabled too (only when all required arguments in the current step are filled).

 

<execute>

This element defines an optional command that will be executed when the step is finished (either before moving to the next step, or finishing the whole wizard). It has the following attributes:

 

Attribute

Description

command

Full type name of the command type to execute or a reference to a TypeDefinition.

description

Friendly short description of the command. Can contain references to arguments in the wizard state.

prompt

A message that will be displayed to the user before the action is taken This message can contain references to arguments in the wizard state.

dependsOn

Dependency expression that determines whether the command must be executed. See DependsOn for the Step element, as it has the same syntax and semantics.

 

prompt and description format is a string that can contain argument references with the form $(StateKey). For example:

 

<execute

  command="AddFolder"

  prompt="Folder $(TargetFolder) will be added. Continue?.">

 

Prompts allow the user to chose Yes/No options.

 

The Step class is responsible for executing commands at the appropriate time. At this point, it will request a service from the controller, ICommandService, which allows execution of commands. Commands may support Undo, by implementing a specialized interface called IUndoCommand. Undo functionality is managed by the controller. If a command does not support undo, the developer can let the user know it through the prompt attibute message.

 

Before execution, the Step sets a restore point in the command service, so that if any one command fails, all commands supporting undo are rolled back. The service implements this restore functionality through the memento design pattern.

 

The command may receive arguments. The mapping between collected state values and command arguments is performed through use elements:

 

<execute command="theCommand">

  <use stateValue="stateKey" value="expression" asArgument="asKey" />

</execute>

 

The use element maps a value into an argument to pass to the command. asArgument defines the key to use for the command execution. Value can be either directly pulled from the wizard state by using stateValue, which must be the same key used by storeIn argument element attribute. Alternatively, an expression built of mixed constant string values and argument references (with the same format as the prompt and description attributes) can be used. In this case, this attribute takes precedence over stateValue. For example:

 

<execute command="AddFolder">

  <use value="BusinessLayer\Services\$(ServiceName)" asArgument="Path" />

</execute>

 

Here we're mixing a fixed relative path and the actual value for argument ServiceName.

 

Commands must implement one of the following interfaces:

 

public interface ICommand : IComponent
{

  void Execute ( IDictionary arguments );

}

 

public interface IUndoCommand : ICommand
{

  void Undo ( IDictionary arguments );

}

 

Commands implement IComponent in order for the container to be able to "site" them, giving access to environment services to them.

 

Note that <execute> element is optional. The reason for this is that complex commands may require multiple input arguments. The wizard developer can split those arguments collection into several UI steps, and only execute the command in the last one in the sequence, passing the values accumulated so far. Steps, therefore, are a UI grouping for argument collection that ultimately are passed to a command for execution. There's no direct 1-to-1 connection between them.

 

Built-in arguments

When a wizard is launched from the Add New ... dialogs, the appropriate context arguments as explained Context Parameters for Launching Wizards are added to the wizard state. Therefore, they can be reused inside the wizard configuration file. For example, an Add New Item wizard can use the ItemName state slot as follows:

 

<argument label="Business action name" storeIn="ItemName" />

 

The value will be pulled from the pre-filled one the first time it's shown to the user in the wizard.

 

Likewise, any custom parameter passed through the .vsz file as a key/value pair, will also be filled. For example, the following .vsz file passes the Language state value to the wizard:

 

VSWIZARD 7.0

Wizard=IPE.IdeWizard

Param="Assembly=Microsoft.ReferenceArchitecture.Wizards"

Param="Wizard=Microsoft.ReferenceArchitecture.Wizards.AddBusinessAction.NewItem.xml"

Param="Language=C#"

 

An argument on the wizard can use this state slot as follows:

 

<use stateValue="Language" asArgument="Kind" />

 

 

On a future post I'll discuss a concrete wizard distributed with the Shadowfax Wizards, most probably the Add New Service one as it's the most comprehensive, from XML configuration, to Add New Project dialog hook to setup and deployment on top of the base Wizard Framework.

posted Friday, July 16, 2004 2:11 AM by kzu with 0 Comments

Shadowfax Wizards for configuration and code generation

The cornerstone of any highly extensible and pluggable framework is configuration. This is even more important in SOA architectures like Shadowfax (Sfx), because business actions (BA), service interface and implementation, pipelines, etc., must be configured. Configuring BAs is specially critical since a typical enterprise application will contain hundreds of them. A set of wizards for Sfx were released for that purpose.

First, what you'll see: after installing both MSIs in the distro, you'll have new items in the Add New Project and Add New Item dialogs, as well as some additional context menus.

All wizards can generate either VB.NET or C# code. Note that both language categories exist inside a new folder at the left called Microsoft IPE Wizard Framework. That's the framework these wizards are built on top, which I'll discuss in another post.

The Word document bundled with the distribution shows all wizards and the actions they perform. You have worked with wizards in the past, so I'll save you the hassle of reading how to use these ones. There's, however, a very interesting feature: you can modify the generated code for the classes, thanks to a template transformation engine (code-named T3 - Templated Text Transformantions) that is distributed with the wizard framework.

Under the wizard framework installation folder, by default C:\Program Files\Microsoft Application Blocks For .Net\Microsoft IPE Wizard Framework, you'll find a Templates folder, containing ProjectItems, Projects, and Transformations subfolders. The last is the one containing templates used for code generation. The templates are named after the assembly using them (for Sfx wizards it's the Microsoft.ReferenceArchitecture.Wizards ) plus the concrete wizard resource name. For example, the one used to generate the BA class definition in C# for context invocation is: Microsoft.ReferenceArchitecture.Wizards.AddBusinessAction.CreateClass.InvocationContext-cs.ipe

If you have used CodeSmith, you'll find the template syntax inmediately familiar, which is also similar to ASP.NET one. Everything between <# and #/> (just like their <% and %> counterparts) is considered code that must be executed at template-rendering time. The language for this code is specified through the <#@ Template Language= "C#|VB" #/> template directive. Everything else, is just text that is emited as-is. Here's the BA class creation template:

#region info //=============================================================================== // Microsoft Services Reference Architecture // http:// // // .cs // // This file contains the implementation of the class // //=============================================================================== // Copyright (C) 2003-2004 Microsoft Corporation // All rights reserved. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR // FITNESS FOR A PARTICULAR PURPOSE. //============================================================================== #endregion info #region using using System; using Microsoft.ReferenceArchitecture.Services; #endregion using namespace { /// /// Summary description for . /// public class : IBusinessAction { #region IBusinessAction Members void IBusinessAction.Validate(IContext context) { // TODO: add semantic validation implementation } void IBusinessAction.Execute(IContext context) { // TODO: add code to set the context.Response.Payload } #endregion IBusinessAction Members } }

Parameters received by the template at run-time, depending on user input, are retrieved at the beginning of the template through a service exposed by the container. You can add your own methods or change the base class of all generated BAs simply by modifying this template.

Wizards are deeply integrated with the IDE and the Sfx configuration file. Therefore, in order to run the wizards you must specify where's the configuration file. You do so by right-clicking the ServicesReferenceArchitecture.config file in the Solution Items folder, and selecting Set as configuration file:

Wizards will show relevant information from both the current solution as well as the configuration file when necessary. For example, in the screenshot above you see a Configure pipeline menu option. If you select it, you'll enter a wizard that allows you to modify existing pipelines in the file. (I have to show this because I like how it looks)

On the next step, you'll have the option of editing either a service interface or implementation pipeline. The dropdown below shows the actual pipeline names in the configuration file for the joinpoint you chose!

And in the next step, you get the current configuration, including handlers associated with the pipeline. You can add/remove handlers too, from a list that is also pulled from the config file:

This can be a real time-saver, and avoids occasional typos.

Currently, the following wizards are supported:

  • Add Business Action: creates a new BA and optionally adds a new project for it.
  • Expose Business Action as new Service Action: allows you to develop BAs and later configure and expose them as service actions in Sfx.
  • Configure Pipeline: the one you saw above.
  • Add New Service: this is probably the first one you should run. It goes through all the steps to setup all projects that will be needed for developing for Sfx. This includes creating a folder for the service you're creating (i.e. Accounting), creating or selecting the project that will hold message definitions, and the one for BAs, creating a new BA (this is basically the same as the first wizard, embedded in this one), configuring it with Sfx, exposing it through a WebService interface (creates the WebService class as well), and updating deploy scripts. 
  • Add Custom Handler: creates skeleton implementations of the three types of handlers, Atomic, Stateful around and Stateless around.
  • Create Service Gateway Class: creates either a MSMQ or Remoting client proxy class. Specially for MSMQ, this is a huge plus!

What other wizards would you like to have?

In a future post, I'll discuss the architecture and integration features of the Wizard Framework that backs all these wizards, which are 100% .NET code (no HTML or JS!), are defined in XML and customized through well known TypeConverter and UITypeEditor classes.

posted Monday, July 05, 2004 12:34 PM by kzu with 1 Comments

Configuration, extensibility and namespaces

The whole week I've been digging into a pretty large configuration file and its schema. It's Shadowfax (Sfx), which I already introduced in a previous post. I see some points that allow for improvements, which mainly have to do with namespaces and extensibility.
Let's recap about what namespaces are for. Here's what the W3C Namespaces in XML specification says in the motivation section:

We envision applications of Extensible Markup Language (XML) where a single XML document may contain elements and attributes (here referred to as a "markup vocabulary") that are defined for and used by multiple software modules. One motivation for this is modularity; if such a markup vocabulary exists which is well-understood and for which there is useful software available, it is better to re-use this markup rather than re-invent it.

Such documents, containing multiple markup vocabularies, pose problems of recognition and collision. Software modules need to be able to recognize the tags and attributes which they are designed to process, even in the face of "collisions" occurring when markup intended for some other software package uses the same element type or attribute name.

So, namespaces should be used when you expect a document to be extended by aggregating elements from multiple disparate schemas. This motivation has to drive the design of the schema, to allow for easy extensibility while retaining XML-friendliness with regards to the format. The following concrete points could be improved:

  1. Element prefixing: this is just a fragment of the file as it is now:
    Clearly, using a prefix is not necessary here. The Sfx namespace is the only one used in the whole document, so a default unprefixed namespace could be used on the root of the hierarchy, and the namespace rules of XML would propagate it to its children. Therefore, the fragment above is absolutely equivalent from the point of view of XML to the following one: Consistency of namespaces and their use is also desired across the schemas for <referenceArchitecture>, <businessActionsDefinition>, <eventConfiguration>, etc.
  2. Attributes with namespace: attributes shouldn't be assigned namespaces. It's common practice (and the W3C default) to leave attributes without namespaces. This also makes for more readable files. This default is changed in the Sfx schema by setting the attributeFormDefault= "qualified". What this means is that all attributes in the instance document (the actual configuration file) must be prefixed, as the attributes are now part of the targetNamespace: ... This is pretty cumbersome to read and author, and doesn't really add value to the extensibilty/usability of the schema and the config file. This may be a valid (and even necessary) approach for a highly composed document such as a SOAP message is, where every WS-* spec defines its own attributes and elements, and almost everything is prefixed. But I wonder if this actually necessary in a config file... Leaving the default attributeFormDefault  (or omitting it) in the schema, gives you the following valid instance: ... I believe this is far better and more familiar. Extensibility isn't hurt, as the xs:anyAttribute can still be used, but now you only force attribute prefixing on extensions, not built-in values, which are the more commonly used. This brings us to the last point.
  3. Schema and configuration extensibility: Sfx is meant to be flexible and allow a wide range of applications. With this idea in mind, almost everything is configurable... to an extent. One of the key pieces in this architecture (and any other SOA-like) is to provide a platform of common services where your services (let's call them business actions -BA- as in Sfx) run. I envision that some BAs may need additional configuration in order to perform their work. I've worked on such an architecture and BA developers started developing custom configuration mechanisms for their libraries because the infrastructure didn't provide it, which led to serious maintenance and deploy problems. 
    So, the schema for BA configuration should allow for open content in order to accomodate extensibility elements/attributes.
  4. Configuration versioning: given the current target namespace for the configuration schema (http://www.microsoft.com/practices/referencearchitecture/services/03-08-2004/ReferenceArchitectureSection.xsd) it's only natural to infer that versioning will be handled through namespace changes, according to the release date. There's a lot of discussion in the community about schema versioning, but most agree that versioning through namespace changes is not recommended. This document explains in a short and consice manner the available options. My suggesion to make the migration path in the future when configuration is upgraded as easy as possible for developers (and an optional upgrade tool) is to use the optional XSD version attribute in the schema, together with a new schemaVersion attribute in the configuration file. The schema would look like the following: ...etc... While the configuration would include the appropriate version attribute: Now when v2 comes out, a tool can detect the version in the configuration file, and perform any relevant upgrade (for example through an XSLT transformation to accommodate elements to the new format).
Finally, special care should be taken to specify the type attribute on all attribute declarations. 

Of course configuration is just the tip of the iceberg of such a comprehensive product. Shadowfax is a very interesting architecture to build applications on top. MS is very open on feedback from the community, so I expect it to become more and more polished and sleek over time. These are my 2 cents with regards to its configuration file.

If I misunderstood some points in the schema design, I'd be glad to hear from the Sfx dev guys!

posted Friday, April 16, 2004 7:25 PM by kzu with 0 Comments

Shadowfax: getting my hands dirty with a SOA-like architecture

Recently, I started working with Shadowfax, a reference architecure coming from the Patterns & Practices group at Microsoft. You have a look at an overview of the architecture at the GDN workspace home. I also recommend Hernan de Lahitte's blog, one of the guys working on it. He has a nice introduction as as well as a closer inspection of the processing pipeline.

I don't to repeat those intros. I'll just say that if you're developing SOA-like architectures, or you need one for your project, you should definitely take a look. It's being developed in a very open manner, with source releases pretty often, with open feedback through the workspace, and even if it's not ready for prime time yet, it's a good indication of where MS thinks you should be going with your projects. It closely follows the advises from Application Architecture for .NET: Designing Applications and Services, and generally represents a pretty good compendium of best practices. It makes heavy use of several application blocks from PAG, su as Configuration Management Application Block, Authorization and Profile Application Block an the Logging Application Block.

As this is going to take most of my working day now, I'll start a new category for these posts. I hope ScottW adds support for subscribing to a single category soon (as dasBlog does since quite a while...). This way, you can subscribe to this single category if you want.

I have the task of helping developers have a smooth experience when programming against Shadowfax. I'll drop my ideas here, as well as the dev. aids I think could be useful. Even if you don't use Shadowfax, it would be cool to get your feedback... because it's possible that some of my ideas seem useful only to me! Stay tunned, lots of posts are coming ;)

posted Friday, April 16, 2004 3:57 PM by kzu with 0 Comments