Thursday, March 14, 2013

Microsoft Dynamics CRM: Oh The Pain - Dialogs

Don't get me wrong. Microsoft Dynamics CRM is an awesome framework. But like any framework, it's a ... framework. If you're given a hammer, everything better be a nail or you're in for trouble.

I'll periodically update this post with whatever I happen to be ranting about at the moment. It's meant to be a cathartic, but not entirely.

The Process/Dialog Editor
I once had a job in the early 90's working for a company that sold bar code printers and developed data collection software. I primarily wrote payroll processing software in C that ran in conjunction with a "user friendly" application. The application was constructed using a 4GL so our clients could make changes.

4GLs R US
A 4GL is supposed to allow humans an easy and friendly way to develop code without writing code. It attempts to solve the same problem COBOL was designed for. How can we let non-geeks develop software solutions to problems without hiring expensive geeks? You usually "programmed" a solution by selecting statement types from a drop down box, and then filling in placeholders with missing values or selecting variables, constants, or operators from other drop down boxes. As long as you could stay within the bounds of the 4GL, it could actually accomplish something.

However, for a computer programmer, working in a table driven 4GL can be frustrating at best and damn near impossible most of the time.

We Cheated
The programmers unfortunate enough to work in it cheated and edited the underlying text file rather than use the 4GL editor. It did nothing about the 4GL limitations, but at least we didn't have to use the crappy editor.

Back to the Future
The MS CRM process/dialog editor makes me feel like I'm reverting back to my earlier experience and I'm not diggin' it. Not at all.

Clicking my way through a gazillion dialog boxes to write a simple expression is painfully slow. Actually, everything is painfully slow.

Substituting variables in a dynamic query is a convoluted painful dead-end process. 
Once you've done it, you cannot edit the dynamic query. The FetchXML is locked in a read-only text box that you cannot edit. All you can do is alter the value parameters or delete it and start over. So close, yet so far away.

The limited logical expression syntax forces excessive statement nesting.
There is no mechanism for re-arranging nested statements. If you need to wrap a condition statement within a condition, you cannot. Don't invest a lot of time and effort within the condition statement blocks because you're going to have to delete them and write click them all over again.

Linking to another dialog is a one way proposition.
Once you leave, the calling dialog is finished. To use a more advanced parlance, think GO TO not GO SUB. Yes, BASIC is more advanced. Sure, you can link to the same dialog. Although this is billed as a recursive dialog, it is not. True recursion would return to the calling dialog and continue execution at the point it was called, not leave and never return.

Option Sets are not query-able. 
Who designs a database system without representing look up values in a table? Hello, every heard of third normal form? You could at least provide a query wrapper around them Now I have to manage a hard coded list in two or more places.

A possible work around?
Or maybe I can add a table that parallels the option set with an automated process to keep them in sync. That didn't work. You cannot use values from a custom entity. You can't substitute an integer or text variable for the value either. At first glance, this makes sense from a referential integrity perspective. There isn't a relationship defined between the custom entity and the field using an option set. However, since the actual option set that does define the valid values for the field cannot be used, and you are forced to define your own "option set", what's the point of preventing this? Referential integrity isn't protected if I have to hard wire up the valid values.

Let's try a custom workflow activity that converts an integer into an option set value. 

It's a convoluted solution, but it worked.

This post by @devkeydet gave me the clue I needed. He wrote a simple workflow activity to convert an integer into a two option type. 


What you need to do is write, compile, and register a custom workflow activity. In the activity, you create a class that takes an int as input and outputs an OptionSetValue.


    public sealed class IntToLeadSourceCode : CodeActivity
    {
        [Input("Integer Value")]
        public InArgument<int> InputValue { get; set; }

        [Output("Option Set Value")]
        [AttributeTarget("lead", "leadsourcecode")]
        public OutArgument<OptionSetValue> OutputValue { get; set; }

        protected override void Execute(CodeActivityContext executionContext)
        {
            var integerValue = InputValue.Get<int>(executionContext);
            OutputValue.Set(executionContext, new OptionSetValue(integerValue));
        }
    }


After you compile and register the assembly in CRM, you can call the activity to convert the integer value from the selected user value from a query which is based on a custom entity that substitutes for the option set (e.g. Lead Source Code).

Now all I have to do is write a workflow activity that executes when changes are made to the custom entity so I can synchronize it with the option set. It should also be easier to maintain the option set this way.

Got it? I'll break it down into the details in a separate blog post.

Is there a way out of this mess?  
What's this? The MS CRM SDK has sample code to create, retrieve, update, and delete a dialog programmatically? Cool! Editing workflow XAML by hand isn't going to be fun, but at least I can use a text editor. If I'm feeling ambitious, I could write a DSL and compiler. Add a little intelli-sense and we'd have something akin to a modern IDE.

A moment of silence please...

According to this, creating and updating a dialog outside of MS CRM is unsupported. I'm not sure what "unsupported" actually means in this case given the sample code from the SDK. Most likely, I'm probably stuck with the "user friendly" GUI editor. Sigh...

Monday, March 4, 2013

Things From My Desk: Here be Tribbles

My wife pretends to understand my obsession with all things Star Trek. Especially, when it comes to the original series. She enjoys the next generation episodes but not TOS. However, she does occasionally supports my TOS addiction.

One of my gifts for Christmas was a pair of Tribbles from Think Geek. I was supposed to receive one tribble, but Think Geek "accidentally" shipped two. When she called them about returning the spare, they said "Merry Christmas" and told her to keep it. Then again, maybe they only shipped one?

They aren't quite as advanced as my tribble design (see my post Nerd Craft: Star Trek Tribble - Initial Plans). But, a tribble in hand is better than two... Actually, counting tribbles is rather pointless unless you are Spock.

If you bump the Think Geek tribble it screams and vibrates, but it does not purr.

Tribble!