« XSLT Best practices: ancestor-or-self vs. descendants-or-self | HomePage | Sitecore and stat analyzers »
Wednesday, 21 February 2007
Integrating MS CRM 3.0 and Sitecore
I’m frequently being asked if Sitecore has integration to Microsoft CRM 3.0. This question is very hard to answer: Answering either yes or no would in most cases be misleading; Sitecore integrates to any aspects of Microsoft Dynamics CRM 3.0, account management and lookup, statistics, reporting, order fulfillment etc. This integration, however, doesn’t come in a standard wrapped package. The level of integration between these systems highly depends on what you are trying to achieve on your web site.
For example, the Sitecore licensing system and ordering system, Developer network, Partner network and Personal Portal are all interconnected to Microsoft CRM. Whenever someone joins the personal portal (http://portal.sitecore.net), they are automatically added as a contact in our CRM. Also, all authentications are handled against CRM. In addition, whenever the user joins the network, they are, depending on their email automatically domain automatically added to an account if the account already exists. E.g. a new user, johndoe@doedoe.net is automatically created with the personal information and additionally added to company DoeDoe. Sitecore staff can hereafter modify John Does rights, for example granting him or her access to e.g. licensing system.
If the user belongs to an organization, it’s possible to see who else are registered from the same company.
Licensing integration is likewise handled through the CRM, but from a Sitecore portal making it possible for Sitecore partners to order licenses online, while maintaining pipe lines, sales forecasts etc. within our CRM.
Now, this integration is pretty extensive and the deepest I have seen to this dynamics: But from this point to release a general integration between these products is meaningless. Naturally a number of controls that allows customers and contacts to maintain their own information are somehow generic. However, other controls, such as licensing ordering are not.
Authentication by CRM contact
Another generic control/integration would be the authentication/authorization layer in order to allow e.g. extranet customization. For example sort/hide documents and web sections from unauthorized CRM users.
This too is easy to do; create a custom .NET web control and use the web service layer, then use the contact lookup. Once you find the user, get the information you need from the user object, such as User name, email and user roles (e.g. member of group a, member of group b). If the user exists, create a Sitecore virtual (extranet) user and fill in the values, for example what roles the user is a member of. All you need now is that these roles exist in your Sitecore installation.
To code this integration manually, you must customize your controls. But this is quite straight-out-of-the-box if you are a developer: It’s simply based on the CRM .NET web services or direct .NET classes depending on the level of integration you wish to do.
As Sitecore is based on .NET these controls embeds directly in to the customization tool, e.g. Visual Studio or Sitecore Developer Center. Also, using the CRM web service layer is a snap. Simply add the service URL into your references and watch the new classes pop up just as any other referenced class.
Example
This example can really be split into two parts; CRM lookup and Sitecore authentication. The code first looks up a contact in the CRM 3.0 by two criteria’s: email-address and a custom field (password). If the user exists, a virtual user is created with a role credential matching a CRM custom field.
Lets first initiate the service with the standard credentials (this allows me to do any request on the CRM system unless we've configured a security lock-down which is not standard):
CrmService service = new CrmService();
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
Ok, now we must build a request set of the values we want to the web service to return. It must also contain the values we with to query for, e.g. emailaddress1 and customfield_password:
ColumnSet cols = new ColumnSet();
cols.Attributes = new string[] {
"fullname", "parentcustomerid",
"emailaddress1", "customfield_password",
"customfield_role"};
Now we want to create the query. The CRM 3.0 web service API requires that you build a query object. A query object consists of several conditions. We need two:
ConditionExpression conditionEmail = new ConditionExpression();
conditionEmail.AttributeName = "email";
conditionEmail.Operator = ConditionOperator.Equal;
conditionEmail.Values = new object[1];
conditionEmail.Values[0] = Email.Text;
ConditionExpression conditionPassword = new ConditionExpression();
conditionPassword.AttributeName = "customfield_password";
conditionPassword.Operator = ConditionOperator.Equal;
conditionPassword.Values = new object[1];
conditionPassword.Values[0] = Password.Text;
Now we must create the filter expression which holds the two conditions:
FilterExpression filterPrincipal = new FilterExpression();
filterPrincipal.FilterOperator = LogicalOperator.And;
filterPrincipal.Conditions = new ConditionExpression[] {conditionEmail, conditionPassword};
Lets build the query object which are querying for a contact type (the entitiy). Then lets add a filter criteria, our filterPrincipal object:
QueryExpression query = new QueryExpression();
query.EntityName = EntityName.contact.ToString();
query.ColumnSet = cols;
query.Criteria = filterPrincipal;
RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();
retrievePrincipal.Query = query;
Excute the request and drop the result(s) into a multiple response object. If the contact is not unique, this could hold several contacts.
// Execute the request.
RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse) service.Execute(retrievePrincipal);
If the result set has at least one response value, I get the first one and returns the role and Full name into separate strings.
if (principalResponse.BusinessEntityCollection.BusinessEntities.Length>0) {
contact con = (contact)principalResponse.BusinessEntityCollection.BusinessEntities[0];
string sRole = con.customfield_role;
string sFullName = con.fullname;
We might want to do further checking (e.g. if sRole is not blank etc.), but this is a basic function.
All we need to do now is to create a virtual user with the full name and log on to Sitecore.
UserItem myUser = Context.Domain.BuildVirtualUser(myUserID, sFullName);
RoleItem role = domain.GetRole(sRole);
user.RuntimeSettings.AddRole(role.ID);
domain.Login(user);
}
What’s next?
Well, as I wrote previously, integration to MS CRM 3.0 from Sitecore is really simple, but it's very hard to get more than the basics "out-of-the-box" as criterias vary from organisation to organisation. If you wish to do a good successfull integration, you should spend some time figuring out what you want integrated. Then as us if we have the code, or simply use the net to grab it.
Good luck
18:39 Posted in Sitecore | Permalink | Comments (2) | Email this | Tags: Sitecore, MS CRM 3.0, Integration, Authentication



Comments
Hi Lars,
the question is, is this method valid as a basic approach for the entire MS dynamics range? I've had some pretty nasty dealing with Navision especially in the past, as this package only supports CPsync (and therefore excludes almost anything but commerce server). Having to write custom interfaces on this type of software is possible, but it would be much nicer and especially much faster and cost effective to integrate using the method above.
Any thoughts on this?
Bert
Posted by: bert | Saturday, 24 February 2007
Hi Bert,
There's a pretty good article about Navision communitcation on MSDN: http://msdn2.microsoft.com/en-us/library/aa973247.aspx
I thought that there's a new Dynamics NAV version upcoming. I guess, by that time, the problem is fully solved. As all the other product such as Axapta does support friendly Webservices as CRM does: http://msdn2.microsoft.com/en-us/library/ms933131.aspx
- Alex
Posted by: Alex de Groot | Sunday, 25 February 2007
The comments are closed.