27 March 2009

Get Entity/Attribute's Display Name from CRM database


The Display Name for CRM Entity/Attribute is always a special case. In CRM 3.0, the Display Name is saved in the table: OrganizationUIBase, column: FieldXml. To get the Display Name for each attributes isn't an easy job. My approach was transfer the FieldXml column(NVARCHAR) into XML type, then get data from there. Here's the code I'd like to show about how to get the Display Name from CRM 3.0 (I suppose that you only want to see entity Account and Contact):



-- Get the display name from xml field
USE [Contoso_MSCRM]
GO
SELECT CONVERT(XML, REPLACE(CONVERT(NVARCHAR(MAX), O.FieldXml),'' ,'')) AS XmlField
INTO #temp1 FROM OrganizationUIBase O
WHERE NOT EXISTS(SELECT 1 FROM OrganizationUIBase WHERE Version>O.Version AND ObjectTypeCode=O.ObjectTypeCode)
SELECT DISTINCT
t2.x.value('(../../@objecttypecode)[1]','int') AS ObjectTypeCode,
t2.x.value('(../../@name)[1]','nvarchar(100)') AS EntityName,
t2.x.value('@name', 'nvarchar(50)') AS AttributeName,
t2.x.value('(displaynames/displayname/@description)[1]','nvarchar(100)') AS DisplayName
INTO #temp2
FROM #temp1 AS t1 CROSS APPLY t1.XmlField.nodes('/entity/fields/field') AS t2(x)

-- Join the metadata database
USE [Contoso_METABASE]
GO
SELECT
Entity.Name AS EntityName,
Attribute.Name AS AttributeName,
#temp2.DisplayName AS AttributeDisplayName,
FROM Attribute
INNER JOIN Entity ON Attribute.EntityId = Entity.EntityId
INNER JOIN #temp2 ON #temp2.AttributeName = Attribute.Name AND #temp2.ObjectTypeCode = Entity.ObjectTypeCode
WHERE EntityName IN ('Account', 'Contact')
ORDER BY EntityName, AttributeName

DROP TABLE #temp1
DROP TABLE #temp2



In CRM 4.0, because it supports multi languages, so the database has been re-designed: the FieldXml field has been abandoned. Instead, Microsoft uses a new table: LocalizedLabelView to save the Entity/Attribute's Display Name, it's much easy to get the Display Name, same example here (English version, the LanguageId is 1033):



USE Contoso_MSCRM
GO

SELECT EntityView.Name AS EntityName, LocalizedLabelView_1.Label AS EntityDisplayName,
AttributeView.Name AS AttributeName, LocalizedLabelView_2.Label AS AttributeDisplayName
FROM LocalizedLabelView AS LocalizedLabelView_2 INNER JOIN
AttributeView ON LocalizedLabelView_2.ObjectId = AttributeView.AttributeId RIGHT OUTER JOIN
EntityView INNER JOIN
LocalizedLabelView AS LocalizedLabelView_1 ON EntityView.EntityId = LocalizedLabelView_1.ObjectId ON
AttributeView.EntityId = EntityView.EntityId
WHERE LocalizedLabelView_1.ObjectColumnName = 'LocalizedName'
AND LocalizedLabelView_2.ObjectColumnName = 'DisplayName'
AND LocalizedLabelView_1.LanguageId = '1033'
AND LocalizedLabelView_2.LanguageId = '1033'
AND EntityView.Name IN ('Account','Contact')
ORDER BY EntityName, AttributeName

21 March 2009

Introduce a Data Audit solution for Microsoft Dynamics CRM

I'm pleased to introduce a Data Audit solution for Microsoft Dynamics CRM:

What it does?
Data Audit add-on can record the fact: Who did What at When. For example: you want to audit changes for the field: Account.EmailAddress1, all you need to do is just 3 clicks! The add-on will record the entity name, audit field, record id, original data, modified data, modified time, modified by information. Those audit histories for this record will associate with the record(for applicable entities), furthermore, you can also see all audit histories in one place.

What it is?
It is an ISV solution to integrate to Microsoft Dynamics CRM seamlessly, with same interface and user experience.

What does it support?
Data Audit 1.0 supports both On-Premise and IFD deployment, Stand-Along and Web-Cluster server structure, and Multi-Tenants. It supports both system entity/attribute and custom entity/attribute.
* The 1.0 version of Data Audit supports 32bit English Version Microsoft Dynamics CRM 4.0.

How it works?
See this 2 minutes demo video:




Please email us to get an evaluation license(30 days full function).

MVP Summit 2009 @ Seattle - Meet the CRM MVPs

It's a great summit and nice to meet CRM team and MVPs.



Meet the famous CRM authors: Jim Steger and Mike Snyder



MVP Darren Liu and me eatting the Red King Crab...



Jim Wang with the coffee which made by the world's first Starbucks @ Seattle, US



Jim Wang with his baby Niu

25 January 2009

Happy Chinese New Year! 2009 - The Year of The Ox


My dear friends, happy Chinese New Year! 2009 - The Year of The Ox ('牛'), and hopefully it could help the economics!!! ;-)

Cheers,
Jim

16 January 2009

CRM 4.0: Checkbox style Multi-Select Picklist

CRM 4.0 doesn't have many out-of-box user controls, e.g: a mulit-select picklist. The standard CRM picklist can only save one value in the database, it's not easy to extend this functionality, in addition, you have to deal with the Advanced Find feature.

You can make a picklist multi-selectable by enable the picklist mulitple attribute , e.g: crmForm.all.new_picklist.multiple = true; And then save the selected values somewhere else. However, it does not very impressive the user because the user has to use the CTRL key to select options, which is not user-friendly (Thanks for Alastair Westland (PM @ Parity) who work with me to improve the interface design:)

The script below will draw a checkbox style mulit-select picklist control on the CRM form, and then get options from the real picklist attribute. So how to use it?

1. Create a standard picklist attribute with all options in CRM, put it on the CRM Form. e.g: new_picklist;
2. Create another nvarchar attribute in CRM to save the selected text, put it on the CRM Form and hide the label. e.g: new_picklistvalue;
3. Put the following script in the Form.OnLoad() event.

*NOTE: There is a 'br' flag(var addBr = document.createElement(...) ) just been ignord by blogspot, please replace it when you paste the code!!!


/*
Checkbox style Multi-Select Picklist
author: Jim Wang @ January 2009
http://jianwang.blogspot.com
*/

// PL - the picklist attribute; PLV - used to save selected picklist values
var PL = crmForm.all.new_picklist;
var PLV = crmForm.all.new_picklistvalue;

if( PL != null && PLV != null )
{
PL.style.display = "none";
PLV.style.display = "none";

// Create a DIV container
var addDiv = document.createElement("<div style='overflow-y:auto; height:80px; border:1px #6699cc solid; background-color:#ffffff;' />");
PL.parentNode.appendChild(addDiv);

// Initialise checkbox controls
for( var i = 1; i < PL.options.length; i++ )
{
var pOption = PL.options[i];
if( !IsChecked( pOption.text ) )
var addInput = document.createElement("<input type='checkbox' style='border:none; width:25px; align:left;' />" );
else
var addInput = document.createElement("<input type='checkbox' checked='checked' style='border:none; width:25px; align:left;' />" );

var addLabel = document.createElement( "<label />");
addLabel.innerText = pOption.text;

var addBr = document.createElement( "<br />"); //it's a 'br' flag

PL.nextSibling.appendChild(addInput);
PL.nextSibling.appendChild(addLabel);
PL.nextSibling.appendChild(addBr);
}

// Check if it is selected
function IsChecked( pText )
{
if(PLV.value != "")
{
var PLVT = PLV.value.split("||");
for( var i = 0; i < PLVT.length; i++ )
{
if( PLVT[i] == pText )
return true;
}
}
return false;
}

// Save the selected text, this filed can also be used in Advanced Find
crmForm.attachEvent( "onsave" , OnSave);
function OnSave()
{
PLV.value = "";
var getInput = PL.nextSibling.getElementsByTagName("input");

for( var i = 0; i < getInput.length; i++ )
{
if( getInput[i].checked)
{
PLV.value += getInput[i].nextSibling.innerText + "||";
}
}
}
}


Note: Please be aware of this is an unsupported customization.

11 January 2009

CRM 4.0 External Connector License

It's very common to extend CRM to external users, however I saw many customers ask if they need license to do something. A External Connector License is used on:

Available for
• Professional Server
• Enterprise Server
Access License only – no additional software/licenses included
Extends access to external users (e.g. Partners, Customers, Suppliers)
Scenarios*

• Create new activities in CRM, such as a case via a portal
• Update information in CRM, such as contact information via a portal
• Fill orders, or update case status via a portal
* Access via Dynamics CRM Client technology requires a CAL


According to the Microsoft Dynamics® CRM 4.0 Licensing & Pricing Guide

The Microsoft Dynamics CRM 4.0 External Connector enables customers to extend Microsoft Dynamics CRM to their external users such as customers, partners, suppliers, and end users who access a copy of the server software (for which a license was acquired), through any application/graphical user interface (GUI), other than the Microsoft Dynamics CRM client. “External Users” are users who are not either (i) your or your affiliates’ employees, or (ii) your or your affiliates’ onsite contractors or agents, External users also does not include hosted-software service users, such as those already licensing via the Microsoft Service Provider License (SPLA).

An External Connector must be purchased for each server that hosts an application that provides external access to Microsoft Dynamics CRM 4.0 data as described above. External users should not be using the Microsoft Dynamics CRM 4.0 applications & GUIs directly. The alternative is for every external user to acquire a CAL

For the Microsoft Dynamics CRM Professional Server and Enterprise Server, there are 3 External Connector functionalities:

External Connector – The full use External Connector provides external users with full read-write access to Microsoft Dynamics CRM 4.0 data, such as that provided through any application/graphical user interface. The Full Use External Connector will appear on price lists as the Dyn CRM Extrnl Con, and consists of both the Limited External Connector and the Full Use Additive External Connector combined to provide full use capability.

Limited External Connector – The Limited External Connector provides external users with read-only access to Microsoft Dynamics CRM 4.0 data, such as described above. The Limited External Connector will appear on the price lists as the Dyn CRM Ltd Extrnl Con.

Full Use Additive External Connector – The Full Use Additive External Connector provides external users with write-access to Microsoft Dynamics CRM 4.0 data such as described above, and may only be purchased to supplement a Limited External Connector with write-access capability. The Full Use Additive External connector will appear on price lists as the Dyn CRM Additve ExtrnlCon.




External Connectors and Limited External Connectors may be mixed within an environment.

The number of Full Use Additive External Connectors may never exceed the total number of Limited External Connectors used within an organization.

An External Connector is a license only, and does not include any physical software components, and does not include licensing for any other Microsoft products. If external scenarios integrate with Microsoft SQL Server, Microsoft Office SharePoint or any other product license rights for these must be established separately.

For more information on Microsoft Dynamics CRM 4.0 Use Rights under Volume Licensing: http://www.microsoftvolumelicensing.com/userights/

Partners and Customers should work with their Microsoft Licensing Specialist or local Microsoft Representative to ensure their licensing compliance.

11 December 2008

CRM 4.0 Get attribute value from entity's GUID using JScript

Recently I have been asked many times about how to get attribute value from entity's GUID using JScript?
The following code demonstrate how to get a user's internalemailaddress by giving user's GUID.
*It has been modified to support multi-tenent deployment.


alert(GetAttributeValueFromID("systemuser", "09DF2AB7-E16D-DD11-88F3-0003FF884968", "internalemailaddress", "systemuserid"));

function GetAttributeValueFromID(sEntityName, sGUID, sAttributeName, sID)
{
var xml = "" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
GenerateAuthenticationHeader() +
" <soap:Body>" +
" <RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
" <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
" <q1:EntityName>"+sEntityName+"</q1:EntityName>" +
" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
" <q1:Attributes>" +
" <q1:Attribute>"+sAttributeName+"</q1:Attribute>" +
" </q1:Attributes>" +
" </q1:ColumnSet>" +
" <q1:Distinct>false</q1:Distinct>" +
" <q1:PageInfo>" +
" <q1:PageNumber>1</q1:PageNumber>" +
" <q1:Count>1</q1:Count>" +
" </q1:PageInfo>" +
" <q1:Criteria>" +
" <q1:FilterOperator>And</q1:FilterOperator>" +
" <q1:Conditions>" +
" <q1:Condition>" +
" <q1:AttributeName>"+sID+"</q1:AttributeName>" +
" <q1:Operator>Equal</q1:Operator>" +
" <q1:Values>" +
" <q1:Value xsi:type=\"xsd:string\">"+sGUID+"</q1:Value>" +
" </q1:Values>" +
" </q1:Condition>" +
" </q1:Conditions>" +
" </q1:Criteria>" +
" </query>" +
" </RetrieveMultiple>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";

var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");

xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);

// retrieve response and find attribute value
var result = xmlHttpRequest.responseXML.selectSingleNode("//q1:" + sAttributeName);
if (result == null)
return "";
else
return result.text;
}

03 December 2008

Quick Find for Inactive Records

CRM Quick Find Active [Entity] view only return active records. It's a common requirement to return both Active/Inactive records. I use a easy way to allow Quick Find view to return both Active/Inactive records, here it is (unsupported!):

1. Export the entity's customization to a xml file;
2. Edit the xml file, search 'Quick Find Active' then locate to the right code piece;
3. Delete the filter which is:





4. Save the xml, import to CRM, then Publish.

Now the Quick Find view can return both Active and Inactive records. ;-)

28 November 2008

Code: CRM 4.0 Dashboard Intergate with FusionCharts

I have been asked many times through email/blog for sharing code about the CRM Dashboard with FusionChart integration. So I decide to extract some code and build a demo project to share, it's a simple work for demo, so please don't expect too much. :)

The demo dashboard supports:
• CRM 4.0, multi-tenants(one URL for different organizations);
• IFD and On-Premise deployment;
• CRM user security(users only see relevant data which their have privileges)

You may deploy the solution under ISV folder, you also need to change sitemap to show the Dashboard:




Download the solution

25 October 2008

Microsoft Outlook is not set as the default mail client?


Today I install CRM Outlook on my Vista(with Outlook 2007), it gives me a strange error:"Microsoft Outlook is not set as the default mail client. Please set Microsoft Outlook as the default mail client from Control Panel\Internet Options\Programs, and then re-run the check."

I'm sure the Outlook is my default mail client, just in case I reset it again. but the error still exist! I'm aware of CRM always query Registry to get information in such cases, so open the default application key: HKLM\SOFTWARE\Clients\Mail, the Default value is Windows Live Mail, so change it to Microsoft Outlook, the error gone!