Friday, 27 June 2008

Associated views on Quote Product and Order Product entities

The facility for adding Write-In products to the Order and Quote entities is implemented within CRM through 2 associated views on each of the Quote Product (quotedetail) and Order Product (salesorderdetail) entities. These are used for the Existing Products and Write-In Products navigation items respectively.

This can have effects elsewhere, however. If you create a custom one to many relationship from another entity to the Quote Product or Order Product entity, then only one of the associated views is used within the parent entity. This can cause a problem, because neither associated view displays all the data (one displays the write-in products only, and the other displays the existing products only). For example, the default associated view is the Existing Products view, so write-in products would not be displayed.

There are 2 possible solutions to this. One is to change which is the default view, the other is to change the filtering within one of the views. Both of these are configured via attributes of the savedquery entity. These can be modified in a supported way by using the CrmService.Update method for the savedquery entity, or in an unsupported way by modifying field values directly in the savedquerybase SQL table.

Which associated view is displayed is controlled by the IsDefault attribute - if you change this then it's your responsibility to ensure only one view has this set to true.

The filtering is applied based on the ColumnSetXml attribute, which is essentially a FetchXml expression. For example, the ColumnSetXml for the Existing Product view is:

<columnset version="3.0">
<filter type="and">
<condition column="isproductoverridden" value="0" operator="eq" />
</filter>
<column>productid</column><column>priceperunit</column><column>quantity</column><column>extendedamount</column><column>salesorderdetailid</column><ascend>productid</ascend>
</columnset>

If you wanted this view to include all Quote Products, then you could remove the whole filter and condition elements. Note that such a change would necessarily affect the Existing Product view within the Quote entity.

Friday, 20 June 2008

Plugin Parameters

Although the CRM 4.0 SDK is generally pretty comprehensive, I find it doesn't contain as much information as I'd like about the information passed to plugins for each of the messages.

The following table lists the main parameters passed to plugins on the most common messages. If the message you want isn't listed here, post a comment and I'll update the table.

MessageParameterDirectionTypeComments
AssignAssigneeInputSecurityPrincipal
AssignTargetInputMoniker
CancelSalesOrderOrderCloseInputDynamicEntity
Close*ActivityCloseInputDynamicEntity
CloseStatusInputInt32
CreateidOutputGuidOnly available on the Post Stage
CreateTargetInputDynamicEntity
DeleteTargetInputMoniker
ExecuteFetchXmlInputString
ExecuteFetchXmlResultOutputString
GrantAccessPrincipalAccessInputPrincipalAccess
GrantAccessTargetInputMoniker
HandleSourceQueueIdInputGuid
HandleTargetInputDynamicEntity
Lose*ActivityCloseInputDynamicEntity
LoseStatusInputInt32
RetrieveBusinessEntityOutputDynamicEntity
RetrieveColumnSetInputColumnSetBase
RetrieveTargetInputMoniker
RetrieveExchangeRateExchangeRateOutputDecimal
RetrieveExchangeRateTransactionCurrencyIdInputGuid
RetrieveMultipleBusinessEntityCollectionOutputBusinessEntityCollection
RetrieveMultipleQueryInputQueryExpression
RetrieveMultipleReturnDynamicEntitiesInputBoolean
RetrievePrincipalAccessAccessRightsOutputAccessRights
RetrievePrincipalAccessPrincipalInputSecurityPrincipal
RetrievePrincipalAccessTargetInputMoniker
RevokeAccessRevokeeInputPrincipalAccess
RevokeAccessTargetInputMoniker
RouteEndpointIdInputGuid
RouteRouteTypeInputRouteType
RouteSourceQueueIdInputGuid
RouteTargetInputMoniker
SendEmailIdInputGuid
SendIssueSendInputBoolean
SendSubjectOutputStringThis is the subject after the tracking token has been added
SendTrackingTokenInputString
SetStateDynamicEntityEntityMonikerInputMoniker
SetStateDynamicEntityStateInputString
SetStateDynamicEntityStatusInputInt32
UpdateTargetInputDynamicEntityTo get the Primary Key, find the KeyProperty within the DynamicEntity
Win*ActivityCloseInputDynamicEntity
WinQuoteCloseInputDynamicEntity
WinStatusInputInt32


Notes:
*ActivityClose. For the Win, Lose and Close messages, one of the parameters is an activity type whose name depends on the primary entity - e.g. the Win message could have a QuoteClose or OpportunityClose entity passed to it

To gather this information I used the plugin tools described on the MSCRM Team blog. The source code for these tools can be found here:
Bulk Registration Tool
Plugin Logger

Other Links:
Plugin Development
Plugin Messages

Thursday, 19 June 2008

Reports in IFrames - Updated for CRM 4.0

One of my earlier posts here and on the CRM Team Blog was about writing reports to display in IFrames and via ISV.Config. This was written for CRM 3.0, and although the principle remains the same for CRM 4.0, a couple of changes are required to the report parameters.

Extra Parameters passed by CRM
To support multi-tenancy and multi-language deployments, CRM 4.0 passes additional parameters on the query string when the 'pass record object-type...' option is set for the IFrame. These extra parameters are orgname, UserLCID and OrgLCID.

For the report to work in reporting services you will have to add parameters with these names to your report. The orgname parameter has to be a string, the UserLCID and OrgLCID can be either strings or integers. As with the type and typename parameters, these new parameters don't have to be used in the report, they just need to exist for reporting services to accept values for them on the query string.

Changes to the query string for ISV.Config buttons
In CRM 4.0, Microsoft have standardised the parameters such that they are the same for IFrames and ISV.Config buttons. This means that your report should have parameters id, type, typename, orgname, UserLCID and OrgLCID.

Wednesday, 11 June 2008

'This entity is already locked' message

I recently had to debug some code that threw the 'This entity is already locked' error message (code 80043B1D) when updating an order product (salesorderdetail) entity.

This error can occur even if the state of both the order and order product allowed editing. The error occurs if the productid property is set on the BusinessEntity that is passed to the Update method. A general principle when coding with the CRM platform is that, if a property value is set on an entity passed to the Update method, then the CRM platform will assume that the value has been changed.

In this case, if the productid is passed, CRM assumes that you are trying to change the product, which is not permitted if the ispricelocked attribute is set to true on the order. So, the solution is to always ensure that you know which attributes are actually changing, and ensure that only these properties and the primary key value are passed to the update method.

Tuesday, 3 June 2008

Differences between Workflow and Plugins in CRM 4.0

A common question I get is ‘what is the difference between workflow and plugins, and when should I use one or the other ?’. This article is intended to be a comprehensive answer to these 2 questions.

First of all, I want to clarify the distinction between what I consider 3 distinct categories of workflow – the terminology is my own:
  • Simple workflow. This is one or more workflow rules created within the MSCRM interface, and which do not include custom workflow activities.
  • Workflow with custom workflow activities. I’ll explain more about custom workflow activities later in this article; for now the key point is that a custom workflow activity is .Net code that is written to perform functions not possible in simple workflow, and this code can be called from a workflow rule
  • Workflows created with the Workflow Designer in Windows Workflow Foundation. It is possible to build workflows outside of the CRM user interface, but I’m not going to include them in this article.
Simple workflows
The main characteristics of simple workflows are:
  • * Creating a simple workflow involves no code
  • Workflows run only on the CRM server – workflow processing is not available within a client that is offline
  • Workflows run asynchronously – any data changes made within a workflow rule will not show up immediately within the CRM user interface
  • Workflows can be run manually or automatically. The automatic running of workflows is based on several data modification events
  • Workflow rules are entity specific
  • The state and stage of a workflow instance can be viewed within the CRM user interface by any CRM user with appropriate permissions

Some limitations of workflows are:

  • Workflow rules cannot be created for all entities
  • Although workflow rules can be triggered by the most common data modification events, there are some events that don’t trigger workflow rules
  • * Simple workflows offering limited capability to perform calculations

Characteristics and limitations marked with an asterix (*) do not apply if using custom workflow activities; the others do still apply.

Custom workflow activities
Custom workflow activities allow you to extend the capabilities of workflow rules. Three common uses are to perform calculations on CRM data, to access CRM functionality that is not available in the out-of-the-box workflow activities, and to access external data.

Custom workflow activities are written as .Net assemblies which have to be registered on the CRM server. These assemblies can include information about parameters that can be passed into or out of the activity.

Plugins
A plugin is .Net code that is registered on the CRM server. A plugin assembly can be registered for one or more steps – these steps correspond to the combination of the message (event), entity and stage. An example of a step would be the Create message for the account entity on the pre-event stage. Registration of the assembly and steps is part of the plugin deployment process, and there is no direct user interaction with plugins

The main characteristics of plugins are:

  • They have to be written as .Net code
  • Although they typically run on the CRM server, they can be deployed and configured to run on a CRM client that is offline
  • They can run either synchronously or asynchronously. If they run synchronously, any data changes made within the plugin will show up immediately within the CRM user interface
  • Synchronous plugins can run on either the pre-event or post-event stage. The pre-event stage happens before data is written to the CRM database, and a plugin registered on a pre-event step can cancel the data writing and provide an error message to the user.
  • More entities can have plugins registered for them than can have workflow rules
  • Plugins can run on more events than can workflow rules. An example is that plugins can run on data retrieval, not just modification events

The main limitations of plugins are:

  • Plugins cannot be run manually; they only run on the steps for which they are registered
  • There is no user interaction with plugins, other than error messages that might be throw by a synchronous plugin

Sample Scenarios
So, having covered the main characteristics and limitations of simple workflows, custom workflow activities and plugins, when should you choose one or another ? Here are some common scenarios:

What you want to achieve can be done with a simple workflow, and it is acceptable or desirable for this to happen asynchronously and on the server only
In this case I’d go with simple workflows; there’s no point writing code if you don’t have to.

What you want to achieve has to run synchronously
If so, workflow won’t do, so it would have to be a plugin. An alternative could be to use client script, but I don’t intend to complicate this article by including this in any more detail

You need to be able to cancel the data operation
A pre-event plugin is the only option covered here, though again client script should be considered

You want to give users the discretion to run the operation manually
Here you’ll need a workflow. Whether or not you need a custom workflow activity depends on the complexity of the operations. Again, there may be an option outside of the scope of this article – to write an ASP .Net application that is called from an ISV Config button

You need to write custom code, but you want users to decide whether this code should run, and under what circumstances
In this case I’d go with a custom workflow activity, as you could make this available for users to add to their own workflows

Further Information
There is more detail about how to write and deploy plugins and custom workflow assemblies within the CRM 4.0 SDK, though unfortunately there’s not a lot of information about when to choose one or the other.

The classroom training material ‘Extending Microsoft Dynamics CRM 4.0’, course number 8969, should have more information both about building plugins and custom workflow assemblies, and when to use them. This course will also cover other solution technologies such as client script and ASP .Net extensions.

One of the MS team, Humberto Lezama has also produced a useful matrix indicating the relative merits of workflow and plugins. This can be found here

Monday, 2 June 2008

CRM SDK version 4.0.5 has been released

The CRM 4.0 SDK has been updated again, and is available for download here

A decent overview of the changes can be found on the CRM Team Blog