Tuesday, 31 May 2011

'Xrm.Page.ui' is null or not an object

It may be more of a silly mistake on my side, but I ran into an interesting problem today that took me a while to resolve. Since I cannot find any information on this anywhere on the web, I thought I may as well write a blog entry on it.

While trying to access the "Xrm.Page.ui" object, I kept on getting an error saying:
'Xrm.Page.ui' is null or not an object.
Turns out that somewhere along the line, I did not have my code inside my JScript Resource file wrapped in a method, and I did not actually call this method on load of the form.

So I simply had:

alert(Xrm.Page.ui.getFormType());

Instead of:
function myFunction()
{
alert(Xrm.Page.ui.getFormType());
}

where the above function is then called on load of the entity.

This lead to a few interesting observations:
  1. It is possible to execute code BEFORE onLoad, by simply not wrapping the code in the Web Resource in a function. Even though this is true, I'd say it is probably very bad practice to "forget" to wrap it in a function/
  2. When JScript is not wrapped in a function, it not only executes BEFORE onLoad, it executes before any Crm objects are initialized. So the developer does not have access to any CRM SDK objects at this point.
  3. I should STOP making noob mistakes ;)

Paul Reyneke

Wednesday, 16 March 2011

ObjectTypeCode - String or Int

I came across a handy little feature today. I have tested this and it works in Crm 4.0 as well as Crm 2011. Funny how I never knew this before. It would not have changed the world, but it would have made the odd task a little easier.

It seems that it is possible to use the object type codes (1,2 etc) interchangeably as integers or strings ("account", "contact") in a QueryExpression (and everywhere else, I guess). Since the Object Type Codes are always stored as integers in the database, I assumed that they will always need to be queried as integers.

For example, if you want all the tasks that has an Account as a Regarding Object you'd need to know what the Object Type Code for Account is. Now anyone that has dabbled in Crm for a while will know that Account = 1 and Contact = 2, but all custom entities start at 10,000 and exporting customizations from one Organization to another does not mean that the custom entity would have the same code. So, in the example above, I would have done something like this, because I knew that the code of 1 will always represent an Account:

QueryExpression query = new QueryExpression()
{
EntityName = "task",
ColumnSet = new AllColumns(),
Criteria =
{
Conditions =
{
new ConditionExpression()
{
AttributeName = "regardingobjecttypecode",
Operator = ConditionOperator.Equal,
Values = new object[] {1}
}
}
}
};

But for custom entities I would have had to find the current code for the entity first and pass that through to the QueryExpression.

Turns out that you can actually pass the string equivalent as a value as well !!!

QueryExpression query = new QueryExpression()
{
EntityName = "task",
ColumnSet = new AllColumns(),
Criteria =
{
Conditions =
{
new ConditionExpression()
{
AttributeName = "regardingobjecttypecode",
Operator = ConditionOperator.Equal,
Values = new object[] {"account"}
}
}
}
};

Brilliant!!

Paul Reyneke

Sunday, 13 March 2011

Transactional features in Crm 2011

One of the very handy features in Crm 2011 is the fact that plugins now execute within the transaction, not outside it anymore. This means that if an error occurs within a plugin that fires on Create of a record, the actions done by the code gets rolled back AND the actual record created to trigger this event is also rolled back. So no more duplicate records if a plugin fails and the user, thinking that the record did not create, resaves the record.

For more information on the pipelines in Crm 2011, see here.

All good and fine so far, we have the ability in the SDK to see whether we are inside a Transaction or not via the IPluginExecutionContext (context.IsInTransaction).

My problem is a little more complex, I need to also know whether we are in the Pre-Event or Post-Event of the plugin. We sometimes need to check whether a plugin is a pre or post event plugin.

In Crm4.0 we simply used the IPluginExecutionContext (context.Stage), so:

if (context.Stage == MessageProcessingStage.BeforeMainOperationOutsideTransaction)
{ ... }

My problem is that I could not find how to do the equivalent in Crm 2011. The actual stage property is of type int, but normally the SDK would give us a static class or enumerator to use here. In Crm4.0 it was the MessageProcessingStage.

The actual integer values of the 5 possible states are published, so I simply added a static class to my helper methods to allow for this. I find it a little annoying that the Crm SDK forces you to use the integer value here when adding a simple enumerator to the SDK would be simple... but oh well.