You can discover all sorts of useful capabilities if you dive your nose deep enough into the Dynamics 365 Online / Common Data Service SDK. And, given that these products are evolving continually within the cloud, new features are being introduced all the time. With this in mind, it’s perhaps natural to expect that even the so-called “experts” of these platforms may sometimes overlook new or seemingly obvious changes…😅  I’m unsure which of these categories the focus of today’s blog post fits into it but, given that Microsoft has not documented its capabilities very well, I thought I’d take some time to explore it further.

We’ve seen previously on the blog how to use the GetAttributeValue method, as being the “nice” way of accessing the various attributes you may need to work with as part of your C# code targeting Dynamics 365 / the Common Data Service. I won’t repeat too much old ground here but, suffice to say, I would highly recommend you always use this method as much as possible. As much as I like it though, one issue it does have is that you must always know the underlying data type that you are attempting to process. If, for example, you’re working with a defined list of attributes, but without their corresponding types declared, this method becomes pretty useless. Consider the following code snippet:

List<string> myAttributes = new List<string>();
myAttributes.Add("name");
myAttributes.Add("description");
myAttributes.Add("industrycode");

Entity e = Service.Retrieve("account", new Guid("9e03afdc-5d37-e911-a97c-0022480749f0"), new ColumnSet(true));
    
foreach(string a in myAttributes)
{
    string aVal = e.GetAttributeValue<string>(a);
    tracer.Trace(aVal);
}

This code works fine and dandy up until it hits the industrycode value in the myAttributes list, as this is the name of an Option Set, not a Single Line of Text (i.e. string) field. If a user has not populated this field with a value, then the code will silently skip over this and return a null value, but if it isn’t, you will get an error thrown with the following message:

An error has occurred: Unable to cast object of type ‘Microsoft.Xrm.Sdk.OptionSetValue’ to type ‘System.String’.

In this situation, therefore, it becomes desirable to test our incoming attributes to confirm they are of the correct type before we try to access their values.

Enter stage left the TryGetAttribute method. You can probably make a reasonable guess as to what this is doing from its name alone; namely, that it allows us to attempt to obtain an attribute’s value into our desired type, without necessarily throwing a nasty error if we screw up at all. What’s more, we can use the method to still obtain our attribute value, in much the same way as GetAttributeValue does, provided we have made the correct assumption regarding its underlying type. The method requires us to declare an object that will potentially store our attribute value when we call it. Apart from this main difference, it works pretty much as we’d hope it to – as the tweaked example below demonstrates:

List<string> myAttributes = new List<string>();
myAttributes.Add("name");
myAttributes.Add("description");
myAttributes.Add("industrycode");

Entity e = Service.Retrieve("account", new Guid("9e03afdc-5d37-e911-a97c-0022480749f0"), new ColumnSet(true));
    
foreach(string a in myAttributes)
{
    string strVal;
    OptionSetValue osVal;    
        
    bool tryStr = e.TryGetAttributeValue<string>(a, out strVal);
    bool tryOS  = e.TryGetAttributeValue<OptionSetValue>(a, out osVal);
        
    if (tryStr)
        tracer.Trace(strVal);
    if (tryOS)
        tracer.Trace(osVal.Value.ToString());      
}

As we can see, all we need to do is declare a Boolean type, through which our code stores the results of the TryGetAttributeValue method. Using this, we can then determine whether to output the value strVal or osVal to our trace log, which will store value obtained by TryGetAttributeValue, provided that this did not result in false when called. If needed, we can extend the solution out to support all possible data types within Dynamics 365 / Common Data Service and, in the process, not worry about implementing a solution to figure out the correct data types or make subsequent API calls to determine this information. In short, the TryGetAttributeValue method provides a flexible and easy means of working with many different types of attributes simultaneously, that may be subject to change at runtime or difficult to infer easily. What’s more, the method shares the same benefit as GetAttributeValue by defaulting to a null value if the attribute, or its underlying value, does not exist, avoiding any needless errors from cropping up in your code.

I guess you could say I derive a weird sense of pleasure whenever I discover a cool new feature as part of Dynamics 365/ the Common Data Service and, as you might have guessed, TryGetAttributeValue very much fits into this category. I’m unsure when Microsoft added this method to the SDK or, indeed, if it’s something that I have naively overlooked for many years now. Regardless, I would urge you to consider using it within your code if the right circumstances arise, and I hope this blog post has been useful in showing you how to use it in practice. 🙂

Share This