Friday, August 21, 2009

How to retrieve server datetime on the client in Microsoft Dynamics CRM 4.0

I have found interesting question on Microsoft Social forum and decided to develop such customization.

I had some ideas of how to do this:
1. Create custom aspx page.
2. Create custom webservice.
3. Use standard Microsoft CRM WebServices for this task.

The first and the second ways were not interesting for me because I had already used in some tasks I'd made. So I decided to implement the third idea.



So the points:
1. Create the plugin which will handle Execute message (Fetch from client side) and insert server datetime in the response XML.
2. Write client side JavaScript code which will execute this Fetch request, retrieve the result XML and parse it.

Plugin code (Registration: Message - Execute, Primary Entity - none, Secondary Entity - none, Stage of Execution - Post Stage, Execution Mode - Synchronous, Triggering Pipeline - Parent Pipeline):

using System;

using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using System.Xml;

namespace TimePlugin
{
public class ExecuteXMLParser : IPlugin
{
#region IPlugin Members

public void Execute(IPluginExecutionContext context)
{
if (context.MessageName == "Execute" && context.OutputParameters.Contains("FetchXMLResult"))
{
//I retrieve response XML
string result = (string)context.OutputParameters.Properties["FetchXMLResult"];

XmlDocument document = new XmlDocument();
//Load this XML into XMLDocument
document.LoadXml(result);

//Create and add attribute with current date time
XmlAttribute timeAttribute = document.CreateAttribute("ServerDateTime");
timeAttribute.Value = DateTime.Now.ToString("yyyy.MM.dd.hh.mm.ss");
document.FirstChild.Attributes.Append(timeAttribute);

//Place modified result XML to context to be returned to client
context.OutputParameters["FetchXMLResult"] = document.OuterXml;
}
}

#endregion IPlugin Members
}
}


Client side JavaScript (You can use any fetch request you have):

//Create simple Fetch xml request

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>"+
"<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"+
"<fetchXml>&lt;fetch mapping='logical'&gt;"+
"&lt;entity name='systemuser'&gt;"+
"&lt;no-attrs/&gt;"+
"&lt;filter type='and'&gt;"+
"&lt;condition attribute='systemuserid' operator='eq-userid'/&gt;"+
"&lt;/filter&gt;"+
"&lt;/entity&gt;"+
"&lt;/fetch&gt;</fetchXml>"+
"</Fetch>"+
"</soap:Body>"+
"</soap:Envelope>";

//Prepare the xmlHttpObject and send the request.
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);

//Capture the result
var resultSet = xHReq.responseXML.text;
resultSet.replace('&lt;','<');
resultSet.replace('&gt;','>');

//Create an XML document that can be parsed.
var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
oXmlDoc.async = false;
oXmlDoc.loadXML(resultSet);

//Value the user is interesed in in string form
var datetime = oXmlDoc.selectSingleNode('resultset').getAttribute('ServerDateTime').split(".");

//And the result - Date object
var result = new Date();
result.setFullYear(datetime[0]);
result.setMonth(datetime[1] - 1);
result.setDate(datetime[2]);
result.setHours(datetime[3] - 1);
result.setMinutes(datetime[4]);
result.setSeconds(datetime[5]);

alert(result);