Following post describes how to allow bulk update of user details.
First step - JavaScript that will do update of data - create webresource, put inside following code, save and publish:
function RefreshUsersADInfo(selectedusers)
{
var orgserviceurl = Xrm.Page.context.prependOrgName("/XRMServices/2011/Organization.svc/web");
for(var i = 0; i < selectedusers.length; i++)
{
var domainname = GetDomainName(selectedusers[i], orgserviceurl);
UpdateUserADInfo(selectedusers[i], domainname, orgserviceurl);
}
crmGrid.Refresh();
}
function UpdateUserADInfo(userid, domainname, orgserviceurl)
{
var oCommand=new RemoteCommand("UserManager","RetrieveADUserProperties");
if(oCommand!=null)
{
oCommand.SetParameter("domainAccountName", domainname);
var oResult = oCommand.Execute();
var request = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">"+
"<s:Body>"+
"<Update xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">"+
"<entity xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">"+
"<a:Attributes xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
if(oResult.Success&&!IsNull(oResult.ReturnValue)&&oResult.ReturnValue.length>0)
for(var oUserXmlDoc=loadXmlDocument(oResult.ReturnValue),oNodeList=oUserXmlDoc.documentElement.childNodes,i=0;i<oNodeList.length;i++)
{
var oNode=oNodeList.item(i);
request += "<a:KeyValuePairOfstringanyType>"+
"<b:key>" + oNode.tagName + "</b:key>"+
"<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + oNode.text + "</b:value>"+
"</a:KeyValuePairOfstringanyType>";
}
request +="</a:Attributes>"+
"<a:EntityState i:nil=\"true\" />"+
"<a:FormattedValues xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\" />"+
"<a:Id>" + userid + "</a:Id>"+
"<a:LogicalName>systemuser</a:LogicalName>"+
"<a:RelatedEntities xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\" />"+
"</entity>"+
"</Update>"+
"</s:Body>"+
"</s:Envelope>";
var req = new XMLHttpRequest();
req.open("POST", orgserviceurl, false);
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Update");
req.send(request);
}
}
function GetDomainName(userid, orgserviceurl)
{
var request = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">"+
"<s:Body>"+
"<Retrieve xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">"+
"<entityName>systemuser</entityName>"+
"<id>" + userid + "</id>"+
"<columnSet xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">"+
"<a:AllColumns>false</a:AllColumns>"+
"<a:Columns xmlns:b=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">"+
"<b:string>domainname</b:string>"+
"</a:Columns>"+
"</columnSet>"+
"</Retrieve>"+
"</s:Body>"+
"</s:Envelope>";
var req = new XMLHttpRequest();
req.open("POST", orgserviceurl, false);
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Retrieve");
req.send(request);
var attributes = req.responseXML.getElementsByTagName("a:KeyValuePairOfstringanyType");
if (attributes == null || attributes.length == 0)
return null;
for(var i = 0; i < attributes.length; i++)
if (attributes[i].selectSingleNode("./b:key").text == "domainname")
{
var node = attributes[i].selectSingleNode("./b:value");
if (node != null)
return node.nodeTypedValue;
}
return null;
}
Second step - modify ribbon to add "Refresh" button to users grid. I prefer to use tools for it and here are screenshots:
Here is RibbonXml:
<RibbonDiffXml>
<CustomActions>
<CustomAction Id="xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.CustomAction" Location="Mscrm.HomepageGrid.systemuser.MainTab.Management.Controls._children" Sequence="41">
<CommandUIDefinition>
<Button Id="xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo" Command="xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.Command" Sequence="96" ToolTipTitle="$LocLabels:xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.LabelText" LabelText="$LocLabels:xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.LabelText" ToolTipDescription="$LocLabels:xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.Description" TemplateAlias="o2" Image16by16="/_imgs/grid/refresh16.gif" />
</CommandUIDefinition>
</CustomAction>
</CustomActions>
<Templates>
<RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
</Templates>
<CommandDefinitions>
<CommandDefinition Id="xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.Command">
<EnableRules>
<EnableRule Id="xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.Command.EnableRule.SelectionCountRule" />
</EnableRules>
<DisplayRules />
<Actions>
<JavaScriptFunction Library="$webresource:xs_refreshusers.js" FunctionName="RefreshUsersADInfo">
<CrmParameter Value="SelectedControlSelectedItemIds" />
</JavaScriptFunction>
</Actions>
</CommandDefinition>
</CommandDefinitions>
<RuleDefinitions>
<TabDisplayRules />
<DisplayRules />
<EnableRules>
<EnableRule Id="xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.Command.EnableRule.SelectionCountRule">
<SelectionCountRule Minimum="1" AppliesTo="SelectedEntity" />
</EnableRule>
</EnableRules>
</RuleDefinitions>
<LocLabels>
<LocLabel Id="xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.LabelText">
<Titles>
<Title languagecode="1033" description="Refresh" />
</Titles>
</LocLabel>
<LocLabel Id="xs.HomepageGrid.systemuser.MainTab.Management.refreshadinfo.Description">
<Titles>
<Title languagecode="1033" description="Refreshes Users' Info from AD" />
</Titles>
</LocLabel>
</LocLabels>
</RibbonDiffXml>
In the case you have performed everything correctly in users ribbon you will find new button:
Functions that are used for fetching of users' information are undocumented so I assume that in common this customization is unsupported.
I want to say special thanks to my friend Artem Grunin who is former MVP and employee of Microsoft. Here is his article regarding similar issue for CRM 4.0 - http://fixrm.wordpress.com/2011/02/02/how-to-update-crm-user-profile-from-active-directory/
I implemented per instructions - removed Main Phone and email address from a user (info came from AD during original import) - refreshed user - Main Phone and email address were NOT updated.
ReplyDeleteIn case fields were not updated you've done something wrong. Try to do everything step-by-step again.
ReplyDeletethis is great, thank you!
ReplyDelete