Friday, January 28, 2011

CRM 2011 SDK - Set owner of record to inactive user

Can you programmatically set the owner of a record in CRM to an inactive user?  Yes, but see below for more information.

I'm working on a data migration project involving Salesforce.com to Dynamics CRM 2011 Online. The source data includes thousands of records that are assigned to inactive Salesforce.com users. Our client wants to maintain the owners in CRM but also wants the users who are inactive in Salesforce to be inactive in CRM.

That brought up the question: "Can you programmatically set the owner of a record in CRM to an inactive user?". Yes (see sample code below). The only requirement is that each user (systemuser) must have at least one security role assigned, otherwise the CRM proxy service will throw a FaultException with the message "SecLib::RetrievePrivilegeForUser failed - no roles are assigned to user.".

Here's the code I used to test this scenario:
Guid ownerIdForInactiveUser = new Guid("1412c4da-fb2a-e011-8526-1cc1def8ea35");

string accountName = "Tim Test 1";
Entity accountEntity = new Entity("account");
accountEntity["name"] = accountName;
accountEntity.Attributes.Add("ownerid", new EntityReference("systemuser", ownerIdForInactiveUser));
try
{
   crmService.Create(accountEntity);
}
catch (FaultException ex)
{
   Console.WriteLine(ex.ToString());
}
Cheers,
-Tim

Thursday, January 20, 2011

CRM 2011 SDK: WinOpportunityRequest and ArgumentNullException

In several of the Dynamics CRM 2011 SDK sample C# files, you'll see this comment and code line:

// This statement is required to enable early-bound type support.
_serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());


You might think that if you're writing late-bound code, like I was doing earlier today for a data migration project, that you wouldn't need that line of code. That's true if all you're doing is creating Entity instances, setting attributes, and executing CRUD operations (e.g., _serviceProxy.Update(myEntity)).

What I learned the hard way today is that you need that line of code if you're calling the Execute method for the service proxy with an instance of WinOpportunityRequest, LoseOpportunityRequest, and the other "Request" classes. If you don't run that code then you'll probably run into the ArgumentNullException after invoking Execute on the service proxy.

In hindsight, the "Opportunity" part of the name "WinOpportunityRequest" should've led me to think "maybe that's an early-bound class and therefore I need to set that ProxyTypesBehavior thing I read about". But I was convinced I was operating late-bound only. Apparently not. Another lesson learned.

Wednesday, January 19, 2011

CRM 2011: Running JScript Code Interactively in IE 8

While working on client-side code in Dynamics CRM, it's often faster to write and test the code incrementally within the context of a a "live" form, so that adjustments can be made quickly. Then, once a block of code is working, most of it can be moved to a code library to be further tested in CRM.

This article shows how to run jscript (javascript) code within an account form to format a phone number. The process utilizes the "Run Script" features in the Developer Tools utility that's included with Internet Explorer 8. The code assumes you are working in Dynamics CRM 2011.

Step 1: Load the CRM form upon which you want to run/test JScript code. For this example, load the Account form since the value of the “telephone1” field will be reformatted later in the example.

Step 2: Enter an unformatted phone number in the Main Phone (telephone1) field.  Example: 4255551212

Step 3: In IE, press F12 to load the Developer Tools window.

Step 4: Click Script and then click the Multi Line Mode button.

Step 5: Run the script shown below.
// Reference the main form window (iframe)

var oWindow = document.getElementById("contentIFrame").contentWindow;

// Reference the field with the phone number to format.
var oField = oWindow.Xrm.Page.data.entity.attributes.get("telephone1");

// Remove any non-numeric characters from the field's data.
var sTmp = oField.getValue().replace(/[^0-9]/g, "");

// If the number has a valid length, format the number.
switch (sTmp.length)
{
case "4255551212".length:
  oField.setValue("(" + sTmp.substr(0, 3) + ") " + sTmp.substr(3, 3) + "-" + sTmp.substr(6, 4));
  break;
case "5551212".length:
  oField.setValue(sTmp.substr(0, 3) + "-" + sTmp.substr(3, 4));
  break;
}
Step 6: View the Main Phone field again in the account form. The value should be formatted as (nnn) nnn-nnnn.