Archive

Posts Tagged ‘Dynamics 365’

[Step by step] Basic Canvas app using Dynamics 365 as Data Source

November 8, 2019 1 comment

In this article, I am going to provide steps to build a basic Canvas app which uses Dynamics 365 (CDS) as Data Source.

If you are new to Power Apps, refer my blog on steps to get started.

The App we are going to build will have 3 screens.

  • Manage Contacts – Displays the list of Contacts using ‘Gallery’ control.
  • Create Contact – Creates a new Contact.
  • Edit Contact – Updates an existing Contact.

Create a new Canvas app:

  • Connect to the Power Apps portal and select the ‘Environment’.
  • Create a new ‘Canvas app from blank’.

PA_Env3

Connect to Dynamics 365 data source:

Now we have the blank App and as a first step, create a new data source by connecting to your D365 instance using ‘Dynamics 365’ connector.

  • Click on the ‘Data source’ tab.
  • Under the ‘Connectors’, select ‘Dynamics 365’ and choose the ‘dataset’.
    • ‘dataset’ is your Dynamics organization name.

PA_Env4

  • Next, under the ‘Choose a table’ pane, select the entities you would like to work with.
    • I’ve chosen ‘Contacts’ entity for this App

PA_Env5

  • Click on ‘Connect’
  • You should see the ‘Contacts’ table under ‘Data sources’ as below:

PA_Env20

Design ‘Manage Contacts’ screen:

Now we have ‘Data source’ ready and lets design our first screen.

  • By default the Canvas app will have a screen.
  • Rename the out of the box screen to ‘ManageContacts’
    • Providing appropriate name to the controls is a best practice.
  • As we need to display available ‘Contacts’ on the screen, select ‘Insert -> Gallery’ and choose ‘Blank Vertical’.
    • ‘Gallery’ is a grid kind of a control.

PA_Env6

  • Now we need to map ‘Contacts’ table to the Gallery.
  • Select the ‘Gallery’ and click on ‘Edit gallery’ icon.

PA_Env7

  • In the ‘Select a data source’ pane, select ‘Contacts’ table. Now the ‘Gallery’ gets mapped with ‘Contacts’ from Dynamics.

PA_Env8

  • To display the Contact details (i.e., Full Name, Email, etc…), add ‘Label’ controls to the ‘Gallery’ and rename the Labels with meaningful names.
  • Labels will not show anything until you map them with the Contacts field.
  • So, select the Label and in the ‘Text’ property, type ‘ThisItem.{field_Name}
    • To map, ‘Full Name’ of the Contact to a label, set ‘Text’ as ThisItem.’Full Name’

PA_Env9

Design ‘New Contact’ screen:

In the ‘Manage Contacts’ screen, we configured a ‘Gallery’ which displays all the Contacts. Now lets design a ‘New Contact’ screen.

  • Add a ‘New Screen’ and rename it.
  • To Create/Edit records, we need to add ‘Forms’ control
    • ‘Edit’ form: Use this to Create or Edit a record.
    • ‘Display’ form: Use this to display the record (Read-only).
  • So, lets add a new ‘Edit’ form to the screen and rename it to ‘formCreateContact‘.

PA_Env12

  • Next, we need to map the ‘formCreateContact’ to ‘Contacts’ Data source and then select and arrange the ‘Contact’ fields, which allows us to input and save.
    • Set the ‘DataSource’ property of ‘formCreateContact’ to ‘Contacts’
    • Click on the highlighted link and add the required columns and click ‘Add’.

PA_Env13

  • Next, we can rearrange the columns using ‘Move up’ and ‘Move down’ options.

PA_Env14

  • We can also set ‘Columns’ to 1 of the ‘formCreateContact‘ which arranges the fields in a single column.
  • Add ‘Save’ icon to the ‘CreateContact’ screen.

PA_Env16.PNG

  • As we need to save the ‘Contact’ (i.e., Submit the Form) on ‘Save’ icon click, add below statement

SubmitForm(formCreateContact);

Link ‘Manage Contacts’ screen and ‘New Contact’ screen:

Now, we have the ‘New Contact’ screen ready. Lets hook it up to ‘ManageContacts’ screen.

  • Go to ‘ManageContacts’ screen and add + icon.
  • There are 2 key steps to create a new Contact
    • First create a new form of type ‘formCreateContact’.
    • Navigate to ‘New Contact’ screen.
  • We need to execute these key steps on click of + icon.
  • Select the + icon and on the ‘OnSelect’ event, add below statement

    NewForm(formCreateContact);Navigate(CreateContact);

PA_Env15.PNG

  • That’s it, run the App and you should be able to see the Contacts on ‘Manage Contact’ screen.

PA_Preview1.PNG

  • Click on + icon, which will take you to ‘New Contact’ screen.

PA_Preview2

  • Lets see ‘Edit Screen’ and Navigation’s in next article.

🙂

 

Categories: CRM, PowerApps Tags: ,

Office 365 Groups + Dynamics 365

July 6, 2019 1 comment

In Dynamics 365 online, records can be owned by ‘Office 365 Groups’. Refer my previous article and following are quick notes.

  • The administrator can create Azure AD group teams that are associated to the Azure AD groups in each of the Customer Engagement and Common Data Service environments and assign a security role to these group teams.
  • When members of these group teams access these environments, their access rights are automatically granted based on the group team’s security role.

If you notice, to get the benefits of AAD group ownership, Users must have assigned ‘Dynamics 365 Customer Engagement Plan’ license.

What if the User don’t have ‘Dynamics 365 Customer Engagement Plan’ license. For example, when a sales team has a major opportunity requiring input from several people who don’t have access to Customer Engagement apps.

Office 365 Groups provides a single location to share documents, conversations, meetings, and notes.

Office 365 Groups can be enabled for any entity.

Install Office 365 Groups solution:

T9

  • Install ‘Office 365 Groups’ solution.

TG_8

Enable entities for Office 365 Groups:

  • Connect to your Dynamics instance.
  • Go to Settings -> Office 365 Groups
  • Add required entities.

T10

Create Office 365 Group:

  • Make sure users must have ‘Office online’ license and Mailbox configured.

T11

  • Create a Group and add the Users.

T12

  • Users get notifications in their Outlook web app
  • From Outlook, Users can click on ‘Discover’ to explore more available groups.

T13

  • Also a new SharePoint Sitemap collection gets created for each Group, which allows Users to share documents.

T14

Use Office 365 Groups from Dynamics App:

As we enabled ‘Office Groups’ for ‘Account’ entity

  • Open any account from Dynamics App.
  • From sitemap, click on ‘Office 365 Groups’
  • You can either ‘Create a new group’ or use an existing group.

TG_12

  • Once the configuration is completed, you can start Conversation and share documents which would be available for all members of the group.

T15

🙂

 

 

D 365 – How to access Customization’s and Solutions in UCI Only Mode

To know more about ‘Unified Interface Only mode’ refer my previous article

Below are the steps to access environment settings, customization’s and solutions when the ‘Unified Interface Only mode’ turned on.

  • Click on ‘Advanced Settings’ from the ribbon Gear button.

FUI_3

  • It will open up ‘Settings’ tab in classic web mode.

FUI_6

  • You can access your solutions and make customizations how you used to do earlier.

Refer the documentation to know more about ‘Unified Interface’.

🙂

[Step by Step] Postman tool to test Dynamics 365 online Web API

February 13, 2019 11 comments

In this article, lets see how to connect and test Dynamics 365 Web API requests using Postman tool, step by step along with troubleshooting steps.

Those who are not familiar with Postman tool, it is a request composer tool, which allows you to authenticate to your Dynamics 365 instance,  compose Web API requests, send them, and view response. Link to download

Prerequisites:

  • Download Postman tool
  • Dynamics 365 online instance. (Subscribe to 30 days trial, if you have not one)
  • Azure Active Directory Portal (You need to login with your Office 365 Credentials)

Register App in Azure Active Directory:

As a first step, you need to register an App in Azure Active Directory (i.e., oAuth) by following below steps

  • Connect to the Azure Active Directory (AD) Portal with your Office 365 credentials.
  • Register a new Dynamics 365 App by following steps mentioned here
  • Once you are done with App registration, copy ‘Application ID’ and ‘Home page’ values, which you need to use next steps.

PostMan_14

Setup your Postman tool:

Create ‘Environment’

  • Create a new Postman ‘Environment’ with below variables. This is one time activity for a single D365 instance.
    • url : Your Dynamics 365 URL
    • clientid : ‘Application ID’ from Azure AD,  generated in above section.
    • version : Dynamics version
    • webapiurl : Set this to {{url}}/api/data/v{{version}}/
    • callback : ‘Home page’ value from Azure AD,  generated in above section.
    • authurl : Set this to https://login.microsoftonline.com/common/oauth2/authorize?resource={{url}}
  • I created a new ‘Environment’ with name ‘DynamicsCRM’ and it looks as below

PostMan_13

Generate oAuth Access Token:

Post ‘Environment’ creation, we need to generate oAuth Access Token. This is one time activity for a single D365 instance.

  • Make sure you select ‘Environment’ created in previous section. In my case its ‘DynamicsCRM’.
  • Under ‘Authorization’ tab, set ‘Type’ to ‘oAuth 2.0’ and click on ‘Get New Access Token’.

PostMan_15

  • In the ‘GET NEW ACCESS TOKEN SCREEN’ make sure you set values as below.

PostMan_1

  • Click ‘Request Token’ and system will prompt you for credentials, pass your O365 credentials.

PostMan_2

  • When you click ‘Next’, you may encounter “response_type ‘token’ is not enabled for the application” exception.
    • To fix this, make sure in your Azure AD Application’s manifest “oauth2AllowImplicitFlow” property is set to ‘true’

PostMan_4

  • You may also encounter “The reply url specified in the request does not match the reply urls configured for the application“.
    • To fix this, make sure you set the Postman’s ‘Environment’ -> ‘callback’ variable set correctly.
  • Click ‘Continue’ to complete the ‘Access Token’ generation process.
  • On successful ‘Access Token’ generation, you would get the screen as below.

PostMan_8

  • Click ‘Use Token’.

That’s it! we are done with settings and its time to test the Dynamics API’s with Postman

Test by executing ‘WhoAmI’ request:

  • Make sure you select the right ‘Environment’ and generated your ‘Access Token’.
  • Select ‘GET’ operation and set the URL as {{webapiurl}}WhoAmI
  • Click ‘Send’
  • You should get “200 OK” response up on success.

PostMan_10

  • You may get “401 Unauthorized” response.

PostMan_11

  • To fix this, make sure you set “Add authorization data to” to “Request Headers”.

PostMan_12

🙂

 

Dynamics 365 – Configure Custom ‘Help Page’

February 4, 2019 Leave a comment

‘Help’ feature in Dynamics 365 is a useful and an intuitive way to provide guidance to the end users.

Sometimes we may get a requirement from customer to configure ‘Custom Help’ page.

Its simple to configure the custom help screen from Dynamics 365 ‘Admin Center’ Settings screen.

Steps to configure custom Help URL:

  • Connect to your Office 365 Admin Center
  • In the ‘Environments’ tab, select the instance  and click on ‘Settings’

HelpPage_1

  • In the ‘Settings’ screen, click on ‘Products -> Features’

HelpPage_5

  • Under ‘Help features’, turn ON the “Custom help for customizable entities”.
  • In the ‘Global custom help URL’, provide your custom web link.
    • I provided my blog URL in this case.
  • Select ‘Append parameters to URL’ option, if you want to pass the “typename”, “formid” etc.. parameters to your custom URL.

HelpPage_2

  • Alternatively, you can also configure the same from ‘Administration -> System Settings’

HelpPage_6

Steps to test the Help URL:

  • Connect to your dynamics instance.
  • Click on Help(?) icon

HelpPage_3

  • You will be redirected to the configured URL

HelpPage_4

🙂

Dynamics 365 – Get ‘April 2019’ update

February 4, 2019 Leave a comment

Last weekend, I subscribed to a Dynamics 365 30 days trail and noticed that now we can upgrade to ‘April 2019’ update and start exploring the features.

Below are the steps to update your instance to ‘April 2019’.

  • Connect to your Office 365 Admin Center
  • In the ‘Environments’ tab, select your environment and navigate to ‘Settings’ page by clicking on Instance name hyperlink.

Apr2019_3

  • In the ‘Settings’ screen, under the ‘Updates’ tab, click on ‘Manage’ link

Apr2019_2

  • In the ‘Updates’ slider window, click on ‘Active now’ to get the ‘April 2019’ update

Apr2019_1

  • Confirm by providing your instance name in the text box, as below.

Apr2019_4

  • That’s all we need and enjoy your ‘April 2019’ update.

Apr2019_5

Note:

  • You cannot revert once you activate the ‘April 2019’ update.

Refer the link for what’s included in ‘April 2019’ update

🙂

[Dynamics CE] – Strange Plug-in issue due to the usage of global variables

December 26, 2018 Leave a comment

Other day, one of my colleagues reported a plug-in issue which could not be reproduced consistently. All the troubleshooting options (i.e., Plug-in Profiler, Tracing) had been used but was unable to found the root cause.

On close retrospection of code, we found out the usage global variables in Plug-in class file, which made the Plug-in ‘Stateful’.

Due to this, issue could not be reproduced when tested with Plug-in Profiler as it creates single Plug-in instance. Issue will only be reproduced when concurrent users instantiate plug-ins.

You have to make sure to create your Plug-in as ‘Stateless’ to avoid issues during concurrent Plug-in execution.

What is ‘Stateful’ Plug-in?

  • If the Plug-in ‘Execute’ method refer any global variable(s), makes the Plug-in ‘Stateful’.

public class CustomersVirtual : IPlugin{

// ‘context’ variable declared as Global
IPluginExecutionContext context = null;
EntityCollection results = new EntityCollection();
public void Execute(IServiceProvider serviceProvider) {
context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

if (context.MessageName.ToLower() == “retrieve”){
Entity customer = new Entity(“raj_virtualcustomer”);
customer[“raj_customersid”] = Guid.NewGuid();
customer[“raj_name”] = “ABC Corporation”;

//add it to the collection
results.Entities.Add(customer);
}

In the above Plug-in sample, variables ‘context’ and ‘results’ been defined as global and referred in ‘Execute’ method which makes it ‘Stateful’

What is ‘Stateless’ Plug-in:

  • If the Plug-in ‘Execute’ method, has its own local variables and does not refer any global variables make the Plug-in ‘Stateless’.

public class CustomersVirtual : IPlugin{
public void Execute(IServiceProvider serviceProvider){

// ‘context’ variable declared as Local variable
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));

EntityCollection results = new EntityCollection();

if (context.MessageName.ToLower() == “retrieve”)
{
Entity customer = new Entity(“raj_virtualcustomer”);
customer[“raj_customersid”] = Guid.NewGuid();
customer[“raj_name”] = “ABC Corporation”;

//add it to the collection
results.Entities.Add(customer);
}

In this sample, variables ‘context’ and ‘results’ been defined as Local in ‘Execute’ method which makes it ‘Stateless’

Why ‘Stateless’ Plug-in is recommended?

  • As per the design, Dynamics platform caches plug-in class instances and hence the constructor is not called for every invocation of plug-in execution.
  • IPlugins should be stateless is that multiple system threads could execute the same, shared, plug-in instance concurrently.
  • This opens up members of classes that implement IPlugin to potential thread-safety issues which could lead to data inconsistency or performance problems.
  • Read-only, static, and constant members are inherently thread-safe and can also be used reliably within a plug-in class.

How the Dynamics platform Caches Plug-in?

  • For performance reasons, Dynamics DOES NOT dispose of the object after it completes execution.
  • Dynamics caches the object and calls Execute on the same object instance on the next activation of the plug-in.
  • Certain operations, such as changing a plug-in’s registration properties, will trigger a notification to the platform to refresh the cache. In these scenarios, the plug-in will be reinitialized..
  • This means that you need to be very careful when defining class-level variables in the plug-in class as multiple threads can execute the code at one time

Bottom line:

  • Don’t use Global variables in Plug-ins

Refer below articles for more insights:

🙂

Categories: CRM, Plug-Ins Tags: , ,

[Logic App and HTTP Request Trigger] Create a record in D365

December 20, 2018 Leave a comment

We got an ask from client that they should be able to Insert contacts in D365 from their Java application and requested our help.

To fulfill the ask, one option would be configuring S2S authentication so that Java application can connect to D365 using ADAL library and insert contacts.

Another option is using “Logic App” with “Http Request Trigger”.

High level approach:

  • Create a Logic App with ‘When a HTTP request is received’ trigger
  • Pass Contact record information in Json format as Request
    • Use ObjGen site to generate desired Json data.
    • This site seamlessly generates Json data based on our input. As I am going to create a Contact record, I generated below JSon data.

LogicApp_3

  • From Logic App, read the Json data and create Contact record using D365 connector
  • Finally capture the created Contact GUID in ‘Response’

Lets see the step by step approach to create Logic App and test.

Pre-requisites:

  • Dynamics 365 instance. Subscribe for trail if you have’t already
  • Azure Subscription.Subscribe for trail if you have’t already

Once you got the D365 and Azure Portal subscriptions below are the steps to create LogicApp.

Create a Logic App:

  • Connect to your Azure Portal and create a new ‘Logic Apps’. Refer article for steps to create Logic App.
  • From the list select ‘When a HTTP request is received’ trigger

LogicApp_4

  • In the next screen, click on “Use sample payload to generate schema” to generate the Json schema.

LogicApp_5

  • Paste the Json format prepared in ObjGen site

LogicApp_6

  • Click on ‘Done’ so that LogicApp generates “Request Body jSON Schema”

LogicApp_7

  • Next, we need to connect to D365 to save the Contact

LogicApp_8

  • Click ‘New Step’ and select ‘Dynamics 365’ connector. From the ‘Actions’ select ‘Create a new record’ and provide credentials and connect to your Instance

LogicApp_9

  • From the ‘Entity Name’, select ‘Contacts’
  • Map the Contact entity fields with the fields from ‘Dynamic content’ popup.
    • As ‘Company Name’ is a Look up to ‘Account’ entity, make sure you map
      • ‘Company Name Type’ = ‘accounts’
      • ‘Company Name’ = ‘id’ passed from Json

LogicApp_10

  • Next we need to capture the ‘Response’, choose ‘Response’ from ‘Actions’

LogicApp_11

  • In the ‘Response’ control,
    • In the ‘Headers’, add ‘Content-Type’ as key and ‘application/json’ as Value.
    • In the ‘Body’, form your output string and ‘Contact’ field from ‘Dynamic Content’ to capture the GUID

LogicApp_12

  • Save the Logic App

Test the Logic App:

  • Copy the “HTTP POST URL” from the “When a HTTP request is received” control.

LogicApp_13

Using Post Man:

  • Create a ‘POST’ request and paste the URL copied from Logic APP
  • In the ‘Headers’, add ‘Content-Type’ as key and ‘application/json’ as Value.

LogicApp_14

  • In the ‘Body’, paste the Json (You can copy the Json format prepared in ObjGen site)
  • Click ‘Send’ to call Logic App and capture the Response.

LogicApp_2

Using jScript and HTML:

  •  Below the jScript to call the Logic APP URL by passing JSon and capture the response

<html lang=”en” xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head>
<meta charset=”utf-8″ />
<title>Test Logic App</title>

function TestLogicApp() {
try {
var xhr = new XMLHttpRequest();
var url = “Logic App URL“;
xhr.open(“POST”, url, true);
xhr.setRequestHeader(“Content-Type”, “application/json”);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
alert(xhr.responseText);
}
};
var data = JSON.stringify({
“firstname”: “Rajeev”,
“lastname”: “Pentyala”,
“Account”: {
“id”: “A16B3F4B-1BE7-E611-8101-E0071B6AF231”,
“Name”: “A Datum Corporation”
}
});
xhr.send(data);
} catch (e) {
alert(“Error – ” + e.description);
}
}

</head>
<body>
<input type=”button” value=”Post” onclick=”TestLogicApp()” />
</body>
</html>

  • Open the HTML page and click the ‘Post’ button to capture the Response returned from LogicApp

LogicApp_1

Troubleshoot and track the history:

  • To troubleshoot and track the Requests, from the ‘Logic App’, click on ‘Overview’ and check under ‘Run history’

LogicApp_15

🙂

Dynamics 365 – New Admin Center (Preview)

October 22, 2018 Leave a comment

Have you noticed the Try the new Admin center link when you connected to your Dynamics 365 Admin Center?

Admin Center_2

When you click on the link, you will be redirected to ‘Admin Center (Preview)’ built on Power platform.

Admin Center_1

Click on the Instance name (i.e.,MS) in above screen, will take you Instance Details page.

Admin Center_5

Click on ‘See all‘ to get the ‘Details’ pane.

Admin Center_6

Click on ‘Edit‘ to get ‘Settings’ edit pane where you can change the Instance Type (i.e., Production/Sandbox)

Admin Center_7

I started exploring and one standout feature so far is ‘Settings’ page where you can manage all your Admin related configurations (i.e., Short cuts) in one page.

Admin Center_3

To go to ‘Settings’ page, you first need to select the ‘Instance’ and click on ‘Settings’ button.

Admin Center_4

🙂

[Code Snippet] Authenticate and Perform Operations using D365 Web API and C#

September 18, 2018 3 comments

As a continuation to my last article Different ways to connect authenticate dynamics 365 , lets see how to Authenticate Dynamics Web API using C#.

Note: Be mindful that this approach is different than connecting to Dynamics 365 using Microsoft.XRM.Tooling.Connector dll approach. This article explains how to connect to D365 using Web API which is no SDK .dll approach.

Pre-requisites:

  • Dynamics 365 subscription. Go for 30 days trail if not already have one.
  • Register an App in “Azure Active Directory” and get ‘Application ID’ and other parameters.
  • Visual Studio Console application

Steps to Register App in “Azure Active Directory”:

We need to register an application with Microsoft Azure Active Directory so that it can connect to the Microsoft Dynamics 365 server, authenticate using OAuth, and access the web services.

WebAPI_Snippet2

  • From the “Azure Active Directory admin center’, select ‘App registrations’ -> New application registration

WebAPI_Snippet3

  • Provide below details
    • Name – Provide name of the App. Can be any name minimum of 4 characters.
    • Application Type – Choose ‘Native’ as we are going to call Web API from Console application
    • Sign-on URL – Can be a valid URL. This you need to pass in the Console application.

WebAPI_Snippet4

  • Click ‘Create’ to complete the App creation
  • Post creation, open the App and copy the ‘Application ID’ which you need in Console application.

WebAPI_Snippet5

  • Click on ‘Settings’ -> Required Permissions -> Add ‘Dynamics CRM Online’ -> Enable the permission as below

WebAPI_Snippet6

  • Finally, select the App, click on ‘Endpoints’ and copy ‘OAuth 2.0 Authorization Endpoint‘ which you would need in Console Application.

WebAPI_Snippet7

Steps to connect to D365 WebAPI from Console Application:

After registering App in ‘Azure Active Directory’ now its time to connect to D365 Web API from Console Application.

  • Create a new C# Console Application project
  • Add below 2 Nuget packages to the project
    • Newtonsoft.Json
    • Microsoft.IdentityModel.Clients.ActiveDirectory

WebAPI_Snippet8

Code Snippet:

In the ‘Program.cs’ file add below

  • Add Using Namespaces:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Net;

  • Add Global Variables:

// O365 User Name and Password
private const string userName = “rajeevpentyala@exploreSept18.onmicrosoft.com”;
private const string password = “YourPasswordHere”;
// D365 Application Url
private const string serviceUrl = “https://exploresept18.crm.dynamics.com&#8221;;
// Azure APP Application Id
private const string applicationId = “1549b5b3-XXXX-XXXX-94be-7a8eeaf3e081”;
// Redirct Uri specified during registration of application
private const string RedirectUri = “https://localhost&#8221;;
// OAuth 2.0 Authorization Endpoint copied from Azure APP
private const string authorityUri = “https://login.microsoftonline.com/9e3039aa-XXXX-XXXX-80e1-f67d40bd01cf/oauth2/authorize&#8221;;

private static AuthenticationResult authResult = null;

  • Main Method:

private static void Main(string[] args){

// Code to connect to D365
var credentials = new UserPasswordCredential(userName, password);
var context = new AuthenticationContext(authorityUri);
authResult = context.AcquireTokenAsync(serviceUrl, applicationId, credentials).Result;

// Call CRUD operations

// Task.WaitAll(Task.Run(async () => await ExecuteWhoAmI()));
// Task.WaitAll(Task.Run(async () => await CreateRecord()));
// Task.WaitAll(Task.Run(async () => await RetrieveContacts()));

}

  • Code to call WhoAmIRequest:

private static async Task ExecuteWhoAmI(){
var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl),
Timeout = new TimeSpan(0, 2, 0)
};
httpClient.DefaultRequestHeaders.Add(“OData-MaxVersion”, “4.0”);
httpClient.DefaultRequestHeaders.Add(“OData-Version”, “4.0”);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, authResult.AccessToken);

// Add this line for TLS complaience
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

// Call WhoAmI
var retrieveResponse = await httpClient.GetAsync(“api/data/v9.0/WhoAmI”);
if (retrieveResponse.IsSuccessStatusCode){
var jRetrieveResponse = JObject.Parse(retrieveResponse.Content.ReadAsStringAsync().Result);

var currUserId = (Guid)jRetrieveResponse[“UserId”];
var businessId = (Guid)jRetrieveResponse[“BusinessUnitId”];

Console.WriteLine(“My User Id – ” + currUserId);
Console.WriteLine(“My User Id – ” + businessId);
Console.ReadLine();
}
}

  • Code to Retrieve Records:

private static async Task RetrieveContacts(){
var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl),
Timeout = new TimeSpan(0, 2, 0)
};
httpClient.DefaultRequestHeaders.Add(“OData-MaxVersion”, “4.0”);
httpClient.DefaultRequestHeaders.Add(“OData-Version”, “4.0”);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, authResult.AccessToken);

// Add this line for TLS complaience
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

// Retrieve Contacts
var retrieveResponse = await httpClient.GetAsync(“api/data/v9.0/contacts”);
if (retrieveResponse.IsSuccessStatusCode){
var jRetrieveResponse = JObject.Parse(retrieveResponse.Content.ReadAsStringAsync().Result);

dynamic collContacts = JsonConvert.DeserializeObject(jRetrieveResponse.ToString());

foreach (var data in collContacts.value){
Console.WriteLine(“Contact Name – ” + data.fullname.Value);
}

Console.ReadLine();
}
}

WebAPI_Snippet1

  • Code to Create Record:

private static async Task CreateRecord(){
JObject contact1 = new JObject{
{ “firstname”, “Peter” },
{ “lastname”, “Cambel” },
{ “annualincome”, 80000 }
};

contact1[“jobtitle”] = “Junior Developer”;

var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl + “/api/data/v9.0/”),
Timeout = new TimeSpan(0, 2, 0)
};
httpClient.DefaultRequestHeaders.Add(“OData-MaxVersion”, “4.0”);
httpClient.DefaultRequestHeaders.Add(“OData-Version”, “4.0”);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, authResult.AccessToken);

// Add this line for TLS complaience
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, “contacts”){
Content = new StringContent(contact1.ToString(), Encoding.UTF8, “application/json”)
};

HttpResponseMessage response = await httpClient.SendAsync(request);if (response.StatusCode == HttpStatusCode.NoContent) //204 {
Console.WriteLine(“POST succeeded, entity created!”);
//optionally process response message headers or body here, for example:
var entityUri = response.Headers.GetValues(“OData-EntityId”).FirstOrDefault();

// Update the Contact record
Task.WaitAll(Task.Run(async () => await UpdateRecord(entityUri)));

// Delete the contact record
Task.WaitAll(Task.Run(async () => await DeleteRecord(entityUri)));
}
else{
Console.WriteLine(“Operation failed: {0}”, response.ReasonPhrase);
throw new CrmHttpResponseException(response.Content);
}
}

  • Code to Update Record:

private static async Task UpdateRecord(string contactUri){
JObject contact1Add = new JObject{
{ “annualincome”, 80000 },
{ “jobtitle”, “Junior Developer” }
};

var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl + “/api/data/v9.0/”),
Timeout = new TimeSpan(0, 2, 0)
};

httpClient.DefaultRequestHeaders.Add(“OData-MaxVersion”, “4.0”);
httpClient.DefaultRequestHeaders.Add(“OData-Version”, “4.0”);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, authResult.AccessToken);

HttpRequestMessage updateRequest1 = new HttpRequestMessage(new HttpMethod(“PATCH“), contactUri){
Content = new StringContent(contact1Add.ToString(), Encoding.UTF8, “application/json”)
};
HttpResponseMessage updateResponse1 = await httpClient.SendAsync(updateRequest1);

if (updateResponse1.StatusCode == HttpStatusCode.NoContent) //204 {
//Console.WriteLine(“Contact ‘{0} {1}’ updated with job title” +
// ” and annual income.”, contactUri.GetValue(“firstname”),
// contactUri.GetValue(“lastname”));
}
else{
Console.WriteLine(“Failed to update contact for reason: {0}”, updateResponse1.ReasonPhrase);
throw new CrmHttpResponseException(updateResponse1.Content);
}

}

  • Code to Delete Record:

private static async Task DeleteRecord(string contactUri){
var httpClient = new HttpClient{
BaseAddress = new Uri(serviceUrl + “/api/data/v9.0/”),
Timeout = new TimeSpan(0, 2, 0)
};

httpClient.DefaultRequestHeaders.Add(“OData-MaxVersion”, “4.0”);
httpClient.DefaultRequestHeaders.Add(“OData-Version”, “4.0”);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Bearer”, authResult.AccessToken);

var response = httpClient.DeleteAsync(contactUri).Result;
if (response.IsSuccessStatusCode) //200-299 {
Console.WriteLine(“Contact has been deleted!!!”);
}
else if (response.StatusCode == HttpStatusCode.NotFound) //404 {
//Entity may have been deleted by another user or via cascade delete.
}
else //Failed to delete {
Console.WriteLine(“Error while deletion; Message: ” + response.Content);
}
}

🙂