This topic provides information for a .NET component (ManagedBase) that allows Microsoft Provisioning System (MPS) providers to be authored in C# and VB.NET. This component serves as an isolation and interoperation layer between the Microsoft Provisioning Framework (MPF) Engine and .NET-based MPS providers.
This is the general constructor for the provider. This constructor initializes the various member variables and loads the hash tables with the proper method signatures allowing for method dispatching when the provisioning engine calls the provider, including:
Provider Method Attributes
The provider base class utilizes a combination of custom class and method attributes in order to emit MPF provider namespace data as well as proper dispatching of methods in response to MPF method calls. This section describes some of these attributes and their use within the provider base.
This custom attribute class is used to decorate types within the .NET assembly that represent individual providers. There can one or more types in the assembly so decorated. The constructor requires two input parameters, one representing the name of the provider namespace as it will be referenced by MPF and the second being a description of the namespace (the latter can be an empty string, however best practices dictate that a reasonably descriptive value be provided). An optional property named ReadOnly is provided to complete the schema support for namespaces; however, this value defaults to false and is not expected to be used.
The following is a sample of a class that has been decorated as a provider:
This custom attribute class is similar to the class with the same name implemented in the original ManagedBase assembly with a few important changes.
The first (and possibly most significant) difference in the current implementation is that only process (execute) methods should be decorated whereas the previous implementation required every method exposed to MPF to be decorated. Any decorated method is assumed to be a process method and decorating methods of other types will cause the provider to fail.
The recommended naming convention for provider methods has been updated in this edition of the managed base. Each method exposed should be in the form of
For example, a method referenced in MPF as Get Current Time should have a C# method name collection similar to the following:
This sample uses the suffix of "Process" for what has commonly been referred to as the "execute" method, whereas previous versions utilized "Execute". The justification of this change was to make the terminology consistent with that of the MPF documentation and references. Also, not every method must implement all four of the method signatures listed above - the implementation requirements differ based on the method type; see following:
While not recommended, there may be valid scenarios in which deviation from the naming convention recommended above. Support for deviation from the standard naming conventions is provided by means of additional properties that can be set on the ProviderMethodAttribute class. These properties are rollbackMethod, prepareMethod, and commitMethod. The application of each should be self explanatory and the value should be set to the string representation of the method name that should be called for the associated action. An example of a method decorated using one of these properties is illustrated below:
The ProviderMethodAttribute constructor requires the name of the method as it is to be exposed to MPF and the method type (Read/Write/TwoPhase). A collection of additional properties such as AuditEnabled, PerformanceEnabled, etc. can also be set. For more information on the collection of properties available please see the object browser. For information on the meaning of each of these properties, see MPS SDK ReferenceA sample method and decoration using the minimum properties is illustrated below:
You should not decorate methods other than the process method.
Exception Handling Best Practices
Throwing an exception within a provider automatically triggers rollback. Further, this allows the developer to return fragments of data that might help the consumer of the error to know what caused the error, what the data looked like at that point in time, and other types of data. Like anything else, features that are often viewed as good can be poorly implemented with the end result being seemingly worse than had the exception never been thrown. This problem has been exemplified in some of the existing providers that return "Unknown Error" or other such exceptions without providing any context to the caller to allow them to derive the actual cause of the error.
The driving goal of each provider author should be to evaluate each line of code such that if it can throw an error, that error should be caught, and then re-thrown with additional information providing the caller with everything the caller needs to adequately ascertain exactly what happened, at which point in the process it happened, what the state of data was at that point, and any additional information. It is imperative that provider authors return detailed and accurate exceptions. To assist in this effort, the following "rules" have been established and will be used as guidelines during code reviews.
One of the desires of the architecture team is to provide consistent guidance with respect to what exceptions are thrown for various actions. It is fully expected that each provider will throw exceptions unique to that provider based on operations unique to the service or platform being provisioned. Excluding those unique scenarios, there are a number of operations that are common to all providers such as retrieving values (argument out of range, argument null, etc.). The goal of this section is to explain some of the common exceptions that should be thrown by provider authors during validation steps.