Advertisements

Archive

Archive for the ‘CRM’ Category

Dynamics online – Internet accessible URLs and IP Address Ranges

February 15, 2019 Leave a comment

Recently we were asked by our client to share the Dynamics Online IP address range and list of URL’s to be added to their firewall settings so that Dynamics online application is accessible.

Why we need to care about IP’s and URL’s?

  • Sometimes in servers, a proxy or firewall may be configured to prevent Microsoft Dynamics CRM URLs from accessing server resources.
  • If certain IP address ranges or Individual IP addresses are blocked in your servers, users may not be able to reach the IP addresses used by Microsoft Dynamics CRM Online.

List of IP’s and URL’s:

  • Refer this KB article for the IP Address Ranges
  • Refer this KB article for the list of internet accessible URL’s

🙂

Advertisements
Categories: CRM Tags: ,

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

February 13, 2019 Leave a comment

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 – Troubleshooting Server Side Sync exceptions

January 22, 2019 Leave a comment

Server-side synchronization is used to synchronize your email system with Dynamics 365 for Customer Engagement apps at the server level.

Now coming to the issue, I was configuring Server side sync on my CRM on-premise instance with ‘Gmail’ as host and got the below error while testing the mail delivery of a ‘Mailbox’ using ‘Test & Enable Mailbox’ option.

ss_1

Reason:

  • In my case, its CRM on-premise installation and were having below 3 servers
    • Front End Server – Contain CRM WebApp
    • Application Server – Contain Services (Async, Sandbox, etc..)
    • Back End Server – Contain SQL Server and SSRS
  • Issue was ‘Incoming Port’ and ‘Outgoing Port’ were not opened on my ‘Application server’ which caused the issue

Now lets see few sanity steps and how to troubleshoot issues.

[Sanity Step] Make sure Ports and Mailbox settings are correct:

  • Test the settings provided in ‘Email Server Profile’ using console application

ss_3

  • Create a simple C# console application with below code and pass the settings (i.e., Port, host names etc) mentioned in ‘Email Server Profile’

using (MailMessage mail = new MailMessage()){
int portNumber = Convert.ToInt32(ConfigurationManager.AppSettings[“port”].ToString());
var smtpAddress = ConfigurationManager.AppSettings[“smtpAddress”].ToString();
var emailFromAddress = ConfigurationManager.AppSettings[“emailFromAddress”].ToString();
var password = ConfigurationManager.AppSettings[“password”].ToString();
var emailToAddress = ConfigurationManager.AppSettings[“emailToAddress”].ToString();

mail.From = new MailAddress(emailFromAddress);
mail.To.Add(emailToAddress);
mail.Subject = “Set mail subject”;
mail.Body = “Set mail body”;
mail.IsBodyHtml = true;
using (SmtpClient smtp = new SmtpClient(smtpAddress, portNumber)){
smtp.Credentials = new NetworkCredential(emailFromAddress, password);
smtp.EnableSsl = enableSSL;
Console.WriteLine(“Sending mail…”);
smtp.Send(mail);
Console.WriteLine(“Mail has been sent…”);
}
}

App Settings:

<appSettings>
<add key=”port” value=”587″/>
<add key=”smtpAddress” value=”smtp.gmail.com”/>
<add key=”emailFromAddress” value=”rajeevpentyala@gmail.com”/>
<add key=”password” value=”*******”/>
<add key=”emailToAddress” value=”rajeevpentyala@live.com”/>
</appSettings>

[Sanity Step] Make sure your Incoming and Outgoing server locations are reachable:

  • From command prompt, ping the locations with below command and make sure you are getting response
    • Ping -t {location}   (Ex- Ping -t smtp.gmail.com)

ss_4

[Issue] If failed with “The SMTP server requires a secure connection” exception

  • Connect to your Gmail account. Link
  • Turn on the “Less secure app access” option
ss_5

Turn on ‘Less secure app access’

Refer this article for more exhaustive list of troubleshooting options

🙂

[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: , ,

[D365 CE] Migrate data to field with “Time Zone” format

December 14, 2018 Leave a comment

Have you ever worked with “Decimal” field with “Time Zone” Format?

Lets assume your Dynamics application has a global presence and you need to capture “Customer” info along with their “Time Zone”, we can create a Decimal field with “Format” set as “Time Zone”.

TZ_2

With “Time Zone” format, even though, you create a field of “Decimal” type, in UI it will render as drop down and in ‘Advanced Find’ you get a string.

TZ_3

Lets see how to migrate data to the “Time Zone” format field.

Whats “Time Zone” format:

As you would have noticed in above screens, “Decimal” field rendered as Drop down with all time zone options. Now the question is where we are getting these option?

The answer is, Dynamics has an internal entity named “Timezonedefinition” which pulls the time zone options from.

“Timezonedefinition” entity will have below 2 fields

  • Standardname – Name of the Time Zone
  • Timezonecode – Time zone code which is a decimal value

When you add a ‘Decimal’ field with ‘Time Zone’ format to an entity, in UI (i.e., Forms, Advanced Find, Views, etc.) you would get the ‘Standardname’ (i.e., Time zone name) however in the back end ‘Timezonecode’ gets saved.

TZ_4

To check that, export the records to Excel and you would find decimal values in “Timezone” field.

TZ_5

As you notice above, “(GMT-10:00) Hawaii” field rendered as 2 in exported excel, which “Timezonecode”

How to migrate data to “Time Zone” format field:

  • First you need to fetch the “Time zone codes” using “RetrieveMultiple” SDK call (Sample code below)

var request = new RetrieveMultipleRequest{
Query = new QueryExpression(“timezonedefinition”){
ColumnSet = new ColumnSet(“timezonecode”, “standardname”),
}
};

var response = (RetrieveMultipleResponse)_service.Execute(request);

foreach (var item in response.EntityCollection.Entities){
var timeZone = (Entity)item;Console.WriteLine(String.Concat(“Time zone name: “, timeZone[“standardname“], “, time zone code: “, timeZone[“timezonecode“]));
}

  • Executing above code would fetch “Timezone Names” along with “Timezonecode”

TZ_1

  • Once you have the codes, you can migrate the records by setting the “Time zone codes” to “Time zone format” field.
  • In the excel file, add new records with “Timezonecode”

TZ_7

  • After the successful excel import you should see new records in UI with “Time Zone Name” replaced with “Time zone code” passed from excel.

TZ_6.PNG

🙂