Tuesday, May 31, 2022

Connect to Dynamics 365 using console application/OAuth

In this blog, I have explained step by step process to connect to Dynamics 365 using the Console Application and using OAuth.

Before we proceed below are some prerequisites that need to be taken care of:

  1. Visual Studio 2015/2017/2019
  2. CRM SDK Nuget Packages
  3. D365 Application
  4. AppId - Get it from Azure Portal : https://portal.azure.com/



Let's Begin...

Note: First Create a ConsoleApp (.NET Framework) project.

In Visual Studio: Go to File -> New -> Project -> ConsoleApp (.NET Framework) -> Next -> Fill Project Name and other details -> Create




1. Add the NuGet package for Microsoft.CrmSdk.XrmTooling.CoreAssembly in the project.

Xrm.Tooling is the preferred way to connect to Dataverse, because of many benefits – we can define connection string, thread safety, support for X.509 certificate authentication, support for secure storage of sign-in credentials and reuse, etc.

2. In App.config file Add below XML code

<?xml version="1.0" encoding="utf-8"?>
<configuration>
       <appSettings>
             <add key="UserKey" value="XXXX.onmicrosoft.com" />
             <add key="UserPassword" value="XXXXX" />
             <add key="Environment" value="https://XXXXXXX.crm.dynamics.com/" />
       </appSettings>
       <startup>
             <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
       </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.9.0" newVersion="5.2.9.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

</configuration>


3.  Navigate to Program.cs file and add the below code to connect to D365

using Microsoft.Xrm.Tooling.Connector;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace D365ConsoleAppCRUDOperation
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Console Application Started!");
            try
            {
                //Step 1 - Retrieving CRM Essential Information.
                string sEnvironment = System.Configuration.ConfigurationManager.AppSettings["Environment"].ToString();
                string sUserKey = System.Configuration.ConfigurationManager.AppSettings["UserKey"].ToString();
                string sUserPassword = System.Configuration.ConfigurationManager.AppSettings["UserPassword"].ToString();
                //Step 2- Creating A Connection String.
                string conn = $@" Url = {sEnvironment};AuthType = OAuth;UserName = {sUserKey}; Password = {sUserPassword};AppId = 6cc5df06-10fc-474c-8db6-5ccd36950af6;RedirectUri = app:https://localhost;LoginPrompt=Auto; RequireNewInstance = True";
                Console.WriteLine("Operating Environment : " + sEnvironment);
                //Step 3 - Obtaining CRM Service.
                using (var service = new CrmServiceClient(conn))
                {
                    if (service.IsReady)
                    {
                        Console.WriteLine("Operating Environment Connected Successfully....");
                        //Executing YOUR CRM OPERATIONS.
                    }
                    else
                    {
                        Console.WriteLine("Operating Environment Connection failed....");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error Occured : " + ex.Message);
            }
        }
    }
}

 4. Build and Run your code



That's all...

Thank you !!!!

Happy ConsoleApping...

Keep D365ing...

Console application to create a .csv file and Add data and Retrieve, and update data into D365

Console application to create a .csv file and Retrieve, and update data into D365

Here in this blog, I have covered 3 scenarios, follow the step by step process to learn and write a better console app within 5 - 10 mins:

1. Write a Console Application to Retrieve or Fetch contact records from Dynamics 365.
2. Create a .csv file and write records into a CSV file row-wise.
3. Read records from the CSV file and Update Contact Records back in CRM

Follow the step by step process :

1. Open Visual Studio Application
2. Navigate to File -> Click on new Project...
3. Select Visual C# -> Console Application(.Net Framework)
4. Give a name to your console application (e.g. ConsoleApp1)
5. Set the location where you want to store your console project (e.g. C:\Users\Console Project)
6. Provide a solution name (e.g. MyConsoleAppSolution)
7. Choose the right Framework and Click Ok to save your console application project.











Once saved the folder structure will look like as shown on the screen below:









Let's begin with your coding part:

1.  First Go to References Add required assembly References from the NuGet Package:
You can see in the below screen, that these are the mandatory references that are required for your console app. Once you added you can verify it in your reference file.


2. Open > App.config file > Write below code in that.

In App.config file you add your connectionStrings and if you have any key-value pair you can add it inside appSettings. Follow the code below.

Sunday, May 29, 2022

Power Automate Flow to Move Email Attachments to SharePoint site

 In this blog, I will cover how email attachments can be moved to the SharePoint site location using power automate flow in D365.

I have already created a common child flow to create a folder on the SharePoint site and move attachments to the SharePoint site location. Child Flow: Click here

This flow will work as a parent flow through which a child flow can be called. I have placed a link above.



Let's begin...

1. When an Email is modified 



Filter row: (directioncode eq false and statuscode eq 4 and _regardingobjectid_value ne null)


2.  Condition to check if regarding type (lookup logical name ) is not null


Regarding(Type) : 



3.  In the yes block add a switch statement to call based on regarding the type 


4. If Incident -> Get a Case by ID


Row ID: 




5. Run a child flow -> Call child flow here and pass all the input values 



Child Flow: Look for the child flow which you created a call it here, in my case -> 
Child Flow to Move Attachments to SharePoint

SharePointFolderName: Pass the folder name you want to give for your SharePoint path: In my case it is a case number.
RelativeURL: incidents (I have given this name in SharePoint document location)
SharePointListOrLibraryName: Case (In SharePoint site this is the folder where i want to create folder and upload attachment)
EntityId: Email Message unique Id 
EntityLogicalName: Pass Regarding(Type)

Child Flow : Click Here

Thank you!

Happy Automating...!

Happy Learning......

Power Automate Flow to Create a Folder and Move Attachments to SharePoint site location

In this blog, I will cover step by step process of writing a common Power Automate flow and I will handle the below business requirements.

1. Write a Power Automate Flow to Create a Folder on the SharePoint site.
2.  Common Child Power Automate flow to Move attachments to the SharePoint location.
3. Move Email attachments to the SharePoint site.
4. Move Case, Account, etc. attachments to the SharePoint site.

Basically for the above scenario, I have created a common child flow and I will be calling this flow through my Parent flow. Which I have shared at the end of this blog.

This is how the entire flow will look once it's created.



Let's begin. Follow the step one by one...

Note: Before that, First create a solution file -> then inside the solution create a Child flows. It should be created within the solution.

Create a solution as shown:



1. Open the solution and create a power automate flow as shown



Click on Instant Flow and give a name to your flow and select Manually trigger a flow -> Click Create


2. Add all the required input variables to your child's flow.

Add input variables to your child's flow as shown


Note: I have added below 5 input variables that seem common to me. I will pass the value for these variables from the parent flow from where this child flow will trigger.

a) 
SharePointFolderName -> It is SharePoint folder name. Pass the value to this variable from the parent flow. b) RelativeURL -> This variable will hold document location. It's the SharePoint Document Location in the D365 to map the records in D365 & SharePoint site.
c) SharePointListOrLibraryName -> This is Library name In SharePoint where attachments can be uploaded.

d) EntityId -> Pass the entity GUID to this variable.
e) EntityLogicalName -> Pass entity logical name from Parent flow.
3.  Add list rows (List SharePoint site-URL) -> Select table name, Column, Filter rows

[This step is to retrieve the SharePoint site absolute URL which will be used in the next step]


4.  Add -> Create a new folder in the SharePoint site

[Using this step to create a new folder in the SharePoint site location to store the attachments within this new folder.
I'm creating this new folder dynamically each time whenever new records are getting created and in the next step I will place attachments within this folder]


Site Address -> 
first(outputs('List_SharePoint_site_-_URL')?['body/value'])?['absoluteurl']
List or Library->
Pass input variable (SharePointListOrLibraryName )

Folder Path -> Pass input variable (SharePointFolderName)

5.  Add -> List rows

[To retrieve the sharepointdoumentlocationid based on the below filter condition. I need this in my next step to create a SharePoint document location]

Table name -> Document Location
Select Column -> sharepointdocumentlocationid
Filter rows -> 
relativeurl eq '@{triggerBody()['text_1']}' and startswith(parentsiteorlocation_sharepointsite/absoluteurl, 'http')


6. Add a Switch condition

[To check based on the type of entity and direct it to the entity it belongs to -> if incident then it will go to the Incident Document location if Account then Account Document Location else go to default]



7.  Add a new row 

[To add case-related attachments to the incident location.]



Table name -> Select Document Locations
Name -> Documents for "SharePointFoldername"
Parent Site or Location (Document Locations) ->
sharepointdocumentlocations(@{first(outputs('List_Document_Location_-_Parent_Document_Location_for_Records')?['body/value'])?['sharepointdocumentlocationid']})

Regarding (Cases) -> Pass Entity Logical Name & Entity Id.

\@{triggerBody()['text_4']}(@{triggerBody()['text_3']})

Relative URL -> SharePointFolderName 


Similarly, add it to the account entity record.

Once both are added It will look as shown below:

8. Add -> Get a row

[To retrieve attachments based on filter criteria as shown from the Attachments table]



9. Add a condition ->
[To check to get attachment body is not empty (empty(outputs('Get_Attachments')?['body']))  and  (EntityLogicalName is not Null)]





10. If the above conditions are true  -> Then Create an Attachments file in the SharePoint site location

Site Address: 
first(outputs('List_SharePoint_site_-_URL')?['body/value'])?['absoluteurl']

Folder Path: Pass the input variables as shown
File Name:

File Content:
base64ToBinary(items('Apply_to_each')?['body'])

Converting from base 64 to binary.

11. Once All are done the last step is to empty the D365 attachment file. Delete the file from the D365 Attachment Location
Table Name: Attachments
Row ID:





12. Pass a response to the parent flow


That's all,
We have successfully created a common child flow to create a folder in the SharePoint site and attach the attachments to the same folder.

Note: Now next step is to create a Parent flow so that this child flow can be triggered. This Child flow can be triggered:  Below is the Parent Flow Link URL ->

Power Automate Flow to Move Email Attachments to SharePoint site

1. When receiving Attachment through Email
2. When a Case, Account, or any entity is Created/modified as per your business requirement you can trigger it and update it accordingly.





SharePoint Integration with Dynamics 365

In this blog, I have shared a step-by-step process to set up a SharePoint with Dynamics 365. Here I discussed how to integrate SharePoint with Dynamics 365? 

SharePoint offers much more storage space than Dynamics 365. No more worrying about your D365 instance running out of storage, and no more increasing costs because you need to expand your storage limits!

Note: For model-driven apps in D365 and SharePoint Online, you need to make sure the site is on the same Office 365 tenant and your Dynamics 365.

Let's proceed.

1.  Go to Settings -> Advanced Settings -> Settings - Document Management 



2. Click on Enable Server-Based SharePoint Integration


3. On open Wizard Click Next



4. Indicate if your SharePoint is Online or On-Premises. The SharePoint integration can connect to both. It can even connect to multiple SharePoint sites, but they all have to be either online or On-Premises.

Select online (in my case) -> Click Next






5. Enter the URL of the SharePoint site you want to use -> Click Next


6. Click On Finish button to complete & enable configuration setup


7. You can now go back to your Document Management screen and select which entities should be enabled for SharePoint folders.


Click on Document Management Settings.



8. On the pop-up window, you check the entities under which you anticipate storing documents and Click Next. I selected only Account & Case entity.


Note: If you want to create a folder structure based on Account or Contact you can proceed with the below, In my case, I kept it unchecked. 

If you checked, You can then define the folder structure. Here are your options:

  • Not check the Based on entity checkbox - Folders will not be automatically created
  • Check the Based on entity checkbox and choose Account - the structure will have an account as the primary folder, and sub-folders based on the actual account names will be created under it
  • Check the Based on entity checkbox and choose Contact - the structure will start with the contact primary folder, and sub-folders based on the actual contact names will be created under it



9.  I kept it as is, As I wanted to create my own folder structure Click Next


10. You might have to wait a little at this point as the document libraries will be created. 

Once it's done you can click Finish.


11. On the screenshot below you can see the document that we created for an Account & Contact. Notice its storage is on SharePoint.




13. 
The integration is done. On the Dynamics 365 side, you will now see a documents option under the entities you enabled. 



14. Go back and Create a SharePoint document location, Navigate to Settings -> Document Management -> Click on SharePoint Documents Location


15. Click on New (+) -> Fill in all the details as shown and Save it.


16.  Custom Document Locations have been created for both account and incident entities.




That's all the now try to add any file to your D365 account record, It will be uploaded to the SharePoint site location and as well as in the SharePoint Documents Location.


Thank you!
Happy SharePointing...