Working with the OData Endpoint in Dynamics 365 for Operations

By Chris Roehrich | January 13, 2017

Working with the odata endpoint in dynamics 365 for operations

The OData endpoint is a new REST-based service that allows for integrating with Dynamics 365 for Operations. Below are some tips to help with using an OData client to authenticate and use methods to read and write data in the system.

Data Entities

Data Entities that are marked ‘Yes’ for the ‘Is Public’ property will be available as an OData endpoint. You can consume this OData endpoint in your external application such as a .Net application for integration scenarios.

In the screenshot below, I have created a custom data entity called CPRCustCreditRatingEntity. Note the Is Public, Public Collection Name and Public Entity Name properties:

odata-endpoint_chris

When viewed using the Chrome browser, I can see my custom Data entity is available:

odata-endpoint_chris-2

od-endpoint_chris-3

Tip: If using IE to view the OData endpoint, you might have to open the JSON results in a separate file download. Chrome will automatically show the JSON results in the browser.

Creating a OData Client Application

Use the OData v4 Client Code Generator in your Visual Studio application to build the OData entity proxy classes. This can be downloaded and installed from with Visual Studio. Once it is installed, you can add the OData client to the application. In the following screenshots, I downloaded it and then added it to my C# Console application project:

od-endpoint_chris-4

od-endpoint_chris-5

This will create a file with an extension of tt which stands for Text Template. Update the MetadataDocumentUri string value in the tt file so it contains your OData metadata endpoint. For example, mine is:

public const string MetadataDocumentUri = “https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/$metadata”;

Lastly, right click on the tt file and choose to ‘Run custom tool’. This will read the metadata and build a large class file (45+ MB). It may take several minutes to complete. You can explore the CS file when it completes.

od-endpoint_6

Using the generated proxy classes

The generated proxy classes let you instantiate the data entity objects, set properties, and call methods to interact with the OData endpoint. The following is an example of reading a CustCreditRating record using a LINQ (System.Linq) query pattern:

//Get Single CustCreditRating
Console.WriteLine("Get a single CustCreditRating instance...");
CustCreditRating existCustCreditRating = GetCustCreditRating("USMF", "US-010");
Console.WriteLine("Credit Rating for {0} is {1}. Press Enter.", existCustCreditRating.CustomerAccount, existCustCreditRating.CreditRating);
Console.ReadLine();

The GetCustCreditRating method:
#region Get Single CustCreditRating
        private static CustCreditRating GetCustCreditRating(string targetAXLegalEntity, string customerAccount)
        {
            context.SendingRequest2 += new EventHandler<SendingRequest2EventArgs>(delegate (object sender, SendingRequest2EventArgs e)
            {
                var authenticationHeader = OAuthHelper.GetAuthenticationHeader();
                e.RequestMessage.SetHeader(OAuthHelper.OAuthHeader, authenticationHeader);
            });

            var custCreditRatingQuery = from entity in context.CustCreditRatings
                                        where entity.DataAreaId == targetAXLegalEntity
                              && entity.CustomerAccount == customerAccount
                              select entity;

            return (custCreditRatingQuery.Count() > 0) ? custCreditRatingQuery.First() : null;
        }
#endregion

The following code is a complete example of creating multiple Customer records using the OData endpoint:
using System;
using AuthenticationUtility;
using Microsoft.OData.Client;
using CustomerOdataClient.Microsoft.Dynamics.DataEntities;

namespace CustomerOdataClient
{
    class Program
    {
        private static string ODataEntityPath = ClientConfiguration.Default.ODataEndpointUri;
        private static Uri oDataUri = new Uri(ODataEntityPath, UriKind.Absolute);
        private static Resources context = new Resources(oDataUri);


        static void Main(string[] args)
        {
            Console.WriteLine("Set HTTP header...");
            context.SendingRequest2 += new EventHandler<SendingRequest2EventArgs>(delegate (object sender, SendingRequest2EventArgs e)
            {
                var authenticationHeader = OAuthHelper.GetAuthenticationHeader();
                e.RequestMessage.SetHeader(OAuthHelper.OAuthHeader, authenticationHeader);
            });

            Console.WriteLine("Creating new customer using Data Entity OData...");
            Customer myCustomer = new Customer();
            DataServiceCollection<Customer> customersCollection = new DataServiceCollection<Customer>(context);

            customersCollection.Add(myCustomer);
            
            myCustomer.CustomerAccount = "US-X11111";
            myCustomer.Name = "ABC Trees  111";
            myCustomer.CustomerGroupId = "10";
            myCustomer.SalesCurrencyCode = "USD";
            myCustomer.CreditRating = "Excellent";
            myCustomer.AddressCountryRegionId = "USA";

            #region Create multiple customers
            
            Customer myCustomer2 = new Customer();
            
            customersCollection.Add(myCustomer2);

            myCustomer2.CustomerAccount = "US-X22222";
            myCustomer2.Name = "ABC Rains vb";
            myCustomer2.CustomerGroupId = "10";
            //myCustomer2.SalesCurrencyCode = "USD";
            myCustomer2.CreditRating = "Excellent";
            myCustomer2.AddressCountryRegionId = "USA";
            
            #endregion

            DataServiceResponse response = null;
            try
            {
                response = context.SaveChanges(SaveChangesOptions.PostOnlySetProperties | SaveChangesOptions.BatchWithSingleChangeset);
                Console.WriteLine("created ok");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.InnerException);
            }
            Console.ReadLine();
        }
    }
}

In the code above, two Customer objects are being created and passed into a DataServiceCollection named customersCollection. I am using the optional SaveChangesOptions.BatchWithSingleChangeset enum in the SaveChanges method. This means if one of the Customer objects fails validation then neither of the Customer objects are created. Since both Customers run under one batch in the HTTP call to the OData endpoint if one fails then they both do.

Lastly, the Resources object that has been instantiated as ‘context’, is using objects from the AuthenticationUtility project to help with authentication. This is a C# library project made of two classes to help in setting up the authentication to the OData endpoint and retrieving the authorization token. This AuthenticationUtility project can be found in Microsoft’s Dynamics AX Github repository at https://github.com/Microsoft/Dynamics-AX-Integration/tree/master/ServiceSamples/AuthenticationUtility.

Hopefully, this post can steer you in the right direction on how to successfully interact with the OData entities in Microsoft Dynamics 365 for Operations.

More on Dynamics 365 for Operations Development

Learn more about OData and the essentials of Dynamics 365 for Operations Development at our online training course! Check out the course agenda and registration information here.

[button title=”Development Workshop” link=”/services/dynamics-training/ax7-development-workshop-registration/” new_tab=”yes”]

Related Posts

Recommended Reading:

Manage U.S. Use Tax on Purchase Orders in Dynamics 365 Finance and Operations

  Managing sales tax requirements on your business purchase can be complicated, but Dynamics 365 Finance and Operations can help […]

Read the Article
5.19.22 Dynamics CRM

How to Write a Great Support Ticket in the Stoneridge Support Portal

Submitting a support ticket through the Stoneridge Support Portal is a quick and effective way to get assistance for any […]

Read the Article

Managing Your Business Through Uncertain Times Using Dynamics 365 Finance and Operations

  Dynamics 365 Finance and Operations (F&O) can help you make informed decisions on how to move your business forward. […]

Read the Article
5.13.22 Power Platform

Using Power BI Object Level Security

  The following article will demonstrate how to use Power BI Object Level Security to disable column data based on […]

Read the Article
5.12.22 Dynamics CRM

How to Use the Stoneridge Support Portal

Stoneridge Software’s support portal is an intuitive and useful function that makes it easy for you to access resources to […]

Read the Article
5.6.22 Dynamics GP

Dynamics GP Transaction Removal: Purchase Orders

  Are you having performance issues with Purchase Orders?  Do you find that there are old Purchase Orders on your […]

Read the Article
5.5.22 Dynamics GP

The Real Story about the Long-Term Future of Dynamics GP Support

I’ve seen a number of people put forward comment that Dynamics GP is going away and you have to get […]

Read the Article

New Features in Dynamics 365 Business Central 2022 Wave 1 Release – Financial Enhancements

The Dynamics 365 Businses Central 2022 Wave 1 Release has a lot of new and exciting features to help your […]

Read the Article
4.29.22 Dynamics GP

Dynamics GP Transaction Removals: Bank Reconciliation

  This is part 2 of a 3 part series on Dynamics GP Transaction Removals. These quick tips will hopefully […]

Read the Article

Start the Conversation

It’s our mission to help clients win. We’d love to talk to you about the right business solutions to help you achieve your goals.

Subscribe To Our Blog

Sign up to get periodic updates on the latest posts.

Thank you for subscribing!

X