Overzicht: Gebruik het Moderne app SOAP eindpunt met JavaScript
Gepubliceerd: november 2016
Is van toepassing op: Dynamics CRM 2015
Dit overzicht toont het maken van een JavaScript bibliotheek voor gebruik met het SOAP eindpunt met webresources. Op dit moment biedt Microsoft Dynamics CRM 2015 en Microsoft Dynamics CRM Online 2015 Update geen JavaScript bibliotheken die u kunt gebruiken voor het aanroepen van beschikbare berichten met het SOAP eindpunt. Dit overzicht toont hoe u een JScript bibliotheek maakt voor het Assign bericht met behulp van de organisatieservicemethode Execute. Elk ander bericht dat de methode Execute gebruikt, zal een vergelijkbaar patroon volgen. Om een JavaScript bibliotheek te maken voor een bericht, is een gelijkaardig proces vereist. Voor een voorbeeld van een JavaScript bibliotheek die is ontwikkeld met dit proces, raadpleegt u Voorbeeld: metagegevens van entiteit ophalen met JavaScript.
Notitie
Voor een volledig voorbeeld van een JavaScript-bibliotheek met het SOAP-eindpunt raadpleegt u de bibliotheek Sdk.Soap.js. De bibliotheek Sdk.Soap.js is gemaakt met het hier beschreven proces.
Het proces bestaat uit het vastleggen van de HTTP aanvragen en de reacties verzonden van een beheerde codeconsoletoepassing en vervolgens het maken van een JavaScript bibliotheek met functies om dezelfde aanvragen te verzenden en gelijkaardige antwoorden te verwerken. Gewoonlijk wordt een toepassing gebruikt zoals Fiddler om HTTP aanvragen en reacties vast te leggen, maar Fiddler en soortgelijke toepassingen kunnen niet het versleutelde HTTP verkeer vastleggen dat is gebruikt voor lokale Microsoft Dynamics CRM 2015. De meegeleverde SOAPLogger voorbeeldoplossing legt de HTTP aanvragen vast voordat ze worden gecodeerd en de HTTP reacties nadat ze zijn gedecodeerd. De voorbeeldoplossing SOAPLogger werkt voor beide Microsoft Dynamics CRM 2015 en Microsoft Dynamics CRM Online 2015 Update.SOAPLogger filtert ook alle HTTP verkeer dat niet relevant is voor de taak voor het maken van een JScript bibliotheek.
Dit scenario begeleidt u door de volgende taken:
In Voorbeeld- HTTP-Aanvraag en Respons vastleggen bewerkt u de Run methode voor het SOAPLogger voorbeeld om een Assign aanvraag uit te voeren met beheerde code.
Vervolgens moet u de SOAPLogger oplossing uitvoeren om informatie te genereren over de verzonden HTTP aanvragen en de ontvangen reacties.
In Een JScript bibliotheek maken maakt u een JScript bibliotheek op basis van het geregistreerde HTTP verkeer om het Assign bericht te verzenden en te ontvangen met de methode voor Organisatieservice Execute.
In De JScript-bibliotheek testen test u de JScript bibliotheek om te bevestigen dat deze kan worden gebruikt om records toe te wijzen.
In Een interactieve webresource maken maakt u een HTML webresource die de bibliotheek gebruikt om Account records toe te wijzen aan een geselecteerde gebruiker zoals getoond in de volgende schermafbeelding.
Een beheerde oplossing voor dit volledig overzicht is beschikbaar in het SDK-pakket in SDK\SampleCode\JS\SOAPForJScript\SOAPEndpointforJScript_1_0_0_1_managed.zip. Download het Microsoft Dynamics CRM SDK-pakket. U kunt deze oplossing installeren (importeren) en de voltooide resultaten weergeven. Omdat dit echter een beheerde oplossing is, kunt u deze eenvoudig verwijderen om deze volledig te verwijderen van uw systeem.
De SDK\SampleCode\JS\SOAPForJScript\SOAPForJScript.sln is een Visual Studio oplossing die de bestanden HTML en JS bevat met de code in dit overzicht.
Vereisten
U moet beheerde code kunnen schrijven die overeenstemt met de functies die u wilt uitvoeren met behulp van JScript.
U hebt toegang nodig tot het SOAPLogger voorbeeld dat beschikbaar is in de SDK-downloadbestanden in SDK\SampleCode\CS\Client\SOAPLogger.
Notitie
Het SOAPLogger voorbeeld in het Microsoft Dynamics CRM SDK is alleen beschikbaar voor Microsoft Visual C#. Als u een Microsoft Visual Basic .NET-versie verkiest, raadpleegt u Microsoft Dynamics CRM VB.Net SoapLogger op CodePlex.
U hebt Microsoft Visual Studio nodig om de SOAPLogger oplossing uit te voeren.
U hebt een goede kennis nodig van JScript en asynchroon programmeren met XMLHttpRequest.
Voorbeeld- HTTP-Aanvraag en Respons vastleggen
De SOAPLogger oplossing bewerken om code toe te voegen om een AssignRequest uit te voeren met SoapLoggerOrganizationService. De SoapLoggerOrganizationService krijgt gegevens van de IOrganizationService en voegt de mogelijkheid toe om een logboekbestand te genereren dat het relevante HTTP dataverkeer weergeeft dat wordt verzonden en ontvangen.
Met behulp van Microsoft Visual Studio, opent u de SOAPLogger oplossing in SDK\SampleCode\CS\Client\SOAPLogger\SOAPLogger.sln.
Zoek in het bestand SoapLogger.cs de methode Run zoals aangegeven in het volgende voorbeeld:
public void Run(ServerConnection.Configuration serverConfig) { try { // Connect to the Organization service. // The using statement assures that the service proxy will be properly disposed. using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri, serverConfig.Credentials, serverConfig.DeviceCredentials)) { // This statement is required to enable early-bound type support. _serviceProxy.EnableProxyTypes(); IOrganizationService service = (IOrganizationService)_serviceProxy; using (StreamWriter output = new StreamWriter("output.txt")) { SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output); //Add the code you want to test here: // You must use the SoapLoggerOrganizationService 'slos' proxy rather than the IOrganizationService proxy you would normally use. } } } // Catch any service fault exceptions that Microsoft Dynamics CRM throws. catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>) { // You can handle an exception here or pass it back to the calling method. throw; } }
Identificeer een geldige id voor een SystemUser record en de id van een Account record dat niet aan die gebruiker is toegewezen.
Tip
Om de Id te krijgen van een record in de toepassing, opent u de record en voert u de opdracht Een koppeling kopiëren uit. Plak de koppeling in Kladblok en isoleer het gedeelte dat de id parameterwaarde bevat zonder de gecodeerde haakjes ("%7b" = "{") en ("%7d" = "}"). Het volgende is bijvoorbeeld een URL voor een Account record.<your organization root url>/main.aspx?etc=1&id=%7bF2CA52DE-552D-E011-A8FB-00155DB059BE%7d&pagetype=entityrecord>. De id-waarde is F2CA52DE-552D-E011-A8FB-00155DB059BE.
Gebruik deze waarden om de tijdelijke aanduidingswaarden in de onderstaande code te vervangen en voeg de code toe aan de uitvoeringsmethode waar aangegeven. Voor meer informatie over de toewijzingsaanvraag, zie AssignRequest.
Guid userId = new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); Guid accountId = new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); AssignRequest assign = new AssignRequest{Assignee = new EntityReference(SystemUser.EntityLogicalName, userId),Target = new EntityReference(Account.EntityLogicalName, accountId)}; AssignResponse assignResp = (AssignResponse)slos.Execute(assign);
Druk op F5 om fouten op te sporen in de toepassing. Voer gegevens in over de server en uw aanmeldgegevens. Als de code met succes wordt uitgevoerd, wordt het recordtype account nu toegewezen aan de gebruiker die u hebt opgegeven. Zie Een eenvoudig programma uitvoeren met Microsoft Dynamics CRM 2015-webservices voor meer informatie over het uitvoeren van voorbeeldcode
Ga in de SOAPLogger projectmappen naar de mappen bin en Debug en zoek het output.txt-bestand.
Open het output.txt bestand en controleer de inhoud. Deze moeten er ongeveer als volgt uitzien, behalve dat de werkelijke GUID-waarden de tijdelijke aanduiding "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX” vervangen.
HTTP REQUEST -------------------------------------------------- POST <your server root>/XRMServices/2011/Organization.svc/web Content-Type: text/xml; charset=utf-8 SOAPAction: https://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute <s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <Execute xmlns="https://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <request i:type="b:AssignRequest" xmlns:a="https://schemas.microsoft.com/xrm/2011/Contracts" xmlns:b="https://schemas.microsoft.com/crm/2011/Contracts"> <a:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic"> <a:KeyValuePairOfstringanyType> <c:key>Target</c:key> <c:value i:type="a:EntityReference"> <a:Id>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</a:Id> <a:LogicalName>account</a:LogicalName> <a:Name i:nil="true" /> </c:value> </a:KeyValuePairOfstringanyType> <a:KeyValuePairOfstringanyType> <c:key>Assignee</c:key> <c:value i:type="a:EntityReference"> <a:Id>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</a:Id> <a:LogicalName>systemuser</a:LogicalName> <a:Name i:nil="true" /> </c:value> </a:KeyValuePairOfstringanyType> </a:Parameters> <a:RequestId i:nil="true" /> <a:RequestName>Assign</a:RequestName> </request> </Execute> </s:Body> </s:Envelope> -------------------------------------------------- HTTP RESPONSE -------------------------------------------------- <s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <ExecuteResponse xmlns="https://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <ExecuteResult i:type="b:AssignResponse" xmlns:a="https://schemas.microsoft.com/xrm/2011/Contracts" xmlns:b="https://schemas.microsoft.com/crm/2011/Contracts"> <a:ResponseName>Assign</a:ResponseName> <a:Results xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic" /> </ExecuteResult> </ExecuteResponse> </s:Body> </s:Envelope> --------------------------------------------------
Noteer de locatie van de variabelen die u in uw code gebruikte, inclusief de logische naam van de Account entiteit.
U hebt de relevante gedeelten van het HTTP dataverkeer vastgelegd dat de bewerking heeft uitgevoerd.
Een JScript bibliotheek maken
U kiest de wijze waarop u de bibliotheek bouwt. Elke JScript moet de volgende elementen hebben:
Een strategie om te garanderen dat de naam van een functie uniek is.
Een middel om de URL naar het SOAP eindpunt op te halen voor webresources.
Afzonderlijke manieren om de aanvraag te verzenden en de respons asynchroon te ontvangen.
Een functie waarmee u geretourneerde WCF-fouten kunt verwerken.
De volgende JScript bibliotheek bevat deze elementen en omvat de functies assignRequest en assignResponse om het Assign bericht te gebruiken op basis van de HTTP aanvragen en responsen die zijn geregistreerd met de SOAPLogger.
if (typeof (SDK) == "undefined")
{ SDK = { __namespace: true }; }
//This will establish a more unique namespace for functions in this library. This will reduce the
// potential for functions to be overwritten due to a duplicate name when the library is loaded.
SDK.SOAPSamples = {
_getClientUrl: function () {
///<summary>
/// Returns the URL for the SOAP endpoint using the context information available in the form
/// or HTML Web resource.
///</summary
var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
var clientUrl = "";
if (typeof GetGlobalContext == "function") {
var context = GetGlobalContext();
clientUrl = context.getClientUrl();
}
else {
if (typeof Xrm.Page.context == "object") {
clientUrl = Xrm.Page.context.getClientUrl();
}
else
{ throw new Error("Unable to access the server URL"); }
}
return clientUrl + OrgServicePath;
},
assignRequest: function (Assignee, Target, Type, successCallback, errorCallback) {
///<summary>
/// Sends the Assign Request
///</summary>
this._parameterCheck(Assignee, "GUID", "The SDK.SOAPSamples.assignRequest method Assignee parameter must be a string Representing a GUID value.");
///<param name="Assignee" Type="String">
/// The GUID representing the System user that the record will be assigned to.
///</param>
this._parameterCheck(Target, "GUID", "The SDK.SOAPSamples.assignRequest method Target parameter must be a string Representing a GUID value.");
///<param name="Target" Type="String">
/// The GUID representing the user-owned entity record that will be assigne to the Assignee.
///</param>
this._parameterCheck(Type, "String", "The SDK.SOAPSamples.assignRequest method Type parameter must be a string value.");
Type = Type.toLowerCase();
///<param name="Type" Type="String">
/// The Logical name of the user-owned entity. For example, 'account'.
///</param>
if (successCallback != null)
this._parameterCheck(successCallback, "Function", "The SDK.SOAPSamples.assignRequest method successCallback parameter must be a function.");
///<param name="successCallback" Type="Function">
/// The function to perform when an successfult response is returned.
///</param>
this._parameterCheck(errorCallback, "Function", "The SDK.SOAPSamples.assignRequest method errorCallback parameter must be a function.");
///<param name="errorCallback" Type="Function">
/// The function to perform when an error is returned.
///</param>
//The request is simply the soap envelope captured by the SOAPLogger with variables added for the
// values passed. All quotations must be escaped to create valid JScript strings.
var request = [];
request.push("<s:Envelope xmlns:s=\"https://schemas.xmlsoap.org/soap/envelope/\">");
request.push("<s:Body>");
request.push("<Execute xmlns=\"https://schemas.microsoft.com/xrm/2011/Contracts/Services\"");
request.push(" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">");
request.push("<request i:type=\"b:AssignRequest\"");
request.push(" xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\"");
request.push(" xmlns:b=\"https://schemas.microsoft.com/crm/2011/Contracts\">");
request.push("<a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">");
request.push("<a:KeyValuePairOfstringanyType>");
request.push("<c:key>Target</c:key>");
request.push("<c:value i:type=\"a:EntityReference\">");
request.push("<a:Id>" + this._xmlEncode(Target) + "</a:Id>");
request.push("<a:LogicalName>" + this._xmlEncode(Type) + "</a:LogicalName>");
request.push("<a:Name i:nil=\"true\" />");
request.push("</c:value>");
request.push("</a:KeyValuePairOfstringanyType>");
request.push("<a:KeyValuePairOfstringanyType>");
request.push("<c:key>Assignee</c:key>");
request.push("<c:value i:type=\"a:EntityReference\">");
request.push("<a:Id>" + this._xmlEncode(Assignee) + "</a:Id>");
request.push("<a:LogicalName>systemuser</a:LogicalName>");
request.push("<a:Name i:nil=\"true\" />");
request.push("</c:value>");
request.push("</a:KeyValuePairOfstringanyType>");
request.push("</a:Parameters>");
request.push("<a:RequestId i:nil=\"true\" />");
request.push("<a:RequestName>Assign</a:RequestName>");
request.push("</request>");
request.push("</Execute>");
request.push("</s:Body>");
request.push("</s:Envelope>");
var req = new XMLHttpRequest();
req.open("POST", SDK.SOAPSamples._getClientUrl(), true)
// Responses will return XML. It isn't possible to return JSON.
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", "https://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
req.onreadystatechange = function () { SDK.SOAPSamples.assignResponse(req, successCallback, errorCallback); };
req.send(request.join(""));
},
assignResponse: function (req, successCallback, errorCallback) {
///<summary>
/// Recieves the assign response
///</summary>
///<param name="req" Type="XMLHttpRequest">
/// The XMLHttpRequest response
///</param>
///<param name="successCallback" Type="Function">
/// The function to perform when an successfult response is returned.
/// For this message no data is returned so a success callback is not really necessary.
///</param>
///<param name="errorCallback" Type="Function">
/// The function to perform when an error is returned.
/// This function accepts a JScript error returned by the _getError function
///</param>
if (req.readyState == 4) {
req.onreadystatechange = null; //avoids memory leaks
if (req.status == 200) {
if (successCallback != null)
{ successCallback(); }
}
else {
errorCallback(SDK.SOAPSamples._getError(req.responseXML));
}
}
},
_getError: function (faultXml) {
///<summary>
/// Parses the WCF fault returned in the event of an error.
///</summary>
///<param name="faultXml" Type="XML">
/// The responseXML property of the XMLHttpRequest response.
///</param>
var errorMessage = "Unknown Error (Unable to parse the fault)";
if (typeof faultXml == "object") {
try {
var bodyNode = faultXml.firstChild.firstChild;
//Retrieve the fault node
for (var i = 0; i < bodyNode.childNodes.length; i++) {
var node = bodyNode.childNodes[i];
//NOTE: This comparison does not handle the case where the XML namespace changes
if ("s:Fault" == node.nodeName) {
for (var j = 0; j < node.childNodes.length; j++) {
var faultStringNode = node.childNodes[j];
if ("faultstring" == faultStringNode.nodeName) {
errorMessage = faultStringNode.textContent;
break;
}
}
break;
}
}
}
catch (e) { };
}
return new Error(errorMessage);
},
_xmlEncode: function (strInput) {
var c;
var XmlEncode = '';
if (strInput == null) {
return null;
}
if (strInput == '') {
return '';
}
for (var cnt = 0; cnt < strInput.length; cnt++) {
c = strInput.charCodeAt(cnt);
if (((c > 96) && (c < 123)) ||
((c > 64) && (c < 91)) ||
(c == 32) ||
((c > 47) && (c < 58)) ||
(c == 46) ||
(c == 44) ||
(c == 45) ||
(c == 95)) {
XmlEncode = XmlEncode + String.fromCharCode(c);
}
else {
XmlEncode = XmlEncode + '&#' + c + ';';
}
}
return XmlEncode;
},
_parameterCheck: function (parameter, type, errorMessage) {
switch (type) {
case "String":
if (typeof parameter != "string") {
throw new Error(errorMessage);
}
break;
case "Function":
if (typeof parameter != "function") {
throw new Error(errorMessage);
}
break;
case "EntityFilters":
var found = false;
for (x in this.EntityFilters) {
if (this.EntityFilters[x] == parameter) {
found = true;
break;
}
}
if (!found) {
throw new Error(errorMessage);
}
break;
case "Boolean":
if (typeof parameter != "boolean") {
throw new Error(errorMessage);
}
break;
case "GUID":
var re = new RegExp("[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}");
if (!(typeof parameter == "string" && re.test(parameter))) {
throw new Error(errorMessage);
}
break;
default:
throw new Error("An invalid type parameter value was passed to the SDK.MetaData._parameterCheck function.");
break;
}
},
__namespace: true
};
De JScript-bibliotheek testen
Nadat u uw JScript bibliotheek hebt voorbereid, moet u enkele tests uitvoeren om te bevestigen dat dit werkt zoals u verwacht. Aangezien alleen de verificatie alleen plaatsvindt in de toepassing, moet u een scriptwebresource maken in Microsoft Dynamics CRM 2015 met de inhoud van uw bibliotheek. Als u de functies in de bibliotheek wilt gebruiken, moet u een UI-element gebruiken; een formulier of een HTML webresource om de JScript functies in uw bibliotheek aan te roepen. In de volgende procedure wordt beschreven hoe u een eenvoudige HTML webresource gebruikt om de functies in de bibliotheek te testen.
Een HTML document maken aan de hand van de volgende code:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Assign Test</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <script src="../ClientGlobalContext.js.aspx" type="text/javascript"></script> <script src="Scripts/SDK.REST.js" type="text/javascript"></script> <script src="Scripts/SDK.SOAPSample.Assign.js" type="text/javascript"></script> <script type="text/javascript"> var resultsArea = null; var userid; var accountid; var userLookup; var accountLookup; var accountsToShow = 10; var usersToShow = 10; var users = []; var accounts = []; document.onreadystatechange = function () { ///<summary> /// Initializes the sample when the document is ready ///</summary> if (document.readyState == "complete") { userid = document.getElementById("userid"); accountid = document.getElementById("accountid"); resultsArea = document.getElementById("results"); userLookup = document.getElementById("userLookup"); accountLookup = document.getElementById("accountLookup"); populateUserLookup(); populateAccountLookup(); } } function testAssign() { //The field to enter the user id of the person the account record should be assigned to. userid.value; // The field to enter the account id of the account record to assign to the user accountid.value; // Since the response does not include any data to parse, simply display a success message. var successCallback = function () { setText(resultsArea, "Success!"); }; // Display the error from the message passed back from the response. var errorCallback = function (error) { setText(resultsArea,"errorCallback error: "+error.message); }; // Call the function try { SDK.SOAPSamples.assignRequest(userid.value, accountid.value, "account", successCallback, errorCallback); } catch (e) { setText(resultsArea, e.message); } } function populateUserLookup() { SDK.REST.retrieveMultipleRecords("SystemUser", "$top=" + usersToShow + "&$select=FullName,SystemUserId&$filter=FullName ne 'INTEGRATION' and FullName ne 'SYSTEM'", function (results) { for (var i = 0; i < results.length; i++) { users.push(results[i]); } }, function (error) { alert(error.message); }, function () { for (var i = 0; i < users.length; i++) { var user = users[i]; userLookup.options[i] = new Option(user.FullName, user.SystemUserId); } userid.value = userLookup.options[0].value; userLookup.onchange = function () { userid.value = userLookup.options[userLookup.selectedIndex].value; clearMessage(); }; }); } function populateAccountLookup() { SDK.REST.retrieveMultipleRecords("Account", "$top=" + accountsToShow + "&$select=AccountId,Name,OwnerId", function (results) { for (var i = 0; i < results.length; i++) { accounts.push(results[i]); } }, function (error) { alert(error.message); }, function () { for (var i = 0; i < accounts.length; i++) { var account = accounts[i]; accountLookup.options[i] = new Option(account.Name + " : " + account.OwnerId.Name, account.AccountId); } accountid.value = accountLookup.options[0].value; accountLookup.onchange = function () { accountid.value = accountLookup.options[accountLookup.selectedIndex].value; clearMessage(); }; }); } function clearMessage() { setText(resultsArea, ""); } function setText(element, text) { if (typeof (element.innerText) != "undefined") { element.innerText = text; } else { element.textContent = text; } } </script> </head> <body> <table> <tr> <td> <label for="userid"> SystemUserId:</label> </td> <td> <input id="userid" type="text" style="width:270px;" /> </td> <td> <select id="userLookup"></select> </td> </tr> <tr> <td> <label for="accountid"> AccountId:</label> </td> <td> <input id="accountid" type="text" style="width:270px;" /> </td> <td> <select id="accountLookup"></select> </td> </tr> </table> <button id="testAssign" title="Click this button to test the testAssign function." onclick="testAssign();"> Test Assign</button> <div id="results"> &nbsp;</div> </body> </html>
Een HTML webresource maken met behulp van deze code. De volledige naam van de HTML webresource hangt af van het aanpassingsvoorzetsel van uw oplossing. Als het voorvoegsel van de oplossingaanpassing "nieuw" is, noemt u deze HTML webresource "new_/AssignTest.htm". Het specifieke aanpassingsvoorvoegsel heeft geen invloed op dit voorbeeld aangezien alle webresources hetzelfde aanpassingsvoorvoegsel gebruiken.
Een scriptwebresource maken met de inhoud van de JScript bibliotheek. Noem deze webresource “new_/Scripts/SDK.SOAPSample.Assign.js”.
Publiceer alle aanpassingen en open de new_/AssignTest.htm webresource. Klik op de knop Voorbeeld.
Met hetzelfde proces dat u in stap drie van de procedure No text is specified for bookmark or legacy link 'c9a435ab-a4cb-4e0c-9ef7-b7ba66278407#BKMK_EditSoapLogger'. gebruikte, identificeert u geldige waarden voor systeemgebruiker-id en accountrecord-id en plakt u deze op de pagina. Klik vervolgens op Test Assign om te bevestigen dat u een succesrespons krijgen.
Voer ongeldige waarden in om te bevestigen dat de fout correct wordt geparseerd.
Als u bijvoorbeeld "Een winkel (voorbeeld)" invoegt in plaats van de id voor een account, kunt u het volgende foutbericht verwachten:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter https://schemas.microsoft.com/xrm/2011/Contracts/Services:request. The InnerException message was 'There was an error deserializing the object of type Microsoft.Xrm.Sdk.OrganizationRequest. The value 'A Store (sample)' cannot be parsed as the type 'Guid'.'. Please see InnerException for more details.
Als er geen accountrecord is voor de AccountId is het bericht dat u kunt verwachten:
Account With Id = 883c3084-1f2f-e011-ad66-00155dba3814 Does Not Exist
Een interactieve webresource maken
De volgende stap is het gebruik van uw JScript bibliotheek in een formulierscript, een lintopdracht of een webresource. Het volgende codevoorbeeld vertegenwoordigt een HTML webresource die het REST eindpunt gebruikt om lijsten van SystemUser en Account records op te halen om een interactieve gebruikersinterface te bieden accountrecords aan gebruikers toe te wijzen. Deze pagina gebruikt de Scripts/SDK.SOAPSample.Assign.js scriptwebresource en een scriptwebresource met de json2.js bibliotheek voor het gebruik van JSON objecten met het REST eindpunt. De SDK.REST.js bibliotheek wordt gebruikt om gegevens op te halen met behulp van het REST eindpunt.
<html lang="en-us">
<head>
<title>Assign Accounts Page</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<style type="text/css">
body
{
font-family: Segoe UI;
background-color: #EFF2F6;
}
.dataTable
{
border-collapse: collapse;
border: 1px solid black;
}
.tableHead
{
background-color: #C0C0C0;
width: 100%;
}
.grid
{
border-bottom: 1px solid black;
}
td
{
padding-left: 5px;
padding-right: 5px;
}
#accountList
{
background-color: White;
}
#checkboxCol
{
border-right: 1px solid black;
width: 20px;
}
#nameCol
{
border-right: 1px solid black;
width: 300px;
}
#ownerCol
{
width: 300px;
}
</style>
<script src="../ClientGlobalContext.js.aspx" type="text/javascript"></script>
<script src="Scripts/SDK.REST.js" type="text/javascript"></script>
<script src="Scripts/SDK.SOAPSample.Assign.js" type="text/javascript"></script>
<script type="text/javascript">
//Set variables for page elements
var userSelect; //The select control used to select the user to assign records to.
var accountList; //The tbody element that rows will be added to for each retrieved account
var selectAll; //The checkbox to select all the retrieved accounts
var btnAssign; //The button to assign assign the accounts
var tableCaption; //A label hidden on load
var dataTable; //the table element hidden on load
var alertFlag; // Alert flag to indicate the changes
var users = []; //SystemUser records retrieved
var accounts = []; //Accounts not assigned to the currently selected user.
var accountsToShow = 5;
var suppressRetrievedAccountsAlert = false;
var accountsToAssign = [];
var userId = null;
function startSample() {
///<summary>
/// Starts the sample
///</summary>
alertFlag = document.getElementById("dispalert");
userSelect = document.getElementById("userList");
//A new set of a 5 accounts will be retrieved when the user changes
userSelect.onchange = getAccounts;
accountList = document.getElementById("accountList");
selectAll = document.getElementById("selectAll");
//When the select all checkbox is clicked, toggle the selection for each row of the table.
selectAll.onclick = toggleSelectAllRecords;
btnAssign = document.getElementById("btnAssign");
//Add a helper function to enable or disable the assign button.
btnAssign.setEnabled = setEnabled;
//Set the event handler to the Assign button
btnAssign.onclick = assignAccounts;
tableCaption = document.getElementById("tableCaption");
dataTable = document.getElementById("dataTable");
var divSample = document.getElementById("divSample");
//Load the list of users
getUsers();
divSample.style.display = "block";
document.getElementById("btnStart").setAttribute("disabled", "disabled");
}
function getUsers() {
SDK.REST.retrieveMultipleRecords("SystemUser",
"$select=FullName,SystemUserId&$filter=FullName ne 'INTEGRATION' and FullName ne 'SYSTEM'",
function (results) {
for (var i = 0; i < results.length; i++) {
users.push(results[i]);
}
},
function (error) {
showMessage(error.message);
},
function () {
if (users.length > 1) {
for (var i = 0; i < users.length; i++) {
var user = users[i];
userSelect.options[i + 1] = new Option(user.FullName, user.SystemUserId);
}
userSelect.removeAttribute("disabled");
if (alertFlag.checked == true) {
alert(users.length + " system users retrieved");
}
}
else {
var notification = "This sample requires that more than one user is available in the organization.";
showMessage(notification);
if (alertFlag.checked == true) {
alert("This sample requires that more than one user is available in the organization.");
}
}
});
}
function getAccounts() {
//Clear out any records displayed in the table
clearAccountList();
var selectedUserId = userSelect.options[userSelect.selectedIndex].value;
if (selectedUserId != "none") {
SDK.REST.retrieveMultipleRecords("Account",
"$top=" + accountsToShow + "&$select=AccountId,Name,OwnerId&$filter=OwnerId/Id ne (guid'" + encodeURIComponent(selectedUserId) + "')",
function (results) {
accounts.length = 0;
for (var i = 0; i < results.length; i++) {
accounts.push(results[i]);
}
},
function (error) {
showMessage(error.message);
},
function () {
//onComplete
if (accounts.length > 0) {
for (var i = 0; i < accounts.length; i++) {
var account = accounts[i];
var row = document.createElement("tr");
row.setAttribute("class", "grid");
row.setAttribute("id", account.AccountId);
var checkboxCell = document.createElement("td");
var checkbox = document.createElement("input");
checkbox.setAttribute("type", "checkbox");
checkbox.onclick = validateAssignButton;
checkboxCell.appendChild(checkbox);
row.appendChild(checkboxCell);
var nameCell = document.createElement("td");
setText(nameCell, account.Name);
row.appendChild(nameCell);
var userNameCell = document.createElement("td");
setText(userNameCell, account.OwnerId.Name);
row.appendChild(userNameCell);
accountList.appendChild(row);
}
if (alertFlag.checked == true && !suppressRetrievedAccountsAlert) {
alert(accounts.length + " account records retrieved.");
suppressRetrievedAccountsAlert = false;
}
}
else {
//If no records are returned display a message.
clearAccountList();
var row = document.createElement("tr");
var cell = document.createElement("td");
cell.setAttribute("colSpan", "3");
setText(cell, "No Accounts were retrieved");
row.appendChild(cell);
accountList.appendChild(row);
}
//Show any of the UI elements that are initially hidden
setVisibleUIElements(true);
});
}
else { setVisibleUIElements(false); }
}
function assignAccounts() {
///<summary>
/// queues the selected accounts to be assigned sequentially
///</summary>
userId = userSelect.options[userSelect.selectedIndex].value;
var checkboxes = accountList.getElementsByTagName("input");
for (var i = checkboxes.length - 1; i >= 0; i--) {
if (checkboxes[i].checked) {
var accountId = checkboxes[i].parentElement.parentElement.id;
accountsToAssign.push(accountId);
}
}
assignNextAccount();
selectAll.checked = false;
}
function assignNextAccount() {
/// <summary>Assigns the queued accounts</summary>
//Prevents a generic SQL error that can occur when too many assign requests occur in rapid succession
if (accountsToAssign.length > 0) {
SDK.SOAPSamples.assignRequest(userId, accountsToAssign.shift(), "account", function () {
assignNextAccount();
}, function (error) {
showMessage("There was an error assigning the account with Id :" + accountId + ". The error message is " + error.message + ".");
assignNextAccount();
});
}
else {
suppressRetrievedAccountsAlert = true;
getAccounts();
btnAssign.setEnabled(false)
if (alertFlag.checked == true) {
alert("Record assignment completed and next set of records retrieved.");
}
}
}
function showMessage(message) {
///<summary>
/// Helper function to display message on the page if necessary.
///</summary
var dvMessage = document.createElement("div");
dvMessage.innerHTML = SDK.SOAPSamples._xmlEncode(message);
document.getElementById("status").appendChild(dvMessage);
}
function clearAccountList() {
///<summary>
/// Helper function remove rows from the Account List table.
///</summary
for (var i = (accountList.rows.length - 1) ; i >= 0; i--) {
accountList.deleteRow(i);
}
accounts.length = 0;
}
function toggleSelectAllRecords() {
///<summary>
/// Helper function to toggle all selected rows in the account list table.
///</summary
var checkboxes = accountList.getElementsByTagName("input");
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = this.checked;
}
btnAssign.setEnabled(this.checked);
}
function validateAssignButton() {
///<summary>
/// Helper function to enable the Assign Records button when rows are selected.
///</summary
if (this.checked == true)
{ btnAssign.setEnabled(true); }
else {
selectAll.checked = false;
var checkboxes = accountList.getElementsByTagName("input");
var checked = false;
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked == true) {
checked = true;
break;
}
}
btnAssign.setEnabled(checked);
}
}
function setEnabled(bool) {
///<summary>
/// Helper method attached to the Assign button to make it easier to enable/disable the button.
///</summary
if (bool)
{ this.removeAttribute("disabled"); }
else
{ this.setAttribute("disabled", "disabled"); }
}
function setVisibleUIElements(display) {
///<summary>
/// Helper function to show those UI elements initially hidden.
///</summary
if (display) {
show(tableCaption);
show(dataTable);
show(btnAssign);
}
else {
hide(tableCaption);
hide(dataTable);
hide(btnAssign);
}
}
function show(element) {
if (element.tagName.toLowerCase() == "table") {
element.style.display = "table";
}
else {
element.style.display = "block";
}
}
function hide(element) {
element.style.display = "none";
}
// setText mitigate differences in how browsers set or get text content.
function setText(node, text) {
if (typeof (node.innerText) != "undefined") {
node.innerText = text;
}
else {
node.textContent = text;
}
}
</script>
</head>
<body>
<h1>
Assign Accounts Sample
</h1>
<p>
This page requires JavaScript and will update dynamically.
</p>
<p>
<input id="dispalert" name="dispalert" type="checkbox" value="alert" /><label for="dispalert">Display alert window when data changes.</label>
</p>
<p>
Click the <b>Start</b> button to begin the sample.
</p>
<input type="button" id="btnStart" name="btnStart" value="Start" onclick="startSample()" />
<div id="divSample" style="display: none">
<label for="userList">
User:
</label>
<select id="userList" name="userList" title="Select a system user from this list." disabled>
<option value="none">Select a User...</option>
</select>
<p id="tableCaption" style="display: none;">
Top 5 Accounts not assigned to the selected user:
</p>
<table class="dataTable" id="dataTable" style="display: none; width: 100%;">
<thead>
<tr class="tableHead">
<th scope="col" id="checkboxCol">
<input id="selectAll" name="selectAll" title="Select this to select all records" type="checkbox" /><label for="selectAll">Select&nbsp;All</label>
</th>
<th scope="col" id="nameCol">
Name
</th>
<th scope="col" id="ownerCol">
Owner
</th>
</tr>
</thead>
<tbody id="accountList"></tbody>
</table>
<label style="display: none;" for="btnAssign">
Click to assign selected records
</label>
<button id="btnAssign" name="btnAssign" disabled style="display: none; float: right;">
Assign Records
</button>
<label style="display: none;" for="btnAssign">
Click to assign selected records
</label>
<button id="Button1" name="btnAssign" disabled style="display: none; float: right;">
Assign Records
</button>
</div>
<div id="status">
&nbsp;
</div>
</body>
</html>
Zie ook
AssignRequest
Voorbeeld: metagegevens van entiteit ophalen met JavaScript
Het SOAP-eindpunt voor moderne toepassingen gebruiken voor moderne toepassingen met webresources
Gebruik webservicegegevens in webresources (OData en het SOAP-eindpunt voor moderne toepassingen)
Toepassingen en serveruitbreidingen schrijven
JavaScript-bibliotheken voor Microsoft Dynamics CRM 2015
Technisch artikel: Optiesetopties gebruiken met het REST-eindpunt - JScript
© 2017 Microsoft. Alle rechten voorbehouden. Auteursrecht