web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Unanswered

OData Services using C#

(0) ShareShare
ReportReport
Posted on by 2

Hi ,

      I want to Import the Data into D365 using Odata services in C# .net.

Should I have to use Odata v4 client code generator or Odata Connected services ?

I tried using using Odata Connected Service Extension using .Net Since I cannot find Odata v4 client code generator in the Extensions.Most of the samples are related to OData v4 client code generator . 

Can someone provide me any link the has the sample to create a record using Odata Connected services Extension ?

Here is the sample code to read the record But I need to create a record usng Odata Services .Can someone help me in this ?

using System;
using System.Linq;
using System.Threading.Tasks;

// added manually
using Microsoft.Dynamics.DataEntities; //Resources
using Microsoft.Identity.Client; //Nuget Package: IConfidentialClientApplication, ConfidentialClientApplicationBuilder, AuthenticationResult
using Microsoft.OData.Client; //DataServiceQueryException, DataServiceClientException
using System.Web; //Manually browsed and added reference to System.Web: HttpUtility
using System.Text.Json; //JsonSerializer

namespace D365_BlogOData_ConsoleApp
{
    class Program
    {

        static string aadClientAppId = "9e9999af-de0c-999d-a1d6-b4ea7f99a8e9"; // Azure App Client ID
        static string aadClientAppSecret = "Abc7FvitABC93oLQEiK0tR1b3mXXXX5sLC1mABCieS8="; // Azure App Secret
        static string baseURL = "https://xxxxxxxxxxxdevaos.cloudax.dynamics.com"; // D365FO instance no slash at end
        static string aadTenant = "https://login.windows.net/domain.com"; //replace domain.com with your azure AD domain
        private static async Task GetAuthenticationHeader()
        {
            IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(aadClientAppId)
                    .WithClientSecret(aadClientAppSecret)
                    .WithAuthority(new Uri(aadTenant))
                    .Build();
            string[] scopes = new string[] { $"{baseURL}/.default" };
            AuthenticationResult result = await app.AcquireTokenForClient(scopes)
                .ExecuteAsync();
            return result.CreateAuthorizationHeader();
        }

        private static void ReportODataError(DataServiceQueryException ex)
        {
            //Client level Exception message
            Console.WriteLine(ex.Message);

            //The InnerException of DataServiceQueryException contains DataServiceClientException
            DataServiceClientException dataServiceClientException = ex.InnerException as DataServiceClientException;

            // You can get ODataErrorException from dataServiceClientException.InnerException
            // This object holds Exception as thrown from the service
            // ODataErrorException contains odataErrorException.Message contains a message string that conforms to dotnet
            // Exception.Message standards
            var odataErrorException = dataServiceClientException.InnerException as Microsoft.OData.ODataErrorException;
            if (odataErrorException != null)
            {
                Console.WriteLine(odataErrorException.Message);
            }

            Console.WriteLine(dataServiceClientException.Message);
        }
        static void Main(string[] args)
        {
            try
            {
                MainAsync().Wait();                
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex);                
            }

            Console.ReadLine();
        }


        private static async Task MainAsync()
        {
            Console.WriteLine("Authenticating with AAD...");
            //AuthenticationConfig config = AuthenticationConfig.ReadFromJsonFile("appsettings.json");
            string bearerToken = await GetAuthenticationHeader();

            var context = new Resources(new Uri($"{baseURL}/data/"));

            //Example to make all the OData requests cross-company, otherwise you will only reference records in the default company
            context.BuildingRequest  = (sender, eventArgs) =>
            {
                var uriBuilder = new UriBuilder(eventArgs.RequestUri);
                var paramValues = HttpUtility.ParseQueryString(uriBuilder.Query);
                if (paramValues.Get("cross-company") != null)
                {
                    //Console.WriteLine("Note: cross-company parameter already present - removing");
                    paramValues.Remove("cross-company");
                }
                paramValues.Add("cross-company", "true");
                uriBuilder.Query = paramValues.ToString();
                eventArgs.RequestUri = uriBuilder.Uri;
            };

            //Add authorization token. This should be requested from AAD programatically, expiry managed, etc.
            context.SendingRequest2  = (sender, eventArgs) =>
            {
                eventArgs.RequestMessage.SetHeader("Authorization", bearerToken);
            };


            //Read and update a customer credit rating using DE-001 customer for example
            Console.WriteLine("Reading the customer rating...");
            try
            {
                var custCreditRating = context.CustomerCreditRatings.Where(x => x.DataAreaId == "usmf" && x.CustomerAccount == "DE-001").First();
                Console.WriteLine(JsonSerializer.Serialize(custCreditRating)); //Should be the same as the response Json after creation

                Console.WriteLine("Updating Customer Credit Rating...");
                custCreditRating.CreditRating = "Good";
                context.UpdateObject(custCreditRating);
                DataServiceResponse dsr = context.SaveChanges();
                var changeResponse = (ChangeOperationResponse)dsr.First();
                Console.WriteLine("HTTP status = {0}", changeResponse.StatusCode); //Success is 204
                var entityDescriptor = (EntityDescriptor)changeResponse.Descriptor;
                var custCreditRatingUpdated = (CustomerCreditRating)entityDescriptor.Entity; 
                Console.WriteLine(JsonSerializer.Serialize(custCreditRatingUpdated));
            }
            catch (DataServiceQueryException queryException)
            {
                ReportODataError(queryException);
            }

            catch (DataServiceClientException clientException)
            {
                Console.WriteLine(clientException.InnerException);
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.InnerException);
            }
        }
    }
}

I have the same question (0)
  • Martin Dráb Profile Picture
    237,967 Most Valuable Professional on at

    Have you tried the way documented at OData Client > Basic CRUD Operations?

  • NoobGamer Profile Picture
    2 on at

    Hi Martin ,

        Thanks for your reply I tried to use the same logic to create a customer entity as mentioned in the sample .

    var customer = CustomerV3.CreateCustomerV3("USMF", "Cust12345");
                    context.AddToCustomersV3(customer);
                    context.SaveChanges();

    But  I get the compile time error, because there are many parameters which needs to be passed inside the CreateCustomerV3()

    When I checked the Method Definitions there are so many parameters. Is there is any way to fix this or should I have to pass all the parameters ?

    pastedimage1664976362201v1.png

  • Martin Dráb Profile Picture
    237,967 Most Valuable Professional on at

    If the constructor is public, you can use it to create an instance and then set values of properties, as you see at last three lines in your screenshot.

  • NoobGamer Profile Picture
    2 on at

    Hi Martin,

                 I have tried this before But I have got the runtime error like  update not allowed for field 'insert not allowed for field 'PrimaryContactFaxRecordId' 

    But I have not set any values for that field .

    context.AddToCustomersV3(new CustomerV3
                    {
                        DataAreaId = "USMF",
                        CustomerAccount = "Cust12345",
                        SalesCurrencyCode = "USD",
                        CustomerGroupId = "10",
                        OrganizationName = "API Testing"
                    });
                    context.SaveChanges();
    

    This is the code which I have tried . Am I missing anything or I need to change anything else ? Can you please help 

  • NoobGamer Profile Picture
    2 on at

    While Debugging Exception occurred in the first line while initializing those values 

  • Martin Dráb Profile Picture
    237,967 Most Valuable Professional on at

    I'm sorry, but this is way too vague to allow us to help you.

    Please tell us which exception you got (type, message) and at which line of code.

  • Martin Dráb Profile Picture
    237,967 Most Valuable Professional on at

    Regarding 'insert not allowed for field 'PrimaryContactFaxRecordId', this seems to be an error coming from F&O, therefore you successfully sent a request.

    I guess that code generated by connected services tries to send all field values by default (which likely can be disabled).

  • NoobGamer Profile Picture
    2 on at

    But How can I disable those ? I can successfully create a record from postman with these mandatory fields DataAreaId,CustomerAccount,SalesCurrencyCode,CustomerGroupId,OrganizationName . But when I use this connected service I am facing the error 'insert not allowed for field 'PrimaryContactFaxRecordId'

  • Martin Dráb Profile Picture
    237,967 Most Valuable Professional on at

    I'm sorry, but I'm not familiar with this library. You decided to use Connected Service, therefore you can't use the usual solution (such as sample code from Microsoft) and you'll need to do some research by yourself. Fortunately there is a good chance that you'll find the answer on the internet.

  • Martin Dráb Profile Picture
    237,967 Most Valuable Professional on at

    By the way, you can test my assumption first. Check how the request sent by your code looks like and compare it with your request from Postman.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Martin Dráb Profile Picture

Martin Dráb 451 Most Valuable Professional

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 428 Super User 2025 Season 2

#3
BillurSamdancioglu Profile Picture

BillurSamdancioglu 239 Most Valuable Professional

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans