I am trying to discern if a user is a member of a certain team in Dynamics 365. I am using the following JavaScript functions to attempt this. My issue is that even though the getUserTeams is finding the user in the team when the result gets passed back to the calling function (UserHasTeam) the value is undefined. I feel like I am missing something here but for the life of me I don't know what. Can anyone help me?
function UserHasTeam(teamName) {
///<summary>
/// Checks to see if the current user is a member of a team with the passed in name.
///</summary>
///<param name="teamName" type="String">
/// A String representing the name of the team to check if the user is a member of.
///</param>
var res;
if (teamName != null && teamName != "") {
// build endpoint URL
var serverUrl = Xrm.Page.context.getClientUrl();
var oDataEndpointUrl = serverUrl + "/XRMServices/2011/OrganizationData.svc/";
// query to get the teams that match the name
oDataEndpointUrl += "TeamSet?$select=Name,TeamId&$filter=Name eq '" + teamName + "'";
console.log(oDataEndpointUrl);
// execute the request
var req = new XMLHttpRequest();
req.open("GET", oDataEndpointUrl, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 200) {
console.log("Success");
result = JSON.parse(this.response);
console.log(result);
console.log(result["d"]["results"][0]["TeamId"]);
res = getUserTeams(result["d"]["results"][0]["TeamId"]);
console.log(res);
} else {
var error = JSON.parse(this.response).error;
console.log(error);
}
}
};
req.send(null);
return res;
}
}
function getUserTeams(teamToCheckId) {
// gets the current users team membership
var res;
var userId = Xrm.Page.context.getUserId().substr(1, 36);
var serverUrl = Xrm.Page.context.getClientUrl();
var oDataEndpointUrl = serverUrl + "/XRMServices/2011/OrganizationData.svc/";
oDataEndpointUrl += "TeamMembershipSet?$filter=SystemUserId eq guid' " + userId + " ' and TeamId eq guid' " + teamToCheckId + " '";
var req = new XMLHttpRequest();
req.open("GET", oDataEndpointUrl, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 200) {
console.log("Success");
result = JSON.parse(this.response);
console.log(result["d"]["results"].length);
if(result["d"]["results"].length == 1) {
res = true;
} else {
res = false;
}
} else {
var error = JSON.parse(this.response).error;
console.log(error);
}
}
};
req.send(null);
return res;
}
you are calling webapi request as Async and not sync.
req.open("GET", oDataEndpointUrl, true);
You should be calling it Sync like below
req.open("GET", oDataEndpointUrl, false);
In addition, if you are using Dynamics 365 you should be using up to date webapi request.
Note: new webapi calls are in build Async and you should be using promise to make it sync.
Take a look at this retrievemultiplerecords
and retrieveRecord
Please mark it as solved if it helps
Related
I would like to utilize Xrm.Page.ui.setFormNotification to display a banner at the top of a Shipment record. This banner would only appear for Shipments where the related entity Account is classified as "Service Watch".
I'm pretty new to Javascript so I'm a bit lost how to pull values from related entities of a record to use.
Xrm.Page.ui.setFormNotification("This Account is currently under Service Watch", "WARNING")
EDIT: Code working;
function checkServiceWatch() {
try{
var account = Xrm.Page.getAttribute("cmm_account").getValue();
var accountid = account[0].id;
var formattedGuid = accountid.replace("}", "");
accountid = formattedGuid.replace("{", "");
"/api/data/v8.2/accounts(" + accountid + ")?
$select=cmm_servicewatch");
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts(" + accountid + ")?$select=cmm_servicewatch", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function()
{
if (this.readyState === 4)
{
req.onreadystatechange = null;
if (this.status === 200)
{
var result = JSON.parse(this.response);
var serviceWatch = result["cmm_servicewatch"];
// alert("serviceWatch: " + serviceWatch);
if(serviceWatch) //set notification
{
Xrm.Page.ui.setFormNotification("This Account is currently under Service Watch","WARNING","1");
} // else
// {
// //Xrm.Page.ui.clearFormNotification("1");
// }
}
else
{
Xrm.Utility.alertDialog("Status: " + this.status + ", Text: " + this.statusText);
}
}
};
req.send();
}
catch (err) {
alert("ServiceWatchCheckRibbon | checkServiceWatch " + err.message);
}
}
You have to query the Account lookup record on form load to pull the extra attribute which says "Service watch" and show the notification banner if so.
You can refer this community thread & use the sample code as is or Xrm.Webapi method to do it based on your CRM version.
function checkAccount(){
var accountid = Xrm.Page.data.entity.attributes.get("new_parentaccount").getValue()[0].id;
if (accountid.startsWith("{") && accountid.endsWith("}"))
{
accountid = accountid.slice(1, accountid.length - 1);
}
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts(" + accountid + ")?$select=new_servicewatch", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function() {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 200)
{
var result = JSON.parse(this.response);
var serviceWatch = result["new_servicewatch"];
if(serviceWatch) //set notification
{
Xrm.Page.ui.setFormNotification("This Account is currently under Service Watch","WARNING","1");
} else
{
//Xrm.Page.ui.clearFormNotification("1");
}
}
else
{
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
}
I've been working on this code. When I run it and some fields don't exist, the error of Entity Type not defined pops up. I tried If statements but it still isn't working. I've read it may have something to do with the currency but I can't seem to figure out what. I'm a beginner and most of this isn't my code. Help! Thanks.
function customerSelected() {
var customerID = Xrm.Page.getAttribute("customerid").getValue();
var custID = customerID[0].id.substr(1, 36);
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts?$select=_defaultpricelevelid_value,paymenttermscode,shippingmethodcode&$filter=accountid eq " + custID + "&$orderby=name asc", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
req.onreadystatechange = function () {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 200) {
var results = JSON.parse(this.response);
for (var i = 0; i < results.value.length; i++) {
var _defaultpricelevelid_value = results.value[i]["_defaultpricelevelid_value"];
var _defaultpricelevelid_value_formatted = results.value[i]["_defaultpricelevelid_value#OData.Community.Display.V1.FormattedValue"];
var _defaultpricelevelid_value_lookuplogicalname = results.value[i]["_defaultpricelevelid_value#Microsoft.Dynamics.CRM.lookuplogicalname"];
var paymenttermscode = results.value[i]["paymenttermscode"];
var paymenttermscode_formatted = results.value[i]["paymenttermscode#OData.Community.Display.V1.FormattedValue"];
var shippingmethodcode = results.value[i]["shippingmethodcode"];
var shippingmethodcode_formatted = results.value[i]["shippingmethodcode#OData.Community.Display.V1.FormattedValue"];
var _defaultpricelevelid_lookupVal = new Array();
_defaultpricelevelid_lookupVal[0] = new Object();
_defaultpricelevelid_lookupVal[0].id = _defaultpricelevelid_value;
_defaultpricelevelid_lookupVal[0].name = _defaultpricelevelid_value_formatted;
_defaultpricelevelid_lookupVal[0].entityType = _defaultpricelevelid_value_lookuplogicalname;
if ("pricelevelid" != null)
{
Xrm.Page.getAttribute("pricelevelid").setValue(_defaultpricelevelid_lookupVal);
}
if ("paymenttermscode" != null)
{
Xrm.Page.getAttribute("paymenttermscode").setValue(_defaultpricelevelid_lookupVal);
}
if ("shippingmethodcode" != null)
{
Xrm.Page.getAttribute("shippingmethodcode").setValue(_defaultpricelevelid_lookupVal);
}
}
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
};
Your query will always return exactly one record, so it does not make sense to use a loop to iterate the results.
Condition ("pricelevelid" != null) will always be true. It probably should be (_defaultpricelevelid_value != null). The same goes for the lines below it.
Your code is assigning _defaultpricelevelid_lookupVal to three separate attributes, which cannot be correct. Apparently this object is supposed to represent a lookup ID value referencing entity pricelevel. Therefore it only makes sense to assign it to attribute pricelevelid. paymenttermscode and shippingmethodcode are option set attributes and apparently need to be filled with the values of the equally named variables.
Replace the for loop with this code:
if (results.value[0]._defaultpricelevelid_value != null) {
var priceLevelId = [{
id = results.value[0]._defaultpricelevelid_value,
name = results.value[0]["_defaultpricelevelid_value#OData.Community.Display.V1.FormattedValue"],
entityType = "pricelevel"
}];
Xrm.Page.getAttribute("pricelevelid").setValue(priceLevelId);
}
if (results.value[0].paymenttermscode != null) {
Xrm.Page.getAttribute("paymenttermscode").setValue(results.value[0].paymenttermscode);
}
if (results.value[0].shippingmethodcode != null) {
Xrm.Page.getAttribute("shippingmethodcode").setValue(results.value[0].shippingmethodcode);
}
The issue I'm having is that I have a dynamic API call whose url changes everytime. So In order to get the proper URL I have to get the text on the page and parse it so it only the first part of the text, then concatenate that to the first part of the URL. When I try to pass the string to the async script it keeps coming up as undefined. How can I get the string into the async script?
Specifically get the string to this line of code:
xhr.open("GET", APIcall, true);
var ID = element(by.css(".sometext")).getText().then(function(getFirstPartOfText) {
//console.log(ID);
var thing = getFirstPartOfText
var thing2 = getFirstPartOfText.toString().split(" ");
var thing3 = thing2[0];
var API = "https://someAPIcall/read/";
APIcall = API + thing3;
return APIcall;
}).then(function(APIcall){
console.log(APIcall);
browser.executeAsyncScript(function(ApiCall) {
var callback = arguments[arguments.length - 1];
var xhr = new XMLHttpRequest();
xhr.open("GET", APIcall, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callback(xhr.responseText);
}
};
xhr.send('');
}).then(function(str) {
console.log(str);
//var whatINeed = JSON.parse(str);
var ID = element(by.css(".sometext")).getText().then(function(getFirstPartOfText) {
// this is synchronous, so there's no need to chain it using .then()
var thing = getFirstPartOfText
var thing2 = getFirstPartOfText.toString().split(" ");
var thing3 = thing2[0];
var API = "https://someAPIcall/read/";
APIcall = API + thing3;
return APIcall;
});
call_something(ID); // ID should be set at this point.
function call_something (APIcall) {
console.log(APIcall);
browser.executeAsyncScript(function(ApiCall) {
var callback = arguments[arguments.length - 1];
var xhr = new XMLHttpRequest();
xhr.open("GET", APIcall, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callback(xhr.responseText);
}
};
xhr.send('');
}).then(function(str) {
console.log(str);
}
}
There are multiple things going on here, first of all the callback in call_something is not required, you are still within webdriver's promise manager. So all you need to do is return the data for the next call chain. Also quote in xhr.send(''); inside the method are not required. All you need to do is call send() and JSON parse the response and return, the next then block should have the JSON result. If you are getting pure HTML, then make sure the URL is correct.
function call_something (APIcall) {
console.log(APIcall);
browser.executeAsyncScript(function(ApiCall) {
var xhr = new XMLHttpRequest();
xhr.open("GET", APIcall, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
return JSON.parse(xhr.responseText);
}
};
xhr.send();
}).then(function(str) {
console.log(str);
}
}
I was missing an extra parameter mentioned here
The first argument is a function which will be called
The second+ arguments will be passed as arguments to the function in the first argument.
var ID = element(by.css(".sometext")).getText().then(function(getFirstPartOfText) {
//console.log(ID);
var thing = getFirstPartOfText
var thing2 = getFirstPartOfText.toString().split(" ");
var thing3 = thing2[0];
var API = "https://someAPIcall/read/";
APIcall = API + thing3;
return APIcall;
}).then(function(APIcall){
console.log(APIcall);
browser.executeAsyncScript(function(ApiCall) {
var callback = arguments[arguments.length - 1];
var xhr = new XMLHttpRequest();
xhr.open("GET", APIcall, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callback(xhr.responseText);
}
};
xhr.send('');
}, APIcall).then(function(str) {
console.log(str);
//var whatINeed = JSON.parse(str);
I am trying to get the price of a product in Dynamics CRM 2016, by javascript on the onChange event for the product. This is on a custom entity I have created and is using the pricelistid and the productid.
When I use the same javascript in the console on Chrome i can get the data out but when it is executed by the CRM form I get an error:
SyntaxError: Unexpected end of JSON input at JSON.parse ()
The code is:
var pricelevelid = Xrm.Page.getAttribute("sg_pricelistid").getValue()[0].id;
pricelevelid = pricelevelid.replace(/[{}]/g, "");
var productdata = Xrm.Page.getAttribute("sg_productid").getValue();
if (productdata != null)
{
console.log("going into productdata loop");
productid = productdata[0].id;
productid = productid.replace(/[{}]/g, "");
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/productpricelevels?$select=amount,_pricelevelid_value,_productid_value,productpricelevelid&$filter=_pricelevelid_value eq " + pricelevelid + " and _productid_value eq " + productid + "", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function() {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 200) {
var results = JSON.parse(this.response);
for (var i = 0; i < results.value.length; i++) {
var amount = results.value[i]["amount"];
var amount_formatted = results.value[i]["amount#OData.Community.Display.V1.FormattedValue"];
}
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
data = JSON.parse(req.responseText);
var amount = data.value[0]["amount"];
Xrm.Page.getAttribute("sg_unitprice").setValue(amount);
}
You are performing an asynchronous request and then attempting to parse the response, before it has been set to anything.
This happens at the bottom of your code block at data = JSON.parse(req.responseText), right after you send the request.
All code that relies on the response should be executed in the req.onreadystatechange callback function.
I am trying to associate two records of custom entities - 'Custom entity 1' and 'Custome Entity 2' having N:N relationship on MS CRM 2016 online instance using Web API. I am getting the following error alert -
An unexpected ‘StartArray’ node was found when reading from the JSON reader. A ‘StartObject’ node was expected.
Following is the code snippet -
function associateRequest() {
var serverURL = Xrm.Page.context.getClientUrl();
var associate = {
"#odata.id": serverURL + "/api/data/v8.0/new_customentity1s(08C7365D-4BD1-E511-80EA-3863BB34BA88)"
};
var req = new XMLHttpRequest();
req.open("POST", serverURL + "/api/data/v8.0/new_customeentity2s(9A1EF77F-4BD1-E511-80EA-3863BB34BA88)/new_new_customentity1_new_customeentity2/$ref", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 204) {
alert('Record Associated');
} else {
var error = JSON.parse(this.response).error;
alert(error.message);
}
}
};
req.send(associate);
}
The disassociation of the records is working fine.
I think you need to use JSON.stringify on the object you're posting:
var association = {'#odata.id': Xrm.Page.context.getClientUrl() + "/api/data/v8.0/new_tests(37A8B2B7-73C9-E511-80DE-6C3BE5A8DAD0)"};
var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/new_test2s(9002CEE2-E9D3-E511-80DD-6C3BE5BD3F5C)/new_new_test_new_test2/$ref", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 204 || this.status === 1223) {
//Success - No Return Data - Do Something
}
else {
alert(this.statusText);
}
}
};
req.send(JSON.stringify(association));