Saturday, March 19, 2016

Blog Series: Introduction to Dynamics CRM 2016 Web API

The release of the Microsoft Dynamics CRM Web API provides non-.Net developer types with true freedom to integrate CRM rich data sets into other platforms. This also provides CRM developers with the ability to create some great visuals within CRM as well when out-of-the-box grids and charts just won't do.  Since I also moonlight as an Angularjs and IonicFramework developer, I'm uber-excited about the possibilities that this provides.  Prior to the release of the Web API, developers had the SOAP based endpoint which was an authentication nightmare for those connecting from non .Net applications or the REST endpoint which was good but provided a very limited set of methods.

The Web API is ODATA 4.0 compliant which means that it adheres to and supports all and provides some awesome new features:
  • OAuth Support - OAuth is the authentication method supported for the Dynamics CRM Web API.  Because users in CRM Online and on-premise Internet Facing Deployments(IFD) are authenticated using Azure Active Directory Services, developers can leverage Azure Active Directory Authentication Library to authenticate to CRM from external applications. Before developers can use OAuth authentication to connect to CRM, the application must first be registered with Azure Active Directory.  Azure Active Directory is used to verify that your application is permitted to access the business data in CRM.  We'll go through a tutorial on how to build a SPA consuming the CRM Web API later in the series.
  • CORS Support - with the increase in popularity of Single-Page Applications(SPA) and javascript frameworks available to support building them, the need for Cross-Origin Resource Support(CORS) support is vital since most browsers restrict requests from other domains.
  • Predefined queries - support for executing saved system views and personal views.
  • Custom FetchXml  - since system and personal views really are just executing saved FetchXml, you can leverage that same principal and use custom FetchXml with your HTTP Get request.
  • Custom Actions and Functions - Those familiar with ASP.Net Web APIs will know the concept of Actions and Functions, if not you can read up on it here.  Essentially actions and functions are a way to encapsulate additional behaviors that are not captured in normal CRUD operations.  The difference between Actions and Functions is that Actions can have server-side effects, meaning data that other HTTP Requests can be performed besides HTTP Get. 
    • Query Functions - query functions are intended to further filter your HTTP GET requests.  Functions available are similar to those found in an Advanced Find filter criteria such as  Last X Months or Equals User or His Reporting Hierarchy.  For a complete list of functions available, check it out here.
    • Functions - The Dynamics CRM Web API has both bound and unbound functions.  In Web API terms, bound functions are those tied to a specific entity while unbound functions are not.  For a complete list of functions supported, click here.
    • Actions - Like Functions, actions For a complete list of actions supported, click here.  The true game changer here is that your custom actions that you create can also be called from Web APIs as well. 
  • Batch Operations - With batch operations, one can execute multiple requests in one transaction.  Use a POST request to submit a batch operation.  The POST request containing the batch must have a Content-Type header with a value set to multipart/mixed with a boundary set to include the identifier of the batch using this pattern. 
  • Optimistic Concurrency - check whether an entity has been modified since it was last retrieved before making changes.

Web API Limitations aka The Fine Print

Of there will be a few gotchas here.  
  • There are a few functions that are not supported found here 
  • Querying date values is a bit quirky - To query date values you can't use "eq" keyword, instead use one of the other supported CRM Web API Functions such as between, greater than, etc.
       Doesn' Work
    /contacts?$select=fullname,birthdate&$filter=birthdate eq 1990-01-01
        
       Works
     /contacts?$select=fullname,birthdate&$filter=Microsoft.Dynamics.CRM.Between(PropertyName='birthdate',PropertyValues=["1990-01-01","1990-01-01"])
    

  • One thing with the Web API is that there are several navigation properties that may not be supported.  One in particular that  I stumbled upon while developing is that retrieving navigation properties for collections is not supported.  For example if you wanted to retrieve the primary contact for a particular account, you can write it like this and works like a charm.
"GET [organization URI]/api/data/v8.0/accounts/primarycontactid?$select=fullname HTTP/1.1
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0"
This will render the following error:
  {
  "error":{
    "code":"","message":"The request URI is not valid. Since the segment 'accounts' refers to a collection, this must be the last segment in the request URI or it must be followed by an function or action that can be bound to it otherwise all intermediate segments must refer to a single resource.","innererror":{
      "message":"The request URI is not valid. Since the segment 'accounts' refers to a collection, this must be the last segment in the request URI or it must be followed by an function or action that can be bound to it otherwise all intermediate segments must refer to a single resource.","type":"Microsoft.OData.Core.ODataException","stacktrace":"   at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.CheckSingleResult(Boolean isSingleResult, String identifier)\r\n   at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.CreateNextSegment(String text)\r\n   at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.ParsePath(ICollection`1 segments)\r\n   at Microsoft.OData.Core.UriParser.Parsers.ODataPathFactory.BindPath(ICollection`1 segments, ODataUriParserConfiguration configuration)\r\n   at Microsoft.OData.Core.UriParser.ODataUriParser.Initialize()\r\n   at Microsoft.OData.Core.UriParser.ODataUriParser.ParsePath()\r\n   at System.Web.OData.Routing.DefaultODataPathHandler.Parse(IEdmModel model, String serviceRoot, String odataPath, ODataUriResolverSetttings resolverSettings, Boolean enableUriTemplateParsing)\r\n   at System.Web.OData.Routing.DefaultODataPathHandler.Parse(IEdmModel model, String serviceRoot, String odataPath)\r\n   at Microsoft.Crm.Extensibility.OData.CrmODataPathHandler.Parse(IEdmModel model, String serviceRoot, String odataPath)"
    }
  }
}

In this 5-part blog series, we will take a deep-dive into the Dynamics CRM Web API.

  • Part 1 - CRM Web API Fundamentals - Exploring the Dynamics CRM Web API
  • Part 2 - Building better visualizations with Dynamics CRM Web API with jQuery DataTables and Chart.js
  • Part 3 - Doing Stuff with the Dynamics CRM Web API using functions and custom actions
  • Part 4 - Authenticating CRM Users with Azure Active Directory Active Library 
  • Part 5 - Putting it all together - Building a SPA with Angular.js and Dynamics CRM Web API 
Get ready!


No comments :

Post a Comment