Sticky

This blog has moved to www.dreamingincrm.com. Please update your feed Url. Thank you.

29 April 2015

Using actions to avoid intermediate entity

When actions were first introduced into Dynamics CRM, I did not quite understand its potential and appreciate how useful they are. But after using actions in quite a few projects, I am true believer of actions. One scenario, where I found actions quite useful is, when you have a intermediate entity, just for triggering a workflow, actions can be used to eliminate the unnecessary entity.

Here a (somewhat) simplified version of an design I worked on recently.

The SSIS Job looks into Invoice, Contact and Communication Configuration entities and creates a Communication entity record. The Communication entity stores information from both Contact and Invoice entity. It also uses Communication Configuration entity to calculate a trigger date for sending the communication.

In this design, the Communication entity exists solely for the Send Communication workflow. The entity itself doesn't serve any useful purpose beyond that. This entity has collated some information from Invoice, Contact and Communication Configuration entities and this is used by the Send Communication workflow.

In this scenario the Communication entity can be replaced by an Action. Any attributes that are defined on the Communication entity, simply translate into input arguments on the action. The workflow that is triggered by create of Communication entity can simply be triggered from the Action. Once the Communication entity has been swapped over for an action, the SSIS task calls the action using a script task, instead of creating a Communication record.

The only disadvantage I see of using this approach is that there is no historial information when you use action i.e. I can't simply use an Advanced Find to see when an action executed and with what parameters (unless you log it somewhere). I would get this capability if I used an entity, as I will store this information in the entity.

20 March 2015

Opportunity Product Permissions

When an assumption is made that something very basic, can be easily configured using OOB functionalities, that is when I find myself stuck occasionally and having to rethink on how to implement a feature. I recently had one such experience. The requirement was to allow users in certain security role, to delete opportunity products, but not opportunities.

My first thought was to use security role, to modify the permissions for opportunity products. To my surprise, I was unable to find opportunity products in Security Role.


It turns out Opportunity Product, Invoice Product, Quote Product and Order Product share a unique trait: they don't have separate permissions and use the permission of their parent. Such being the limitation, I could implement this using ribbons or plugins. I implemented this using ribbon. Here are the steps
  1. Grant Delete permission on the Opportunity entity for the appropriate security role
  2.  Use Ribbon Workbench to edit the ribbon for opportunity entity
  3. Add a new Enable Rule of type Custom Javascript Rule. I am calling a function in the Javascript webresource
  4.  Add the Enable Rule to the following commands:  
    • Mscrm.DeletePrimaryRecord
    • Mscrm.DeleteSelectedRecord
    • Mscrm.HomePageGrid.DeleteSplitButtonCommand
This change should be done on HomePage, Form and Subgrid ribbons. The code for the getOppDeletePermissionByRole itself is quite simple, as I am using XrmServiceToolkit.

var CVN = window.CVN || {};

CVN.getOppDeletePermissionByRole = function() {
 return !XrmServiceToolkit.Soap.IsCurrentUserRole('1.1 CRM - Base User Role');
};

window.CVN = CVN;

I did this on a CRM2011 organisation, but the process in same for a CRM2015 organisation. You'll just be editing the command bar instead of the ribbon. Here are the relevant buttons in CRM2015, whose command you'll need to edit.



18 March 2015

Deploying a CRM2015 solution to CRM2013

There have been some great posts recently on how to deploy a CRM2011/CRM2013 solution to CRM2015.

1. Deepesh Somani -> https://dynamicsofdynamicscrm.wordpress.com/2014/12/05/issue-resolutionsolution-compatibility-crm-2013-to-crm-2015/
2. Andre Margono -> https://andz88.wordpress.com/2015/03/02/unsupported-customisation-importing-crm-2011-managed-solution-to-crm-2015/

I had recently to deploy one, the other way around: from CRMOnline to a CRM2013 instance. In my case the solution contained only html, png and Javascript webresources. The entity dependencies for the solution, were already present in the CRM2013 organisation. The CRM2013 organisation was on SP1 UR1 (6.1.1). Refer to https://support.microsoft.com/en-us/kb/2917899 if you are on a higher/lower rollup and modify the version number appropriately.

In order to import the CRMOnline solution I had to

1. Extract the solution zip file

2. Change the first line of the solution.xml from '<ImportExportXml version="7.0.0000.5026" SolutionPackageVersion="7.0" languagecode="1033" generatedBy="CrmLive" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' to '<ImportExportXml version="6.1.0001.0132" SolutionPackageVersion="6.1" languagecode="1033" generatedBy="CrmLive" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'

3.Delete <IsEnabledForMobileClient>0</IsEnabledForMobileClient> from every single webresource node in customizations.xml

4. Rezip the files

After performing these steps, I was able to import the solution into the CRM2013 environment. As with the other two posts, this is an unsupported method, so use it at your own risk.

11 March 2015

Create New User Error

Yesterday, I got the following error when I tried to add a new user:

You are attempting to create a user with a domain logon that is already used by another user. Select another domain logon and try again.


The strange thing I noticed about the error is that, the user I was trying to add was not already there in CRM. I checked this in the SystemUser table and confirmed that it is definitely not there. After tracing SQL Server, I found CRM uses SystemUserAuthentication table to do this check.

Here is the sequence to events

No user A -> Backup organisation database -> User A created -> Restore organisation db from backup

In my situation, the error started happening after I restored the organisation db from the backup. At the time of the backup, the user I was trying to add had not been created. After the organisation db was restored from backup, the SystemUser table in the organisation database does not contain User A, but the MSCRM_CONFIG does (as per SystemUserAuthentication). This is the root cause of this error message.

The fix was to delete the organisation and re-import the organisation from the Deployment Manager. Once this is done, the new user can be added without any issue. This was the additional step I had to perform after I restored the db from the backup.

21 February 2015

Bug: Limitation of Action EntityReference Input Argument

Actions are great for lot of things, but there are few bugs/limitations that I experienced and found particularly frustrating. One of such bugs is that you cannot use the attributes of an entityreference input argument on an action step. This is not the same with custom workflow step with an entityreference output. You would be able to use any attribute from the entityreference output off the custom workflow step.

Here is the action definition

The entityreference action argument is available in the dropdown and all the properties appear as if they can be used.




Here is the create email step with values from workflow and action argument being used.



I also have a custom workflow step that accepts an entityreference input and just sets the entityreference output.

The custom workflow step input is set the action input argument.


This code for the custom workflow step is quite simple.

using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;

namespace TestWorkflows
{
    public sealed class ActionParameterToContactEntityReference : CodeActivity
    {
        [Input("Contact")]
        [ReferenceTarget("contact")]
        [RequiredArgument]
        public InArgument<EntityReference> ContactInput { get; set; }

        [Output("Contact")]
        [ReferenceTarget("contact")]
        public OutArgument<EntityReference> ContactOutput { get; set; }

        protected override void Execute(CodeActivityContext executionContext)
        {
            ContactOutput.Set(executionContext, ContactInput.Get(executionContext));
        }
    }
}


This is the email activity after the action is created.



As you can see, the Email and Firstname properties from the action's input entity reference comeup as blank, but there is no such issue with the ones retrieved from the custom workflow step.

28 January 2015

Bookmarklet to copy FetchXml

This is basically an extension of this post -> http://nycrmdev.blogspot.com.au/2014/12/using-advanced-find-fetchxml-capability.html. The bookmarklet below displays fetchxml that was used to display the results.

javascript:var fetchXml;if(frames[0]&&frames[0].document.getElementById('FetchXml')){fetchXml=frames[0].document.getElementById('FetchXml').value;} else if(frames[1]&&frames[1].document.getElementById('FetchXml')){fetchXml=frames[1].document.getElementById('FetchXml').value;} if(fetchXml){window.prompt('FetchXml',fetchXml);} else{alert('No FetchXml query found');} void 0;

Run this bookmarket from the Advanced Find results page and it will display the FetchXml in a dialog window for copy pasting.



Sometimes I just want to develop a starting point fetchxml using advanced find and work on it more using FetchXml Builder or Fetch Tester 3000. This bookmarklet saves me the hassle of exporting the fetchxml file, and copy pasting the result into the appropriate tool.

27 January 2015

Notes Control in CRM 2013 SP1

If you have a note control on a form and the default tab on this note control is Notes, no note records might be displayed, even though there are notes that are related to the record. Once you click the Notes link on the form, you'll suddenly see notes being populated. This is a bug that has been fixed in 6.1.1.


In order to automatically click the Notes link, I have a small script running in the onLoad event of the form to fix this issue on CRM 2013 SP1. This script is a stop gap measure, till 6.1.1 is applied to the server.

setTimeout("(function() { var t = document.querySelector('.tabLink.active'); if(t) { t.click(); } })();",2000);

This issue doesn't seem to be happening in CRM2013 SP1 UR1 and CRM2015 and hence this (unsupported) fix is not applicable to these versions.