Multiple Persona or Profiles per customer contact in Microsoft Dynamics CRM Online & CRM 2016 on-premise: CRM contact architecture approach

A CRM contact with multiple personas or separate individual profiles is a fairly common scenario in many Dynamics CRM projects. For example:  A contact could be a Managing Director of an organisation while at the same time they are non-executive director in a different firm or sits on the board of a Charity.

In Dynamics CRM, a contact is normally one person. Setting an individual contact to have multiple profiles and personas can be delivered in a number of ways – arguably most of them are not 100% ideal.

First option for delivering the multiple personas for the same individual contact is to create a custom entity for each persona/profile and have the contact record as a parent (or a child) for each one of these entities. Other options, which I wouldn’t recommend, is to create a custom entity for each persona and not include or use the contact entity at all – i.e. you will be re-creating the contact entity multiple times, once for each persona. This is not a good practice and a highly discouraged approach.

Another option which is also not recommended, but more common, is to create a separate contact for each persona allowing for duplicate contacts – for example: John Smith, the Director of company X and another contact, John Smith, sitting on the board of company Y. Again, duplicating contacts is never a good practice.

There are other additional options to achieve the multiple persona scenario in Dynamics CRM such as as customising the contact entity heavily so that it allows for capturing multiple personas on the same form and entity. Again, this might work for some CRM solutions but is not ideal.

Let’s explore the first option further. In this approach, a custom entity for each persona or profile is created while having the contact entity as either a parent or a child for each custom entity. This option is the most commonly used and was unofficially suggested by a highly qualified Microsoft contact for a number of scenarios. One main challenge, among other challenges and limitations of this approach, was to be able to display all contact information within the custom entity for each persona.

For example, let’s say John Smith is an Ex-employee, a Director in company X and also a non-executive director on the board of company Y. You will have 3 persona records (same custom entity or different) all linked to the same contact record. Then, if there is a process where you want to show 1st Persona, you will use data from the 1st Persona form and so on, just using the relevant persona entity record.

However, if you want to show contact information from the contact record such as mobile number or email address, you were left with limited options as you couldn’t directly show this information within the persona entity form. Your options where to copy the contact information across from the contact to the persona record and always keep them both in Sync programmatically. Synchronising the contact information was a lot of overhead of custom development though. The other option was to show the persona without the contact information and then expect users to click their way through from the persona record all the way up to the parent contact record, just to be able to see the persona phone number! This wasn’t helpful either.

Now, in Dynamics CRM 2016 and Dynamics CRM Online, there is a new feature that I found to be very useful to help resolve this limitation in the persona situation or even in other situation where you need to show fields, information or data from the parent record on the child entity form.

My suggestion is to do this using calculated fields. I found this to be very powerful. You can now go to the form of any entity and add a calculated field that shows the data from the parent record. So in our persona example, you could simply have the contact entity as the parent of the persona custom entity and then add a calculated field on the persona entity form. This calculated field is then set to be equal to the relevant parent contact record information such as: mobile number or email address. This is done just like you would do a formula on CRM calculated fields where you are now able to select the parent field from field calculation formula building screen.

 

This applies to many other situations where you can show data or calculation of data from parent records of any child entity form. I found it to be a powerful new feature with many  other useful uses. Anyone else found this interesting or have other recommended approaches?

Dynamics CRM Entity and Field Display Name, Field Schema Name and Field Logical name or Attribute name

In Dynamics CRM there is a difference between CRM Entities and Fields Display Name, Entity/Field Schema Name and Entity/Field Logical name (also known as Attribute name).

Display name is clear. It is the name shown to the CRM user and can have spaces, etc. Then you got these two:

  • SchemaName: Name that will be used to create the database column  for the field. This name can be mixed case. The casing that you use sets the name of the object generated for programming with strong types or when you use the REST endpoint. So it could be something like new_FieldSchemaName
  • LogicalName: This is the name, auto generated based on Schema name but the system sets it to all lowercase letters.

Every entity and field has a schema name (DB name – mixed case) and a logical name (all lower case).

Schema name retains the casing but logical name will always be lowercase.

When writing code to call/use fields, we always use schema names (DB names) not logical/attribute name.

As you can see from the following screenshot, you decide the display and schema name during creation while the attribute name will be generated by Dynamics CRM exactly as the schema name but all lower case.

 

Schema-vs-Logical-Name

 

Once your field is created, you can see in the following screenshot the Name (logical name), the schema name (DB name – mix case) and the Display name (the one the customer sees).

 

Schema-vs-Logical-Name

 

The same applies to entities.

This post may sound like it is targeting only those who are starting to work with Dynamics CRM for the first time, but in reality I have met a number of Dynamics CRM developers who didn’t know this information. Hence, I hope this is useful. Please comment with your views below.

 

Creating, consuming and using Microsoft Dynamics CRM 4.0 Service, Using CRM API and CRM SDK to access CRM database via the webservice

  

Creating, consuming and using Microsoft Dynamics CRM 4.0 Service, Using CRM API and CRM SDK to access CRM database via the webservice. Custom .NET code to access CRM, create, update (edit), insert, delete, retrieve (return) and retrievemultiple records for system entities and custom entities using both entity objects and dynamic entities. 

This post is a collection of the main methods that you would frequently use in your .NET code (Plugin, Website) that is accessing a dynamics CRM 4.0 system and consuming its CRM services. 

The CrmService Web service provides a set of methods used to perform the most common operations on system and custom entities. 

This collection mainly comes from sevaral pages on MSDN. I just thought it will be useful to have them all together if we need one or more of them. 

  

The following code shows how to set up the Web service, and how to use the Create and Retrieve methods. 

  

  

// Set up the CRM Service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
token.AuthenticationType = 0; 
token.OrganizationName = "AdventureWorksCycle";
 
CrmService service = new CrmService();
service.Url = "http://<servername>:<port>/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
// Create an account entity and assign data to some attributes.
account newAccount = new account();
newAccount.name = "Greg Bike Store";
newAccount.accountnumber = "123456";
newAccount.address1_postalcode = "98052";
newAccount.address1_city = "Redmond";
 
// Call the Create method to create an account.
Guid accountId = service.Create(newAccount);
 
Guid contactId = new Guid("2B951FBC-1C56-4430-B23B-20A1349068F3");
 
// Call the Retrieve method to retrieve an existing contact.
ColumnSet myColumnSet = new ColumnSet();
myColumnSet.Attributes = new string[] { "firstname" };
contact myContact = (contact) service.Retrieve ("contact", contactId, myColumnSet)

  

 

 

—————————- 

The following example demonstrates the use of the Create method. 

  

// Set up the CRM Service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
 
// You can use enums.cs from the SDK\Helpers folder to get the enumeration 
//   for Active Directory authentication.
token.AuthenticationType = 0; 
token.OrganizationName = "AdventureWorksCycle";
 
CrmService service = new CrmService();
service.Url = "http://<servername>:<port>/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
// Create the contact object.
contact contact = new contact();
 
// Create the properties for the contact object.
contact.firstname = "Jesper";
contact.lastname = "Aaberg";
contact.address1_line1 = "23 Market St.";
contact.address1_city = "Sammamish";
contact.address1_stateorprovince = "MT";
contact.address1_postalcode = "99999";
contact.donotbulkemail = new CrmBoolean();
contact.donotbulkemail.Value = true;
 
// Create the contact in Microsoft Dynamics CRM.
Guid contactGuid = service.Create(contact);

  

———————————- 

  

The following example demonstrates the use of the Retrieve method. 

  

// Set up the CRM Service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
 

// You can use enums.cs from the SDK\Helpers folder to get the enumeration
//   for Active Directory authentication

  

token.AuthenticationType = 0; 
token.OrganizationName = "AdventureWorksCycle";
 
CrmService service = new CrmService();
service.Url = "http://<servername>:<port>/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
// Create the column set object that indicates the properties to be retrieved.
ColumnSet cols = new ColumnSet();
 
// Set the properties of the column set.
cols.Attributes = new string [] {"fullname"};
 
// contactGuid is the GUID of the record being retrieved.
Guid contactGuid = new Guid("4D507FFE-ED25-447B-80DE-00AE3EB18B84");
 
// Retrieve the contact.
// The EntityName indicates the EntityType of the object being retrieved.
contact contact = (contact)service.Retrieve(EntityName.contact.ToString(), 
                                             contactGuid, cols);

  

  

—————————- 

  

The following example demonstrates the use of the RetrieveMultiple method. 

  

// Set up the CRM Service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
 

// You can use enums.cs from the SDK\Helpers folder to get the enumeration
//   for Active Directory authentication

  

token.AuthenticationType = 0; 
token.OrganizationName = "AdventureWorksCycle";
 
CrmService service = new CrmService();
service.Url = "http://<servername>:<port>/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
// Create the ColumnSet that indicates the properties to be retrieved.
ColumnSet cols = new ColumnSet();
 
// Set the properties of the ColumnSet.
cols.Attributes = new string [] {"fullname", "contactid"};
 
// Create the ConditionExpression.
ConditionExpression condition = new ConditionExpression();
 
// Set the condition for the retrieval to be when the 
//    contact's address' city is Sammamish.
condition.AttributeName = "address1_city";
condition.Operator = ConditionOperator.Like;
condition.Values = new string [] {"Sammamish"};
 
// Create the FilterExpression.
FilterExpression filter = new FilterExpression();
 
// Set the properties of the filter.
filter.FilterOperator = LogicalOperator.And;
filter.Conditions = new ConditionExpression[] {condition};
 
// Create the QueryExpression object.
QueryExpression query = new QueryExpression();
 
// Set the properties of the QueryExpression object.
query.EntityName = EntityName.contact.ToString();
query.ColumnSet = cols;
query.Criteria = filter;
 
// Retrieve the contacts.
BusinessEntityCollection contacts = service.RetrieveMultiple(query);

  

—————————- 

  

  

The following example demonstrates the use of the Update method. 

  

// Set up the CRM Service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
 

// You can use enums.cs from the SDK\Helpers folder to get the enumeration
//   for Active Directory authentication

  

token.AuthenticationType = 0; 
token.OrganizationName = "AdventureWorksCycle";
 
CrmService service = new CrmService();
service.Url = "http://<servername>:<port>/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
// Create the contact object.
contact contact = new contact();
 
// Set the contact object properties to be updated.
contact.address1_line1 = "34 Market St.";
 
// The contactid is a key that references the ID of the contact to be updated.
contact.contactid = new Key();
// The contactid.Value is the GUID of the record to be changed.
contact.contactid.Value = new Guid("4D507FFE-ED25-447B-80DE-00AE3EB18B84");
 
// Update the contact.
service.Update(contact);

  

—————————- 

  

The following example demonstrates the use of the Delete method. 

  

// Set up the CRM Service.
CrmAuthenticationToken token = new CrmAuthenticationToken();
 

// You can use enums.cs from the SDK\Helpers folder to get the enumeration
//   for Active Directory authentication

  

token.AuthenticationType = 0; 
token.OrganizationName = "AdventureWorksCycle";
 
CrmService service = new CrmService();
service.Url = "http://<servername>:<port>/mscrmservices/2007/crmservice.asmx";
service.CrmAuthenticationTokenValue = token;
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
// contactGuid is the GUID of the record being deleted.
Guid contactGuid = new Guid("4D507FFE-ED25-447B-80DE-00AE3EB18B84");
 
// Delete the contact.
// The EntityName indicates the EntityType of the object being deleted.
service.Delete(EntityName.contact.ToString(), contactGuid);

  

—————————- 

  

For Dynamic Entities: The following sample shows how to create a new entity instance by calling the CreateEntity method followed by the AddObject method. 

  

var contact = crm.CreateEntity("contact");
 
// Set the string properties.
contact.SetPropertyValue("firstname", "Allison");
contact.SetPropertyValue("lastname", "Brown");
contact.SetPropertyValue("emailaddress1", "allison.brown@contoso.com");
 
// Setting an explicit ID value is optional, it can be left unassigned, 
//    but here it is being explicitly assigned.
var id = Guid.NewGuid();
contact.SetPropertyValue("contactid", id);
 
// Pass the entity name of the entity being created as the first parameter.
crm.AddObject("contact", contact);
crm.SaveChanges();
 
// The ID value can be retrieved after you have called the SaveChanges method.
var id2 = contact.GetPropertyValue<Guid>("contactid");

  

  

  

These methods have been collected from MSDN mainly from these two locations:  http://msdn.microsoft.com/en-us/library/cc151016.aspx and http://msdn.microsoft.com/en-us/library/ff681571.aspx  

  

  

Script to Hide Add Existing Record button and Add New Record button using Javascript in Microsoft Dyanmics CRM

If you want to hide the two top left  buttons in the assicated view of any entity,  Add Existing Record and Add New Record Buttons, you can use the following javascript code i the onLoad Event of the Microsofty Dyanmics CRM 4 Form.  This post relies on and is an extension to the existing useful post by Dave Hawes.

 //This javascript should be added to the onLoad event for the form of the entity where you want to hide buttons for the associated views of other entities

//-------Hide Add Existing Record Button Only----Method 1----
HideAssociatedViewButton('new_account_new_project', 'Add existing Project to this record');
function HideAssociatedViewButton(loadAreaId, buttonTitle)
{
    var navElement = document.getElementById('nav_' + loadAreaId);
    if (navElement != null)
    {
        navElement.onclick = function LoadAreaOverride()
        {
            // Call the original method to launch the navigation link
            loadArea(loadAreaId);
            var associatedViewIFrame = document.getElementById(loadAreaId + 'Frame');
            if (associatedViewIFrame != null)
            {
                associatedViewIFrame.onreadystatechange = function HideTitledButton()
                {
                    if (associatedViewIFrame.readyState == 'complete')
                    {
                        var iFrame = frames[window.event.srcElement.id];
                        var liElements = iFrame.document.getElementsByTagName('li');
                        for (var i = 0; i < liElements.length; i++)
                        {
                            if (liElements[i].getAttribute('title') == buttonTitle)
                            {
                                liElements[i].style.display = 'none'; //this will hide and align properly
                                liElements[i].style.visibility = 'hidden'; // this is needed when re-sizing cause button to re-appear.
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

//—End of Hide Add existing button Only

//——————Hide Add New Record Button and Add Existing Button ———

//Hide Both Buttons-----------
HideAssociatedViewButtons('new_account_new_project', ['Add existing Project to this record', 'Add a new Project to this record']); //Where "Project" is a custom entity.
//OR Hide Add Existing Button Only-----Method 2-------
HideAssociatedViewButtons('new_account_new_project', ['Add existing Project to this record']);  //Where "Project" is a custom entity.

function HideAssociatedViewButtons(loadAreaId, buttonTitles){
    var navElement = document.getElementById('nav_' + loadAreaId);
   if (navElement != null)    {
        navElement.onclick = function LoadAreaOverride()        {
            // Call the original CRM method to launch the navigation link and create area iFrame
            loadArea(loadAreaId);
            HideViewButtons(document.getElementById(loadAreaId + 'Frame'), buttonTitles);
        }
    }
}

function HideViewButtons(Iframe, buttonTitles) {
    if (Iframe != null ) {
        Iframe.onreadystatechange = function HideTitledButtons() {
            if (Iframe.readyState == 'complete') {
                var iFrame = frames[window.event.srcElement.id];
                var liElements = iFrame.document.getElementsByTagName('li');

                for (var j = 0; j < buttonTitles.length; j++) {
                    for (var i = 0; i < liElements.length; i++) {
                        if (liElements[i].getAttribute('title') == buttonTitles[j]) {
                             liElements[i].style.display = 'none'; //this will hide and align properly
                             liElements[i].style.visibility = 'hidden'; // this is needed when re-sizing cause button to re-appear.
                            break;
                        }
                    }
                }
            }
        }
    }
} 

Credit goes to Dave Hawes Blog post mentioned above.

 

Creating left navigation menu items (Links) to other entities on an entity form in Microsoft CRM 4

This is a short and quick post. If you have an entity and you want to add a link to the left hand side navigation menu of its form, then you can do this by one of two things:

1) Using ISV.CONFIG if this link is to an external website, application, etc.. This was discussed in more details in my post on using and editing ISV.CONFIG file

2) Creating a 1:N relationship between this entity and the entity you want to have a link for on the left menu bar.

So for example, if you want to have a link to all projects associated with an account in the account form, you will need to create a relationship between them. i.e. When you open an account form, you want to have a link to projects on the left handside navigation menu of the account form. To do this, you go to customisations, Account entity and in there, create a new 1:N relationship with your required entity (custom entity Project in this case). Create the relationship with Account as the primary entity and Project as the related entity. Save and publish the account form.

Now when you go and open any account record, you will see a link – submenu – item called projects on the left hand side of the Account form. If you click on it, it will allow you to add existing Projects (project records or whatever entity you selected) or you can create new project record.

You can of course apply this to any combination of entities whether customisable or custom.

To rename the left hand side menu navigation bar items, you can have a loo at my other two posts about renaming and hiding these items.

Thanks.

Hiding Left Navigation Menu Items in an Entity Form using Javascript in Microsoft CRM 4

This is just a follow on from my previous post (http://www.mohamedibrahim.net/blog/2009/07/30/renaming-left-menu-items-leftnav-entity-microsoft-dynamics-crm-4/). In this post, I explained how to rename left menu items in an entity form using javascript.

These links are created when a new N:1 relationship is created between two entities. The primary entity in this relationship will get a new left navigation link everytime a new N:1 relationship is created.

We have discussed in the previous post that the code to rename left menu navigation items (links to other N:1 entities) is:

var navItem = document.getElementById(’leftNavMenuItemID’);
navItem.innerHTML = navItem.innerHTML.replace(’>CurrentLinkValue’,’>NewLinkValue’);

So for example:

var navLeftItem = document.getElementById(’navContactsMenuItem’); // this will look for the element contact in the left menu of an account form
navLeftItem .innerHTML = navItem.innerHTML.replace(’>Contacts’,’>Employees’); //This will rename Contacts to Employees in the Account form

Now, to Hide specific links in the left menu, you can use the following script:

// Hide left menu navigation links on an entity form
var navLeftItem = document.getElementById(’navContactsMenuItem’);
navLeftItem .style.display = ‘none’;

This script will be in the OnLoad event of the form of the entity that you want to hide links created on the left handside of this entity form.

Renaming Left Navigation Menu items (leftnav) of an Entity in Microsoft Dynamics CRM 4

I will try to make this as simple and straight to the point as possible.

This post is to explain how to to change the name and rename one or more of the left menu items – leftnav – items of an Entity, for example the Account entity or the Contact entity or any other Custom entity. In summary, this should be done using a script in the onload event of the entity form and apparently can NOT be done using the Isv.Config file.

So for example, when you open an account record, on the left hand side of the Account form you will have the left navigation list of entities which are: Activites, History, Sub-Accounts, Contacts, Relationshiips, Workflows, Opportunities, Leads, Quotes, Orders, Invoices, cases, contracts, marketing lists and campaigns.

To rename any of these entities or any other custom entity has a 1:N relationship with the Account entity, you will need to put some javascript code (or script really) in the OnLoad event of the Account Form. This code will look for the name of the left navigation item (link to an entity) and rename it to whatever you want. You can not do this in ISV.CONFIG as you can only add new links to ISV.CONFIG but you can not edit already existing left menu items in this file as they don’t exist and are not displayed.

So, in the OnLoad event of the entity that you want to rename its left navigation menu items, you will need to put the fulling code (or something like it):

var navItem = document.getElementById(‘leftNavMenuItemID’);
navItem.innerHTML = navItem.innerHTML.replace(‘>CurrentLinkValue’,’>NewLinkValue’);

This code will look for the menu item that has an id (‘leftNavMenuItemID’) in your chosen entity form and replace its current link name to a new link name.

So for example:

var navItem = document.getElementById(‘navContactsMenuItem’);
navItem.innerHTML = navItem.innerHTML.replace(‘>Contacts’,’>Employees’);

If you input this code in the OnLoad event of the Account entity Form, this code will look for the “Contact” entity link in the left navigation and rename it from Contacts to Employees.

You can apply the same to any other entity either it is a customisable (system) or custom entity. You will need to use a HTML tool such as Microsoft’s Internet Explorer Developer Toolbar to find out the ID of the navigation item that you want to rename (‘navContactsMenuItem’).

Please let me know if you have a question or if you want me to clarify more.

Thanks,

Mohamed Ibrahim