Development, Howto

Microsoft Dynamics 365 v9.0: Usage of new OOB WebApi functions – Part 2

In previous post I described how to perform CRUD operations using OOB wrapper for WebApi operations released as a part of v9.0 release. In this I will describe 2 remaining methods – execute and executeMultiple. Methods are used to execute actions or functions.

Let me start from execute and actions. execute method accepts “request” object as parameter and returns Promise object as all other methods described before. To get understanding of those objects I had to reverse-engineer source code. If you’re interested about in all requests available OOB you can check following JS files for reference:

https://yourcrm.crm.dynamics.com/webresources/sales/clientcommon/sales_clientcommon.js

Request has to contain not only data of request itself but special function getMetadata that returns object that completely describes request here are required members for that function:

  1. “boundParameter” – if your Action/Function has no binding then pass null, if it’s bound to entity – pass “entity”, if it’s bound to set of entities, pass “entityset”.
  2. “parameterTypes” property should contain metadata that describes all the parameters you have in your action/function.
  3. “operationName” is self-explanatory – it’s a name of Action of Function you want to call.
  4. “operationType” – set 0 for Action and 1 for Function
Example of Unbound Action Example of Entity-Bound Action Example of EntitySet-Bound Action

Here is example of WinOpportunity action that is unbound action:

var winOpportunityRequest = {
    OpportunityClose: {
        "opportunityid@odata.bind": "/opportunities(32DE8FA9-03AA-E711-A94E-000D3A109280)",
        "actualrevenue": 100,
        "actualend": new Date(),
        "description": "Your description here"
    },
    Status: -1,
    getMetadata: function() {
        var metadata = {
            boundParameter: null,
            parameterTypes: {
                "OpportunityClose": {
                    "typeName": "Microsoft.Dynamics.CRM.opportunityclose",
                    "structuralProperty": 5
                },
                "Status": {
                    "typeName": "Edm.Int32",
                    "structuralProperty": 1
                }
            },
            operationName: "WinOpportunity",
            operationType: 0
        };

        return metadata;
    }
};

Xrm.WebApi.execute(winOpportunityRequest)
    .then(function(result) {
        //Handle retrieved data
    })
    .fail(function(error) {
        var message = error.message;
        //Add handling of error that occurred
    });

Following screenshot demonstrates mapping between metadata of request and request object:

Example of CalculateActualValueOpportunity action that is entity-bound action:

var calculateActualValueOpportunityRequest = {
    entity: {
        id: "32DE8FA9-03AA-E711-A94E-000D3A109280",
        entityType: "opportunity"
    },
    getMetadata: function () {
        var metadata = {
            boundParameter: "entity",
            parameterTypes: {
                "entity": {
                    "typeName": "Microsoft.Dynamics.CRM.opportunity",
                    "structuralProperty": 5
                }
            },
            operationName: "CalculateActualValueOpportunity",
            operationType: 0
        };

        return metadata;
    }

};

Xrm.WebApi.execute(calculateActualValueOpportunityRequest)
    .then(function (result) {
        var response = JSON.parse(result.responseText);
        var calculatedValue = response.Value;
        //Handle retrieved data
    })
    .fail(function (error) {
        var message = error.message;
        //Add handling of error that occurred
    });

Following screenshot demonstrates mapping between metadata of request and request object for Entity-Bound Action. Main difference between this and previous request objects – boundParameter property of object is set to “entity” instead of null and “entity” property in parameterTypes:

Example of FulfillSalesOrder that is EntitySet-Bound action. Main difference between this and previous requests – “boundParameter” property is set to “entityset” instead of “entity” like in previous example and “entityset” property available in “parameterTypes” instead of “entity”.

var fulfillSalesOrderRequest = {
    OrderClose: {
        "subject": "Put Your Fulfill Subject Here",
        "salesorderid@odata.bind": "/salesorders(58D2C742-9F0D-E711-8102-3863BB354FF0)",
        "description": "Additional Description Here",
        "actualend": new Date()
    },
    Status: -1,
    getMetadata: function () {
        var metadata = {
            boundParameter: "entityset",
            parameterTypes: {
                entityset: {
                    typeName: "mscrm.salesorder",
                    structuralProperty: 4
                },
                OrderClose: {
                    typeName: "Microsoft.Dynamics.CRM.orderclose",
                    structuralProperty: 5
                },
                Status: {
                    typeName: "Edm.Int32",
                    structuralProperty: 1
                }
            },
            operationName: "FulfillSalesOrder",
            operationType: 0
        };

        return metadata;
    }

};

Xrm.WebApi.execute(fulfillSalesOrderRequest)
    .then(function (result) {
        var response = JSON.parse(result.responseText);
        //Handle retrieved data
    })
    .fail(function (error) {
        var message = error.message;
        //Add handling of error that occurred
    });

In the next part I will demonstrate how to build and use request objects for functions.

15 Comments

  1. Any idea if this is supported or if this is the intended usage? I was thinking that eventually this will be added to Xrm.WebApi.messages that refreshes with changes and probably also a tsd file to go along, so I can reduce the boilerplate.

    1. Natraj,
      To be honest I can’t give you exact answer until SDK is released.
      Andrii

    1. Mark,
      Xrm.WebApi namespace was released as a part of v9.0 and it’s not available in earlier versions. With 8.2 you will have to use other approach like in article you mentioned.
      Thanks,
      Andrew

  2. I have created an action , New_SendReportToSharePoint

    Call metadata, I see this definition

    java-script request looks like this.

    var accountid = Xrm.Page.data.entity.getId();
    var new_SendReportToSharePointRequest = {
    entity: {
    id: accountid,
    entityType: “account”
    },
    ReportPayload: “mybase64 encoded string”,
    getMetadata: function () {
    var metadata = {
    boundParameter: “entity”,
    parameterTypes: {
    “entity”: {
    “typeName”: “Microsoft.Dynamics.CRM.account”,
    “structuralProperty”: 5
    },
    “ReportPayload”: {
    “typeName”: “Edm.String”
    }
    },
    operationName: “new_SendReportToSharePoint”,
    operationType: 0
    };

    return metadata;
    }

    };

    Execution looks like this.

    Xrm.WebApi.execute(new_SendReportToSharePointRequest)
    .then(function (result) {
    var response = JSON.parse(result.responseText);
    var calculatedValue = response.Value;
    //Handle retrieved data
    })
    .fail(function (error) {
    var message = error.message;
    //Add handling of error that occurred
    });
    }

    I don’t see the response entering success or failure branches. I suspect it is my ‘ReportPayLoad’ input parameter. I’m not sure if there is a specific value for structuralproperty I am supposed to pass for ReportPayLoad. Also, I do not see any trace of the plug-in executing.

    Cheers

    1. Mark,
      What version are you on? If it’s earlier then 9.0 usage of Xrm.WebApi should cause error in your code.
      Thanks,
      Andrew

  3. It seems like you can also use

    result.json().then(function(json) {
    //this contains the response properties in JSON format
    });

    in your response handler.
    Probably Microsoft has implemented some custom json deserializing :-).

  4. Hello Andrew, Thanks for your usefull posts; Do you have any suggestion or example to develop Xrm.WebApi.Execute samples with user defined Action like new_myaction (or new_webapiaction56e28da25300e811a959000d3a1a941e) ??

    Best regards.

  5. Hello I tried on my Demo (365 V9.0) this code

    var calculateAccountWebApiRequest = {
        entity: {
            id: accountid,
            entityType: “account”
        },
        getMetadata: function () {
            var metadata = {
                boundParameter: “entity”,
                parameterTypes: {
                    “entity”: {
                        “typeName”: “Microsoft.Dynamics.CRM.account”,
                        “structuralProperty”: 5
                    }
                },
                operationName: “cg_webapiaction56e28da25300e811a959000d3a1a941e”,
                operationType: 0
            };
     
            return metadata;
        }
     
    };
     
    Xrm.WebApi.execute(calculateAccountWebApiRequest)
        .then(function (result) {
            var response = JSON.parse(result.responseText);
            var calculatedValue = response.Value;
            //Handle retrieved data
        })
        .fail(function (error) {
            var message = error.message;
            //Add handling of error that occurred
        });

    I received this error : –> error.message = “Request message has unresolved parameters.”
    Do you have any suggestion to solve this Issue ?

    1. I have similar issues. It seems that request is not get serialized in proper way. Here is the code that worked for me. Check if it worked for you:

      var parameters = {
      Target: {
      entityType: “account”,
      id: accountid
      }
      };

      Xrm.Utility.invokeProcessAction(“cg_webapiaction56e28da25300e811a959000d3a1a941e”, parameters)
      .then(function (result) {
      var actionResponse = result.get_outputParameters();
      var resultString = actionResponse.Result;
      console.log(“Action was executed. Result is equal to ” + resultString);
      })
      .fail(function (error) {
      console.log(“error during execution of action -” + error.debugMessage);
      });

  6. Hello Andrew

    your code work (I changed only characthers –>”<– )

    this my code changes
    1) I created new action cg_onboundwebapiaction
    2) set up Entity = none(global)
    3) I changed the code i this way

    var calculateAccountWebApiRequest = {
       /* entity: {
            id: accountId.toString().replace("{","").replace("}",""),
            entityType: "entity"
        }, */
        getMetadata: function () {
            var metadata = {
                boundParameter: null,
                parameterTypes: {
                   /*  "entity": {
                        "typeName": "Microsoft.Dynamics.CRM.account",
                        "structuralProperty": 5
                    } */
                },
                operationName: "cg_onboundwebapiaction",
                operationType: 0
            };
     
            return metadata;
        }
     
    };
     
    Xrm.WebApi.execute(calculateAccountWebApiRequest)
        .then(function (result) {
            var response = JSON.parse(result.responseText);
            var calculatedValue = response.Result;
           
        })
        .fail(function (error) {
            var message = error.message;
            
        });
    it works
    thanks for your help !!

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.