Wednesday 6 November 2019

D365 CE - Duplicate detection approach and options



Hello All,

It feels great to be back with an interesting topic around duplicate detection and approaches.

Duplicate detection is essential to maintaining data integrity and quality in any system and when it comes D365 though there are multiple options to achieve this we are going to concentrate on the following four

1. Duplicate Detection Rules

Duplicate detection rules are out of the box way to manage duplicates. The same can be configured at the UI level.
  • Not enforced and users can override optionally
  • Works within current users access, so there is a chance that duplicates beyond current users access are not considered
  • Needs to be specified explicitly while creating records via OrgService/WebApi

2. Alternate keys
MSCRM alternate Keys are handy in performing duplicate detection and the alternate keys are primarily used for simplifying Integration and Migration activities. Beyond that, it implements a unique constraint for one column or combination of columns.

  • Robust and applies across the board. No need for impersonation
  • Covers UI, Import, OrgService and WebApi
  • Allows null values and duplicate detection is not applied here
  • It also can be used for upsert, retrieve, update and delete. 
  • Errors are system defined and cannot be customized
3. Plugin/Workflow
We can write our own logic to detect and avoid duplicates using plugin and workflows.
  • Allows custom error messages
  • Provides better control on duplicate detection logic
  • Covers UI, Import, OrgService and WebApi
  • Works within the current user's access, so there is a chance that duplicates beyond the current user's access is not considered. Needs impersonation.
4. JavaScript
Like plugin, we can achieve this using a simple JavaScript but the same has its own limitations
  • Covers only UI
  • Allows custom error messages
  • Provides better control on duplicate detection logic
  • Works within the current user's access, so there is a chance that duplicates beyond the current user's access is not considered. Needs impersonation.



Monday 15 April 2019

D365 CE Quick Hacks - Switch to UCI from Classic UI - ForceUCI

With D365 CE there are lot of cool stuff's happening, we are right in middle of all the rapid evolution of the industry and product.

Before reading below content around UCI/Classic app, its recomended to go through below blogs, 



Its always handy to have URL's in armory to navigate to specific areas/interfaces with ease. Lets have a look at them now

How to quickly navigate to default UCI app from Classic UI?

Append a forceuci Query string parameter after main.aspx
https://<your orgname>/main.aspx?forceuci=1 

Ex: https://contoso.crm.dynamics.com/main.aspx?forceuci=1

How to quickly switch the current Classic app to UCI?

Append a forceuci query string parameter after appid. Please make sure to remove session idenfier("#<somerandomnumber>") before appending foreuci tag.

https://<your orgname>/main.aspx?appid=<yourappid>&forceuci=1 

Ex: https://contoso.crm.dynamics.com/main.aspx?appid=ec876248-c755-e911-a832-000d3a127836&forceuci=1

Happy Learning!

Sunday 14 April 2019

D365 CE Quick Hacks - Switch to Classic UI from UCI - ForceClassic

With D365 CE there are lot of cool stuff's happening, we are right in middle of all the rapid evolution of the industry and product.

Before reading below content around UCI/Classic app, its recomended to go through below blog, 

Its always handy to have URL's in armory to navigate to specific areas/interfaces with ease. Lets have a look at them now

How to quickly navigate to default Class UI app when the "UCI only" setting is enabled?

Append a forceclassic Query string parameter after main.aspx
https://<your orgname>/main.aspx?forceclassic=1 

Ex: https://contoso.crm.dynamics.com/main.aspx?forceclassic=1

How to quickly switch the current UCI app to Classic UI?

Append a forceclassic query string parameter after appid. Please make sure to remove session idenfier("#<somerandomnumber>") before appending foreclassic tag.

https://<your orgname>/main.aspx?appid=<yourappid>&forceclassic=1 

Ex: https://contoso.crm.dynamics.com/main.aspx?appid=ec876248-c755-e911-a832-000d3a127836&forceclassic=1

Happy Learning!

Saturday 13 April 2019

D365 CE - Set Classic UI or Navigate to Classic UI

With the introduction of the power platform and UCI lot of the settings in customer engagement is evolving rapidly. One of those were, the UCI is the default interface and not able to get into the classic UI.

Now I am on UCI, how to I navigate to the settings area that controls UCI/Classic UI?

Option 1:

  • Using the setting gear icon on the right hand top corner and select advanced setting.
  • Navigate to Settings => Administration => System settings
Option 2: 
Option 3:
  • Go to URl "https://<your org>/main.aspx?settingsonly=true"
  • Navigate to Settings => Administration => System settings

Under general tab you would see below options,(In powerplatform admin you might see this under basic behaviour section)
    • Set "Use the new Unified interface only" option to No




Friday 8 March 2019

D365 - Revise Quote using Workflow - ReviseQuoteRequest

As a result of constant feature rich updates from MS Team, we were able to call actions from workflows which personally if one of my favorites. I am exploring lot of options around the same, one such is revising the Quote via Workflow.

Why should I need this as I already have a ribbon button to achieve this?

Many businesses have their own business specific quote processflow which might not be in sync OOB quote process flow. In such situation we might need this revise option to minimize the coding effort and leverage OOB revision process. 


Lets not wait anymore, diving into the configuration

1. Create a workflow against quote(Set Scope and sync/async)
2. Hit "Add Step" => "Change Status". Set the status to Closed(Lost/Won/Cancelled) as only closed quotes can be revised using "ReviseQuoteRequest". In this case I am setting it to Closed(Cancelled).

3. Hit "Add Step" => "Perform Action". Select "Revise" against Action optionset and "Quote" should be auto selected against Entity optionset.

4. Hit "Set Properties" => select current quote as dynamic value against QuoteId

Happy Learning!


Thursday 7 March 2019

D365 CE - JS Deprecated Methods cheatsheet - Xrm.Page deprecated and replaced by formContext



Its important for every dynamics developer to understand the deprecated functionalities so that we can stay away from them in our current implementations. This would save lot of time and money when it comes to upgrade and rework when the functionalities are obsolete.

JavaScript is a key piece in  Dynamics UI tuning and with D365 there are a wave of updates when it comes to JS and its hard to remember all the deprecated methods/objects so Microsoft has provided a cheat sheet for deprecated methods. I have copy pasted the same below, please make use of it.


Deprecated Client API
Replacement Client API
Comments
Forms: ExecutionContext.getFormContext 
Commands: Send it as the PrimaryControl parameter
Use of the Xrm.Page object as a static access to the primary form context is still supported to maintain backward compatibility with the existing scripts. Based on the feedback, we understand that the usage of Xrm.Page is high, and it won’t be removed as soon as some other client API methods listed in this section. We encourage you to use the new way of getting form content where possible. More information: Client API form context
Although Xrm.Page is deprecated, parent.Xrm.Page will continue to work in case of HTML web resources embedded in forms as this is the only way to access the form context from the HTML web resource.
Xrm.Utility.getGlobalContext
Allows access to the global context without going through the form context.
formContext.data.attributes
The formContext.data.attributes API will make retrieval of non-entity bound data consistent across entity forms, metadata-driven dialogs, and task-based flows. The data will be a combination of custom values sent using the query string and what was specified in the parameters in the openForm method.
globalContext.userSettings.getTimeZoneOffsetMinutes
Moved to globalContext.userSettings
globalContext.userSettings.userId
Moved to globalContext.userSettings
globalContext.userSetings.languageId
Moved to globalContext.userSettings
globalContext.userSettings.userName
Moved to globalContext.userSettings
globalContext.userSettings.securityRoles
Moved to globalContext.userSettings
globalContext.organizationSettings.isAutoSaveEnabled
Moved to globalContext.organizationSettings
globalContext.organizationSettings.languageId
Moved to globalContext.organizationSettings
globalContext.organizationSettings.uniqueName
Moved to globalContext.organizationSettings
No change in the method, but use "typename" instead of type for lookup attributes.

GridRow.data
GridRow is essentially a form context. This change unifies the interface of GridRow with formContext.
GridRowData.entity
GridRowData is form data. This change unifies the interface of GridRowData with formContextData.
Xrm.Mobile.offline
Moved the offline-related methods under Xrm.WebApi.offline

Earlier: An HTML web resource may interact with the Xrm.Page or Xrm.Utility objects within the form by using parent.Xrm.Page or parent.Xrm.Utility. 
Now: parent.Xrm.* will work if the HTML web resource is loaded in a form container. It won't work for HTML web resources that are stand alone, or referenced from the site map or any other places.
addOnKeyPress
Use a custom control

removeOnKeyPress
Use a custom control

showAutoComplete
Use a custom control and corresponding UI

hideAutoComplete
Use a custom control and corresponding UI

Xrm.Navigation.openAlertDialog
The new signature is consistent with other APIs (openForm) and takes a new set of parameters for flexibility.
Xrm.Navigation.openConfirmDialog
The new signature is consistent with other APIs (openForm) and takes a new set of parameters for flexibility.
Xrm.Utility.getEntityMetadata
The isActivityType method is synchronous so it was suitable for ribbon rules. However, the replacement method, getEntityMetadata, is asynchronous, and is not suitable for ribbon rules.
Xrm.Navigation.openForm
Moving navigation actions to Xrm.Navigation
Xrm.Navigation.openForm
Moving navigation actions to Xrm.Navigation
Xrm.Navigation.openWebResource
Moving navigation actions to Xrm.Navigation 
Note: This API returns VOID in Unified Interface.


Sunday 3 March 2019

D365 CE - Quote Revise Approach and Error Troubleshooting - The quote cannot be revised because it is not in closed state.

I have recently faced an error while revising an active quote using ReviseQuoteRequest action via plugin/workflow. Below is the error message

"The quote cannot be revised because it is not in closed state. If you contact support, please provide the technical details."

Root Cause
Its due to the state of Quote. Only the quotes in closed state can be revised, if we are trying to revise a quote in a different state, then its going to error out with above message.

Fix/Approach
  1. First change the Quote status to Closed(Won/Lost/Cancelled). 
  2. Then execute the ReviseQuoteAction which would result in new revised Quote as expected
You can read how to implement the above revise quote with a workflow here.

Wednesday 6 February 2019

D365 Js Tips - Hide / Show / Enable / Disable a field - Best Practice Tip 1



Quick tip to avoid redundant code to enable/disable/show/hide a field. 

1. Hold the result of hide or disable condition in a variable.

Var isDisable =(formContext.getAttribute('accounttype').getValue()==1);
2. Use the result in disable rule so that it will flip between enable and disable without redundant script lines for enable/disable and avoids if branching

formContext.getControl("<Field Name>").setDisabled(isDisable);