How to – convert basic queue to an advanced queue – Dynamics 365


We can convert our basic queue to an advanced queue by setting the field “Is Omnichannel Queue” or “Automatic work distribution” schema name “msdyn_isomnichannelqueue“- to Yes.

We would usually do it to use the existing basic queue in the Unified Routing.

We can find that option in the Conflicts Tab of the Queue form

Or in case you cannot find the conflicts tab, you can add the field to the form

Here we need to be careful while converting the basic queue to an advanced queue, as we cannot revert this. If we try to do this we will get the below error –

Get more details here.

Hope it helps..

Advertisements

Fixed – Feature ‘Semantic classification, Document Highlights, etc. ’ is currently unavailable due to internal error – Visual Studio


Recently we were getting the below notifications in our Visual Studio 2019.

The way we managed to fix it was by disabling the following option – “Use 64-bit process for code analysis

Navigate to Tools >> Options >> Text Editor >> C# >> Advanced

The “Use 64-bit process for code analysis” option in Visual Studio allows the code analysis tools to run in a 64-bit process instead of a 32-bit process. This option is relevant when we are performing static code analysis, and here we had recently installed a Visual Studio extension that does the same. So might as well be a compatibility issue with that extension.

Hope it helps..

Advertisements

Find email templates faster with the new Insert Template dialog – Dynamics 365 / Dataverse


The new insert template dialog box adds features to quickly find and insert the appropriate email template.

For the below email record, we have a contact, account, and user type record selected in To (Regarding), click on Insert Template to open the dialog box.

The new dialog box allows selecting the view for filtering the email templates.

Clicking on Filter shows the filter for the selected view, and allows updating the filter to find the required template.

The Record options allow filtering the views based on the record type specified in the To (Regarding)

Selecting the A. Datum Corporation (Sample) account record, filters the view to show email templates related to the account.

We can also specify the type of view – either List (default), Grid, or Tiles.

From Advanced Settings >> System Settings >> Email tab, we can control these options i.e. specify the default view, and show and hide for Record and Filter options.

The enhanced email template selection is enabled for default for Customer Service Workspace and Customer Service Hub Apps.

To enable it for other Model-driven apps, add and enable the following setting “Enable the New Insert Template Dialog” in the solution.

Below is how the old Insert Email Template dialog box looks

Get more details here

Hope it helps..

Advertisements

How to – enable the enhanced email template editor in Model-driven Apps(Dynamics 365 / Dataverse)


Below is what our existing or current Email Template editor looks like (Sales Hub >> Personal Settings >> Email templates)

Let us now enable the Enhanced Email Template editor for the App / Environment (it is enabled by default for Customer Service workspace and Customer Service Hub apps)

Create or Open an existing solution, Add existing >> Setting >> Enable the New Email Template Editor

We can set the value as Yes for the Setting environment value to apply it for the environment.

To enable it for a specific app, make sure we have the option “Environment and apps” and “Apps Only” selected for Value can be changed for option.

To specify the app(s) for which we want to enable the new email template editor, we need to add that corresponding app to the solution.

Here we have added the Sales Hub.

Add Existing >> App >> Model-driven App >> Sales Hub

On adding the Sales Hub App, we get the option to set the value for the Sales Hub app, which we have set as Yes.


Publish all customization.

We can now see the new Editor tab added for the new Email Template record inside Sales Hub.

We can drag and drop, and specify properties, of the layout section and elements in the new editor.

The new email template editor uses the same design as the email editor in Dynamics 365 Marketing, making it more consistent across the different apps in the platform.

Get all the details here.

Hope it helps..

Advertisements

Dataverse Custom API – Global and Entity (Binding Type) example


We can define the Custom API’s binding type as Global, Entity, or Entity Collection. In this post, we can see how a Global and Entity binding type Custom API can be defined, write a corresponding plugin, and then invoke/test through Postman.

We can create Custom API through Plugin Registration Tool, Power Apps, Code, Solution files, and or can use XrmToolBox Plugin – Custom API Manager.

Below we have defined a Custom API name custom_GlobalAPI, with binding type as Global and one Request (input) parameter and Response (output) Property of type string.

Below is how we define the plugin type for it and can access the input and output parameters through context.

To test it we can use the XrmToolBox Custom API Tester plugin as shown below

And from Postman, once we have the access token, we can call the Custom API as shown below.

Now for a Bound Custom API, we have the following definition. It is bound to the Contact table and has one input parameter and one output parameter similar to our Global Custom API.

Below is how we define the plugin type for it, and can access the input and output parameters similar to Global Custom API.

However, in the case of binding type Entity, we will have the Request parameter named Target of type Entity Reference for the bound entity added automatically.

We can test it using the Custom API Tester plugin, however as it is bound type, we need to select/specify the contact record (the table it is bound to), before we can execute it.

To call it from Postman, we need to use the fully qualified name i.e. Microsoft.Dynamics.CRM.[unique name of the Custom API] unlike Global one.

 public class APIPluginGlobal : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService orgService = factory.CreateOrganizationService(context.UserId);

            try
            {
                tracingService.Trace("start plugin execution: {0}", this.GetType().FullName);

                // check for the message name i.e. Unique Name of the Custom API
                if (context.MessageName.Equals("custom_GlobalAPI", StringComparison.OrdinalIgnoreCase))
                {
                    // check for the request parameter in the inputparamters of the context 
                    if (context.InputParameters.Contains("inputParam"))
                    {
                        // get the value of the input parameter
                        string inputValue = context.InputParameters["inputParam"].ToString();
                        // set the value of response property through outputparameters 
                        context.OutputParameters["outputParam"] = "Got following value as Input : " + inputValue;
                    }
                }

                tracingService.Trace("end plugin execution: {0}", this.GetType().FullName);
            }
            catch (System.ServiceModel.FaultException<OrganizationServiceFault> ex)
            {
                tracingService.Trace(ex.Detail.Message);
                throw;
            }
            catch (Exception ex)
            {
                tracingService.Trace(ex.ToString());
                throw;
            }
        }
    }
public class APIPluginBound : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService orgService = factory.CreateOrganizationService(context.UserId);

            try
            {
                tracingService.Trace("start plugin execution: {0}", this.GetType().FullName);

                // unique name of the custom api
                if (context.MessageName.Equals("custom_BoundAPI", StringComparison.OrdinalIgnoreCase))
                {
                    // Target property of type Entity Reference
                    if (context.InputParameters.Contains("Target") &&
                        context.InputParameters["Target"] is EntityReference)
                    {
                        var contact = (EntityReference)context.InputParameters["Target"];
                        // access the input request parameter
                        if (context.InputParameters.Contains("inputParam"))
                        {
                            string inputValue = context.InputParameters["inputParam"].ToString();
                            // set the output parameter value
                            context.OutputParameters["outputParam"] = "Got following as Input Parameter : " + inputValue
                                + " for record : " + contact.Id.ToString();
                        }
                    }
                }

                tracingService.Trace("end plugin execution: {0}", this.GetType().FullName);
            }
            catch (System.ServiceModel.FaultException<OrganizationServiceFault> ex)
            {
                tracingService.Trace(ex.Detail.Message);
                throw;
            }
            catch (Exception ex)
            {
                tracingService.Trace(ex.ToString());
                throw;
            }
        }
    }

Hope it helps..

Advertisements

Fixed – Plug-in assembly fullnames must be unique (ignoring the version build and revision number) – Dynamics 365 / Dataverse


Recently while trying to register the plugin, we got the below error

Microsoft.Crm.CrmException: Plug-in assembly fullnames must be unique (ignoring the version build and revision number). —&gt; Microsoft.Crm.CrmException: Plug-in assembly fullnames must be unique (ignoring the version build and revision number).

It was because we were trying to register the assembly which was already registered in that environment, instead of updating it.


Also, refer – https://helpfulbit.com/plugin-assemby-fullnames-must-be-unique/

Hope it helps.

Advertisements


 

Nishant Rana's Weblog

Everything related to Microsoft .NET Technology

Skip to content ↓