Bad request error when calling a custom action through Javascript - javascript

I created a custom action on CRM 365 which has one input parameter of type entity reference and it refers to the user entity, I tried to change the input parameter into another type and it works well. So I think the issue is in the way I pass the entity reference value, I tried to change it but I haven't had any luck so can someone tell me what is the wrong in the below code?
function CreateBlockHistory() {
var Id = Xrm.Page.data.entity.getId();
Id = Id.replace("{", "").replace("}", "");
var data = {
"BlockedBy": {
"ohd_blockedby": Xrm.Page.context.getUserId().replace("}", "").replace("{", ""),
"#odata.type": "Microsoft.Dynamics.CRM.systemuser"
}
};
var serverURL = window.parent.Xrm.Page.context.getClientUrl();
var req = new XMLHttpRequest();
req.open("POST", serverURL + "/api/data/v8.1/new_units(" + Id + ")/Microsoft.Dynamics.CRM.ohd_ActionTest", false);
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 /* request completed */) {
req.onreadystatechange = null;
if (this.status == 200 /* response ready */) {
var data = JSON.parse(this.response);
}
else {
var error = JSON.parse(this.response).error;
}
}
};
req.send(window.JSON.stringify(data));
}

To start with 400 Bad request - it is a very generic useless error, instead of relying on this - try to run the same snippet in browser console or CRM REST Builder by passing hardcoded guid parameters to see execution status. You can debug too
I see your XMLHttpRequest is running synchronous ( bool param as false), switch it to Async & see
Also I see you are getting Xrm context with mixed approach like window.parent sometimes & directly sometimes. window.JSON too. If this is executing in web resource not in any entity form then fix it appropriately
You can register a plugin on that custom action message, profile/debug & see for any clue

Related

JavaScript XRM library for model-driven/Dynamics Power app not populating field

I have built a custom PowerApps model-driven app which is in very wide use across our organisation which manages workflow and database administration for our contracts.
In this app, the main Form is virtually all free-text input fields plus some Choice columns. What we would now like to do is, for some fields where the user is required to enter a Colleague’s name, is lookup to the AAD User table. This is a pretty straightforward Lookup column. However, what we then want is, when the person has been ‘lookedup’ and selected in this field, is to populate another column field automatically (so not on saving the record) with the selected Colleague’s email address which is in the AAD User table. I’m hoping I can get the JS code nailed for this, which I can then reuse across other fields where similar will likely be required.
I have written this code and added it as a web resource and associated it to the Form, but the email address field is not returning anything when someone is selected in the lookup column...
function populateEmailAddress() {
var lookupField = Xrm.Page.getAttribute("crc1e_peoplepickertest");
var emailAddressField = Xrm.Page.getAttribute("crc1e_ppemail");
if (lookupField.getValue() != null) {
var lookupValue = lookupField.getValue()[0];
var lookupId = lookupValue.id;
var lookupType = lookupValue.entityType;
if (lookupType === "systemuser") {
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/systemusers(" + lookupId + ")?$select=internalemailaddress", 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.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);
emailAddressField.setValue(result["internalemailaddress"]);
}
else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
}
}
}
lookupField.addOnChange(populateEmailAddress);
I've asked around and cannot get this to work, even asking MS. I don't know if I need an event handler on the form?
Cheers
K.
Tried with the code, expecting that the email address field would be populated, but nothing happens. Does it need an event handler?
There are several things you may need to do:
Add populateEmailAddress function as an OnChange event handler for the lookup field. Then when the lookup value gets changed, the function gets called. Remember to check the "Pass execution context as the first parameter" option when you add the event handler.
Xrm.Page is not recommended anymore, replace it with the new formContext object.
Replace XMLHttpRequest with existed API Xrm.WebApi.online.
In the final, your code should look like this:
function populateEmailAddress(executionContext) {
// get formContext
var formContext = executionContext.getFormContext();
var lookupField = formContext.getAttribute("crc1e_peoplepickertest");
var emailAddressField = formContext.getAttribute("crc1e_ppemail");
if (lookupField.getValue() != null) {
var lookupValue = lookupField.getValue()[0];
var lookupId = lookupValue.id;
var lookupType = lookupValue.entityType;
if (lookupType === "systemuser") {
Xrm.WebApi.online.retrieveRecord("systemuser", lookupId, "?$select=internalemailaddress").then(
function success(result) {
if(result && result["internalemailaddress"]){
emailAddressField.setValue(result["internalemailaddress"]);
}
},
function (error) {
Xrm.Utility.alertDialog(error.message);
}
);
}
}
}

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.

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.

Jena Fuseki not working when making an insert query from javascript. No Update parameter error

I have this JavaScript function which aims to insert a keyword in a named graph which belongs to the project Dataset.
function insert(keyword) {
var query = "INSERT DATA {GRAPH <http://test1> {<subj> <pred>'" + keyword + "'. }}";
var endpoint = "http://localhost:3030/project/update";
sparqlQueryJson(query, endpoint, showResults, true);
}
I have executed Jena Fuseki with the --update option. The sparqlQueryJson function is as follows:
function sparqlQueryJson(queryStr, endpoint, callback, isDebug) {
var querypart = "query=" + escape(queryStr);
// Get our HTTP request object.
var xmlhttp = null;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// Code for older versions of IE, like IE6 and before.
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} else {
alert('Perhaps your browser does not support XMLHttpRequests?');
}
// Set up a POST with JSON result format.
xmlhttp.open('POST', endpoint, true); // GET can have caching probs, so POST
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.setRequestHeader("Accept", "application/sparql-results+json");
// Set up callback to get the response asynchronously.
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
// Process the results
callback(xmlhttp.responseText);
} else {
// Some kind of error occurred.
alert("Sparql query error: " + xmlhttp.status + " " + xmlhttp.responseText);
}
}
};
xmlhttp.send(querypart);
};
The showResults function is, in my opinion, not very important here, since it takes the results of the query and show them in HTML.
I followed what is discussed here and here, executing the query using the http://localhost:3030/project/update. The thing is that if I execute the same query on top of the local Fuseki server with the same endpoint url by using the web, it works, but from the JavaScript code, it raises the error:
"SPARQL query error: 400 Error 400: SPARQL Update: No 'update=' parameter".
I'm using Ubuntu 16.04 and Jena Fuseki - version 2.4.1.
To solve this problem the =query parameter has to be changed to =update. In addition, a parameter with the type of the query has to be handled, i.e., update or query.
if(type==="update"){
var querypart = "update=" + escape(queryStr);
}else if(type === "query"){
var querypart = "query=" + escape(queryStr);
}
...
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
if(type==="query"){
xmlhttp.setRequestHeader("Accept", "application/sparql-results+json");
}

Sending data from javascript to php file

I have this function that gets text from a php file on the server and plonks it into an HTML page.
What changes do I need to make to it to SEND data (just a couple of javascript variables) to the php file rather than read from it ? Hoping not many !!
function process() {
if (xmlHttp) // the object is not void
{
try {
xmlHttp.open("GET", "testAJAX.php", true);
xmlHttp.onreadystatechange = handleServerResponse;
xmlHttp.send(null);
} catch (e) {
alert(e.toString());
}
}
}
Take a look at what all headers you can make use of. In your case, you would want to use POST instead of GET
xmlHttp.open("POST", "testAJAX.php", true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");//or JSON if needed
xmlHttp.onreadystatechange = handleServerResponse;
xmlHttp.send(data);
You are probably better of using POST to send data it has less limitations. e.g:
var data = {
user: 'Joe',
age: 12
};
var httpReq = new XMLHttpRequest();
// true means async - you want this.
httpReq.open('POST', 'testAJAX.php', true);
// json is just a nice way of passing data between server and client
xmlhttpReq.setRequestHeader('Content-type', 'application/json');
// When the http state changes check if it was successful (http 200 OK and
// readyState is 4 which means complete and console out the php script response.
httpReq.onreadystatechange = function () {
if (httpReq.readyState != 4 || httpReq.status != 200) return;
console.log(httpReq.responseText);
};
httpReq.send(JSON.stringify(data));
And read it:
$name = json_decode($_POST['name']);
$age = json_decode($_POST['age']);
If it's just a couple of variables, you can pop them into the query string - although you'll want to make sure their values won't break your PHP script or open a security hole (for example, don't interpret user input as a SQL string). For more complicated data structures, use POST as others have suggested.
function process(var1value, var2value) {
if(xmlHttp) {
try {
xmlHttp.open("GET", "testAJAX.php?var1="+var1value+"&var2="+var2value, true);
xmlHttp.onreadystatechange = handleServerResponse;
xmlHttp.send(null);
} catch(e) {
alert(e.toString());
}
}
}

Categories