Extend EmpowerID Components

Extend EmpowerID Components

Organizations needing to store and maintain attributes not defined for a given object in the object tables of the EmpowerID Identity Warehouse, can extend those objects as needed by overriding the class definition or schema for those objects with each new attribute. Doing so is preferable to using extension attributes in that extending an object's class definition makes any custom attributes you add to that definition available to your workflows and user interfaces as actual component properties that can be edited and updated in the same way as the stock component properties.

 

Overriding the class definition for EmpowerID components involves creating a class library project that contains an edited version of a file called GeneratedComponents.cs for the each component you wish to customize. This file contains references pointing to the default WCF data contracts for each EmpowerID component. Because this file changes frequently, you must contact EmpowerID for the correct version for this file before you can customize objects. This ensures that you have the latest version of the file for your build.

 

In this topic, we demonstrate how to add a custom attribute to an EmpowerID component by adding an attribute named "Clearance Level" to the Person component. Doing so involves the following:

  • Adding custom attributes to objects by extending EmpowerID component definitions

  • Extending the EditPersonMultiOperations Operation Activity to allow delegated users the ability to edit the new attribute

  • Adding the custom attribute to the PersonEditFullForm form so that delegated users editing a person can make changes to the attribute

  • Creating a Localized Text Key for the attribute

  • Overriding the appropriate Web application pages to allow the new attribute to appear in the Web UI

 

Adding custom attributes to EmpowerID Components

 

In this example, we create a class library project named EIDComponents with a custom definition for the Person component that when published to the GAC places a record in the GACReferenceLibrary table of the EmpowerID Identity Warehouse. This tells EmpowerID to ignore the stock EIDComponents.dll that ships with EmpowerID and look instead at this assembly for the attributes available for each EmpowerID component. This project contains four classes, the EIDComponents class, which contains a customized version of the GeneratedComponents.cs file you received from EmpowerID, the AccountStoreIdentityEntry class, and the Person and PersonView classes, which is where we will add code to define the custom attributes.

To add the custom attribute to the Person component, we will do the following:

  • Create a class library named EIDComponents, adding the contents of the GeneratedComponents.cs file to it

  • Add a Person class to the class library that defines the custom attribute

  • Add a PersonView class to the class library that defines the custom attribute

  • Publish and compile the class library to make the new custom attribute available to EmpowerID

When creating the custom attributes for the Person and PersonView classes, we write code to inherit those classes from the base PersonCore and PersonViewCore objects, respectively. This makes all the properties and methods of the default Person and PersonView objects available to our customized components. Additionally, we implement the CustomizedComponentHelper.ICustomizedComponent interface while declaring those objects. This interface requires us to add a public property named CustomData of type CustomizedComponentHelper.ICustomizedComponent, which is a helper variable used for storing custom information. We then write code to get and set the value for one primitive property, ClearanceLevel . Additionally, we decorate the classes with the [CreateRbacProperty], [System.Runtime.Serialization.IgnoreDataMemberAttribute], and the [TheDotNetFactory.Framework.People.Components.Serialization.CustomSerializationAttribute] decorators. These decorators instruct EmpowerID to make any decorated properties (primitives only) available to forms, lookups, reports and Web pages once the class library project is compiled and published to the Identity Warehouse.

Create a new EIDComponents class library

  1. In Workflow Studio, start a new class library project by clicking the Workflow Studio application icon and selecting Extensibility > EmpowerID Class Library from the context menu.




  2. In the Add New Class Library dialog that appears, type EIDComponents in the Name field, select a Package from the Package drop-down and click OK.




    Workflow Studio creates the class library in the specified Package and opens the object in the C# Editor.



  3. From the C# Editor, delete all of the generated code for the EIDComponents class.

  4. Locate the GeneratedComponents.cs file sent to you by EmpowerID and copy and paste the contents of the file into the C# Editor for the EIDComponents class.

  5. Reorder the using and namespace statements so that the using statements are contained within the namespace statement.

    namespace TheDotNetFactory.Framework.People.Components { using System; using System.Collections.Generic; using System.Linq; using System.Text; [Serializable][global::System.Runtime.Serialization.DataContractAttribute (Namespace = "http://empowerid.sts.com/svc/2010/03/schemas")] public class MultivalueAttribute : TheDotNetFactory.Framework.People.Components.Core.MultivalueAttributeCore { } [Serializable][global::System.Runtime.Serialization.DataContractAttribute (Namespace = "http://empowerid.sts.com/svc/2010/03/schemas")] public class ResourceGroup : TheDotNetFactory.Framework.People.Components.Core.ResourceGroupCore { } [Serializable][global::System.Runtime.Serialization.DataContractAttribute (Namespace = "http://empowerid.sts.com/svc/2010/03/schemas")] public class CommunicationZone : TheDotNetFactory.Framework.People.Components.Core.CommunicationZoneCore { } ... }



  6. In the C# Editor locate the line of code for the class you wish to extend and comment it out. In our case, we are extending the Person object, so we have commented out the lines specifying the attributes for the default Person and PersonView classes.



  7. Save your changes.

  8. Add a new class to the class library by right-clicking the Classes folder in the Code Tree to the right of the C# Editor and selecting Add Visual C# Source Item > Add Class Source from the context menu.




  9. In the Add New Class dialog that appears type OtherComponents in the Name field and then click OK to close the dialog.



    Workflow Studio creates the class and opens it in the C# Editor.



  10. From the C# Editor, delete all of the generated code for the OtherComponents class.

  11. Locate the OtherComponents.cs file sent to you by EmpowerID and copy and paste the contents of the file into the C# Editor for the OtherComponents class.

  12. Reorder the using and namespace statements so that the using statements are contained within the namespace statement, as shown by the below image.




  13. Save your changes.

Add a new Person class to the EIDComponents class library

  1. Add a new class to the class library by right-clicking the Classes folder in the Code Tree to the right of the C# Editor and selecting Add Visual C# Source Item > Add Class Source from the context menu.




  2. In the Add New Class dialog that appears type Person in the Name field and then click OK to close the dialog. The name of the class must match the name of the component you are extending.




    Workflow Studio creates the class and opens it in the C# Editor.



  3. In the C# Editor for the Person class, change the namespace from TheDotNetFactory.Framework.ClassLibrary to TheDotNetFactory.Framework.People.Components.




  4. From the Code Tree, expand the Classes node and then double-click the EIDComponents.cs file to open the class in the C# Editor.




  5. From the C# Editor for the EIDComponents class, locate and copy the Serializable portion of the Data Contract for the Person component you commented out previously.




  6. From the Classes node of the Code Tree, open the Person.cs class file and then paste the line of code you just copied into the C# Editor, placing it just above the class statement.




  7. Add code to inherit the Person class from the base PersonCore object, as well as the CustomizedComponentHelper.ICustomisedComponent interface.

    [Serializable][global::System.Runtime.Serialization.DataContractAttribute(Namespace = "http://empowerid.sts.com/svc/2010/03/schemas")] public class Person : TheDotNetFactory.Framework.People.Components.Core.PersonCore, CustomizedComponentHelper.ICustomizedComponent { }
  8. In the C# Editor, add code to the Person class to do the following:

    1. Decorate the class with the [System.Runtime.Serialization.IgnoreDataMemberAttribute] decorator.

    2. Implement the CustomData property of type CustomizedComponentHelper.ConfigurationXmlWrapper

    3. Create a property for the custom attribute, decorating it with the [CreateRbacProperty], [DataMember]  and [TheDotNetFactory.Framework.Components.Serialization.customPropertySerializationAttribute] decorators and using the GetExtendedAttribute() method of the CustomizedComponentHelper class to get and set its value. When getting the value of the attribute, you pass in parameters for the customized component, the name of the custom attribute, and a boolean for xml serialization. When setting the value of the property, you pass in the same parameters with the addition of value.

        The following shows what the code for the above looks like:

      [Serializable][global::System.Runtime.Serialization.DataContractAttribute(Namespace = "http://empowerid.sts.com/svc/2010/03/schemas")] public class Person : TheDotNetFactory.Framework.People.Components.Core.PersonCore, CustomizedComponentHelper.ICustomizedComponent { [System.Runtime.Serialization.IgnoreDataMemberAttribute] public CustomizedComponentHelper.ConfigurationXmlWrapper CustomData {get; set;} [CreateRbacProperty] [DataMember] [TheDotNetFactory.Framework.People.Components.Serialization.CustomPropertySerializationAttribute] public string ClearanceLevel { get { return CustomizedComponentHelper.GetExtendedAttribValue<string>(this, "Person", "ClearanceLevel", true); } set { CustomizedComponentHelper.SetExtendedAttribValue<string>(this, "Person", "ClearanceLevel", value, true); } }
  9. Save your changes.

    When completed, the code for the Person class should look similar to the following code.

    namespace TheDotNetFactory.Framework.People.Components { usings [Serializable][global::System.Runtime.Serialization.DataContractAttribute(Namespace = "http://empowerid.sts.com/svc/2010/03/schemas")] public class Person : TheDotNetFactory.Framework.People.Components.Core.PersonCore, CustomizedComponentHelper.ICustomizedComponent { [System.Runtime.Serialization.IgnoreDataMemberAttribute] public CustomizedComponentHelper.ConfigurationXmlWrapper CustomData {get; set;} [CreateRbacProperty] [DataMember] [TheDotNetFactory.Framework.People.Components.Serialization.CustomPropertySerializationAttribute] public string ClearanceLevel { get { return CustomizedComponentHelper.GetExtendedAttribValue<string>(this, "Person", "ClearanceLevel", true); } set { CustomizedComponentHelper.SetExtendedAttribValue<string>(this, "Person", "ClearanceLevel", value, true); } } } }

Add a new PersonView Class to the class library

  1. Add a new class for the PersonView component to the class library by right-clicking the Classes folder in the Code Tree to the right of the C# Editor and selecting Add Visual C# Source Item > Add Class Source from the context menu.




  2. In the Add New Class dialog that appears type PersonView in the Name field and then click OK to close the dialog. The name of the class must match the name of the component you are extending.



    Workflow Studio creates the class and opens it in the C# Editor.



  3. In the C# Editor for the PersonView class, change the namespace from TheDotNetFactory.Framework.ClassLibrary to TheDotNetFactory.Framework.People.Components.




  4. From the Code Tree, under the Classes node, double-click the EIDComponents.cs file to open the class in the C# Editor.

  5. From the C# Editor for the EIDComponents class, locate and copy the Serializable portion of the Data Contract for the PersonView component you commented out previously.




  6. From the Classes node of the Code Tree, open the PersonView.cs class file and then paste the line of code you just copied into the C# Editor, placing it just above the class statement.




  7. Add code to inherit the PersonView class from the base PersonViewCore object, as well as the CustomizedComponentHelper.ICustomisedComponent interface.

    [Serializable][global::System.Runtime.Serialization.DataContractAttribute(Namespace = "http://empowerid.sts.com/svc/2010/03/schemas")] public class PersonView : TheDotNetFactory.Framework.People.Components.Core.PersonViewCore, CustomizedComponentHelper.ICustomizedComponent { }



  8. In the C# Editor, add code to the PersonView class to do the following:

    1. Decorate the class with the [System.Runtime.Serialization.IgnoreDataMemberAttribute] decorator.

    2. Implement the CustomData property of type CustomizedComponentHelper.ConfigurationXmlWrapper.

    3. Create a property for the custom attribute, decorating it with the [CreateRbacProperty], [DataMember]  and [TheDotNetFactory.Framework.Components.Serialization.customPropertySerializationAttribute] decorators and using the GetExtendedAttribute() method of the CustomizedComponentHelper class to get and set its value. When getting the value of the attribute, you pass in parameters for the customized component, the name of the custom attribute, and a boolean for xml serialization. When setting the value of the property, you pass in the same parameters with the addition of value.

      The following shows what the code for the PersonView class should look like when you have completed the above steps.

      [Serializable][global::System.Runtime.Serialization.DataContractAttribute(Namespace = "http://empowerid.sts.com/svc/2010/03/schemas")] public class Person : TheDotNetFactory.Framework.People.Components.Core.PersonCore, CustomizedComponentHelper.ICustomizedComponent { [System.Runtime.Serialization.IgnoreDataMemberAttribute] public CustomizedComponentHelper.ConfigurationXmlWrapper CustomData {get; set;} [CreateRbacProperty] [DataMember] [TheDotNetFactory.Framework.People.Components.Serialization.CustomPropertySerializationAttribute] public string ClearanceLevel { get { return CustomizedComponentHelper.GetExtendedAttribValue<string>(this, "Person", "ClearanceLevel", true); } set { CustomizedComponentHelper.SetExtendedAttribValue<string>(this, "Person", "ClearanceLevel", value, true); } } }
  9. Save your changes.

The next step is to add an assembly for the new EIDComponents class library to the GAC. This is accomplished by compiling and publishing the class library. We demonstrate this below.

Compile and publish the EIDComponents class library

  1. From the toolbar located just above the C# Editor, click the Compile button. Compiling the class library allows you to see if there are any code errors in the class library before attempting to publish it.




    After the compilation completes, you should see an Operations Log appear with a status of Succeeded. If the compilation failed, locate and fix the errors as specified in the log and then recompile the class library.



  2. Click Close to close the Operations Log.

  3. Next, publish the class library by clicking the Compile and Publish button located just above the C# Editor.




  4. From the Class Library Publishing wizard that appears, click Next.




  5. Select an EmpowerID server as the publishing location and then click Next.




  6. Click Yes when prompted to restart the services.

  7. In the Active Services dialog that appears, select the services to be restarted and then click Restart.

Update existing RBAC object data

  1. Navigate to the EmpowerID > Programs folder on your EmpowerID server and locate the RbacObjectDatabaseUtility.exe file.




  2. From the the Programs folder, double-click the executable and in the command prompt that appears, then type ALL (all caps) and then press ENTER.




  3. Wait for the utility to complete updating the RBAC object data and then restart the EmpowerID services and reset IIS.

  4. Close and restart Workflow Studio.

 

Now that the RBAC object data is updated, the new attribute can be used in existing workflows, activities and forms. We demonstrate this next by adding code to the Edit Person Multi Operations operation to allow delegated users the ability to edit the custom attribute.

 

Adding code to extend the EditPersonMultiOperations Operation Activity

  1. From the Workflow Studio Solution Explorer, search for the EditPersonMultiOperations Operation activity.




  2. Double-click the activity to open it in the Workflow Studio Activity Designer.

  3. From the Workflow Designer, right-click on the Operation activity and select Edit Operation Executor > Edit Edit Person Organization Attributes Executor from the context menu.




  4. In the C# Editor for the EditPersonOrganizationAttributes operation that opens, add code to the ExecuteOperation() method to set the ClearanceLevel property for each person being edited to the value entered in the Clearance Level field of the workflow form.

    person.ClearanceLevel = CurrentWorkflow.Form_TargetPerson.ClearanceLevel;


    The below image shows what the above code looks like in the C# Editor.




  5. From the Workflow Designer, right-click on the Operation activity again and select Operation Event Handlers > Edit GetEnabledOperations from the context menu.




  6. In the C# Editor for the GetEnabledOperations() method that opens, navigate to the case statement for "Edit Person Organization Attributes" and add the following code to the end of the case's if statement to enable the change entered in the form field to be persisted to the database.

    || Form_TargetPerson.IsPropertyChanged(E.PersonColumn.ConfigurationXml)


    The following image shows what the above code looks like in the C# Editor.




  7. Save your changes.

  8. From the toolbar located just above the Activity Designer, click the Compile button. Compiling the activity allows you to see if there are any code errors in the activity before attempting to publish it.




    After the compilation completes, you should see an Operations Log appear with a status of Succeeded. If the compilation failed, locate and fix the errors as specified in the log and then recompile the operation.



  9. Click Close to close the Operations Log.

  10. Next, publish the activity by clicking the Compile and Publish button located just above the Activity Designer.




  11. From the Publish Workflow wizard that appears, click Next.




  12. Select the host EmpowerID server and click Next.

  13. Click Yes when prompted to replace the activity.

  14. Click Yes when prompted to restart the services.

  15. In the Active Services dialog that appears, select the services to be restarted and then click Restart.




  16. Click No when prompted to restart Workflow Studio.



Next, add the custom attribute to any applicable workflow forms so that it shows as a form field to delegated users running connected workflows. In our case, we are going to add the attribute to the PersonEditFullForm form. This form appears when editing people.

 

Adding the Custom attribute to the form

  1. From the Workflow Studio Solution Explorer, search for the PersonEditFullForm form.




  2. Double-click the form to open it in the Workflow Studio Form Designer.

  3. From the Components tree of the Form Designer, expand the Resource node and locate the ClearanceLevel attribute you created earlier.




  4. From the Form Designer, click the Organization tab and then drag the ClearanceLevel attribute from the Components tree onto the design surface of the form. To drag the attribute onto the form, click it to select it and hold the left mouse button down while placing the attribute onto the form.