Making CrmWebApi Entity References Suck Less For Creates and Updates
account["[email protected]"] = "/contacts(E15C03BA-10EC-E511-80E2-C4346BAD87C8)";Was it “"@odata.bind” or “@bind.odata”? Was it a forward slash or backward slash? Did the Guid have curly braces?
Yes it’s a small pain, but it is bigger if you normally use field accessors (“entity.field” rather than array accessors: “entity[‘field’]”) because "[email protected]" isn't a valid field name. It’s probably because of my C# background, but I prefer not to use the object array accessor method when possible. So the question is, how to make this syntax better and help me remember it.
On my current project I use David Yack’s CRMWebAPI. It’s simple, and uses standard Promises, so no need for a new library, just polyfill Promises (if you’re using IE 11) and you’re all set. The calls are wrapped by a custom TypeScript library (CrmWebApiLib) to allow for some custom changes, of which, this implementation is one. First, the library defines an Entity Reference class (*Note, this is TypeScript, get it, use it, love it)
export class EntityReference implements ODataFormattable {The class has two public properties, “collectionName” and “id”, and implements the two functions of the ODataFormattable interface, “toODataFromat” and “getODataPropertyName”. The toODataFormat adds the forward slash and formats the guid correctly, and the getODataPropertyName appends the “@data.bind” to the property name parameter.
constructor(public collectionName: string, public id: string) { }
toODataFormat = (): string => {
return `/${this.collectionName}(${CrmWebApiLib.removeCurlyBraces(this.id)})`;
}
getODataPropertyName = (propertyName: string): string => {
return `${propertyName}@odata.bind`;
}
}
The ODataFormattable interface just defines the two functions. Then there is also a User Defined Type Guard to determine if any given object implements the ODataFormattable interface:
export interface ODataFormattable {This then is all used in the prepareForOData function:
toODataFormat(): string;
getODataPropertyName(propertyName: string): string;
}
export function isODataFormattable(arg: any): arg is ODataFormattable {
const formattable = arg as ODataFormattable;
return formattable && formattable.toODataFormat !== undefined && formattable.getODataPropertyName !== undefined;
}
/**It creates a new object, and basically loops through all properties of the data object, copying it over to the new object. If the value of the property is a ODataFormatable, it will update the value as well as the property name. There is then a recursive map call to handle arrays as well (think party lists). prepareForOData is then called from within the create and update methods:
* Loops through properties, searching for any ODataFormattable properties or arrays with ODataFormattable, and updates the format to be OData Friendly
* @param data
*/
function prepareForOData(data: any): any {
const oData = {};
for (const propName in data) {
if (!data.hasOwnProperty(propName)) {
continue;
}
const value = data[propName];
if (isODataFormattable(value)) {
oData[value.getODataPropertyName(propName)] = value.toODataFormat();
} else if (value instanceof Array) {
oData[propName] = value.map(prepareForOData);
} else {
oData[propName] = value;
}
}
return oData;
}
export function create(entityCollection: string, data: any): Promise<any> {And now, these two calls, will result in the same exact request made to the CrmWebApi:
return instance().Create(entityCollection, prepareForOData(data));
}
export function update(entityCollection: string, key: string, data: any, upsert?: boolean): Promise<any> {
if (key.indexOf("{") >= 0 || key.indexOf("}") >= 0) {
key = CrmWebApiLib.removeCurlyBraces(key);
}
return instance().Update(entityCollection, key, prepareForOData(data), upsert);
}
No Bueno
const note = {};
note["notetext"] = CommonLib.getValue(fields.description);
note["[email protected]"] = `/allgnt_locations(${CommonLib.getSelectedLookupId(fields.location)})`;
CrmWebApiLib.create("annotations", note);
Muy Bueno
const note = {
notetext: CommonLib.getValue(fields.description),
objectid_allgent_location: new CrmWebApiLib.EntityReference("allgnt_locations", CommonLib.getSelectedLookupId(fields.location))
};
CrmWebApiLib.create("annotations", note);
Published on:
Learn moreRelated posts
Enhancing Knowledge Retrieval with Microsoft Copilot Agents in Dynamics CRM and SharePoint
Studies show that 70% of employees spend unnecessary time searching for information across multiple systems, leading to productivity losses an...
{How to} become MCT Microsoft Certified Trainer on Microsoft Dynamics 365 Customer Engagement step by step instructions
Hello Everyone,Today i am going to share guidelines on becoming Microsoft Certified Trainer on Microsoft Dynamics 365 Customer Engagement or P...
Default Value vs. Current Value in Dynamics 365 CE: Key Differences
In Dynamics 365 CE (Customer Engagement), environment variables are used to manage configuration settings for solutions. When dealing with env...
How to Write and Understand a Dynamics CRM Plugin
Here’s a sample plugin code in Dynamics CRM written in C#, along with a detailed explanation of each line. This plugin will update the "...
Dynamics 365 CE Solution Import Failed in Azure DevOps Pipelines
Got the below error while importing Dynamics CRM Solution via Azure DevOps Pipeline. 2024-12-18T23:14:20.4630775Z ]2024-12-18T23:14:20.74...
Exploring the Differences: Managed vs. Unmanaged Solutions in Dynamics CRM/Dataverse
In Dynamics CRM/Dataverse, solutions are central to Application Lifecycle Management (ALM), providing a structured way to manage, package, and...
Effective Strategies for Debugging Plugins in Dynamics CRM
In a recent interview, I was asked about debugging plugins in Dynamics CRM. The interviewer specifically wanted to know my approach to plugin ...
Is Microsoft Dynamics CRM Affordable for Small Nonprofits?
Satish Reddy By Satish Reddy | Reading time 6 mins When considering a CRM solution, affordability is often a primary concern for small no...
How Microsoft Dynamics CRM Services Helps a Startup Nonprofit
Satish Reddy By Satish Reddy | Reading time 6 mins For startup nonprofits, the right Customer Relationship Management (CRM) system can be...
Easy Plugin Registration Tool Installation for Dynamics 365 CE Developers
Hi Folks, Are you a Power Platform or Dynamics 365 CE Developer, you would definitely need to work on Plugin Registration tool at any given po...