Contact entities in CRM 2011 have a lot of built-in fields, and I've added some custom fields as well.
I want to fetch all field names as a list using Javascript. If you want to create a email template, CRM will let you choose from all of the fields from a dialog. I'd like to get the field names and values as they appear in that dialog.
I used the following code to fetch all attributes for a contact, but this list includes all object properties, not just the contact fields.
ODataPath = GetServerUrl() + "/XRMServices/2011/OrganizationData.svc";
var retrieveRecordsReq = new XMLHttpRequest();
var result = "";
retrieveRecordsReq.open('GET', ODataPath + "/AccountSet(guid'" + guid + "')", false);
retrieveRecordsReq.setRequestHeader("Accept", "application/json");
retrieveRecordsReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveRecordsReq.send();
var entity = JSON.parse(retrieveRecordsReq.responseText).d;
When I inspect the entity object using IE developer tools, it shows me all of the contact's properties, but with different names. For example, in CRM Contact, there is a field mobilephone, but in IE it is entity.MobilePhone. Further, IE does not display any of the custom fields.
You don't get different names, with the REST endpoint you get the Schema Name.
Read this article for more information: http://www.mohamedibrahim.net/blog/2012/10/04/dynamics-crm-entity-and-field-display-name-field-schema-name-and-field-logical-name-attribute-name/
The entity contains also the custom fields, the endpoint returns all fields, OOB and custom one.
Your solution for get a list of all attribute is correct. as Guido told it is Schema Name.
i test your code and add some line off Codes for create a list off all attribute:
ODataPath = GetServerUrl() + "/XRMServices/2011/OrganizationData.svc";
var retrieveRecordsReq = new XMLHttpRequest();
var url = "";
if (entityname == 'account')
url = "/AccountSet(guid'" + guid + "')";
else if (entityname == 'contact')
url = "/ContactSet(guid'" + guid + "')";
else if (entityname == 'lead')
url = "/LeadSet(guid'" + guid + "')";
else if (entityname == 'systemuser')
url = "/SystemUserSet(guid'" + guid + "')";
retrieveRecordsReq.open('GET', ODataPath + url, false);
retrieveRecordsReq.setRequestHeader("Accept", "application/json");
retrieveRecordsReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveRecordsReq.send();
var entity = JSON.parse(retrieveRecordsReq.responseText).d;
var AllContactFields = new Array();
for(var x in entity)
{
if (typeof entity[x] == 'object') {
if (entity[x] == null)
AllContactFields.push(x);
}
else {
AllContactFields.push(x);
}
}
the AllContactFields array is the result list.
Good Luck
Related
Lets assume that I have 3 related Entities (PhoneCall-Account-Contact). For detailed information I must say in phonecall form I have a custom lookup field that related to account and another one that related to contact and last one again related to account which used for parent account. Now I want a solution that help me when I fill account field after that fill parent account lookup with correct data or if I fill contact lookup first of all fill account with correct data then fill parent account field with correct data. I search many ways but I couldn't find any way to find correct parent account and fill my lookups even I use business rules but it can't help me.
Now I have seen on many websites that CRM REST BUILDER was suggested. I had Used it but it couldn't solve my problem.
What you need is, a Javascript function to trigger on change of first lookup to query necessary fields from parent record and fill it in current child record form. Read more
function fillParentAccount() {
var lookup= Xrm.Page.getAttribute("accountfieldname").getValue(); //you will get the id with exxtra double quotes or square brackets by doing get value hence you to make it readable by CRM , you must slice it. i have use the below method:
var newid = lookup[0].id.slice(1, -1); // you will get perfect id like "EDCJDKDJDKJDJDKJDJKD" here.
var req = new XMLHttpRequest(); //once you have the id , you have frame to make a webapi GET call by proving the newid we got.
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.1/accounts(" + newid + ")?$select=_parentaccountfieldname_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); // you will get the retrieved value in object we stored in result var.
var retrivedvalue= result._parentaccountfieldname_value; //get the id of the field
var retrivedformatedvalue= result["_parentaccountfieldname_value#OData.Community.Display.V1.FormattedValue"]; //get the formatted name of the field
if (retrivedvalue!= null) {
var value = new Array();
value[0] = new Object();
value[0].id = retrivedvalue;
value[0].name = retrivedformatedvalue;
value[0].entityType = "account";
Xrm.Page.getAttribute("parentaccountfield").setValue(value); //set the lookup value finally
}
else
alert("some textt!!!!!!") // optional
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
Make sure to change the field names and accuracy of your customizations.
I have to remake FetchUtil.js for using it in CRM 2011 UR 12. I'm not very good in javascript, so I need some help.
This is the native code
var sFetchResult = xmlhttp.responseXML.selectSingleNode("//a:Entities").xml;
var resultDoc = new ActiveXObject("Microsoft.XMLDOM");
resultDoc.async = false;
resultDoc.loadXML(sFetchResult);
It doesn't work even in IE now, because of .selectSingleNode("//a:Entities").xml
I did it like this, but there is no xml field there.
sFetchResult = xmlhttp.responseXML.getElementsByTagName('a:Entities')[0].xml;
var resultDoc = new ActiveXObject("Microsoft.XMLDOM");
resultDoc.async = false;
resultDoc.loadXML(sFetchResult);
Help me to remake this for IE and Chrome.
Thanks a lot!
Here is my calling module (include as webresource)
(function (module, undefined) {
module.buildFetchRequest = function (fetch) {
/// <summary>
/// builds a properly formatted FetchXML request
/// based on Paul Way's blog post "Execute Fetch from JavaScript in CRM 2011"
/// http://blog.customereffective.com/blog/2011/05/execute-fetch-from-javascript-in-crm-2011.html
/// </summary>
var request = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
request += "<s:Body>";
request += '<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">' +
'<request i:type="b:RetrieveMultipleRequest" ' +
' xmlns:b="http://schemas.microsoft.com/xrm/2011/Contracts" ' +
' xmlns:i="http://www.w3.org/2001/XMLSchema-instance">' +
'<b:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic">' +
'<b:KeyValuePairOfstringanyType>' +
'<c:key>Query</c:key>' +
'<c:value i:type="b:FetchExpression">' +
'<b:Query>';
request += CrmEncodeDecode.CrmXmlEncode(fetch);
request += '</b:Query>' +
'</c:value>' +
'</b:KeyValuePairOfstringanyType>' +
'</b:Parameters>' +
'<b:RequestId i:nil="true"/>' +
'<b:RequestName>RetrieveMultiple</b:RequestName>' +
'</request>' +
'</Execute>';
request += '</s:Body></s:Envelope>';
return request;
};
module.sendFetchQuery = function (fetchRequest, doneCallback, failCallback) {
//path to CRM root
var server = window.location.protocol + "//" + window.location.host;
//full path to CRM organization service - you may need to modify this depending on your particular situation
var path = server + "/XRMServices/2011/Organization.svc/web";
$.ajax({
type: "POST",
dataType: 'xml',
async: false,
contentType: "text/xml; charset=utf-8",
processData: false,
url: path,
data: fetchRequest,
beforeSend: function (xhr) {
xhr.setRequestHeader(
"SOAPAction",
"http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute"
); //without the SOAPAction header, CRM will return a 500 error
}
}).done(doneCallback)
.fail(failCallback);
};
}(window.xFetch = window.xFetch || {}));
Usage
(the parser requires jQuery ... I am doing most of my fetch calls in web resourced html pages so this isn't a problem) this works in IE and Chrome haven't checked firefox but I can't see why it wouldn't work.
var fetchXml =
xFetch.buildFetchRequest("<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>" +
" <entity name='ENTITYNAME'>" +
" <attribute name='ATTRIBUTE' />" +
" </entity>" +
"</fetch>");
var entityList = new Array();
xFetch.sendFetchQuery(fetchXml,
function (fetchResponse) {
// chrome doesn't like the namespaces because of
// selectSingleNode implementations (which make sense btw)
// I'll never understand why Microsoft have to pepper their xml
// with namespace dross
$(fetchResponse).find("a\\:Entity, Entity").each(function () {
var entityData = {};
$(this).find("a\\:KeyValuePairOfstringanyType, KeyValuePairOfstringanyType").each(function () {
var xmlElement = $(this);
var key = xmlElement.find("b\\:key, key").text();
var value = xmlElement.find("b\\:value, value").text();
entityData[key] = value;
});
//inner loop
$(this).find("a\\:KeyValuePairOfstringstring, KeyValuePairOfstringstring").each(function () {
var xmlElement = $(this);
var key = xmlElement.find("b\\:key, key").text();
var value = xmlElement.find("b\\:value, value").text();
entityData[key] = value;
});
entityList.push(entityData);
});
}, function (jqXhr, textStatus, errorThrown) {
// if unsuccessful, generate an error alert message
});
for (var i = 0; i < entityList.length; i++) {
if (entityList[i].ATTRIBUTE === "Yes" ){
// DO WHATEVER
}
}
I only needed attributes with KeyValuePairOfstringstring and KeyValuePairOfstringanyType but you could parse out any attribute with the right combination of selectors
each item in retrieved
I was facing the similar issue and I resolved it by using below workaround.
var sFetchResult = xmlhttp.response;
var tempresultDoc = new ActiveXObject("Microsoft.XMLDOM");
tempresultDoc.async = false;
tempresultDoc.loadXML(sFetchResult);
// Now at this point we will have the XML file. Get the singleNode from the XML by using below code.
var resultDoc = new ActiveXObject("Microsoft.XMLDOM");
resultDoc.async = false;
resultDoc.loadXML(tempresultDoc.childNodes[0].selectSingleNode("//a:Entities").xml);
Regards,
Krutika Suchak
If you're looking for a version that doesn't require JQuery, and one that parses the results, check this out. It not only wraps the FetchXML, but also parses the response XML into JavaScript objects for easy retrieval.
I have some javascript code on my form that when the record is first being created it auto populates 2 lookup fields with the current user. This works fine most of the time but I've noticed that on the first time that I use it (per day/session?) the first field that I want to fill in does get populated however the field still looks empty, as if the code has not worked.
I've confirmed that the field is getting filled in and it is only the display for this field that isn't working, but I can't figure out why, especially why it is only the one field that this is happening with.
I will post the code I use below, when calling it I pass in an array of the field names that I want to set. Can anyone help me find out why this isn't working?
Thanks
function RetrieveUserInfo(fieldsToSet) {
//Retrieve user information
var context;
var serverUrl;
var UserID;
var ODataPath;
context = Xrm.Page.context;
serverUrl = context.getServerUrl();
UserID = context.getUserId();
ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc";
var retrieveUserReq = new XMLHttpRequest();
retrieveUserReq.open("GET", ODataPath + "/SystemUserSet(guid'" + UserID + "')", true);
retrieveUserReq.setRequestHeader("Accept", "application/json");
retrieveUserReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveUserReq.onreadystatechange = function () {
SetUserValues(this, fieldsToSet);
};
retrieveUserReq.send();
}
function SetUserValues(retrieveUserReq, fieldsToSet) {
if (retrieveUserReq.readyState == 4
/* complete */
) {
if (retrieveUserReq.status == 200) {
var retrievedUser = this.parent.JSON.parse(retrieveUserReq.responseText).d;
if (retrievedUser.FullName != null)
//Get details of current user
var setUservalue = new Array();
setUservalue[0] = new Object();
setUservalue[0].id = Xrm.Page.context.getUserId();
setUservalue[0].entityType = 'systemuser';
setUservalue[0].name = retrievedUser.FullName;
//get form type
var formType = Xrm.Page.ui.getFormType();
if (formType != undefined) { //Create
if (formType == 1) {
//for each field specified, set it to the current user
for (var i = 0; i < fieldsToSet.length; i++) {
Xrm.Page.getAttribute(fieldsToSet[i]).setValue(setUservalue);
}
}
}
}
else {
}
}
}
This is a long shot, but the field that doesn't work - it doesn't happen to be a disabled field? If it's a readonly field you might have to add
Xrm.Page.getAttribute(“fieldname”).setSubmitMode(“always”);
on the onsave event.
I'm currently working on incorporating an authorization feature for Twitter following the approach described here: https://dev.twitter.com/docs/auth/implementing-sign-twitter. I'm using Ajax to send my POST 'http' request, but I've been constantly running into a '401: Unauthorized' error. My code is below:
function getTweets() {
var time = generateTimestamp();
var nonce = generateNonce();
var signature = generateSignature(time, nonce);
var headers = {
"Authorization": 'OAuth oauth_callback="http%3A%2F%2Fwww.google.com%2F", oauth_consumer_key="eEeAAz9fakedtAOlIUhPgQ", oauth_nonce="bbc34b2ca6faabogus6dfc025907fa334", oauth_signature="' + signature + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + time + '", oauth_version="1.0"'
};
$.ajax({
type: "POST",
url: "https://api.twitter.com/oauth/request_token",
dataType: "text",
headers: headers,
success: function(data) {
alert("Success!");
console.log(data);
},
error: function(jq) {
alert("Request Failed.");
console.log(jq.statusText);
}
});
}
function generateTimestamp() {
var currentTime = new Date;
currentTime = Math.floor(currentTime.getTime() / 1000);
return currentTime;
}
function generateNonce() {
var code = "";
for (var i = 0; i < 20; i++) {
code += Math.floor(Math.random() * 9).toString();
}
return code;
}
function generateSignature(timestamp, nonce) {
var http_method = "POST";
var base_url = "https://api.twitter.com/oauth/request_token";
var consumer_key = "eEeAAz9hUKtdjunkeIUhPgQ";
var consumer_secret = "c7wHxnjubxVDcc5hYFqnotactuallymysecretWs2XazUFde0lPRBtBQ";
var signature_method = "HMAC-SHA1";
var token = "609493744-kNPzLKSI4Hg9NWQnopeFPb91eXFUutFm1nZ2hDk2";
var token_secret = "15WOJS9Ji1AXsKRkyAZrxKdsalted5Gj5ZyEAb9aVrJxI";
var version = "1.0";
var parameter_string = "oauth_callback=" + encodeURIComponent(base_url) + "&oauth_consumer_key=" + consumer_key + "&oauth_nonce=" + nonce + "&oauth_consumer_key=" + consumer_key + "&oauth_signature_method=" + signature_method + "&oauth_timestamp=" + timestamp +"&oauth_version=" + version;
var base_string = http_method + "&" + encodeURIComponent(base_url) + "&" + encodeURIComponent(parameter_string);
var signing_key = encodeURIComponent(consumer_secret) + "&";
var signature = encodeURIComponent(window.btoa(CryptoJS.HmacSHA1(base_string, signing_key)));
alert(signature);
return signature;
}
Feel free to post below if there's any other information that would make this error clearer. Thanks.
I created a node.js library to mess around with the Twitter OAuth dance and API. Code is here, tweeter.js
You're welcome to walk through the logic for creating the header and signature (starting at line 348 )
One thing I don't see in the code you've posted and which will make a huge difference is that the signature string must be generated to include the original header, then the header must be rebuilt with the generated string. It's a huge pain and it took me a while to figure it out.
Although the code I wrote is geared toward node.js, you should be able to reuse a lot of the logic to meet your needs.
EDIT
I found a site called hueniverse documented OAuth very well. In fact, there is a utility here to build your own headers for validating your logic (select the 'Create your own' radio button).
EDIT 2
To better explain including the oauth_signature value in the header, suppose you have all of the data up to this point:
var headerObj = {
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0"
};
You create the HMAC-SHA1 signature and receive: "jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
You would then add that return value to headerObj, giving you:
headerObj = {
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0",
oauth_signature="jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
};
And this modified version of headerObj is what you build your HTTP headers from.
GET / HTTP/1.1
Host: api.twitter.com:443
Authorization: OAuth realm="https://api.twitter.com/",
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0",
oauth_signature="jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
NOTE: I didn't verify the host/realm/port, so these are probably wrong. Check the API for those.
The reason this is done is that on Twitter's side (this is an OAuth implementation detail), the oauth_signature value is removed and the rest of the header is hashed and its return value is compared to the value sent in oauth_signature. It's sort of like a wax seal on an envelope... if the hash of the rest of the header doesn't match the hash value you sent in oauth_signature, Twitter knows not to trust the sender or the contents.
EDIT 2.5
I'm moving this from the comment to the answer.
If you check out this line in tweeter.js, you'll see the logic.
var signature = self.oauthSignature(method, path, headerObj, query);
headerObj.oauth_signature = qs.escape(signature);
// concat the header object into a csv string
var header = 'OAuth realm="Twitter API",';
var oauthParts = [];
for (var h in headerObj) {
oauthParts.push(h + '="'+headerObj[h]+'"');
}
header+= oauthParts.join(',');
//...
return header;
This bit of code does as I've explained in EDIT 2, by converting a JSON object into key="value" strings stored in oauthParts[], then joins each element in that array into a single comma-separated string which begins with OAuth realm="Twitter API",
I wrote this script to for a contact form on my website, everything works however instead of storing the data in me database all is get is
[object HTMLCollection] c
an anyone tell me what this is?
or what is going wrong? i have had a look on google but i cant find much information on it.
<script type="text/javascript">
//when the button is clicked
$(document).ready(function() {
$("#button").click(function() {
$('.small').hide();
var name = $("input#name").val();
if (name == "") {
$("span#name").show();
return false;
}
var name = $("input#email").val();
if (name == "") {
$("span#email").show();
return false;
}
var name = $("input#subject").val();
if (name == "") {
$("span#subject").show();
return false;
}
var name = $("textarea#message").val();
if (name == "") {
$("span#message").show();
return false;
}
var dataString = 'name='+ name + '&email=' + email + '&subject=' + subject + '&message=' + message;
$.ajax({
type: "POST",
url: "/scripts/send_message.php",
data: dataString,
});
$("#messagearea").load("console/new_message_profile.php?sent=1");
});
});
</script>
As #Namit mentioned, you use name as a variable everywhere. Building your string, email, subject and message are uninitialised.
They should give you an undefined - but no, due to a weird Internet Explorer behaviour (see Is there a spec that the id of elements should be made global variable?) these variables hold DOM elements. As you seem to have multiple elements with the same id (NEVER DO THAT), here a <span> and an <input>, the variables even seem to hold HTMLCollection objects. Which are casted to the string [object HTMLCollection], when you concat them with other strings.
You're reusing the variable name for all the other fields as well. You need to change the field name to the respective input id.
var name = $("input#email").val(); // needs to be email
var name = $("input#subject").val(); // needs to be subject