cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
ManishJain
Solution Sage
Solution Sage

How to call custom actions using PCF

How do I make calls to custom actions from PCF ? Any suggestions , please help.

 

Thanks

18 REPLIES 18
tvd_nzi
Advocate II
Advocate II

I'm unable to call a custom action following the ms documentation on using custom actions and this thread. The following is my query I append to the url:

 

const query = `/api/data/v9.0/incidents(${this._entityId})/Microsoft.Dynamics.CRM.my_CustomAction`;

 

 

I'm now getting this error:

{"error":{"code":"","message":"No HTTP resource was found that matches the request URI 'https://XXX.crm4.dynamics.com/api/data/v9.0/incidents(1234567890)/Microsoft.Dynamics.CRM.my_CustomAction'."}}

What am I missing?

 

 

let response = await fetch(query, {
			method: 'post',
			headers: headers,
			body: body
		});

 

 

HI @tvd_nzi ,

 

If you are able to make custom action call from D365 , I would suggest solution by @ben-thompson , I used the same xmlhttp call as I was not sure about Xrm.Webapi being suppported for custom action call.

 

Thanks

Daniel_Bergsten
New Member

This is how I implemented PCF call to custom action / Custom API:

        //execute custom api action
        /*
        <Action Name="sos_customapi_getcontactinfo">
        <Parameter Name="ContactID" Type="Edm.Guid" Nullable="false"/>
        <ReturnType Type="mscrm.sos_customapi_getcontactinfoResponse" Nullable="false"/>
        </Action>
        */
        // Execute request
        var apiRequest = new class {

            ContactID = {
                guid: "934fd982-988c-eb11-b1ac-0022489bcf55"
            };

            getMetadata(): any {
                return {
                    parameterTypes: {

                        ContactID: {
                            typeName: "Edm.Guid",
                            structuralProperty: 1
                        }
                    },
                    operationType: 0,
                    operationName: "sos_customapi_getcontactinfo"
                };
            }
        }();

        // <li-user uid="7429" login="TS"></li-user>-ignore
        this.context.webAPI.execute(apiRequest).then(
            function success(response: any) {
                console.log(response);
            },
            function (errorResponse: any) {
                // Error handling code here
                console.log(errorResponse);
            }
        );

A small improvement of the code above. This example uses casting to enable calling the execute method:

 //execute custom api action
        /*
        <Action Name="sos_customapi_getcontactinfo">
        <Parameter Name="ContactID" Type="Edm.Guid" Nullable="false"/>
        <ReturnType Type="mscrm.sos_customapi_getcontactinfoResponse" Nullable="false"/>
        </Action>
        */
        // Execute request
        var apiRequest = new class {

            ContactID = {
                guid: "934fd982-988c-eb11-b1ac-0022489bcf55"
            };

            getMetadata(): any {
                return {
                    parameterTypes: {

                        ContactID: {
                            typeName: "Edm.Guid",
                            structuralProperty: 1
                        }
                    },
                    operationType: 0,
                    operationName: "sos_customapi_getcontactinfo"
                };
            }
        }();

        var anyWebAPI = <any>this.context.webAPI;
        anyWebAPI.execute(apiRequest).then(
            function success(response: any) {
                console.log(response);
                console.log(response.json());
            },
            function (errorResponse: any) {
                // Error handling code here
                console.log(errorResponse);
            }
        );
Mab
Regular Visitor

I am quite new with PCF controls and had a task to call a Custom API from PCF control which is built using React, Typescript and Fluent UI. @ScottDurow is right webAPI (which is pulled from context (ComponentFramework.Context<IInputs>) does have execute method in it.

This method is not part of Typescript but if you debug the control you should be able to see it on the WebAPI.

then I used "//@ts-ignore" to ignore typescript as you can see below. It works like a charm

 var apiRequest = new class {
                AreaCode = inputText;
            
                getMetadata(): any {
                        return {
                        parameterTypes: {
                            "AreaCode ": {
                                "typeName": "Edm.String",
                                "structuralProperty": 1
                            }
                        },
                        operationType: 0,
                        operationName: "customapiname",
                    };
                    }
            }();

//@ts-ignore
this.context.webAPI.execute(apiRequest).then(
            function success(response: any) {
                console.log(response);
                console.log(response.json());
            },
            function (errorResponse: any) {
                // Error handling code here
                console.log(errorResponse);
            }
        );

 

skoofy5
Advocate V
Advocate V

I haven't checked it, but I feel like the xhr wouldn't be difficult - something like this:

 

function callCustomAction(newAreaCode: string, customapiname:string) {

  var data = {
    "AreaCode": newAreaCode
  };

  const url = "/api/data/v9.2/" + customapiname;
  var req = new XMLHttpRequest();
  req.open("POST", url, 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 == 200) {
        //callback or processing goes here
      }
    }
  };
req.send(JSON.stringify(data));
}

 

DianaBirkelbach
Super User
Super User

I still prefer the context.webApi.execute, since the xhr won't work offline.

Anothe problem is setting up the url for the webAPI xhr request. At least the version from the url will change some time. 
Integrated ways are the best.

Kind regards,
Diana
----------
Please click "Accept as Solution" if my post answered your question so that others may find it more quickly. If you found this post helpful consider giving it a "Thumbs Up."


@DianaBirkelbach wrote:

I still prefer the context.webApi.execute, since the xhr won't work offline.

Anothe problem is setting up the url for the webAPI xhr request. At least the version from the url will change some time. 
Integrated ways are the best.


Integrated is definitely the way to go, but only when they're documented or there has been communication that things are stable enough to start implementing. Unfortunately this is all I've seen, but would be really happy to hear that it's safe/stable now!

 

Also, you mention execute being used for offline mode, but the client api warns that it's only available for online - is that not the case for the component framework implementation? That would be awesome!

 

skoofy5_1-1648444500368.png

DianaBirkelbach
Super User
Super User

Hi @skoofy5 , 

 

For the Xrm.WebApi there are not only the "online" or "offline" modes, but also we find the methods directly in the Xrm.WebApi namespace, which takes care by themselves if the user is online or offline and calls the appropriate method: https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/xrm-webap...

I think this is similar with the PCF webAPI methods. It's true that is not specified in the docs, but it's also not stated that it won't work offline.

 

I've actually made a test using the WebAPI Sample PCF: https://docs.microsoft.com/en-us/powerapps/developer/component-framework/sample-controls/webapi-cont.... It worked in offline mode without problems. Also the Dataset .save() method worked in offline mode too.

In both cases, the changes were sync as soon I've changed to online mode.

 

Kind regards,
Diana
----------
Please click "Accept as Solution" if my post answered your question so that others may find it more quickly. If you found this post helpful consider giving it a "Thumbs Up."

Helpful resources

Announcements
Power Apps News & Annoucements carousel

Power Apps News & Announcements

Keep up to date with current events and community announcements in the Power Apps community.

Community Call Conversations

Introducing the Community Calls Conversations

A great place where you can stay up to date with community calls and interact with the speakers.

Power Apps Community Blog Carousel

Power Apps Community Blog

Check out the latest Community Blog from the community!

Top Solution Authors
Users online (1,497)