Monday, September 22, 2008

Showing child grids in an IFRAME without custom grid

Here is some code where you can just insert some fetch xml in JavaScript and display the data in the standard grid. just replace the IFRAME_<name> and adjust the CHANGE HERE section with some custom fetch xml and the entity type name.

//Load view data
function GetAdvFindView(entityname)
{
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>" + 
"    <RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" + 
"      <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" + 
"        <q1:EntityName>savedquery</q1:EntityName>" + 
"        <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" + 
"          <q1:Attributes>" + 
"            <q1:Attribute>savedqueryid</q1:Attribute>" + 
"            <q1:Attribute>layoutxml</q1:Attribute>" + 
"          </q1:Attributes>" + 
"        </q1:ColumnSet>" + 
"        <q1:Distinct>false</q1:Distinct>" + 
"        <q1:Criteria>" + 
"          <q1:FilterOperator>And</q1:FilterOperator>" + 
"          <q1:Conditions>" + 
"            <q1:Condition>" + 
"              <q1:AttributeName>querytype</q1:AttributeName>" + 
"              <q1:Operator>Equal</q1:Operator>" + 
"              <q1:Values>" + 
"                <q1:Value xsi:type=\"xsd:int\">1</q1:Value>" + 
"              </q1:Values>" + 
"            </q1:Condition>" + 
"            <q1:Condition>" + 
"              <q1:AttributeName>fetchxml</q1:AttributeName>" + 
"              <q1:Operator>Like</q1:Operator>" + 
"              <q1:Values>" + 
"                <q1:Value xsi:type=\"xsd:string\">%&lt;entity name=\""+entityname+"\"&gt;%</q1:Value>" + 
"              </q1:Values>" + 
"            </q1:Condition>" + 
"          </q1:Conditions>" + 
"        </q1:Criteria>" + 
"      </query>" + 
"    </RetrieveMultiple>" + 
"  </soap:Body>" + 
"</soap:Envelope>" + 
"";
 
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
 
xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
 
var resultXml = xmlHttpRequest.responseXML;
 
if(resultXml.getElementsByTagName('BusinessEntity').length>0)
{
  return resultXml.getElementsByTagName('BusinessEntity')[0];
}
else
{ return null; }
 
 
}
 
//Loads page with child grid
function LoadChildGrid()
{
crmForm.all.IFRAME_LOCS.onreadystatechange= null;
 
//Create a new HTTP request.
    var request = new ActiveXObject("Msxml2.XMLHTTP");    
    request.onreadystatechange = function() 
    { 
      if (request.readyState == 4) 
      {
         if (request.status == 200) 
        {
           var newDoc=crmForm.all.IFRAME_LOCS.contentWindow.document.open();
           newDoc.write(request.responseText);
           newDoc.close();
         } 
        else 
        {
            alert('There was a problem with the request:'+request.status);
        }   
      }
    }
 
request.Open("POST", "/AdvancedFind/fetchData.aspx",true);
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
 
//CHANGE HERE------------------
var entityname='account';
var fetchxml = "<fetch mapping='logical'><entity name='account'><all-attributes/></entity></fetch>";
//CHANGE HERE-----------------
 
var view = GetAdvFindView(entityname);
if (view)
{
  var layoutxml = view.getElementsByTagName('q1:layoutxml')[0].firstChild.data;
  var defaultAdvFindViewId =view.getElementsByTagName('q1:savedqueryid')[0].firstChild.data;
 
  request.send("FetchXml="+escape(fetchxml)+"&DefaultAdvFindViewId="+defaultAdvFindViewId  +"&LayoutXml="+escape(layoutxml)+"&ViewType=1039");
}
 
}
crmForm.all.IFRAME_LOCS.onreadystatechange= LoadChildGrid;

2 comments:

Ludger said...

Hi Tim,

beim Deployment Deines Skriptes ist mir aufgefallen, dass sich ein tückische Fehlerteufelchen eingeschlichen hat.
Wenn du den Request öffnest, tust du das mit der Zeile:

request.Open("POST", "/AdvancedFind/fetchData.aspx",true);

der Request geht dann an die Standard-Organisation. Das hat hier zu einem Fehler geführt. Der korrekte Weg wäre:

request.Open("POST", "/" + ORG_UNIQUE_NAME + "/AdvancedFind/fetchData.aspx",true);

Dann klappts auch, wenn mehrere Organisationen auf dem Server eingerichtet sind. Vielleicht willst du das in Deinem Blog ja korrigieren.

Gruß,
Ludger

Ludger said...

moin Tim.
Nachtrag zu dem Kommentar:
Damit das Skript auch offline funktioniert, muss natürlich der Organisationsname bei Offline-Ausführung wieder raus:

var advfindurl = "/AdvancedFind/fetchData.aspx";
if (IsOnline())
advfindurl = "/" + ORG_UNIQUE_NAME + "/AdvancedFind/fetchData.aspx";

request.Open("POST", advfindurl ,true);