Here is a simple trick that will allow you to store JSON formatted data in a Web Resource in Microsoft Dynamics CRM. This provides a much more developer-friendly alternative to the XML data type that CRM offers. The benefits of using JSON to store and transfer data versus using XML are well known. It can be done using far less code, and it is much more consistent between different browsers. Having to support multiple browsers is difficult when working with XML data in javascript because different browsers (or even different versions of the same browser) can behave very differently. Storing data as a JSON web resource is a much simpler approach, but unfortunately, CRM does not offer a JSON data type for a Web Resource. Even a plain text type would work for that purpose as well, but that too is unavailable to us. Luckily, there is a way that we can make this work using a JScript type Web Resource.
Where would you actually use this? In my case, I’ve used this to store configuration details for a managed solution. The same thing can be accomplished using an XML web resource or a using a custom entity. A JSON Web Resource is significantly easier and less code than working with an entity when loading the data. The other problem with using an entity record to control solution settings is that records cannot be included in a solution whereas the JSON Web Resource can be included in a solution.
Example
Start by creating a new jscript type Web Resource, let’s call it new_config.js. Then define your object like this:
1 |
var configJSON = ‘{“value1″:”Hello”,”value2″:”World”}’; |
Next, create a custom configuration page, we will call it new_configuration.htm, as an html Web Resource, and include the script at the top of the file (this will load the string value). To load the entire set of config values, use JSON.parse(). This can also be done on a CRM form by including the config.js library on the form. Now, any other scripts on the page can access your custom settings without the need to perform any web service requests at all!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”> <html> <head> <title>My Config Page</title> <script type=“text/javascript” src=“ClientGlobalContext.js.aspx”></script> <script type=“text/javascript” src=“new_config.js”></script> // This is the reference to the “JSON” Web Resource <script type=“text/javascript”> var config = {}; function init() { // One single line of code to read our entire configuration table config = JSON.parse(configJSON); document.getElementById(“value1”).value = config.value1; document.getElementById(“value2”).value = config.value2; } </script> </head> <body onload=“init()”> Value 1: <input id=“value1” type=“text” /><br /> Value 2: <input id=“value2” type=“text” /><br /> <input id=“submit” onclick=“onSaveClick()” type=“button” value=“Save” /> </body> </html> |
As mentioned, you can use the same “config = JSON.parse(configJSON);” command inside any form jscript that will give you access to these values whenever you need them. To do this, add the new_config.js library to the form. No additional web service calls or XML parsing is needed.
Now you might ask “But how do we update these values?”. It’s true, without the ability to update, we might as well just hardcode an actual javascript object instead of as a JSON string, but storing this as a JSON string is what makes it so easy to update. To update the Web Resource, use a REST call. For example, add this function, and its helpers, to the page:
Note: This example makes the assumption that the guid of the webresource is known in advance, which should usually not be a problem
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function onSaveClick() { // Get the updated values, and re-create the JSON object config.value1 = document.getElementById(“value1”).value; config.value2 = document.getElementById(“value2”).value; var updatedConfig = “var configJSON = ‘” + JSON.stringify(config) + “‘;”; // Build the web resource record var webResource = {}; // Web Resource content attribute is 64-bit encoded webResource.Content = encode64(updatedConfig); // Send a REST call to update the Web Resource updateWebResource(webResourceId, webResource); } |
One last thing that you need to remember: when you update a Web Resource, you must Publish before you will see the change take effect. That can be done manually, or that can be done in javascript using a PublishAllXml SOAP request.
Lastly, here are the two re-usable helper functions you will need that get called by the onSaveClick function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
function updateWebResource(id, object) { var req = new XMLHttpRequest(); req.open(“POST”, encodeURI(Xrm.Page.context.getClientUrl() + “/XRMServices/2011/OrganizationData.svc/WebResourceSet(guid'” + id + “‘)”), true); req.setRequestHeader(“Accept”, “application/json”); req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”); req.setRequestHeader(“X-HTTP-Method”, “MERGE”); req.onreadystatechange = function () { if (this.readyState == 4 /* complete */) { req.onreadystatechange = null; if (this.status == 204 || this.status == 1223) { alert(“Saved!”); } else { alert(“Error!”); } } }; req.send(JSON.stringify(object)); } function encode64(input) { var keyStr = “ABCDEFGHIJKLMNOP” + “QRSTUVWXYZabcdef” + “ghijklmnopqrstuv” + “wxyz0123456789+/” + “=”; var output = “”; var chr1, chr2, chr3 = “”; var enc1, enc2, enc3, enc4 = “”; var i = 0; do { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); chr1 = chr2 = chr3 = “”; enc1 = enc2 = enc3 = enc4 = “”; } while (i < input.length); return output; } |
To see this technique in action, create a new solution in CRM and set the new_configuration.htm Web Resource as the configuration page for the solution. You will see the default values in the text boxes, which you can update and save (remember to publish after!). And finally, create an additional JScript Web Resource and set it to run onLoad of any form. Include the onLoad resource and the config resource as form libraries:
1 2 3 4 5 |
function accountFormOnLoad() { var config = JSON.parse(configJSON); Xrm.Page.ui.setFormNotification(config.value1 + ” “ + config.value2, ‘INFORMATION’, ‘555’); } |
After reading this, maybe you have some creative ideas of how to apply this technique that I haven’t yet thought of yet? Let me know in the comments below if you’ve found any other clever uses for this technique.