5. November 2009 – 00:02 | No Comment

I have been working on quite a lot of small quick posts this last week but I’m also working on some more complex posts to put in the xRM development category.I  hope these I’ll find …

Read the full story »
xRM Development

This area is mostly about dev related stuff – tips, tricks, code snippets and more

xRM Integration

System integration in xRM deployments is a key factor for user adoption – Intelligent integration makes is even more valuable

xRM Network

The Dynamics CRM Developer Group is intended to be the place for Dynamics CRM developers to network, discuss ideas and have fun!

xRM News

News in the xRM world – and in the Danish xRM community!

xRM Toolbox

Codesnippets and other stuff for download

xRM Development »

JavaScript fetch
31. December 2009 – 11:47 | No Comment

When working on partner hosted Dynamics CRM deployments it is not possible to deploy assemblies on the server – so the solution does often involve JavaScript.

This solution is based on elements found round and about on different blogs and some ideas of my own.

This solution displays a picture on the account form saved attached to a note (annotation).

First the Fetch sentence to retrieve the annotationid

   1:  function getAccountLogoAnnotationId() {
   2:      var fetchXml = '';
   3:      fetchXml += '<fetch mapping="logical" count="50" version="1.0">';
   4:      fetchXml += '<entity name="annotation">';
   5:      fetchXml += '<attribute name="annotationid" />';
   6:      fetchXml += '<filter>';
   7:      fetchXml += '<condition attribute="filename" operator="eq" value="logo.png" />';
   8:      fetchXml += '<condition attribute="isdocument" operator="eq" value="1" />';
   9:      fetchXml += '<condition attribute="objecttypecode" operator="eq" value="1" />';
  10:      fetchXml += '<condition attribute="objectid" operator="eq" value="'+crmForm.ObjectId+'" />';
  11:      fetchXml += '</filter>';
  12:      fetchXml += '</entity>';
  13:      fetchXml += '</fetch>';
  14:      fetchXml += '';
  15:   
  16:      /* Make the fetch and retrieve xml result */
  17:      var resxml = Fetch(fetchXml);
  18:      /* Create an ObjTree Object */
  19:      var xotree = new XML.ObjTree();
  20:      /* Objectize xml result  */
  21:      var tree = xotree.parseXML(resxml);
  22:      return (tree.resultset.result.annotationid);
  23:   
  24:  }

 

Notice the xotree object – it’s a method to kind of create a JS object in this case a annotation object, but it could be any CRM entity – for more information have a look here: Objectizing Ajax (XML) results

My code is copy pasted from Adi Katz blog post – i’ll repost it here:

   1:  if ( typeof(XML) == 'undefined' ) XML = function() {};
   2:   
   3:  //  constructor
   4:   
   5:  XML.ObjTree = function () {
   6:      return this;
   7:  };
   8:   
   9:  //  object prototype
  10:  XML.ObjTree.prototype.xmlDecl = '<?xml version="1.0" encoding="UTF-8" ?>\n';
  11:  XML.ObjTree.prototype.attr_prefix = '';
  12:   
  13:  //  method: parseXML( xmlsource )
  14:  XML.ObjTree.prototype.parseXML = function ( xml ) {
  15:      var root;
  16:      if ( window.ActiveXObject ) {
  17:          xmldom = new ActiveXObject('Microsoft.XMLDOM');
  18:          xmldom.async = false;
  19:          xmldom.loadXML( xml );
  20:          root = xmldom.documentElement;
  21:      }
  22:      if ( ! root ) return;
  23:      return this.parseDOM( root );
  24:  };
  25:   
  26:  //  method: parseDOM( documentroot )
  27:  XML.ObjTree.prototype.parseDOM = function ( root ) {
  28:      if ( ! root ) return;
  29:   
  30:      this.__force_array = {};
  31:      if ( this.force_array ) {
  32:          for( var i=0; i<this.force_array.length; i++ ) {
  33:              this.__force_array[this.force_array[i]] = 1;
  34:          }
  35:      }
  36:   
  37:      var json = this.parseElement( root );   // parse root node
  38:      if ( this.__force_array[root.nodeName] ) {
  39:          json = [ json ];
  40:      }
  41:      if ( root.nodeType != 11 ) {            // DOCUMENT_FRAGMENT_NODE
  42:          var tmp = {};
  43:          tmp[root.nodeName] = json;          // root nodeName
  44:          json = tmp;
  45:      }
  46:      return json;
  47:  };
  48:   
  49:  //  method: parseElement( element )
  50:  XML.ObjTree.prototype.parseElement = function ( elem ) {
  51:      //  COMMENT_NODE
  52:      if ( elem.nodeType == 7 ) {
  53:          return;
  54:      }
  55:   
  56:      //  TEXT_NODE CDATA_SECTION_NODE
  57:      if ( elem.nodeType == 3 || elem.nodeType == 4 ) {
  58:          var bool = elem.nodeValue.match( /[^\x00-\x20]/ );
  59:          if ( bool == null ) return;     // ignore white spaces
  60:          return elem.nodeValue;
  61:      }
  62:   
  63:      var retval;
  64:      var cnt = {};
  65:   
  66:      //  parse attributes
  67:      if ( elem.attributes && elem.attributes.length ) {
  68:          retval = {};
  69:          for ( var i=0; i<elem.attributes.length; i++ ) {
  70:              var key = elem.attributes[i].nodeName;
  71:              if ( typeof(key) != "string" ) continue;
  72:              var val = elem.attributes[i].nodeValue;
  73:              if ( ! val ) continue;
  74:              key = this.attr_prefix + key;
  75:              if ( typeof(cnt[key]) == "undefined" ) cnt[key] = 0;
  76:              cnt[key] ++;
  77:              this.addNode( retval, key, cnt[key], val );
  78:          }
  79:      }
  80:   
  81:      //  parse child nodes (recursive)
  82:      if ( elem.childNodes && elem.childNodes.length ) {
  83:          var textonly = true;
  84:          if ( retval ) textonly = false;        // some attributes exists
  85:          for ( var i=0; i<elem.childNodes.length && textonly; i++ ) {
  86:              var ntype = elem.childNodes[i].nodeType;
  87:              if ( ntype == 3 || ntype == 4 ) continue;
  88:              textonly = false;
  89:          }
  90:          if ( textonly ) {
  91:              if ( ! retval ) retval = "";
  92:              for ( var i=0; i<elem.childNodes.length; i++ ) {
  93:                  retval += elem.childNodes[i].nodeValue;
  94:              }
  95:          } else {
  96:              if ( ! retval ) retval = {};
  97:              for ( var i=0; i<elem.childNodes.length; i++ ) {
  98:                  var key = elem.childNodes[i].nodeName.replace("#","");
  99:                  if ( typeof(key) != "string" ) continue;
 100:                  var val = this.parseElement( elem.childNodes[i] );
 101:                  if ( ! val ) continue;
 102:                  if ( typeof(cnt[key]) == "undefined" ) cnt[key] = 0;
 103:                  cnt[key] ++;
 104:                  this.addNode( retval, key, cnt[key], val );
 105:              }
 106:          }
 107:      }
 108:      return retval;
 109:  };
 110:   
 111:  //  method: addNode( hash, key, count, value )
 112:  XML.ObjTree.prototype.addNode = function ( hash, key, cnts, val ) {
 113:   key = this.key_qualify(key);
 114:      if ( this.__force_array[key] ) {
 115:          if ( cnts == 1 ) hash[key] = [];
 116:          hash[key][hash[key].length] = val;      // push
 117:      } else if ( cnts == 1 ) {                   // 1st sibling
 118:          hash[key] = val;
 119:      } else if ( cnts == 2 ) {                   // 2nd sibling
 120:          hash[key] = [ hash[key], val ];
 121:      } else {                                    // 3rd sibling and more
 122:          hash[key][hash[key].length] = val;
 123:      }
 124:  };
 125:   
 126:  XML.ObjTree.prototype.key_qualify = function( key ){
 127:   return key.replace(/\W/gi,"");
 128:  }
 129:  //  method: xml_escape( text )
 130:  XML.ObjTree.prototype.xml_escape = function ( text ) {
 131:      return String(text).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
 132:  };
 133:   
 134:  /*
 135:  Copyright (c) 2005-2006 Yusuke Kawasaki. All rights reserved.
 136:  This program is free software; you can redistribute it and/or
 137:  modify it under the Artistic license. Or whatever license I choose,
 138:  which I will do instead of keeping this documentation like it is.
 139:  */
 140:   

 

So there you have it – it’s actually pretty easy – and using Stunnware Javascript Factory it’s manageable in spite of the many lines of code.

Take care

Record Cloning
31. December 2009 – 00:01 | No Comment

One of my customers wanted to create Quote templates we had to figure out how it should be done – we thought about using opportunities as templates when choosing an opportunity as leading opp it …

xRM Application in 24 hours
4. November 2009 – 23:17 | No Comment

At Microsoft Partner Conference the MS CRM Team took the challenge of creating a xRM application in 24 hours. The team to fulfill this was Barry Givens, Nikhil Hasija, Reuben Krippner and Bryan Nelson.
To decide …

xRM Integration – make your systems play together
28. October 2009 – 23:09 | No Comment

Integration with Dynamics CRM is not the most popular task to do. But it can actually be done very easy and within a reasonable budget.
With the Rapidi Online integration solution you can easily hook up …