When creating a plugin you have to try and cater for any possible issues that may occur. You want to handle these issues in a way that is acceptable to the browsing client. As there are many things which can go wrong, there are also many things we can do to handle errors. One way is to simply check our collection of attributes actually contains the attribute we are trying to access!
If we try and access a property directly, and it doesn’t exist our plugin will crash with an index out of bounds exception. If you are not handling exceptions then the browsing client will see this error. NOT GOOD!
At the point of developing you many think you don’t need a contains check because
- The attribute will always exist
- Leaving out the check will increase efficiency
- Leaving out the check reduce complexity.
However, you cannot predict the future changes that may occur on the entity that your plugin is dependant on. A future change may mean your attribute doesn’t always exist in the collection!
So the golden rule is make sure the property exists before accessing it.
I have seen a lot of different ways of doing this depending on the circumstances, eg within a plugin, workflow assembly, Silverlight application, web services etc… I have seen Contains, ContainsKey on the Entity, or on the Attribute list. I have even seen contains checks which lead to type checks, which lead to value checks. The latter being a bit over kill if you ask me but it does guarantee that the object is exactly what you expect before you start to interact with it. If it isn’t what you expect then you can avoid all the functionality that uses the property, even if its the whole plugin!
Until recently a personal favourite of mine was the use of an inline if statement. The statement means my result always exists to use further down the line.
var name = entity.Contains("name") ? (string)entity["name"] : string.Empty;
Recently I have been favouring the following which returns a nulled value if it cannot be found.
var name = entity.GetAttributeValue<String>("name");
I think the code looks a lot tidier, and if the type is not nullable I can simply make it nullable within the template type.
var allowemail = entity.GetAttributeValue<bool?>("allowmail");
Lets not forget later on in the code before we perform our functionality around the property we need to check for not null as GetAttributeValue returns null if the property cannot be found. We don’t want to swap Index out of bounds for an object not set to an instance of an object error!