TypeScript: How to do Associate and Disassociate request in Model Driven Apps

Happy to connect again through this post.

I was looking for handy code snippet to use it in a project for associate and disassociate request in Typescript and couldn’t find one.

So though of sharing here if anyone in need.

Associate Request:

static async associateRecord(
    entitySetName: string | undefined,
    currentRecordId: string | undefined,
    relationshipName: string | undefined,
    relatedEntitySetname: string | undefined,
    relatedRecordId: string | undefined,
  ): Promise<any> {
    if (
      typeof entitySetName === "undefined" ||
      typeof currentRecordId === "undefined" ||
      typeof relationshipName === "undefined" ||
      typeof relatedEntitySetname === "undefined" ||
      typeof relatedRecordId === "undefined"
    ) {
      return Promise.reject(new Error("Invalid arguments"));
    }

    const url = Xrm.Utility.getGlobalContext().getClientUrl();

    const queryString = `${url}/api/data/v9.2/${entitySetName}(${currentRecordId})/${relationshipName}/$ref`;

    return new Promise<any>(function (resolve, reject) {
      const reqHeaders = new Headers();
      reqHeaders.append("OData-MaxVersion", "4.0");
      reqHeaders.append("OData-Version", "4.0");
      reqHeaders.append("Accept", "application/json");
      reqHeaders.append("Content-Type", "application/json");
      reqHeaders.append("Prefer", 'odata.include-annotations="*"');

      const associateBody = {
        "@odata.id": `${url}/api/data/v9.2/${relatedEntitySetname}(${relatedRecordId})`,
      };

      fetch(queryString, { headers: reqHeaders, method: "POST", body: JSON.stringify(associateBody) })
        // Handle success
        .then((response) => {
          resolve(response.status);
        }) // convert to json
        .catch((err) => {
          console.log("Error in Request (CreateFetchAPI)", err);
          reject(err);
        });
    });
  }

Dis-Associate Request: 

static async disassociateRecord(
    entitySetName: string | undefined,
    currentRecordId: string | undefined,
    relationshipName: string | undefined,
    associatedRecordId: string | undefined,
  ): Promise<any> {
    if (
      typeof entitySetName === "undefined" ||
      typeof currentRecordId === "undefined" ||
      typeof relationshipName === "undefined" ||
      typeof associatedRecordId === "undefined"
    ) {
      return Promise.reject(new Error("Invalid arguments"));
    }

    const url = Xrm.Utility.getGlobalContext().getClientUrl();

    const queryString = `${url}/api/data/v9.2/${entitySetName}(${currentRecordId})/${relationshipName}(${associatedRecordId})/$ref`;

    return new Promise<any>(function (resolve, reject) {
      const reqHeaders = new Headers();
      reqHeaders.append("OData-MaxVersion", "4.0");
      reqHeaders.append("OData-Version", "4.0");
      reqHeaders.append("Accept", "application/json");
      reqHeaders.append("Prefer", 'odata.include-annotations="*"');

      fetch(queryString, { headers: reqHeaders, method: "DELETE" })
        // Handle success
        .then((response) => {
          resolve(response.status);
        }) // convert to json
        .catch((err) => {
          console.log("Error in Request (DeleteFetchAPI)", err);
          reject(err);
        });
    });
  }

Parameters Example:

  1. entitySetName  – Table1 logical name
  2. currentRecordId – Table 1 record Id
  3. relationshipName:  relationship name
  4. associatedRecordId: Table 2 record id

hope it helps someone in need or to cross check. 

Please do share your thoughts and suggestions in comments.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.