Associated views have always been a sore subject in CRM. When CRM 3 was released, they did not include inactive records and, despite the ever present Activate menu item, there was no any way to actually show all associated records not just active ones. People complained. Then rollup 2 changed the behaviour. People complained. Then there was a hotfix for custom entities. People complained that it should be available for system entities as well. CRM 4 is released and hotfix no longer works. People complain.

Plug-ins to the rescue

The good news is that CRM 4 plug-in model is flexible enough to solve this problem once and for all. The idea is to intercept RetrieveMultiple message and modify its query so that all associated records are returned. And the code is surprisingly simple:

using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;

namespace Acme.Plugins
{
    public class AssociatedViewPlugin : IPlugin
    {
        public void Execute(IPluginExecutionContext context)
        {
            if (context.InputParameters.Contains(ParameterName.Query))
            {
                QueryExpression qe = context.InputParameters[ParameterName.Query] as QueryExpression;
                // If it's RetrieveMultiple multiple with two conditions
                if (qe.EntityName == context.PrimaryEntityName
                      && qe.Criteria != null
                      && qe.Criteria.Conditions != null
                      && qe.Criteria.Conditions.Count == 2)
                {
                    // If first condition is a statecode filter for inactive entities
                    ConditionExpression ce = qe.Criteria.Conditions[0] as ConditionExpression;
                    if (ce != null
                        && ce.AttributeName == "statecode"
                        && ce.Operator == ConditionOperator.Equal
                        && ((int)ce.Values[0]) == 0)
                    {
                        // Remove statecode filter
                        qe.Criteria.Conditions.Remove(ce);
                    }
                }
            }
        }
    }
}

Installation

  1. Compile the code and sign the assembly.
  2. Using Plug-in Registration Tool register the plug-in.
  3. Register execution step for the entity that you'd like to show all records in associated views. Note that we use PreStage (a.k.a. BeforeMainOperationOutsideTransaction) and Synchronous execution mode. For example, to always show inactive contacts in associated view:
    image
  4. Optionally add Status column to the associated view for the entity not to confuse users.
  5. Rinse and repeat 3-4 for other entities.

The result for the Contacts associated view inside account entity:

image

At long last Activate menu command makes sense.

Note: this code is a sample only and is included "AS IS" without any warranties whatsoever. In Real Life™ more stringent tests would have to be performed to ensure that RetrieveMultiple message indeed originated from the associated view and was not sent by your poor fellow co-worker complaining (or, worse still, raising support request with Microsoft) about filtering state code not working.

Currently rated 4.1 by 13 people

  • Currently 4.076923/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Synchronous plugins want localhost

Posted on February 22, 2008 16:55 by George Doubinski

Yesterday I was working on some plug-in code which was working fine earlier. I changed pipeline to synchronous and started to get consistent "404 - Not Found" error from calls to CrmService. I reduced the problem to something like this:

public class MyPlugin: IPlugin
{
    public void Execute(IPluginExecutionContext context)
    {
        ICrmService service = context.CreateCrmService(true);
        account a = new account();
        a.name = "test";
        service.Create(a);      // this line fails with 404
    }
}

And it just was not working. We all know about very "informative" SoapException which would have been fine but I was getting simple http-level 404. Something was pointing somewhere it shouldn't have... More...

Currently rated 4.1 by 7 people

  • Currently 4.142857/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Packaging plugins

Posted on February 22, 2008 04:09 by George Doubinski

You spent years polishing your algorithm, moving bytes around, replacing strings with StringBuilders, extracting every last bit of performance from your code. The assembly Acme.CoolTools.dll is into its' 3rd major version, competitors are begging for mercy. Life is good. Then Microsoft CRM 4 comes along with its' beastly architecture wanting plug-ins to be deployed in a database. And offline CRM clients, clutching a copy of Reflector all want your dazzling assembly as well.

Perhaps you simply wanted to avoid GAC, which Chris Sells knew to be evil back in 2004. Or may be you just felt that instead of being sucked into assembly hell you would rather distribute one and only one assembly.

Whatever the real reason might be, today's challenge is to write a Microsoft CRM 4 plug-in that uses classes and methods from other assemblies; then package it all into one blob that can be deployed and distributed as required. In fact, it was the challenge from one of our customers as well as from the newsgroups (speaking of good timing!). More...

Currently rated 4.5 by 6 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5