Overview of the Forms Infrastructure and the Generic Form

Overview of the Forms Infrastructure and the Generic Form

  • Comments 9
  • Likes

This blog post is intended for developers and people doing advanced customizations in Service Manager.

An earlier blog post illustrated how to use the <Form> element in Service Manager's management pack infrastructure to create rich, custom forms for classes and relationships in the CMDB. Custom forms offer complete flexibility in displaying class and relationship information to end users, and they are well-suited to displaying data that spans multiple classes and relationships or requires unique UI elements.

When the data that needs to be displayed originates in an object of one class, presenting an editable table of property-value pairs is often sufficient. To prevent customers from having to develop these simple forms for each class added to a Service Manager installation, Service Manager ships with a Generic Form that renders a property-value display for any class that does not already appear in a custom form.

This blog post will provide background on the forms infrastructure used in our product and the options available to customize the Generic Form.

Part 1: Understanding the forms infrastructure

Let's take a look at the <Form> element tag in the ServiceManager.ConfigurationManagement.Library management pack that causes the computer form to display for computer objects in the console.

<Form TypeName="Microsoft.EnterpriseManagement.ServiceManager.ConfigurationManagement.Forms.ComputerForm" Target="Microsoft.Windows.Computer.ProjectionType" ID="ComputerForm" Assembly="ConfigurationManagementFormsAssembly" Accessibility="Public">

Each attribute in the Form tag indicates the following:

Attribute

Description

TypeName

The qualified name of the .NET Class that contains the form code.

Target

The class (<ClassType>) or type projection (<TypeProjection>) for which the form should display.

ID

A unique identifier for the form element.

Assembly

A reference to an <Assembly> MP element that points to the DLL containing the form code. The Assembly element is defined in the <Resources> section of an MP.

 

The Assembly element for this form is:

 

 <Assembly ID="ConfigurationManagementFormsAssembly" QualifiedName="Microsoft.EnterpriseManagement.ServiceManager.ConfigurationManagement.Forms" FileName="Microsoft.EnterpriseManagement.ServiceManager.ConfigurationManagement.Forms.dll" Accessibility="Public" />

Accessibility

The accessibility of the form element, set to "Public" here so that this Form element can be referenced by other MPs.

The Target attribute of the form tag links the form to a class or a type projection. When the user selects the "Create" task associated with a view or the "Edit" task associated with an object or object projection, the class to be created or edited is determined. Our UI code then looks for a form that is either (1) targeted to that class or (2) targeted to a type projection that has a seed that is that class. If a form is found, it is displayed. If a form is not found, the check is repeated on each of the parent classes until a form is found.

This logic is summarized in the Figure 1 below:

 

 

GenericForm_Figure1_FormSelection 

Figure 1: Form selection process

 

Note that a form is designated to appear in one of two modes:

1. Pop-out mode, the default, indicates that the form will surface when the "Create" task or the "Edit" task is clicked.

2. Preview mode, which is enabled by adding a category with a special enumeration value and targeting it to the form, indicates that the form will display in the details pane when an item in a grid view is selected.

The search that is performed to find a form for a given object (as depicted in Figure 1) is limited to forms in the desired display mode. For example, when a grid view item is selected, it is determined that a form in preview mode is needed and a search for a form is performed using only the set of forms categorized as preview forms.

The enumeration value used to demarcate a preview form resides in the Microsoft.EnterpriseManagement.ServiceManager.UI.Console management pack. The following category definition, for example, would mark the form named "ClassForm" as a preview form.

<Category ID="someuniqueID" Target="ClassForm" Value="Console!Microsoft.EnterpriseManagement.ServiceManager.UI.Console.OverviewForm" />

Preview and pop-out forms will always be found for a given class because preview and pop-out versions of the Generic Form are targeted to System.Entity, the root class in Service Manager's class model.

Part 2: The Generic Form

The Generic Form is a WPF UserControl that consists of up to three tabs:

1. A General tab displays all of the properties of the object that serves as the form's data context. If the data that underlies the form is a projection object, properties are displayed for the seed class object in that projection. Properties in the tab are grouped under their respective classes starting from the top of the class hierarchy (System.Entity) and moving down.

When the object displayed in the form inherits from System.ConfigItem or System.WorkItem:

2. A Related Items tab presents an updatable display of objects related to the object, and

3. A History tab chronicles the changes that have been made to properties on the object and the object’s relationships to other objects.

There are two display modes for the Generic Form. The Generic Preview Form displays property information for the currently selected object in a grid view. Alternatively, the Generic Pop-Out Form displays property information when a class object or projection object is displayed within a form window. These two display modes are juxtaposed below (click to enlarge):

 

GenericForm_Figure2_PreviewLeft GenericForm_Figure2_EditRight

Figure 2: Generic Form displaying a Software Item object in preview mode (left) and pop-out mode (right)

 

Note that in preview mode, no related items tab or history tab is shown, and the properties in the form are not editable.

The Generic Form appears in four management pack form element (i.e.: <Form> tag) definitions. A preview form and a pop-out form are targeted to the System.Entity base class, one pop-out form is targeted to a type projection with seed class System.ConfigItem, and one pop-out form is targeted to a type projection with seed class System.WorkItem. The pop-out form definitions targeted to the Configuration Item and Work Item type projections are used to populate the Related Items Tab with a standard set of related objects on Configuration Item and Work Item classes.

This is summarized in Figure 3 below.

 

GenericForm_Figure3_GenericFormMPElements

Figure 3: Occurrence of Generic Form <Form> elements in the class model

 

Part 3: The Extension Tab

When a pop-out form is displayed in a form window using the Create task or the Edit task, a check is made to determine:

1. The class of the object being displayed, and

2. The class to which the form that is being displayed is targeted.

These classes can differ if the form that was selected to display an object is targeted to one of the parent classes of that object (e.g.: displaying an object of a class derived from Change Request in the Change Request form).

If the form that is being displayed is a custom form and is not the Generic Form (which, by default, displays all of an object's properties in the General tab), and classes 1 and 2 differ, an Extension tab is added to the custom form. This tab displays property-value pairs for all classes in the object's class hierarchy that inherit from the form's target class.

The tab also displays (again, only for custom forms) all of the properties of any extension classes in the class hierarchy of the object. These properties are grouped under the extended class.

Suppose, for example, that a sealed MP were imported with class definitions below:

<ClassTypes>

  <ClassType ID="Incident_Extension" Base="CoreIncident!System.WorkItem.Incident" Abstract="false" Accessibility="Public" Hosted="false" Extension="true">

    <Property ID="incident_extension_1" Type="string" />

    <Property ID="incident_extension_2" Type="string" />

    <Property ID="incident_extension_3" Type="string" />

  </ClassType>

  <ClassType ID="Incident_Derived" Base="CoreIncident!System.WorkItem.Incident" Abstract="false" Accessibility="Public" Hosted="false" Extension="false">

    <Property ID="incident_derived_1" Type="string" />

    <Property ID="incident_derived_2" Type="string" />

  </ClassType>

</ClassTypes>

These definitions extend the System.WorkItem.Incident class with 3 string properties and add a class that derives from System.WorkItem.Incident with 2 string properties.

If a view were created on the Incident_Derived class and the user attempted to create a new Incident_Derived object using the Create task that appears for the view, the user would see the form in Figure 4 below (click to enlarge):

 GenericForm_Figure4_IncidentLeft GenericForm_Figure4_ExtensionRight

Figure 4: Generic Form displaying an Incident_Derived object with the extension tab. Extension properties and derived class properties appear in the extension tab.

 

Since any extension properties of an object are shown in the Extension tab, the Incident_Extension properties are shown in the Extension tab. The Incident_Derived properties also appear in the extension tab because the Incident form is targeted to System.WorkItem.Incident and the object being displayed is of the derived class Incident_Derived.

Below, Figure 5 displays all of the classes (in hierarchical order) of which the Incident_Derived object is a member. Our console assumes that only the non-extension properties that appear in the Incident Form's target class (System.WorkItem.Incident) hierarchy will be displayed in the custom form. Since extension classes and derived classes outside this hierarchy have properties which may not be displayed in the form, the extension tab is added to display the properties of these extended and derived classes.

 

GenericForm_Figure5_IncidentHierarchy

Figure 5: The properties in the blue classes are assumed to be present in the Incident custom form. Properties in the derived class (red) and the extension class (teal) are added to the extension tab.

 

To prevent the extension tab from displaying on a form, MP authors can target a category to the form with an Enumeration value in the Microsoft.EnterpriseManagement.ServiceManager.UI.Administration MP:

<EnumerationValue ID="Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideExtensionTab" Accessibility="Public" />

For example, to prevent the extension tab from displaying in the Incident form in the example above, the following MP could be imported:

 <ManagementPack ContentReadable="true" SchemaVersion="1.1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <Manifest>

    <Identity>

      <ID>hidetest</ID>

      <Version>7.0.5000.0</Version>

    </Identity>

    <Name>hidetest</Name>

    <References>

      <Reference Alias="Admin">

<ID>Microsoft.EnterpriseManagement.ServiceManager.UI.Administration</ID>

        <Version>7.0.5000.0</Version>

        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>

      </Reference>

      <Reference Alias="Incident">

        <ID>ServiceManager.IncidentManagement.Library</ID>

        <Version>7.0.5010.0</Version>

        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>

      </Reference>

    </References>

  </Manifest>

  <Categories>

    <Category ID="HideIncidentFormExtensionTab" Target="Incident!System.WorkItem.Incident.ConsoleForm" Value="Admin!Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideExtensionTab" />

  </Categories>

</ManagementPack>

 

Part 4: Additional Generic Form Customizations

1. Disabling the preview pane for a class (and its descendants)

To disable the preview form for an object of a particular class, target a category with the enumeration value

<EnumerationValue ID="Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideDetailsPane" Accessibility="Public" />

(which appears in the Microsoft.EnterpriseManagement.ServiceManager.UI.Administration MP) to the class (not the form) for which the preview pane should not be displayed.

For example, to prevent the Generic Form preview pane (targeted to System.Entity) from appearing when a connector is selected in the grid view under Administration > Connectors, we use the following category:

<Category ID="Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.ConnectorHideDetails" Target="SystemCenter!Microsoft.SystemCenter.Connector" Value="Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideDetailsPane" />

2. Hiding properties in the Generic Form in Preview and Edit Modes

To remove properties that appear in the preview and pop-out versions of the Generic Form, two view types defined in the Microsoft.EnterpriseManagement.ServiceManager.UI.Authoring MP are used. The PreviewViewType excludes properties that appear in the preview version of the form while the EditViewType excludes properties that appear in the pop-out version of the Generic Form.

To hide properties in either form mode, an MP author creates a view based on the desired view type in an MP and targets it to the class that contains the properties that should be removed. The configuration supplied to the view specifies the classes for which the properties should not appear and the names of the properties that should not appear. If no target classes are specified, it is assumed that the properties on the target class should be excluded whenever they are displayed (i.e.: for a Generic Form displayed with any class object).

In our console, we use the following view definition to exclude properties of the System.User class in the Generic Preview Form when displaying objects of AD User Groups:

<View ID="UserPreviewExclusionRule" Accessibility="Public" Enabled="true" Target="System!System.User" TypeID="Authoring!PreviewViewType" Visible="true">

        <Category>NotUsed</Category>

        <Configuration>

          <TargetClassList>

            <TargetClass>Microsoft.AD.Group</TargetClass>

          </TargetClassList>

          <PropertyExcludeList>

            <Property>FirstName</Property>

            <Property>Initials</Property>

            <Property>LastName</Property>

            <Property>Company</Property>

            <Property>Department</Property>

            <Property>Office</Property>

            <Property>Title</Property>

            <Property>EmployeeId</Property>

            <Property>StreetAddress</Property>

            <Property>City</Property>

            <Property>State</Property>

            <Property>Zip</Property>

            <Property>Country</Property>

            <Property>BusinessPhone</Property>

            <Property>BusinessPhone2</Property>

            <Property>HomePhone</Property>

            <Property>HomePhone2</Property>

            <Property>Fax</Property>

            <Property>Mobile</Property>

            <Property>Pager</Property>

          </PropertyExcludeList>

        </Configuration>

      </View>

 

We use the view definition below to prevent the ObjectStatus property from appearing on the pop-out Generic Form for Configuration Items. If this view definition were not present, users would be able to change the status of a Configuration Item in the forms that appear for Software, Software Updates, and Printers (we use the Generic Form for those classes).

 <View ID="ConfigItemExclusionRule" Accessibility="Public" Enabled="true" Target="System!System.ConfigItem" TypeID="Authoring!EditViewType" Visible="true">

        <Category>NotUsed</Category>

        <Configuration>

          <PropertyExcludeList>

            <Property>ObjectStatus</Property>

          </PropertyExcludeList>

        </Configuration>

     </View>

Note that, here, the list of TargetClasses is omitted from the view configuration. As a result, the ObjectStatus property will be excluded whenever the pop-out Generic Form appears for a Configuration Item object.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Neil,

    I'm extending the incident class. I have followed your instruction strictly on how to hide the extention tab by adding Category ID, Target and Value as Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideExtensionTab. I can successfully import the management pack into service manager however, the extention tab is still visible. Would you please help what do I need further to hide the extention tab once I have extended a class.

    Thanks

  • Dear Neil Lydick ,

    We are extending the incident class, as a result, the extention tab automatically shows. We try to hide it by following strictly your instruction above by adding a Category tab with ID, Target and Enumeration value. We can successfully import the management pack into service manager. However, the extention tab is not invisible. Do we need to add any further details? Please help to ping us soon.

    Thanks

  • Below are 2 cases that you might be encountering. Let me know if these are not related to your problem.

    - Neil

    ====

    Case 1: Extension tab is not hidden in DCM form (but IS hidden in normal Incident Form) after importing the MP above

    Since the DCM Incident Form is defined in a separate <Form> element, you need to add a Category like

    <Category ID="HideDCMIncidentFormExtensionTab" Target="Incident!System.WorkItem.Incident.DCMConsoleForm" Value="Admin!Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideExtensionTab" />

    to the "hidetest" MP defined in the post above.

    ====

    ====

    Case 2: Extension tab is not hidden on incident form that was customized using the Authoring Tool

    If you've used the Service Manager Authoring Tool to customize the incident form, you'll be importing an MP with a Form element that looks something like this:

    ...

    <Presentation>

       <Forms>

         <Form ID="CustomForm_2cb04bc7_3b76_4bdd_bb59_782a4f26bbae" Accessibility="Public" Target="CustomForm_2cb04bc7_3b76_4bdd_bb59_782a4f26bbae_TypeProjection" BaseForm="Alias_9c4bf671_3297_442d_a802_4cf702c61c38!System.WorkItem.Incident.ConsoleForm" TypeName="Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.IncidentFormControl">

           <Category>Form</Category>

           <Customization>

             <ReorderStackPanel StackPanel="UpperGeneralGrid/Index:10">

               <Element Name="labelAffectedUser" NewIndex="0" />

             </ReorderStackPanel>

           </Customization>

         </Form>

       </Forms>

    </Presentation>

    ...

    Currently, we do not examine the "BaseForm" attribute to see if a Form's BaseForm or any of its parents are targeted by a Category with the HideExtensionTab Enum value. To hide the extension tab on the customized form, you'll need to add a category that targets the customized form directly. This can be done in the customized MP.

    (Example for customized form above):

    <Category ID="CustomFormHideExtensionTabCategory" Target="CustomForm_2cb04bc7_3b76_4bdd_bb59_782a4f26bbae" Value="Admin!Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideExtensionTab"></Category>

    ====

  • Dear Neil Lydick,

    I created Mp with your help, but SCSM do not hidden extensions tab.

    Could you give me your email? I will send you my MP.

    Thanks

  • Dear Neil Lydick,

    I was hidden extension tab.

    Thanks Neil!

  • Dear Neil Lydick,

    I have a class and a category:

    <ClassType ID="Test.EmailEscalation" Accessibility="Public" Abstract="false"

              Base="System!System.Entity" Hosted="false" Singleton="false" Extension="false">

      <Property ID="EmailEscalationId" Type="guid" AutoIncrement="false" Key="true"

              CaseSensitive="false" MaxLength="256" MinLength="0" Required="true" />

      <Property ID="Name" Type="string" AutoIncrement="false" Key="false"

              CaseSensitive="false" MaxLength="256" MinLength="0" Required="true" />

    </ClassType>

    <Category ID="Test.Calendar.HideDetailsPane" Target="Test.Calendar"

    Value="Administration!Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideDetailsPane"/>

    I can successfully import the management pack into service manager however, the detail pane is still visible.

    Thanks.

  • Did you mean to target your category to "Test.Calendar" instead of the "Test.EmailEscalation" class that you supplied in your post?

    Is the details pane hidden for views on "Test.Calendar"?

  • Dear Neil Lydick,

    <ClassType ID="Test.EmailEscalation" Accessibility="Public" Abstract="false"

             Base="System!System.Entity" Hosted="false" Singleton="false" Extension="false">

     <Property ID="EmailEscalationId" Type="guid" AutoIncrement="false" Key="true"

             CaseSensitive="false" MaxLength="256" MinLength="0" Required="true" />

     <Property ID="Name" Type="string" AutoIncrement="false" Key="false"

             CaseSensitive="false" MaxLength="256" MinLength="0" Required="true" />

    </ClassType>

    <Category ID="Test.EmailEscalation.HideDetailsPane" Target="Test.EmailEscalation"

    Value="Administration!Microsoft.EnterpriseManagement.ServiceManager.UI.Administration.Enumeration.HideDetailsPane"/>

    <View ID="View.EmailEscalation.MainView" Accessibility="Public" Enabled="true"

         Target="Test.EmailEscalation" TypeID="Console!GridViewType" Visible="true">

           <Category>NotUsed</Category>

           <Data>

             <Adapters/>

             </Adapters>

             <ItemsSource/>

             <Criteria />

           </Data>

           <Presentation>

             <Columns/>

             <ViewStrings/>

           </Presentation>

    </View>

    I want hidden the details pane when selected item on views "View.EmailEscalation.MainView".

    Thanks!

  • Looking for pointers on below:

    I have a included a custom check box field in the service request ticket. When someone clicks on the close button ( to close the service request) I want to check whether the check box is checked and it is not checked it should pop-up a message to the user.