In this post we’ll discuss the new Prototype Public Resource Management client. I uploaded the MSDN-style documentation to MSDN Code Gallery. The purpose of this post is to walk you through the direction I’m thinking about for a supported API. These ideas are a snapshot of my thinking today and will change in the future. I welcome feedback about both the high-level approach and specific granular details. There may be scenarios or features overlooked which should be incorporated into an eventual supported client.
Changes from previous prototype
Changes since the last version of the public prototype:
- This client is called “rmclient” to clearly differentiate it from the previous one.
- The source code is not yet available.
- Since the previous source code was meant only as documentation and never would become production code, there were few restrictions on publishing it.
- Elements of this prototype may become production code. As a result, we are not yet sure what pieces we may release at this time.
- We expect to have either a compiled binary, source code, or supported alternative ready for the RC1 release.
- The client and object model are decoupled.
- The client is layered on top of WCF.
- The client uses MEX for metadata.
- The original client was never intended to be copied into complex environments. As a result, many of you discovered the silent requirement to have the xsd file present for the previous public client to work.
- We have a factory method that instantiates strongly-typed objects. It is now possible to use casting to check whether an object is a Person or Group.
- There is a “DefaultClient” which provides basic functionality that I’ve seen in POCs. This DefaultClient isn’t the only client, however, unlike the previous prototype.
- There is a pattern of “Promoted Properties” which enable developers to use Intellisense for discovering FIM object schema.
The basic architecture of the client has 3 layers: Default Client, WS-* clients, and WCF ClientBase. All three layers are publically accessible with the intention that your code can call the layer which is most appropriate. For most customers, the DefaultClient will be sufficient since it enables basic CRUD and Enumeration operations at a high level. The diagram below summarizes these three layers, with DefaultClient depending on the WS-* clients underneath it, and those clients depending on WCF ClientBase.
All of these classes are in the Microsoft.ResourceManagement.Client namespace. The DefaultClient is expected to be the client you use for 80% of scenarios. We intend it to be a low barrier to entry and sufficiently abstracted from the actual SOAP messages. Customers who need to modify the specific SOAP messages will need to use one of the WS-* clients. Customers who need to modify the WCF channel will have to use their own WCF ClientBase. Those three options should encompass 99% of all scenarios our customers want:
- DefaultClient for easy, straight-forward use
- WS-* clients for power users needing advanced control
- WCF ClientBase for extreme special cases
The object model is completely decoupled from the client into the Microsoft.ResourceManagement.ObjectModel namespace. There are two key points I would like to make.
First, there is a base class called RmResource which is a Dictionary. You can always use a key to index any attribute out of RmResource using the Dictionary interface. RmResource also exposes public properties for some well-known attributes like ObjectId and ObjectType so that developers can use Intellisense and pass those properties as arguments to methods.
We created derived classes RmPerson and RmGroup. These classes get the common public properties like ObjectId from the parent class, but they also expose additional attributes specific for their types. For example, RmPerson exposes FirstName and EmployeeId. RmGroup exposes ComputedMember and ExplicitMember. We intend to have a class for each object type in FIM and that each object type has all of the necessary promoted properties.
Since all of these objects are public, customers can create their own derived classes for custom object types in FIM. For example, Contoso may create a Contact object with an Email address. Contoso simply needs to create a new class that derives from RmResource and create a public property for Email. The class diagram below summarizes the relationships and intended inheritance:
Second, RmResource just stores data. To commit changes back to the web service, we’re musing with the idea of requiring transactions. The reason is our web service is designed to accept “differences” to objects rather than entire representations. We are considering calculating these differences with a transaction object rather than inside the RmResource object itself. At first glance it feels more clean to separate data and operations about the data. We’ll show how these transactions work in the upcoming examples, and we hope that you agree they are a natural way to program against the FIM web service.
I hope this was a useful introduction for our direction of the new prototype. Please contact me with feedback about this direction.