Web API Functions and Actions Sample

 

Applies To: Dynamics 365 (online), Dynamics 365 (on-premises), Dynamics CRM 2016, Dynamics CRM Online

This group of samples demonstrate how to perform bound and unbound functions and actions, including custom actions, using the Microsoft Dynamics 365 Web API. This sample is implemented as a separate project for the following languages:

This topic explains the structure and content of the sample at a higher, language-neutral level. Review the linked sample topics above for language-specific implementation details about how to perform the operations described in this topic.

Demonstrates

This sample is divided into the following principal sections, containing Web API functions and actions operations which are discussed in greater detail in the associated conceptual topics.

Topic section

Associated topic(s)

Sample data

Using unbound function with no parameters

Unbound functions

WhoAmI Function

systemuser EntityType

Using unbound function with parameters

Unbound functions

GetTimeZoneCodeByLocalizedName Function

Using bound function with no parameters

Bound functions

CalculateTotalTimeIncident Function

Using unbound action with parameters

Unbound actions

WinOpportunity Action

opportunity EntityType

Using bound action with parameters

Bound actions

AddToQueue Action

WhoAmI Function

systemuser EntityType

letter EntityType

Using bound custom action with parameters

Use a custom action

Bound actions

contact EntityType

Using unbound custom action with parameters

Use a custom action

Unbound actions

account EntityType

Handling custom action exceptions

Use a custom action

Unbound actions

contact EntityType

The following sections contain a brief discussion of the Dynamics 365 Web API operations performed, along with the corresponding HTTP messages and associated console output.

Sample data

To ensure the operations in this sample work properly, we first create sample data on the Dynamics 365 server. These sample data will be deleted from the server unless the user chooses to not delete them. The data in this sample are created individually as follows.

  • Create an account (e.g.: Fourth Coffee) and associate it with an incident that has three 30 minute tasks (90 minutes total). After the tasks are created, they are then marked as completed. The operation will calculate the total time it took to complete these three tasks.

    {
      title: "Sample Case",
      "customerid_account@odata.bind": accountUri,
      Incident_Tasks: [
       {
        subject: "Task 1",
        actualdurationminutes: 30
       },
       {
        subject: "Task 2",
        actualdurationminutes: 30
       },
       {
        subject: "Task 3",
        actualdurationminutes: 30
       }
      ]
     };
    
  • Create an account and associate it with an opportunity. This opportunity will be mark as won in the sample operation.

    {
     name: "Sample Account for WebAPIFunctionsAndActions sample",
     opportunity_customer_accounts: [{
      name: "Opportunity to win"
     }]
    };
    
  • Create a letter activity. The letter will be added to the current user's queue in the sample operation.

    {
      description: "Example letter"
    }
    
  • Create a contact to use with a custom action sample_AddNoteToContact in the sample operation.

    {
      firstname: "Jon",
      lastname: "Fogg"
    }
    

Sample operations

The sample operations in this topic are organized in the following ways.

  • Working with functions: These operations show bound and unbound functions that either accept parameters or not.

  • Working with actions: These operations show bound and unbound actions that either accept parameters or not.

  • Custom actions: These operations show bound and unbound actions and how to handle custom error exceptions.

Working with functions

Functions are operations that do not have side effects. A function can be bound to an entity instance or an entity collection. Query functions are never bound. For more info, see Use Web API functions. This section shows samples of how bound and unbound functions are used and how parameters are passed in.

Using unbound function with no parameters

Use an unbound function to retrieve the current user's full name by making use of the WhoAmI Function. This operation demonstrates how to call an unbound function that does not accept parameters. This operation returns the current user's full name.

Getting the request and response for the WhoAmI Function.

HTTP Request

GET http://[Organization URI]/api/data/v8.2/WhoAmI HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8

HTTP Response

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0
Content-Length: 273

{
   "@odata.context":"http://[Organization URI]/api/data/v8.2/$metadata#Microsoft.Dynamics.CRM.WhoAmIResponse",
   "BusinessUnitId":"0d6cc84a-d3f6-e511-80d0-00155da84802",
   "UserId":"b08dc84a-d3f6-e511-80d0-00155da84802",
   "OrganizationId":"0f47eae2-a906-4ae4-9215-f09875979f6a"
}

Using unbound function with parameters

Use an unbound function to retrieve the time zone code. This operation demonstrates how to call an unbound function that accept parameters. This operation returns the current time zone code for the specified time zone. More information: Passing parameters to a function

HTTP Request

GET http://[Organization URI]/api/data/v8.2/GetTimeZoneCodeByLocalizedName(LocalizedStandardName=@p1,LocaleId=@p2)?@p1='Pacific%20Standard%20Time'&@p2=1033 HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8

HTTP Response

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0
Content-Length: 154

{
   "@odata.context":"http://[Organization URI]/api/data/v8.2/$metadata#Microsoft.Dynamics.CRM.GetTimeZoneCodeByLocalizedNameResponse",
   "TimeZoneCode":4
}

Console output

Unbound function: GetTimeZoneCodeByLocalizedName
    Function returned time zone Pacific Standard Time, with code '4'.

Using bound function with no parameters

Use a bound function to retrieve the total time it took to complete all the tasks of an incident. This operation demonstrates how to call a bound function that does not accept parameters. This operation returns the total minutes the incident took to close out all its tasks. This function also makes use of the incident data we created for this sample program. More information: Bound functions

HTTP Request

GET http://[Organization URI]/api/data/v8.2/incidents(3d920da5-fb4a-e611-80d5-00155da84802)/Microsoft.Dynamics.CRM.CalculateTotalTimeIncident() HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8

HTTP Response

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0
Content-Length: 148

{
   "@odata.context":"http://[Organization URI]/api/data/v8.2/$metadata#Microsoft.Dynamics.CRM.CalculateTotalTimeIncidentResponse",
   "TotalTime":90
}

Console output

Bound function: CalculateTotalTimeIncident
    Function returned 90 minutes - total duration of tasks associated with the incident.

Working with actions

Actions are operations that allow side effects. An action is either bound or unbound. For more info, see Use Web API actions. This section shows samples of how bound and unbound actions are used and how parameters are passed in. It also shows how custom actions are used and how to handle exceptions from these custom actions.

Using unbound action with parameters

Use an unbound action that takes a set of parameters. This operation closes an opportunity and marks it as won by calling the WinOpportunity Action. The opportunity EntityType was created as sample data earlier in the program. More information: Unbound actions

HTTP Request

POST http://[Organization URI]/api/data/v8.2/WinOpportunity HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8

{
   "Status":3,
   "OpportunityClose":{
      "subject":"Won Opportunity",
      "opportunityid@odata.bind":"http://[Organization URI]/api/data/v8.2/opportunities(47920da5-fb4a-e611-80d5-00155da84802)"
   }
}

HTTP Response

HTTP/1.1 204 No Content
OData-Version: 4.0

Console output

Unbound Action: WinOpportunity
    Opportunity won.

Using bound action with parameters

Use a bound action that takes parameters. This operation adds a letter to the current user's queue. To accomplish this, we use the WhoAmI Function and the systemuser EntityType to get a reference to the current user's queue. We also need reference to the letter EntityType. This letter was created as sample data earlier in the program. Then the bound AddToQueue Action is called to add the letter to the current user's queue. More information: Bound actions

HTTP Request

POST http://[Organization URI]/api/data/v8.2/queues(1f7bcc50-d3f6-e511-80d0-00155da84802)/Microsoft.Dynamics.CRM.AddToQueue HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8
Content-Length: 110

{
   "Target":{
      "activityid":"4c920da5-fb4a-e611-80d5-00155da84802",
      "@odata.type":"Microsoft.Dynamics.CRM.letter"
   }
}

HTTP Response

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0
Content-Length: 170

{
   "@odata.context":"http://[Organization URI]/api/data/v8.2/$metadata#Microsoft.Dynamics.CRM.AddToQueueResponse",
   "QueueItemId":"67bdfabd-fc4a-e611-80d5-00155da84802"
}

Console output

Bound Action: AddToQueue
    QueueItemId returned from AddToQueue Action: 67bdfabd-fc4a-e611-80d5-00155da84802

Working with custom actions

If you define custom actions for your solution, you can call them using the Dynamics 365 Web API. Regardless of whether the operations included in your custom action have side effects, they can potentially modify data and therefore are considered actions rather than functions. There is no way to create a custom function. More information: Use a custom action.

This sample comes with two custom actions. They both require parameters but one is bound and the other is unbound.

  • sample_AddNoteToContact: A bound custom action that takes two parameters. One is a NoteTitle and the other is a NoteText. This custom action adds a note to a contact EntityType. Below is a screen shot of the Information page for this custom action.

    Custom Action - AddNoteToContact information

  • sample_CreateCustomer: An unbound custom action that require different parameters depending on what type of customer is being created. For example, when the AccountType is "account" then it only requires AccountName parameter. When the AccountType is "contact", a ContactFirstName and ContactLastName parameters are required. Below is a screen shot of the Information page for this custom action.

    Custom Action - CreateCustomer information

Using bound custom action with parameters

This example calls the sample_AddNoteToContact custom action which is bound to the contact entity with the required parameters. This custom action adds a note to an existing contact. This action returns an entity with an annotationid property. To show that the note was added, the annotationid is used to request information about the note.

The request and response of the action.

HTTP Request

POST http://[Organization URI]/api/data/v8.2/contacts(4d920da5-fb4a-e611-80d5-00155da84802)/Microsoft.Dynamics.CRM.sample_AddNoteToContact HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8
Content-Length: 80

{
   "NoteTitle":"The Title of the Note",
   "NoteText":"The text content of the note."
}

HTTP Response

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0
Content-Length: 149

{
   "@odata.context":"http://[Organization URI]/api/data/v8.2/$metadata#annotations/$entity",
   "annotationid":"ba146d0b-fd4a-e611-80d5-00155da84802"
}

The request and response of the annotation.

HTTP Request

GET http://[Organization URI]/api/data/v8.2/annotations(ba146d0b-fd4a-e611-80d5-00155da84802)?$select=subject,notetext&$expand=objectid_contact($select=fullname) HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8

HTTP Response

HTTP/1.1 200 OK
OData-Version: 4.0
Content-Length: 450

{
   "@odata.context":"http://[Organization URI]/api/data/v8.2/$metadata#annotations(subject,notetext,objectid_contact,objectid_contact(fullname))/$entity",
   "@odata.etag":"W/\"622978\"",
   "subject":"The Title of the Note",
   "notetext":"The text content of the note.",
   "annotationid":"ba146d0b-fd4a-e611-80d5-00155da84802",
   "objectid_contact":{
      "@odata.etag":"W/\"622968\"",
      "fullname":"Jon Fogg",
      "contactid":"4d920da5-fb4a-e611-80d5-00155da84802"
   }
}

Console output

Custom action: sample_AddNoteToContact
    A note with the title 'The Title of the Note' and the content 'The text content of the note.' was created and associated with the contact Jon Fogg.

Using unbound custom action with parameters

This operation calls the sample_CreateCustomer custom action to create an "account" customer. Required parameters are passed in for a CustomerType of account.

HTTP Request

POST http://[Organization URI]/api/data/v8.2/sample_CreateCustomer HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8
Content-Length: 103

{
   "CustomerType":"account",
   "AccountName":"Account Customer Created in WebAPIFunctionsAndActions sample"
}

HTTP Response

HTTP/1.1 204 No Content
OData-Version: 4.0

Handling custom action exceptions

This example shows that custom actions can return custom error messages. You handle custom exceptions the same way you handle standard exceptions. To get the custom error message from the sample_CreateCustomer custom action , this example creates a "contact" customer. However, we intentionally pass in the wrong parameters for this CustomerType parameter. This operation then catches the exception and displays the error message, then continues with the sample program.

HTTP Request

POST http://[Organization URI]/api/data/v8.2/sample_CreateCustomer HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Content-Type: application/json; charset=utf-8
Content-Length: 103

{
   "CustomerType":"contact",
   "AccountName":"Account Customer Created in WebAPIFunctionsAndActions sample"
}

HTTP Response

HTTP/1.1 500 Internal Server Error
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0
Content-Length: 2760

{
   "error":{
      "code":"",
      "message":"ContactFirstName and ContactLastName are required when CustomerType is contact.",
      "innererror":{
         "message":"ContactFirstName and ContactLastName are required when CustomerType is contact.",
         ...[truncated]
      }
   }
}

Console output

Expected custom error: ContactFirstName and ContactLastName are required when CustomerType is contact.

See Also

Use the Microsoft Dynamics 365 Web API
Use Web API functions
Use Web API actions
Web API Functions and Actions Sample (C#)
Web API Functions and Actions Sample (Client-side JavaScript)

Microsoft Dynamics 365

© 2016 Microsoft. All rights reserved. Copyright