Export (0) Print
Expand All

Restricting Additions to an Application Through ELEMENTSET Nodes

Visual Studio .NET 2003

An ELEMENTSET provides ways to control or filter what can be added to various parts of an application. You can use an ELEMENTSET to control which projects are allowed within an application, which project items are allowed within a project, or which particular controls or components are allowed on a form.

While ELEMENTSET definitions can contain CONSTRAINTS and MEMBERCONSTRAINTS nodes, those items are not covered in this topic. For more information about those concepts, see Walkthrough: Applying Constraints in an Enterprise Template Policy File.

The following sections show how an ELEMENTSET can be used to handle some common scenarios. The vast majority of ELEMENTSET definitions fall into the following general cases:

  • No restrictions are imposed; anything that can be added as a child is allowed.
  • Tight restrictions are imposed; only a small, well-defined set of items is allowed as children.
  • Moderate but specific restrictions are imposed; only a small, well-defined set of items is disallowed.
  • Moderate restrictions are imposed; anything recognized as mapping to an ELEMENT is allowed, everything else is disallowed.

The following scenarios cover a wide range of ELEMENTSET restrictions. Additional links to related information are provided where appropriate.

Scenario One: Allowing Only Specific Child Nodes of an ELEMENT
Understand how a DEFAULTACTION node set to EXCLUDE affects an ELEMENTSET.
Scenario Two: Preventing Improper References
Issue a policy reminder when an improper reference is added.
Scenario Three: Using FEATURELINKS with ELEMENTSET Nodes to Enable or Disable Menu Items and Toolbox Items
Understand the concepts behind FEATURELINKS and how to use them.
Scenario Four: Working with Web Forms in an Application
Design an ELEMENTSET that reflects some complex rules.
Note   The examples in this topic refer to MyTemplate, an example template. You can create MyTemplate by following the steps covered in Walkthrough: Creating a New Enterprise Template. In addition to learning about implementing policy and using the Template Description Language (TDL), you can familiarize yourself with the different file types required.

Scenario One: Allowing Only Specific Child Nodes of an ELEMENT

Most ELEMENTSET nodes tend to be quite simple. Many of the ELEMENTSET nodes in MyTemplate, as well as the ones in the standard Distributed Application Template follow the same pattern. To control which projects are allowed as children of an Enterprise Template project, or which project items are allowed within a project, it is easy to specify an ELEMENTSET that defaults to EXCLUDE, and then specifically INCLUDE only the items that should be allowed as children.

For example, the ELEMENTSET for etpMyTemplate, the top-level project in MyTemplate, is as follows:

<ELEMENTSET>
    <DEFAULTACTION>EXCLUDE</DEFAULTACTION>
    <ORDER>INCLUDEEXCLUDE</ORDER>
    <INCLUDE>etpBackendProjects</INCLUDE>
    <INCLUDE>etpUIProjects</INCLUDE>
    <INCLUDE>etpUtilityProjects</INCLUDE>
</ELEMENTSET>

It specifically includes only the three Enterprise Template projects that should be allowed as children.

The ELEMENTSET for etpUIProjects is as follows:

<ELEMENTSET>
    <DEFAULTACTION>EXCLUDE</DEFAULTACTION>
    <ORDER>INCLUDEEXCLUDE</ORDER>
    <INCLUDE>projWinApp</INCLUDE>
    <INCLUDE>projCSharpWinApp</INCLUDE>
    <INCLUDE>projCSharpWebApp</INCLUDE>
    <INCLUDE>projCSharpEmptyProject</INCLUDE>
</ELEMENTSET>

This ELEMENTSET excludes anything not specifically named. The ELEMENTSET explicitly allows your special WinApp project, and the general C# Windows Application, C# Web Application, and the C# Empty Project.

The ELEMENTSET for your projWinApp is as follows:

<ELEMENTSET>
    <DEFAULTACTION>EXCLUDE</DEFAULTACTION>
    <ORDER>INCLUDEEXCLUDE</ORDER>
    <INCLUDE>catWinUIProjectItems</INCLUDE>
    <INCLUDE>catCommonProjectItems</INCLUDE>
    <INCLUDE>catCSCommonProjectItems</INCLUDE>
    <INCLUDE>catWinCodeItems</INCLUDE>
    <INCLUDE>catComponentCodeItems</INCLUDE>
<!-- Constraints section deleted for clarity -->
<!-- MemberConstraints section deleted for clarity -->
</ELEMENTSET>

The definition is only slightly more complex than in the previous examples. Again, the ELEMENTSET excludes anything not explicitly included. In this case, the ELEMENTSET explicitly includes categories (defined as CATEGORY nodes) of allowed items. Categories merely reduce the number of lines of INCLUDE or EXCLUDE statements that are needed in an ELEMENTSET by allowing you to collect related items into a single CATEGORY node.

They also provide a secondary benefit in that they convey some semantic meaning, allowing a reader of the policy file to understand that you want Windows UI-related project items, common project items, C# common project items, Windows code items (Windows Forms entries from the Toolbox), and Component code items (Component entries from the Toolbox). In contrast, the following ELEMENTSET expresses the same items but does not take advantage of CATEGORY nodes. Notice how much harder it is to understand the "rules" the author had in mind.

<ELEMENTSET>
    <DEFAULTACTION>EXCLUDE</DEFAULTACTION>
    <ORDER>INCLUDEEXCLUDE</ORDER>
    <INCLUDE>codeWinForm</INCLUDE>
    <INCLUDE>projItemVBInheritedForm</INCLUDE>
    <INCLUDE>codeUserControl</INCLUDE>
    <INCLUDE>codeCustomControl</INCLUDE>            
    <INCLUDE>projItemXMLFile</INCLUDE>
    <INCLUDE>projItemTextFile</INCLUDE>
    <INCLUDE>projItemCrystalReport</INCLUDE>
    <INCLUDE>projItemXMLDataSet</INCLUDE>
    <INCLUDE>projItemXSDDataSet</INCLUDE>
    <INCLUDE>projItemXMLSchema</INCLUDE>
    <INCLUDE>projItemXSLTFile</INCLUDE>
    <INCLUDE>projItemXMLLocalizableStringResourceFile</INCLUDE>
    <INCLUDE>codeClass</INCLUDE>
    <INCLUDE>projItemCSharpFile</INCLUDE>
    <INCLUDE>codeComponent</INCLUDE>
    <INCLUDE>codeInstallerClass</INCLUDE>
    <INCLUDE>codeGlobalApplicationClass</INCLUDE>
    <INCLUDE>codeWinFormsLabel</INCLUDE>
    <INCLUDE>codeWinFormsLinkLabel</INCLUDE>
    <INCLUDE>codeWinFormsButton</INCLUDE>
    <INCLUDE>codeWinFormsTextBox</INCLUDE>
    <INCLUDE>codeWinFormsMainMenu</INCLUDE>
    <INCLUDE>codeWinFormsCheckBox</INCLUDE>
    <INCLUDE>codeWinFormsRadioButton</INCLUDE>
    <INCLUDE>codeWinFormsGroupBox</INCLUDE>
    <INCLUDE>codeWinFormsPictureBox</INCLUDE>
    <INCLUDE>codeWinFormsPanel</INCLUDE>
    <INCLUDE>codeWinFormsDataGrid</INCLUDE>
    <INCLUDE>codeWinFormsListBox</INCLUDE>
    <INCLUDE>codeWinFormsCheckedListBox</INCLUDE>
    <INCLUDE>codeWinFormsComboBox</INCLUDE>
    <INCLUDE>codeWinFormsListView</INCLUDE>
    <INCLUDE>codeWinFormsTreeView</INCLUDE>
    <INCLUDE>codeWinFormsTabControl</INCLUDE>
    <INCLUDE>codeWinFormsDateTimePicker</INCLUDE>
    <INCLUDE>codeWinFormsMonthCalendar</INCLUDE>
    <INCLUDE>codeWinFormsHorizontalScrollBar</INCLUDE>
    <INCLUDE>codeWinFormsVerticalScrollBar</INCLUDE>
    <INCLUDE>codeWinFormsTimer</INCLUDE>
    <INCLUDE>codeWinFormsSplitter</INCLUDE>
    <INCLUDE>codeWinFormsDomainUpDown</INCLUDE>
    <INCLUDE>codeWinFormsNumericUpDown</INCLUDE>
    <INCLUDE>codeWinFormsTrackBar</INCLUDE>
    <INCLUDE>codeWinFormsRichTextBox</INCLUDE>
    <INCLUDE>codeWinFormsImageList</INCLUDE>
    <INCLUDE>codeWinFormsHelpProvider</INCLUDE>
    <INCLUDE>codeWinFormsToolTip</INCLUDE>
    <INCLUDE>codeWinFormsContextMenu</INCLUDE>
    <INCLUDE>codeWinFormsToolBar</INCLUDE>
    <INCLUDE>codeWinFormsStatusBar</INCLUDE>
    <INCLUDE>codeWinFormsNumericFormat</INCLUDE>
    <INCLUDE>codeWinFormsDateTimeFormat</INCLUDE>
    <INCLUDE>codeWinFormsTrayIcon</INCLUDE>
    <INCLUDE>codeWinFormsOpenFileDialog</INCLUDE>
    <INCLUDE>codeWinFormsSaveFileDialog</INCLUDE>
    <INCLUDE>codeWinFormsFontDialog</INCLUDE>
    <INCLUDE>codeWinFormsColorDialog</INCLUDE>
    <INCLUDE>codeWinFormsPrintDialog</INCLUDE>
    <INCLUDE>codeWinFormsPrintPreviewDialog</INCLUDE>
    <INCLUDE>codeWinFormsErrorProvider</INCLUDE>
    <INCLUDE>codeWinFormsPrintDocument</INCLUDE>
    <INCLUDE>codeWinFormsPageSetupDialog</INCLUDE>
    <INCLUDE>codeComponentsEventLog</INCLUDE>
    <INCLUDE>codeComponentsMessageQueue</INCLUDE>
    <INCLUDE>codeComponentsPerformanceCounter</INCLUDE>
    <INCLUDE>codeComponentsProcess</INCLUDE>
    <INCLUDE>codeComponentsScheduler</INCLUDE>
    <INCLUDE>codeComponentsServiceController</INCLUDE>
    <INCLUDE>codeComponentsTimer</INCLUDE>
<!-- Constraints section deleted for clarity -->
<!-- MemberConstraints section deleted for clarity -->
</ELEMENTSET>

With this lengthy ELEMENTSET definition, it is much easier to make mistakes and much harder to visually verify whether the ELEMENTSET definition contains your intended policy. Using CATEGORY nodes reduces the complexity of this area of TDL. For more information about CATEGORIES and CATEGORY nodes, see CATEGORY Nodes in TDL. You can also browse the DAP.tdl file that ships with Visual Studio to get a better idea of how to construct CATEGORY nodes.

Scenario Two: Preventing Improper References

Since you can define an ELEMENT that corresponds to a reference, you can easily use your ELEMENTSET definition to issue a policy reminder if a developer adds a reference that violates the intended architectural policy. For example, in the Distributed Application template you might want to prevent developers from bypassing the BusinessFacade and calling directly into the DataAccess layer from the UI. You must define an ELEMENT node that corresponds to each DLL and then specifically include or exclude each ELEMENT node in the ELEMENTSET. To accomplish this, you first define ELEMENT nodes that correspond to the DLLs for DataAccess and BusinessFacade as follows:

<ELEMENT>
    <ID>refDataAccessDll</ID>
    <IDENTIFIERS>
        <IDENTIFIER>
            <TYPE>REFERENCE</TYPE>
            <IDENTIFIERDATA>
                <NAME>FileName</NAME>
                <VALUE>DataAccess.dll</VALUE> 
            </IDENTIFIERDATA>
        </IDENTIFIER>
    </IDENTIFIERS>
</ELEMENT>
<ELEMENT>
    <ID>refBusinessFacadeDll</ID>
    <IDENTIFIERS>
        <IDENTIFIER>
            <TYPE>REFERENCE</TYPE>
            <IDENTIFIERDATA>
                <NAME>FileName</NAME>
                <VALUE>BusinessFacade.dll</VALUE> 
            </IDENTIFIERDATA>
        </IDENTIFIER>
    </IDENTIFIERS>
</ELEMENT>

Once you have defined those ELEMENT nodes, include the BusinessFacade ELEMENT and exclude the DataAccess ELEMENT in the ELEMENTSET node for your projWinUI ELEMENT:

<ELEMENTSET>
    <DEFAULTACTION>EXCLUDE</DEFAULTACTION>
    <ORDER>INCLUDEEXCLUDE</ORDER>
    <INCLUDE>catVBCommonProjectItems</INCLUDE>
    <INCLUDE>catWinUIProjectItems</INCLUDE>
    <INCLUDE>catCommonProjectItems</INCLUDE>
    <INCLUDE>catCSCommonProjectItems</INCLUDE>
    <INCLUDE>catWinCodeItems</INCLUDE>
    <INCLUDE>catDataCodeItems</INCLUDE>
    <INCLUDE>catComponentCodeItems</INCLUDE>
    <INCLUDE>refBusinessFacadeDll</INCLUDE>
    <EXCLUDE>refDataAccessDll</EXCLUDE>
</ELEMENTSET>

Note that in addition to specifying which code items are allowed, the ELEMENTSET node specifically includes the reference to the BusinessFacade and excludes the reference to the DataAccess DLL. Technically the latter is not required, but if you later opt to change the DEFAULTACTION to INCLUDE, you would still catch errant references.

Scenario Three: Using FEATURELINKS with ELEMENTSET Nodes to Enable or Disable Menu Items and Toolbox Items

Using menu and Toolbox constraints is not always the best way of turning off a menu item or Toolbox item, especially if that item has an associated ELEMENT definition. In these cases, it is often more appropriate to take advantage of FEATURELINKS nodes. This provides a way to associate a feature in the Visual Studio IDE (either a menu item or Toolbox item) with a particular ELEMENT definition. Once that association has been made, whenever an ELEMENT is excluded from an ELEMENTSET, the corresponding menu item or Toolbox item is also disabled.

You can see example uses of FEATURELINKS in the Windows Forms and Web Forms Toolbox items in MyPolicy.tdl. All have a corresponding ELEMENT definition. If you look at the definition for codeWebFormsButton, for example, you see that a TOOLBOXLINK is defined:

<ELEMENT>
    <ID>codeWebFormsButton</ID>
    <IDENTIFIERS>
        <IDENTIFIER>
            <TYPE>CODEVARIABLE</TYPE>
            <IDENTIFIERDATA>
                <NAME>TYPENAME</NAME>
                <VALUE>System.Web.UI.WebControls.Button</VALUE>
            </IDENTIFIERDATA>
        </IDENTIFIER>
    </IDENTIFIERS>
    <FEATURELINKS>
        <TOOLBOXLINKS>
            <TOOLBOXLINK>tboxWebFormsButton</TOOLBOXLINK>
        </TOOLBOXLINKS>
    </FEATURELINKS>
</ELEMENT>

Similarly, the codeWebForms ELEMENT has an associated MENULINK:

<ELEMENT>
    <ID>codeWebForm</ID>
        <IDENTIFIERS>
            <IDENTIFIER>
                <TYPE>code</TYPE>
                <IDENTIFIERDATA>
                    <NAME>Inherits</NAME>
                        <VALUE>System.Web.UI.Page</VALUE>
                 </IDENTIFIERDATA>
                </IDENTIFIER>
            </IDENTIFIERS>
            <FEATURELINKS>
                <MENULINKS>
                    <MENULINK>menuProject.AddWebForm</MENULINK>
                </MENULINKS>
            </FEATURELINKS>
        <!-- section deleted for clarity -->
        </ELEMENT>

Any time one of these ELEMENT nodes is excluded in an ELEMENTSET, the corresponding menu or Toolbox item is disabled, without going through the effort of including an additional menu or Toolbox constraint.

Scenario Four: Working with Web Forms in an Application

In this more complex scenario, you walk through a full ELEMENTSET definition. Assume you, as software architect, decide to disallow use of COM components on any Web Forms in an application. The only exception is for objects that implement ISerializable. You do want to encourage the use of .NET Framework objects. In addition, you do not want your developers to use the SQLConnection or SQLDataAdapter Toolbox items. Finally, you prefer the developers use the appropriate Web Form control when it exists, instead of the corresponding HTML control.

Implementing these rules might seem rather daunting but it is relatively easy as long as you take it one step at a time. Here is a breakdown of the requirements:

  • Since you want to define what items are allowed on a Web Form, you can do so by specifying an ELEMENTSET definition for codeWebForm.
  • You need to identify COM components so you can exclude them from the ELEMENTSET.
  • You need to identify an ELEMENT mapping to ISerializable and include it in the ELEMENTSET, so that it is allowed as an exception to the COM components exclusion rule above.
  • You must exclude SQLConnection and SQLDataAdapter items.
  • You must include Web Form controls.
  • You must exclude HTML controls.

To implement the rules

  1. Define a new ELEMENT node that identifies all COM components. Since all COM components implement the IUnknown interface, IUnknown is a good choice to use for the identification process. Create the ELEMENT node by including IUnknown in the IDENTIFIERDATA node as follows:
    <ELEMENT>
        <ID>codeCOMClassicComponent</ID>
        <IDENTIFIERS>
            <IDENTIFIER>
                <TYPE>code</TYPE>
                <IDENTIFIERDATA>
                    <NAME>Implements</NAME>
                    <VALUE>IUnknown</VALUE>
                </IDENTIFIERDATA>
            </IDENTIFIER>
        </IDENTIFIERS>
    </ELEMENT>
    
  2. Define an ELEMENT that corresponds to any component that implements ISerializable. The ELEMENT definition is as follows:
    <ELEMENT>
        <ID>codeISerializableComponent</ID>
        <IDENTIFIERS>
            <IDENTIFIER>
                <TYPE>code</TYPE>
                <IDENTIFIERDATA>
                    <NAME>Implements</NAME>
                    <VALUE>ISerializable</VALUE>
                </IDENTIFIERDATA>
            </IDENTIFIER>
        </IDENTIFIERS>
    </ELEMENT>
    
  3. Define codeDataSQLConnection and codeDataSQLDataAdaptor. If you are working with MyPolicy.tdl or another policy file based on DAP.tdl, it already contains definitions for codeDataSQLConnection and codeDataSQLDataAdaptor. If not, you can copy the definitions from DAP.tdl.
  4. Define the Web Form controls. Again, if you are working with MyPolicy.tdl, all the controls in the Web Forms tab of the Toolbox already have corresponding ELEMENT definitions. Even better, an appropriate CATEGORY node, catWebCodeItems, is already defined. If you are not using a policy file based on DAP.tdl, you can copy the Web Forms ELEMENT and CATEGORY definitions from DAP.tdl.
  5. The HTML Toolbox items are defined in MyPolicy.tdl but there is no corresponding CATEGORY node present. Add the following CATEGORY definition:
    <CATEGORY>
        <ID>catHTMLControls</ID>
        <CATEGORYMEMBER>codeHTMLForm</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLButton</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLResetButton</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLSubmitButton</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLTextField</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLTextArea</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLFileField</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLPasswordField</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLCheckBox</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLRadioButton</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLTable</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLPanelLinearLayout</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLPanelGridLayout</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLImage</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLListBox</CATEGORYMEMBER>
        <CATEGORYMEMBER>codeHTMLHorizontalRule</CATEGORYMEMBER>
    </CATEGORY>
    
  6. Define the ELEMENTSET node for codeWebForm. You can use a default action of INCLUDE and then specifically disallow items you do not want with EXCLUDE nodes. The ELEMENTSET definition should read as follows:
    <ELEMENTSET>
        <DEFAULTACTION>INCLUDE</DEFAULTACTION>
        <ORDER>EXCLUDEINCLUDE</ORDER>
        <EXCLUDE>codeCOMClassicComponent</EXCLUDE>
        <INCLUDE>codeISerializableComponent</INCLUDE>
        <EXCLUDE>codeDataSQLConnection</EXCLUDE>
        <EXCLUDE>codeDataSQLDataAdaptor</EXCLUDE>
        <INCLUDE>catWebCodeItems</INCLUDE>
        <EXCLUDE>catHTMLControls</EXCLUDE>
        <!-- MemberConstraints section deleted for clarity -->
    </ELEMENTSET>
    

    Note the ORDER node is set to EXCLUDEINCLUDE. This setting ensures that all EXCLUDE nodes are evaluated before INCLUDE nodes. Therefore the two bold lines above are interpreted as, "Exclude all COM components except ISerializable ones." If the ORDER node were set to INCLUDEEXCLUDE, you could not represent this. You do not need to specifically list catWebCodeItems, because the DEFAULTACTION is INCLUDE so it is permitted by default. By explicitly stating it in an INCLUDE node, however, it is easy to remember the intended rules. If you leave it out, it is possible to accidentally violate your rules the next time you edit the policy file. For example, if you decide to change the DEFAULTACTION setting to EXCLUDE, anything not explicitly listed in an INCLUDE node is disallowed.

  7. Save the changes to the policy file and reopen the application associated with it. Open the Web Form (WebForm1.aspx) and view the Toolbox. Notice that the SQL-specific data controls are disabled, the Web controls are enabled, and the HTML controls are disabled.

See Also

Using ELEMENTSET Nodes to Specify Constraints in Policy Files | Defining ELEMENTSET Nodes in TDL

Show:
© 2014 Microsoft