Is it possible to recreate the entity record with the predefined Id?
The purpose of this question is to figure out how to create the entity record with the id you have provided.
For example when I delete Account record with the id '00-00-02' it does not exist in MS Dynamics CRM anymore. So now I want to recreate this Account record using REST API with it`s old id ('00-00-02').
Can anyone suggest me how to do it (or it is not possible)?
D365 allows you to set the primary key Guid of an entity. Often when doing data migrations from one D365 org to another we'll push the id's across.
Here's an example of setting the accountId on a new account via the Web API. (Created in Jason Lattimer's CRMRESTBuilder):
var entity = {};
entity.accountid = "008A5AD9-59B7-43BB-BA41-BA59CB5B4769";
entity.name = "Acme Inc.";
var req = new XMLHttpRequest();
req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/accounts", 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 {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send(JSON.stringify(entity));
Here is an OrganizationService version of the same code:
Entity account = new Entity("account");
account.Id = new Guid("008A5AD9-59B7-43BB-BA41-BA59CB5B4769");
account["name"] = "Acme Inc.";
service.Create(account);
Related
How can I retrieve records behalf of another user.
Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name&$top=3").then(
function success(result) {
for (var i = 0; i < result.entities.length; i++) {
console.log(result.entities[i]);
}
// perform additional operations on retrieved records
},
function (error) {
console.log(error.message);
// handle error conditions
}
);
I know we can do impersonation using XMLHttpRequest by passing MSCRMCallerID header. Not sure we can achieve the same in Xrm.WebApi.
This is my Prod code, doing some update/assign operation under Admin impersonation from a HTML webresource.
var entity = {};
entity["ownerid#odata.bind"] = "/systemusers(" + currentUserId + ")";
var req = new XMLHttpRequest();
req.open("PATCH", parent.Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.1/new_customentity(" + opptyid + ")", 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("MSCRMCallerID", "0AFB2F7E-D323-E511-80F0-C4346BAC29F0"); //CRM Admin impersoantion
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));
Update
Passing header is the only way and Xrm.WebApi cannot accept request headers.
Documentation says:
There are two ways you can impersonate a user, both of which are made possible by passing in a header with the corresponding user id.
Preferred: Impersonate a user based on their Azure Active Directory (AAD) object id by passing that value along with the header CallerObjectId.
Legacy: To impersonate a user based on their systemuserid you can leverage MSCRMCallerID with the corresponding guid value.
I can only distinguish parent references based on the data from the entity record I have retrieved. The question is
how to list all child references for a specific entity record?
I have an account entity and I want to find all related child entities (contacts ... etc) using REST API.
Try using below code to retrieve related child entities for parent:
function RetrieveRelatedChildEntities() {
var url = Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.0/EntityDefinitions(LogicalName='account')?$select=LogicalName,DisplayCollectionName&$expand=ManyToManyRelationships,ManyToOneRelationships,OneToManyRelationships";
req.open("GET", url, 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 results = JSON.parse(this.response);
for (var i = 0; i < results.OneToManyRelationships.length; i++) {
}
}
}
}
}
We are in the process of remediation, re-engineering old JS web resources for latest D365 v9 sdk changes w.r.t Client scripting API improvements & deprecation.
When rewriting the web api methods using Xrm.WebApi, we end up with this blocker.
The scenario is setting null to lookup, and tried the below code:
var data = {
"abc_relatedentity#odata.bind": null
};
Xrm.WebApi.updateRecord("abc_entity", abc_entityid, data).then(successCallback, errorCallback);
This is throwing error:
"The 'odata.bind' instance or property annotation has a null value. In OData, the 'odata.bind' instance or property annotation must have a non-null string value."
The idea is to retire the below redundant XHR request code. But this is the only workaround we have now (referring MSDN).
var req = new XMLHttpRequest();
req.open("DELETE", Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.0/accounts(recordGUID)/account_parent_account/$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
}
}
};
req.send();
Anybody faced this & handled it? Am I missing something?
You have to use Delete method to remove the lookup value
format is as follows:
/api/data/v8.0/accounts(1DD18913-11CB-E511-80D2-C4346BDC11C1)/primarycontactid/$ref
I think set the column to null is enough, please make sure you removed '#odata.bind'
var data = {
"abc_relatedentity": null
};
This is working for me.
you should try Xrm.WebApi.online.execute or Xrm.WebApi.online.executeMultiple
var Sdk = window.Sdk || {};
/**
* Request to execute an update operation
*/
Sdk.UpdateRequest = function(entityName, entityId, payload) {
this.etn = entityName;
this.id = entityId;
this.payload = payload;
};
// NOTE: The getMetadata property should be attached to the function prototype instead of the
// function object itself.
Sdk.UpdateRequest.prototype.getMetadata = function () {
return {
boundParameter: null,
parameterTypes: {},
operationType: 2, // This is a CRUD operation. Use '0' for actions and '1' for functions
operationName: "Update",
};
};
// Construct a request object from the metadata
var payload = {
"_abc_relatedentity_value": null
};
var updateRequest = new Sdk.UpdateRequest("abc_entity", abc_entityid, payload);
// Use the request object to execute the function
Xrm.WebApi.online.execute(updateRequest).then(
function (response) {
console.log(response)
},
function(error) {
console.log(error.message);
// handle error conditions
}
);
Great news! You can set lookup field to null in PATCH request by adding this header to your request.
autodisassociate: true
And then you can use something like this to alter your lookup field in any way:
SetLookupField(requestBody, "systemusers", "msdfm_MyUser", null)
// Or
SetLookupField(requestBody, "systemusers", "msdfm_MyUser", "f5b0b514-aea8-ea11-a812-000d3a569fe1")
// ...
private static void SetLookupField(JObject requestBody, string typePlural, string name, string value)
{
if (!string.IsNullOrEmpty(value))
{
requestBody.Add($"{name}#odata.bind", $"/{typePlural}({value})");
}
else
{
requestBody.Add($"_{name.ToLower()}_value", null);
}
}
OP uses XMLHttpRequest anyway, so I thought, a way to do this using PATCH will be relevant here.
To set null on the lookup use:
var data = { _[LookupFieldName]_value : null }
Xrm.WebApi.updateRecord("abc_entity", abc_entityid, data).then(successCallback, errorCallback
For example to remove contact.parentcustomerid field value you need to use:
var data = {};
data._parentcustomerid_value = null
var t = await Xrm.WebApi.updateRecord("contact", "{0200E6F5-1D21-E811-A954-0022480042B3}", data)
I just tried in v9.1.0.3832
var data = { _[LookupFieldName]_value : null } is working for me.
var data =
{
"statecode": 1,
"*_myprefix_mylookupfieldname_value*": null
}
Xrm.WebApi.updateRecord("*entityName*", *recordId*, data);
I am trying to create an email entity in Dynamics 365 using Logic Apps.
I am filling in the From and Recipient fields but the when I check the record created in Dynamics, I see that these fields are empty. I know that to and from fields are activity parties in Dynamics 365 email entity. Do we have a sample json which I can use in Logic Apps to create an Email Activity with To and From fields set?
As per the product group its not available right now to create and set to and from fields of email entity from logic apps
Sorry, answering without access to laptop. And this is not straightforward answer for you. But just a start to build your own request Json object.
Replace your record guids in below snippet & execute this in browser console or CRM js web resource. Take the JSON.stringify(email) at the end & that's what you're looking for.
var serverURL = Xrm.Page.context.getClientUrl();
var email = {};
email["subject"] = "Email Subject";
email["description"] = "email body description";
email["regardingobjectid_contact#odata.bind"] = "/contacts(guid1)";
//activityparty collection
var activityparties = [];
//from party
var from = {};
from["partyid_systemuser#odata.bind"] = "/systemusers(guid2)";
from["participationtypemask"] = 1;
//to party
var to = {};
to["partyid_contact#odata.bind"] = "/contacts(guid3)";
to["participationtypemask"] = 2;
activityparties.push(to);
activityparties.push(from);
//set to and from to email
email["email_activity_parties"] = activityparties;
var req = new XMLHttpRequest();
req.open("POST", serverURL + "/api/data/v8.0/emails", 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.setRequestHeader("Prefer", "return=representation");
req.onreadystatechange = function() {
if (this.readyState == 4 /* complete */ ) {
req.onreadystatechange = null;
if (this.status == 201) {
var emailUri = this.getResponseHeader("OData-EntityId");
}
else {
var error = JSON.parse(this.response).error;
alert(error.message);
}
}
};
req.send(JSON.stringify(email));
}
In case if you need it, Code referred from this blog.
I have two urls to call to get json object and tabulate them in tableviewcontroller. However, I could not able to figure out how to Create a single TableSource that can handle two different instances of List.
public void Inbox()
{
var ts= new TableSource(this);
TableView.Source=ts;
var client1 = new RestClient ("MyURL");
client1.Authenticator = new HttpBasicAuthenticator ("admin", "admin");
var request1 = new RestRequest ("MYURL/x/y");
request1.AddHeader ("Accept", "application/json");
request1.AddHeader ("Content-Type", "application/json");
var client2 = new RestClient ("MyURL");
client2.Authenticator = new HttpBasicAuthenticator ("admin", "admin");
var request2 = new RestRequest ("MYURL/a/b");
request2.AddHeader ("Accept", "application/json");
request2.AddHeader ("Content-Type", "application/json");
client1.ExecuteAsync (request1, response1 => {
aTasks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<HTask>> (response1.Content);
InvokeOnMainThread (() => {
ts.Data1= aTasks;
TableView.ReloadData();
});
});
client2.ExecuteAsync (request2, response2 => {
bTasks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<HTask>> (response2.Content);
InvokeOnMainThread (() => {
ts.Data2= bTasks;
TableView.ReloadData();
});
});
}
create your TableSource and assign it when you create your TableView. Instead of passing the data in the constructor, create two public properties for the two different datasets you're working with.
var ts = new TableSource(this);
TableView.Source = ts;
later, then you have your data loaded, update your existing TableSource
ts.Data1 = aTasks;
TableView.ReloadData();
when your second set of data loads, update your existing TableSource again
ts.Data2 = bTasks;
TableView.ReloadData();