DocumentHandlerParameter Best Practices
When you create a custom DocumentHandler, it is very likely that you may need to supply it with some configuration data. Common examples include the address of your back-end server, credentials to the back-end system, etc.
DocumentHandlers can be configured by adding public read/write string properties and decorating them with the DocumentHandlerParameter attribute. This is all described in the documentation, but in this post, I'd like to expand a bit on the subject to describe some best practices for dealing with such parameters.
If all you need is a string, you can get by with an implementation as simple as this:
[DocumentHandlerParameter("Description template")]
public string DescriptionTemplate { get; set; }
However, if you really need something else, you will have to parse the text yourself, since only strings are supported. Imagine that you really need to expose an integer property. Basically, you have two options:
- You can parse it as the value is being assigned
- You can parse it when you need it
Parsing the value right away is the preferable alternative, since this gives Mobile Server a chance to verify the configuration as soon as the operator saves the document type (right now, Mobile Server doesn't do that, but it might do that in a future version, in which case you'll get validation for free). It also makes for cleaner code.
Here's one possible implementation of an integer property:
[DocumentHandlerParameter("My integer")]
public string MyInteger
{
get { return this.myInt.ToString(); }
set
{
int i;
if (int.TryParse(value, out i))
{
this.myInt = i;
return;
}
throw new ArgumentException(
"Value was not an integer", "value");
}
}
where myInt is a private member variable. Notice how the setter attempts to parse the string to an integer, and throws a descriptive exception if this is not possible.
Whenever the value of this property is required, the rest of the code can simply reference this.myInt, which is now guaranteed to be correct. Int32 is a value type, so referencing this.myInt will always be correct, since the default is 0.
This is not the case for reference type properties like the DescriptionTemplate property above. Keep in mind that reference types may be null, so that it becomes necessary to check for this before using the property:
public override DocumentResponse Submit(string xmlDocument,
Guid messageId, string deviceId, IPrincipal mobileUser)
{
string template =
string.IsNullOrEmpty(this.DescriptionTemplate) ?
"Message {0} was successfully submitted" :
this.DescriptionTemplate;
DocumentResponse dr = new DocumentResponse();
dr.Description = string.Format(template, messageId);
return dr;
}
In this implementation of the Submit method, I test the DescriptionTemplate property's value before using it, defaulting to a hard-coded value if it's not defined. It is important to realize that Mobile Server makes no guarantee regarding the values of DocumentHandlerProperties, since it is entirely up to the operator whether he or she cares to fill in the values or not, so either have some good default values or throw an exception with a descriptive error message.
As the above example illustrates, you can reference DocumentHandlerProperties from within the Submit method. This is the main scenario, but Mobile Server will also fill in the values of these properties when invoking the GetDocumentDescription method.
As a contrast to the Submit and GetDocumentDescription methods, the FriendlyName property of DocumentHandler is only being used in the UI when the operator selects a DocumentHandler to configure; that is, before the properties are being configured. For that reason, when the code inside the FriendlyName property executes, the property values will always have their default values.
In short:
- Validate parameter values in their setters and fail fast.
- Don't assume values have been set.
- Consume values from Submit and GetDocumentDescription only. You cannot consume the values from within the FriendlyName property's code.
Comments
- Anonymous
January 12, 2009
In my previous post , I described how to unit test custom DocumentHandlers. When your DocumentHandler