[gelöst] Umstellen auf OData um Upgrade fähig zu werden

5. Mai 2015 10:12

Hallo zusammen,

ich stehe grade etwas auf dem Schlauch. Vielleicht verstehe ich da auch was grundsätzliches nicht. :-( Ich habe folgende Webservice Abfrage (heißen die so ich meine ja), die ich gerne in OData umstricken würde. Denn das CodeValidationTool meckert dies für CRM 2013 an.
Code:
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>equipment</q1:EntityName>" +
   " <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
   " <q1:Attributes>" +
   " <q1:Attribute>name</q1:Attribute>" +
   " </q1:Attributes>" +
   " </q1:ColumnSet>" +
   " <q1:Distinct>false</q1:Distinct>" +
   " <q1:Criteria>" +
   " <q1:FilterOperator>And</q1:FilterOperator>" +
   " <q1:Conditions>" +
   " <q1:Condition>" +
   " <q1:AttributeName>opd_ist_fahrzeug</q1:AttributeName>" +
   " <q1:Operator>Equal</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">1</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +   
   " </q1:Conditions>" +
   " </q1:Criteria>" +
   " <q1:LinkEntities>" +
   " <q1:LinkEntity>" +
   " <q1:LinkFromAttributeName>equipmentid</q1:LinkFromAttributeName>" +
   " <q1:LinkFromEntityName>equipment</q1:LinkFromEntityName>" +
   " <q1:LinkToEntityName>activityparty</q1:LinkToEntityName>" +
   " <q1:LinkToAttributeName>partyid</q1:LinkToAttributeName>" +
   " <q1:JoinOperator>Inner</q1:JoinOperator>" +   
   " <q1:LinkEntities>" +
   " <q1:LinkEntity>" +
   " <q1:LinkFromAttributeName>activityid</q1:LinkFromAttributeName>" +
   " <q1:LinkFromEntityName>activityparty</q1:LinkFromEntityName>" +
   " <q1:LinkToEntityName>serviceappointment</q1:LinkToEntityName>" +
   " <q1:LinkToAttributeName>activityid</q1:LinkToAttributeName>" +
   " <q1:JoinOperator>Inner</q1:JoinOperator>" +
   " <q1:LinkCriteria>" +
   " <q1:FilterOperator>And</q1:FilterOperator>" +
   " <q1:Conditions>" +
   " <q1:Condition>" +
   " <q1:AttributeName>scheduledstart</q1:AttributeName>" +
   " <q1:Operator>Between</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sVon + "</q1:Value>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sBis + "</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +
   " <q1:Condition>" +
   " <q1:AttributeName>scheduledend</q1:AttributeName>" +
   " <q1:Operator>Between</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sVon + "</q1:Value>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sBis + "</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +
   " </q1:Conditions>" +
   " </q1:LinkCriteria>" +
   " </q1:LinkEntity>" +
   " </q1:LinkEntities>" +
   " </q1:LinkEntity>" +
   " </q1:LinkEntities>" +
   " </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;


nun habe ich einen Anfang gemacht, das ganze in OData zu übersetzen komme aber nicht weiter weil ich nicht weiß wie ich nach dem expand Equipment_activity_parties noch auf die Serviceaktivität komme. Geht das mit OData überhaupt? Und der Filter mit ScheduledEnd und ScheduledStart würde sich ja auch auf die Serviceaktität beziehen klappt dies und muss ich da noch was spezielles vorschreiben das klar ist über welcher der Entitäten gefiltert werden soll?

Code:
var resultSet = GetResultSetWithOData("/EquipmentSet?$select=*&$expand=equipment_activity_parties&$filter=ScheduledStart ge '"+ sVon +"' and ScheduledStart le '"+ sBis +"' and ScheduledEnd ge '"+ sVon +"' and ScheduledStart le '"+ sBis +"'");


Sollte das mit OData nicht gehen was ich da vor habe, hat dann jemand eine andere Idee wie ich das Ganze CRM 2013 und am besten auch gleich CRM 2015 tauglich bekomme?

Danke und viele Grüße
Nicole
Zuletzt geändert von Nicole Schmitz am 13. August 2015 13:12, insgesamt 3-mal geändert.

Re: Umstellen auf OData um Upgrade fähig zu werden

6. Mai 2015 08:33

Hallo NIcole,

der folgende Artikel beschreibt ganz gut die Unterschiede, und wie diese Programmiert werden:
Fetch XML vs. Retrieve Multiple vs. oData

Und hier noch ein KB Artikel, der die Nutzung von Odata mit Retrieve multiple erklärt:
Sample: Retrieve multiple records using the OData endpoint with JavaScript

Re: Umstellen auf OData um Upgrade fähig zu werden

6. Mai 2015 13:27

Hallo Michael,

ist es denn richtig das dieses GenerateAuthenticationHeader() im crm 2015 nicht mehr funktionieren wird? ich habe versucht den Soap Header selber zu schreiben, und die zugrundeliegende Funktion die mir Fahrzeuge zurückgeben soll funktioniert damit scheinbar auch allerdings kommt ständig ein Loginfenster das nach der Benutzerauthentifizierung fragt. Das bekomm ich irgendwie nicht weg. Vielleicht hast du oder jemand anderes da auch noch einen Tipp zu. Ich ging davon aus das diese Webserviceanfragen im neuen CRM nicht mehr funktionieren aber nach den Artikeln die du mir geschickt hast versteh ich das so das sie schon noch funktionieren. Das Validationtool meckert ja auch nur die Authentifizierung an. Aber irgendwie bekomm ich die nicht passend umgestrickt. Was mache ich falsch?

Code:
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:Header>" +
   "<CrmAuthenticationToken xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
   "<AuthenticationType xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">0</AuthenticationType>" +
   "<OrganizationName xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">Organisation</OrganizationName>" +
   "</CrmAuthenticationToken>" +
   "</soap:Header>" +
   " <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>equipment</q1:EntityName>" +
   " <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
   " <q1:Attributes>" +
   " <q1:Attribute>name</q1:Attribute>" +
   " </q1:Attributes>" +
   " </q1:ColumnSet>" +
   " <q1:Distinct>false</q1:Distinct>" +
   " <q1:Criteria>" +
   " <q1:FilterOperator>And</q1:FilterOperator>" +
   " <q1:Conditions>" +
   " <q1:Condition>" +
   " <q1:AttributeName>opd_ist_fahrzeug</q1:AttributeName>" +
   " <q1:Operator>Equal</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">1</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +   
   " </q1:Conditions>" +
   " </q1:Criteria>" +
   " <q1:LinkEntities>" +
   " <q1:LinkEntity>" +
   " <q1:LinkFromAttributeName>equipmentid</q1:LinkFromAttributeName>" +
   " <q1:LinkFromEntityName>equipment</q1:LinkFromEntityName>" +
   " <q1:LinkToEntityName>activityparty</q1:LinkToEntityName>" +
   " <q1:LinkToAttributeName>partyid</q1:LinkToAttributeName>" +
   " <q1:JoinOperator>Inner</q1:JoinOperator>" +   
   " <q1:LinkEntities>" +
   " <q1:LinkEntity>" +
   " <q1:LinkFromAttributeName>activityid</q1:LinkFromAttributeName>" +
   " <q1:LinkFromEntityName>activityparty</q1:LinkFromEntityName>" +
   " <q1:LinkToEntityName>serviceappointment</q1:LinkToEntityName>" +
   " <q1:LinkToAttributeName>activityid</q1:LinkToAttributeName>" +
   " <q1:JoinOperator>Inner</q1:JoinOperator>" +
   " <q1:LinkCriteria>" +
   " <q1:FilterOperator>And</q1:FilterOperator>" +
   " <q1:Conditions>" +
   " <q1:Condition>" +
   " <q1:AttributeName>scheduledstart</q1:AttributeName>" +
   " <q1:Operator>Between</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sVon + "</q1:Value>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sBis + "</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +
   " <q1:Condition>" +
   " <q1:AttributeName>scheduledend</q1:AttributeName>" +
   " <q1:Operator>Between</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sVon + "</q1:Value>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sBis + "</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +
   " </q1:Conditions>" +
   " </q1:LinkCriteria>" +
   " </q1:LinkEntity>" +
   " </q1:LinkEntities>" +
   " </q1:LinkEntity>" +
   " </q1:LinkEntities>" +
   " </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;


Viele Grüße
Nicole

Re: Umstellen auf OData um Upgrade fähig zu werden

6. Mai 2015 13:35

Funktioniert doch mit dem selbst gebastelten Header ich hatte im Organisationsnamen eine Tippfehler :roll:

Re: [gelöst] Umstellen auf OData um Upgrade fähig zu werden

6. Mai 2015 14:29

Hier nochmal die gesamte Funktion (falls nochmal jemand wie der Ochs vorm Berg steht und nicht weiß wie anpacken :-) ) mit eingebautem Soap Header und Browserunterscheidung. Da meckert auch das Validationtool nicht mehr bzw. nur noch an der Verzweigung zum alten IE wegen dem ActiveX aber das ist ja ok. Das ganze geht vielleicht auch eleganter aber das tut es auch.

Code:
function gebuchteFirmenwagen(sVon,sBis){
   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\">" +
   "<soap:Header>" +
   "<CrmAuthenticationToken xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
   "<AuthenticationType xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">0</AuthenticationType>" +
   "<OrganizationName xmlns=\"http://schemas.microsoft.com/crm/2007/CoreTypes\">"+Xrm.Page.context.getOrgUniqueName()+"</OrganizationName>" +
   "</CrmAuthenticationToken>" +
   "</soap:Header>" +
   " <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>equipment</q1:EntityName>" +
   " <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
   " <q1:Attributes>" +
   " <q1:Attribute>name</q1:Attribute>" +
   " </q1:Attributes>" +
   " </q1:ColumnSet>" +
   " <q1:Distinct>false</q1:Distinct>" +
   " <q1:Criteria>" +
   " <q1:FilterOperator>And</q1:FilterOperator>" +
   " <q1:Conditions>" +
   " <q1:Condition>" +
   " <q1:AttributeName>opd_ist_fahrzeug</q1:AttributeName>" +
   " <q1:Operator>Equal</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">1</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +   
   " </q1:Conditions>" +
   " </q1:Criteria>" +
   " <q1:LinkEntities>" +
   " <q1:LinkEntity>" +
   " <q1:LinkFromAttributeName>equipmentid</q1:LinkFromAttributeName>" +
   " <q1:LinkFromEntityName>equipment</q1:LinkFromEntityName>" +
   " <q1:LinkToEntityName>activityparty</q1:LinkToEntityName>" +
   " <q1:LinkToAttributeName>partyid</q1:LinkToAttributeName>" +
   " <q1:JoinOperator>Inner</q1:JoinOperator>" +   
   " <q1:LinkEntities>" +
   " <q1:LinkEntity>" +
   " <q1:LinkFromAttributeName>activityid</q1:LinkFromAttributeName>" +
   " <q1:LinkFromEntityName>activityparty</q1:LinkFromEntityName>" +
   " <q1:LinkToEntityName>serviceappointment</q1:LinkToEntityName>" +
   " <q1:LinkToAttributeName>activityid</q1:LinkToAttributeName>" +
   " <q1:JoinOperator>Inner</q1:JoinOperator>" +
   " <q1:LinkCriteria>" +
   " <q1:FilterOperator>And</q1:FilterOperator>" +
   " <q1:Conditions>" +
   " <q1:Condition>" +
   " <q1:AttributeName>scheduledstart</q1:AttributeName>" +
   " <q1:Operator>Between</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sVon + "</q1:Value>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sBis + "</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +
   " <q1:Condition>" +
   " <q1:AttributeName>scheduledend</q1:AttributeName>" +
   " <q1:Operator>Between</q1:Operator>" +
   " <q1:Values>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sVon + "</q1:Value>" +
   " <q1:Value xsi:type=\"xsd:string\">" + sBis + "</q1:Value>" +
   " </q1:Values>" +
   " </q1:Condition>" +
   " </q1:Conditions>" +
   " </q1:LinkCriteria>" +
   " </q1:LinkEntity>" +
   " </q1:LinkEntities>" +
   " </q1:LinkEntity>" +
   " </q1:LinkEntities>" +
   " </query>" +
   " </RetrieveMultiple>" +
   " </soap:Body>" +
   "</soap:Envelope>" +
   "";
   
   var xmlHttpRequest;
    var resultXml;
    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlHttpRequest = new XMLHttpRequest();
        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);
        resultXml = xmlHttpRequest.responseXML;
    }
    else {// code for IE6, IE5
        xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);

        xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
        xmlHttpRequest.send(xml);
        resultXml = xmlHttpRequest.responseXML;
    }

   var resultSet = resultXml.xml.split("<q1:name>");
   var firmenwagenArray = new Array();
   for(i=1; i<resultSet.length; i++){
      var firmenwagen = resultSet[i].split("</q1:name>");
      var firmenwagenschonda = false;
      for(j=0; j<firmenwagenArray.length; j++){
         if(firmenwagen[0]==firmenwagenArray[j]){
            j=firmenwagenArray.length+1
            firmenwagenschonda = true;
         } else {
            firmenwagenschonda = false;
         }
      }
      if(!firmenwagenschonda){
         firmenwagenArray.push(firmenwagen[0]);
      }
   }
   
   return firmenwagenArray;
}

Re: [gelöst] Umstellen auf OData um Upgrade fähig zu werden

8. Mai 2015 09:11

Hallo Nicole,

hab vielen Dank für die Rückmeldung und die Bereitstellung des Codes :-)

Re: [gelöst] Umstellen auf OData um Upgrade fähig zu werden

8. Juli 2015 10:25

Hallo zusammen,

leider doch noch nicht ganz gelöst. Da hab ich mit zu früh gefreut. Es funktionierte zwar so in CRM 2011 aber was ich nicht bedacht bzw. nicht aufgepasst habe ich benutze immer noch den alten Webservice Endpoint. :-( Das geht für CRM 2013 und 2015 dann natürlich nicht mehr. Das Upgrade meckert schon.
Ich habe mit die REST Beispiele zu RetrieveMultiple nochmal angesehen und auch die zugehörigen OData Befehle. Leider sieht es für mich so aus, das ich bei den Verlinkten Entitäten die ich dort angeben kann nicht filtern kann. Dann bringt mir das ganze leider so gar nichts. Die Abfrage die ich starten möchte sucht ja alle Equipments die den Haken bei IstFahrzeug gesetzt haben verknüpft mit der Activityparty über partyid und dann noch verknüpft mit serviceappointment über activityid. Von den Serviceappointment sollen aber nur die ausgegenen werden wo scheduledstart zwichen von und bis liegt sowie scheduledend zwichen von und bis. Ich kanns nicht besser beschrieben und hoffe das war halbwegs zu verstehen. Ich muss also über eine verknüpfte Entität filtern. Soweit ich das bis jetzt verstanden habe geht das mit OData nicht. Gibt es einen anderen weg? In CRM 4 und 11 ging das so schön mit den crmservices das muss doch im neuen auch noch irgendwie gehen. jemand ne Idee?

Viele Grüße
Nicole

Re: Umstellen auf OData um Upgrade fähig zu werden

10. August 2015 15:23

Ich empfehle dir das folgende Tool:
https://crmrestbuilder.codeplex.com/
Einfach als Solution einspielen und die Solution öffnen. Damit kannst du dir ganz einfach Filterkriterien zusammenklicken. Das Tool generiert dir dann den entsprechenden Javascript Code zum Webservice-Aufruf den du dann in deine Forms einbauen kannst. Hat mir sehr geholfen für die Standard-Retrieve/RetrieveMultiple-Calls.