uigen.exe generates a complete Visual Studio ASP.NET project from a re-motion domain, i.e. one or more assemblies containing the domain object classes constituting the domain.
uigen.exe gets a path to a directory, inspects all assemblies in it and checks whether it contains domain object classes. Based on what it sees,
uigen.exe generates a basic ASP.NET application to work with those domain objects.
uigen.exe is template-based. It uses a directory tree with templates for generating a typical Visual Studio ASP.NET projects. The directory tree corresponds roughly to the generated tree.
This is how the "template tree" looks like:
This is how the generated tree for a PhoneBook ASP.NET application project looks like:
(The extra folders are
Properties. They are not part of
uigen.exe's program generation,
they are build products from building the PhoneBook web application from generated sources.)
The original tree contains files and templates from which
uigen.exe makes the actual files in the generated project – at the same relative path where their copies or expansions will show up in the generated tree. Some files - like images - are just copied.
A typical example is the top-level folder in the template tree. To the left you see the templates in
uigen.exe's root of the template tree, to the right you see the corresponding top-level of the generated PhoneBook tree:
In other words: most of the templates have the same name as the resulting file. The notable exception here is the name of the resulting project, in this case
PhoneBook.Web.csproj. This file originates from the template named
WebClient.csproj and is renamed in the course of template expansion.
If you open a template file, you will see that it contains "placeholders", denoted by "Dollar-Dollar". (e.g. "
$(...) items are NOT uigen-placeholders! They are Visual Studio placeholders!
You might recognize the highlighted placeholder
$PROJECT_ROOTNAMESPACE$ in the picture: this is the placeholder you set in the
uigen.exe configuration file. It is substituted by the placeholders value (a string).
Other good examples for directories with template files corresponding to exactly one output file is the
Classes directory, with templates for
Not all templates work in such a fun-and-easy 1:1 fashion, however. If you look into the
WebClient\UI template subfolder you will find the following templates:
All the first three files,
NavigationTabs. serve as templates not for a single file, but for one file per domain object class. For example, for each of the classes
PhoneNumber, a set of
EditPhoneNumberControl. will be generated from the corresponding
The rule applies to
SearchResultForm.. From the
NavigationTabs.* only one instance is generated, independently from the number of domain classes. These placeholders get their values from inspection of domain assemblies.
More about placeholders
$PLACEHOLDERS$ get their values from the
uigen.exe configuration file as strings. Some placeholders get their values from other sources. The central example here are the names for domain object classes.
uigen.exe provides a mechanism to iterate over all domain object classes.
If you open the
WebClient\UI\NavigationTabs.ascx template, you will see three
$REPEAT_FOREACHCLASS_END$ acts as a bracket around a loop, iterating over all domain object classes. The
$DOMAIN_CLASSNAME$ acts as a counter variable with the current domain object class name as value. We call such special placeholders "Loopers".
This construction is needed in several templates – whenever some code/text has to be expanded for each domain object class.
WebClient\UI\NavigationTabs.ascx is an example for iterating over domain object classes in a single template. This is in contrast to templates like
WebClient\UI\EditForm.aspx, which iterate over domain object classes and generate one file per domain object class. How can that be done? We will return to this question in section TabbedEditor.xml below. Let's look at how the looper constructions are used within a single file.
In more general terms, a looper is always based on a list of thingies (classes, properties, enums) that can be represented as strings. The class looper might be based on the list of classes
PhoneNumber (the classes in the PhoneBook). The class looper expands the text between the start placeholder and the end placeholder for each item in the list and uses the string representation as value for the iterator variable(s).
An example for the class looper at work is the
UrlMapping.xml template that expands to a full-blown
UrlMapping.xml configuration file for the PhoneBook app (for example). The task here is to create an
SearchX- entry for each domain object class in the domain (i.e.
PhoneNumber in the PhoneBook application).
Look at this section in the
In the expanded
UrlMapping.xml file this section has been expanded three times, once for
A looper can have more than one iterator variable. The class looper sports not only
$DOMAIN_CLASSNAME$, but also
$DOMAIN_QUALIFIEDCLASSTYPENAME$ expanding to the class name plus namespace for the current class.
More loopers exist besides $REPEAT_FOREACHCLASS_BEGIN/END$. There are:
A complete list of placeholders can be found in the file
Placeholder.cs. Not all of them are used in the current templates.
Placeholders.cs can be found here.
(The many faces of application generation)
uigen.exe configuration file provides "placeholders" (macros) for substitution in other files, but not more. The central piece, the file that tells
uigen.exe what to do, is the
TabbedEditor.xml file. If you inspect it you will sense that generating a project for a re-motion ASP.NET web client application has several different parts:
- copying files from various directories to the web client project (directories)
- substituting place-holders in template files
- using a set of template files and class- and property names from the domain to create various .aspx .ascx and .cs files
- mapping property types to controls
- adding extra information to particular controls, like fixed column nodes for BocLists
In a way, the
TabbedEditor.xml file can be seen as a batch file written in a special programming language, and
uigen.exe can be seen as an interpreter for that language. The TabbedEditor.xml file is the batch file for creating tabbed editor applications (with their distinctive feature being that each domain object class gets its own tab/page in the application). You could write generators for other types of applications simply by writing a "batch file" like
TabbedEditor.xml with different instructions. Flexibility is limited, however, since the "batch language" is not Turing-complete.
When staring at
uigen.exe, alert readers will notice that
TabbedEditor.xml is itself a template file. The
$DOMAIN_CLASSNAME$, etc. put it away:
TabbedEditor.xml is subject to placeholder substitution and thus clearly a template. Its expansion is never stored anywhere, however.
Not contained in the template, however, are the looping elements
$REPEAT_FOREACHCLASS_END$. This function is taken over by corresponding XML tags, namely
Another such looping element is
<forEachEnum>, with an iterator placeholder named
TabbedEditor.xml is the master configuration file for
uigen.exe. Apart from containing a list of files to copy and templates to expand it controls the following chores:
- generating globalization (resource) files for enums (currently commented out)
- mapping domain class property types to BOC controls
- injecting extra .aspx-XML into .aspx/.ascx-declarations
Each of the chores is discussed separately in the following sections.
Files and templates
<file template=...>operator to expanding single template files
<files pattern=...>operator to expanding multiple template files, specified by path names with wild-cards
<copy source=...>operator to simply copying multiple files with wildcards
This works for "inner expansion" and "outer expansion". Inner expansion means that the specified file(s) are expanded, and the expanded product gets the same name as the original template file. Example: In
<files pattern="WebClient*.aspx" target="$WebClientName$" />
default.aspx is fingered (among others) in the template tree and expanded to the project tree as
Outer expansion means that the specified file(s) are expanded for each class, and the expanded products each get a name that reflects the class for which it has been expanded. Example: In
<file template="WebClient\UI\EditControl.ascx" target="$WebClientName$\UI\Edit$DOMAIN_CLASSNAME$Control.ascx" />
EditControl.ascx in the template tree is expanded to
EditPhoneNumberControl.ascx if there are three classes named
All template expansion- and copy-operators under the node global are submitted to inner expansion, all the template expansions under the ndoe
<forEachClass> are subject to outer expansion.
Generating globalization (resource) files for enums
This looked like a good idea in 2006, but has run out of fashion since then. The argument is that it is bad taste for a program generator to add code to the DOMAIN, and globalizing enums clearly is part of the domain. That's why the corresponding section in
TabbedEditor.xml has been commented out.
Mapping domain class property types to BOC controls
This important mapping is expressed under the node properties/controlMappings and simply contains a set of operators –
<mapping>. Example: The line
simply maps an enumeration property to a
The extra optional attribute
isList controls whether the value can be represented by a list (drop-downlist, list box, etc.)
injecting extra .aspx-XML into .aspx/.ascx-declarations
Under the node
properties/additionalElements we find extra code for supplementing aspx-declarations for each property = extra attributes and extra elements.
Structure of the generated web project
bin– contains the assembly for the actual web program, re-motion assemblies and the domain assembly/ies.
Classes– contains the base classes for re-call functions/pages. You are supposed to lodge the extra class files for your project here.
Globalization– the resources for globalizing your application.
Images– the images your application needs. Out of the box it contains an arrow-picture and a rubicon logo
res– a local copy of re-motion-generic resources for the web client application
UI– the ASP.NET pages that comprise your application.
Other notable files
Default.aspx.designer.cs– generated from the templates of the same names. This is the "splash screen"/"start screen" you see after the application has started.
Global.asax.csthe meat is
Global.asax.cs. Out of the box it initializes various provides. Put initialization code for your application here.
UrlMapping.xml– just what the name suggests, maps URLs to re-call page/functions. This file is created using the domain object classes as input (one entry per domain object class).
Web.Config– created from a template of the same name. This is your regular ASP.NET configuration file, of course.
WxeFunctions.cs– out of the box this file is empty. It is written by another code generator,
- WxeHandler.ashx – declares the handler for .wxe (re-call) "files".
Where to find
uigen.exe in the SVN-repository
For the re-motion version 1.13.6, the one supported by the PhoneBook tutorial:
Later versions have a new