James Downey’s CRM Blog
Thoughts on the technology and business of CRM

Displaying CRM Views in IFRAMES

Thursday, 13 November 2008 03:21 by James Downey

Recently I needed to display a CRM view in an IFRAME and built a solution using the approach outlined by Michael Michael Höhne's on his blog. Michael was himself building upon an idea suggested by Stefan on the CRM newsgroup microsoft.public.crm.developer. I've made a slight addition to this technique that I'd like to share with the community.

As is noted in Michael's article, it is fairly easy to display an associated view in an IFRAME, but since each entity supports only one associated view and it is not possible to customize the filter, the use of an associated view will not always meet the requirements.

A more flexible approach is based on Advanced Find, which builds a query by forming an HTTP POST request that returns a set of records in a view. The form elements included in the post define the FetchXML query, which determines which rows get returned, as well as the layout of the columns.

After defining an Advanced Find, you can extract the form elements by placing javascript:alert(resultRender.outerHTML) in the address bar and looking for the resultRender form. Another way to get at the resultRender form is to use the IE developer toolbar. After extracting the resultRender form, insert it into an html page with an onload event that posts it to /AdvancedFind/fetchData.aspx. You can then reference this html page in an IFRAME to display it on a CRM form.

However, you will frequently need to make the view dynamic by displaying only the records related to another entity, such as all of the contacts related to an account. Michael suggests using an ASP.NET page that would accept the parent record id and insert it into the FetchXML query. I took a somewhat different approach and used JavaScript to accomplish the same task.

Here are the steps:

1) Open the Advanced Find window and click Ctrl-N to open the browser with the menu. Define an Advaned Find query for Contact (or any other entity) and set the Parent Customer (or any other field that you need to filter by) to equal a specific customer. Make sure to define the columns by clicking Edit Columns.

2) Click on the icon for the IE developer toolbar. (Download the toolbar from http://www.microsoft.com/downloads/details.aspx?familyid=e59c3964-672d-4511-bb3e-2d5e1db91038&displaylang=en.) Right-click on the element <FORM id=resultRender> and select Element Source.

3) Copy all of the elements between the <FORM> and </FORM> tags.

4) Paste the form elements into the html page below between the FORM tags in the html below.

<html>
<head>
<SCRIPT LANGUAGE="JavaScript" SRC="ViewFunctions.js">
</SCRIPT>
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
</head>

<body onload="setKey('id');resultRender.submit();">
        <FORM id=resultRender action="/AdvancedFind/fetchData.aspx" method="post">

     
        </FORM>
    </body>
</html>

5) Find the Condition element that contains the GUID for the account. Delete the uiname attribute and replace the GUID (including the braces) with __ID.

Before: <condition attribute='parentcustomerid' operator='eq' uiname='Blue Yonder Airlines' uitype='account' value='{D44D44AD-36D0-DC11-AA32-0003FF33509E}'/>

After: <condition attribute='parentcustomerid' operator='eq' uitype='account' value='__ID'/>

6) Save the html file to a subdirectory under the ISV folder on your CRM web server.

7) Save the following JavaScript code into a .js file named ViewFunctions.js and save it to the same directory as the html page.

function PageQuery(q) {
 if(q.length > 1) this.q = q.substring(1, q.length);
 else this.q = null;
 this.keyValuePairs = new Array();
 if(q) {
  for(var i=0; i < this.q.split("&").length; i++) {
   this.keyValuePairs[i] = this.q.split("&")[i];
  }
 }
 this.getKeyValuePairs = function() { return this.keyValuePairs; }
 this.getValue = function(s) {
 for(var j=0; j < this.keyValuePairs.length; j++) {
  if(this.keyValuePairs[j].split("=")[0] == s)
   return this.keyValuePairs[j].split("=")[1];
  }
  return false;
 }
 this.getParameters = function() {
 var a = new Array(this.getLength());
 for(var j=0; j < this.keyValuePairs.length; j++) {
  a[j] = this.keyValuePairs[j].split("=")[0];
 }
 return a;
 }
 this.getLength = function() { return this.keyValuePairs.length; }
}

function queryString(key){
 var page = new PageQuery(window.location.search);
 return unescape(page.getValue(key));
}

function setKey(id){
 var id = queryString(key);
 var fetch = resultRender.FetchXml.value;
 fetch=fetch.replace(/__ID/g,id);
 resultRender.FetchXml.value=fetch;
}

8) Place an IFRAME and your form and set the URL property to the html file. Make sure to check the "Pass record object-type code" check box.

After publishing, the result looks like the screen below.

By way of warning, this is not a supported customization because it depends upon the html structure in Dynamics CRM. When it comes time to migrate to CRM 5.0, these views may break. On the other hand, it is a fast and powerful technique for meeting many business requirements without writing custom Asp.Net pages. When CRM 5.0 is released, keep tuned to the newsgroup and blogs on ways to make this customization work in the new version.

Currently rated 4.7 by 6 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5