How to call Actions from Javascript Microsoft Dynamics - javascript

I have a requirement to call a Action Process from Javascript.
My Action Accept 2 Input Parameters and 1 output Param. Below is the screenshot of my Action
I have a textField in my Form, and on it's onChange event I'm calling this CallAction Method. Below is the JavaScript
function CallAction() {
var actionName = "taqi_getPrice";
var actionParameters = {
"base": "USD",
"TotalPrice": "200"
};
var actionResponse = activateCustomAction(actionName, actionParameters);
}
function activateCustomAction(actionName, actionParams) {
var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.0/taqi_getPrice", false);
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);
alert('Success');
} else {
alert('fail');
//Xrm.Utility.alertDialog(this.statusText);
console.log(this);
}
}
};
req.send(JSON.stringify(actionParams));
}
When running this script I'm getting the following error in chrome console
POST https://techgulf.crm4.dynamics.com/api/data/v9.0/taqi_getPrice 404
Sometime it also says
Request header field Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers

Well I created Exact same Action as you mentioned in your screenshot, Except Entity I used is Account. I used below code to fire Action and it did worked for me without any issue and returned the value as expected.
May be for Testing you could provide static Guid and see how you get the result.
var parameters = {};
parameters.base = "123";
parameters.TotalPrice = "222";
var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/accounts(DC86C293-CA4F-E911-A82F-000D3A385A1C)/Microsoft.Dynamics.CRM.crmp_TestAction2", false);
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);
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send(JSON.stringify(parameters));

Change the below line
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.0/taqi_getPrice", false);
like this one below:
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.0/taqi_cars(" + Id + ")/Microsoft.Dynamics.CRM.taqi_getPrice", false);
Basically we need to pass name of the Entity Set with id of the record
followed by name of the action appended with Microsoft.Dynamics.CRM.
In case of global action, we just need the
Microsoft.Dynamics.CRM.<<ActionName>>.
Reference
Looks like you need a synchronous Action call execution (as you’re using false in req.open) otherwise you can use Xrm.WebApi.online.execute which is always Asynchronous. Read more

Related

"Resource not found for the segment *publisherguid*" in XMLHTTP query to create solution in the CRM

I'm trying to create a solution in the CRM with javascript.
My code is a webresource that I get through a Ribbon I created with "Ribbon Workbench 2016". These things work very good, but when I try to pass the data I get from user ( from a form ) to the CRM, I get the error in the title.
At first I thought the problem was that the guid was all in lower case, so I converted it in upper case. Nothing changed.
Then I tried using the friendlyname of the publisher instead of the guid.
Nothing changed.
Al last, I was frustrated, so I used an empty string, and the error changed from the one in the title, to "linkPath should have 2 segments". Guess it was a progress...but still have no idea what the real error might be.
What am I doing wrong? Is it right to treat the solution as an entity an create it that way? Is there a better way?
PS: The query was generated with CRM Rest Builder
var entity = {};
entity.friendlyname = $("#solutionForm").dxForm("instance").getEditor("Friendly name").option("value");
entity.uniquename = $("#solutionForm").dxForm("instance").getEditor("Unique name").option("value");
entity.version = $("#solutionForm").dxForm("instance").getEditor("Version").option("value");
entity["publisherid#odata.bind"] = keyValueContainerForPublishers[($("#solutionForm").dxForm("instance").getEditor("Publisher").option("value"))]; //contains guid of selected publisher
entity["configurationpageid#odata.bind"] = "";
entity.description = $("#solutionForm").dxForm("instance").getEditor("Description").option("value");
entity.solutionid = newGuid(); //create unique guid
entity.solutionpackageversion = null;
entity.solutiontype = 0;
var req = new XMLHttpRequest();
req.open("POST", window.parent.opener.Xrm.Page.context.getClientUrl() + "/api/data/v8.2/solutions", 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 === 204) {
var uri = this.getResponseHeader("OData-EntityId");
var regExp = /\(([^)]+)\)/;
var matches = regExp.exec(uri);
var newEntityId = matches[1];
} else {
window.parent.opener.Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send(JSON.stringify(entity));
Alright below Webapi query I tried for creating solutiona and it did worked form me.
Few points to take care of
version should be someting like 1.0 or 2.0 or so. only 1 or 2 will not work
Publisher, If you compare your code and my code it should be "publishers" and not "publisher"
SolutionID you don't have to mention it will automatically create
I did not used configuraitonPageID and solutionPackageVersion for now.
Taking care of above things did created a solution for me.
var entity = {};
entity.friendlyname = "Test solution from WebAPI";
entity.uniquename = "TestSolutionFromWebAPI";
entity.version = "1.0";
entity["publisherid#odata.bind"] = "/publishers(6007BA03-EE7A-4CA1-A146-7EB0044E504F)";
entity.description = "This is test solution form webapi";
entity.solutiontype = 0;
var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/solutions", false);
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 === 204) {
var uri = this.getResponseHeader("OData-EntityId");
var regExp = /\(([^)]+)\)/;
var matches = regExp.exec(uri);
var newEntityId = matches[1];
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send(JSON.stringify(entity));

BAD REQUEST When making an AJAX CALL: This.readyState is undefined

I wrote a function that fetches the guid of a lookup field and uses that to make an AJAX call. This is the the call that I made:
fetchOptionSet: function (executionContext) {
var formContext = executionContext.getFormContext(); //get form context
var client = Xrm.Page.context.getClientUrl(); //get client url
var childId = formContext.getAttribute("new_childid").getValue()[0].id;
var child = childId.replace(/[{}]/g, "");
var contract;
var req = new XMLHttpRequest();
req.open("GET", client + `/api/data/v8.2/new_childallergieses(${child})?$select=_new_childid_value`, 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 result = JSON.parse(this.response);
var _new_childid_value = result["_new_childid_value"];
contract = _new_childid_value.replace(/[{}]/g, "");
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
However, I get a bad request every time that the script runs. I need the guid returned by the call (contractid) to make another ajax call! The uri is fine,I tested the link in the browser and it returns the contractid that I want.
First issue Bad request can be solved by replacing GUID value childId for any {}.
Second issue, this is Ajax call which is asynchronous by mentioning true in req.open, hence you may have some other issue with request uri. That’s why readyState is undefined.
Try this. Take your uri & paste in browser address bar to see any clear error.
http://test.crm.dynamics.com/api/data/v8.2/new_childallergieses(guid)?$select=_new_childid_value
Changed from Asychronous to Sychronous and all of a sudden it worked!
var path_one = Xrm.Page.context.getClientUrl() + "/api/data/v8.2/new_childallergieses(" + child + ")?$select=_new_childid_value";
req.open("GET", path_one , false);
I did some investigating and realized that the function is set to execute on load, and sending an asynchronous call on load gives a bad request.

Can't close Incident through Web API client side

On Dynamics 365, we are trying to close incidents using the client side Web API.
After looking at the doc (in C#), we understand that we first need to create a IncidentResolution activity, which we did successfully.
However, we don't understand how to fully close the Incident entity then.
I assume we need to update the record's stateCode and statusCode.. However, if I do so, ajax always return a 500 error.
Other updates are working fine.
Is there anything that we're missing here ?
var entity = {};
entity.statecode = 1; // Resolved
entity.statuscode = 5; // Problem Solved
entity.title = "Title of my case";
var req = new XMLHttpRequest();
req.open("PATCH", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/incidents(Case's guid)", 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 === 204) {
//Success - No Return Data - Do Something
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send(JSON.stringify(entity));
You have to use CloseIncident Action & POST method to do this. It's not a simple update request by using PATCH method, basically case closure will create an Incident Resolution entity record.
Normally I will compose the request using CRM REST builder, even that snippet is not executing successfully in this case. The complete working code example:
var incidentresolution = {
"subject": "Put Your Resolve Subject Here",
"incidentid#odata.bind": "/incidents(<GUID>)", //Replace <GUID> with Id of case you want to resolve
"timespent": 60, //This is billable time in minutes
"description": "Additional Description Here"
};
var parameters = {
"IncidentResolution": incidentresolution,
"Status": -1
};
var context;
if (typeof GetGlobalContext === "function") {
context = GetGlobalContext();
} else {
context = Xrm.Page.context;
}
var req = new XMLHttpRequest();
req.open("POST", context.getClientUrl() + "/api/data/v8.2/CloseIncident", 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 === 204) {
//Success - No Return Data - Do Something
} else {
var errorText = this.responseText;
//Error and errorText variable contains an error - do something with it
}
}
};
req.send(JSON.stringify(parameters));
Reference

Javascript make HTTP request on regular interval not working

I have a page to show the chat messages. I need to refresh the chat body every 30 seconds to load the new messages. I have set the interval to 30 seconds , the function is running , but its not making the HTTP request. Here is my code
function loadmessages(){
var ids = document.getElementById("pid").value;
var request = new XMLHttpRequest();
request.open("get", '/refresh_message/'+ ids );
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
request.setRequestHeader("X-CSRF-TOKEN", document.querySelector('meta[name="csrf-token"]').content);
request.onload = function(){
if(this.status == 200){
var resp = JSON.parse(this.responseText);
console.log(resp.message);
}
else{
console.log(this.status);
}
request.send(null);
}
}
loadmessages();
setInterval(function(){
loadmessages()
}, 30000);
Consistent indentation matters. You're putting request.send(null); inside the request.onload function, so of course it never gets sent in the first place. Try putting it outside, instead:
function loadmessages() {
var ids = document.getElementById("pid").value;
var request = new XMLHttpRequest();
request.open("get", '/refresh_message/' + ids);
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
request.setRequestHeader("X-CSRF-TOKEN", document.querySelector('meta[name="csrf-token"]').content);
request.onload = function() {
if (this.status == 200) {
var resp = JSON.parse(this.responseText);
console.log(resp.message);
} else {
console.log(this.status);
}
}
request.send(null);
}

What does readyState ==1 means?

I am using this below function to fetch the product number for a particular productid.
function GetQuickCode(){
var material = Xrm.Page.getAttribute("one_materialid").getValue();
var id = material[0].id;
id=id.replace("{","").replace("}","");
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/products("+id+")?$select=productnumber", 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 result = JSON.parse(this.response);
var productnumber = result["productnumber"];
Xrm.Page.getAttribute("one_quickcode").setValue(productnumber.Value);
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
}
this function is returning readyState==1 which is why I am unable to find the value of product number. Also the response value does not contain anything. Can anyone tell me if I am wrong somewhere.
Try to debug your code in a few steps to find the problem.
First replace this line of code
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/products("+id+")?$select=productnumber", true);
by
var url= Xrm.Page.context.getClientUrl() + "/api/data/v8.2/products("+id+")?$select=productnumber";
console.log(url);
req.open("GET", url, true);
Does URL look correct?
Does it return correct result if you open directly in your browser?
If it works, you can continue further. If not, you need to fix the URL. You can start by removing parts from the end of the URL. Also, what is your CRM version? Is it 8.2 (Dynamics 365)?
Second, by using debug mode, inspect object this, especially attributes response and responseText, whether they contains some message.
Third, in F12 tool inspect the request and response. The tab is called Net or Network depending on browser. There can be many items. Clear the list before running your code. Look there what happened, what is returned for your request.

Categories