Archive

Archive for the ‘CRM’ Category

Plugin Registration Tool (PRT) | ‘Invalid plug-in registration stage’ error while unregistering Assembly

While unregistering one of my custom plug-in assemblies from the Plugin Registration Tool (PRT), I got the following error:

Invalid plug-in registration stage. Steps can only be modified in stages BeforeMainOperationOutsideTransaction, BeforeMainOperationInsideTransaction, AfterMainOperationInsideTransaction and AfterMainOperationOutsideTransaction.

Reason:

  • Which means, a Dataverse Custom API record already, mapped with the Plug-in CAT.APIs.ExecuteOnBoardCustomerAPI in the background. Refer ‘Plugin Type’ column below.
  • Hence we can’t unregister the CAT.APIs Assembly without un-mapping the CAT.APIs.ExecuteOnBoardCustomerAPI from the Dataverse Custom API record.

Fix:

  • Either un-map (i.e., Clear the ‘Plugin Type’ column) the CAT.APIs.ExecuteOnBoardCustomerAPI from the Dataverse Custom API record as below.
  • Or delete the Dataverse Custom API record.
  • Proceed with unregistering the Plug-in Assembly from Plugin Registration Tool and it should unregister now.

If you are looking for downloading and launching Plugin Registration Tool, please refer article here.

šŸ™‚

Advertisement
Categories: CRM

[Beginners] Canvas Apps | Options to store configuration data

February 6, 2023 Leave a comment

While building Canvas apps, its pretty common ask to store the configuration data or a Dictionary of key and value pairs. As an example, you might be sending an email from Canvas App and you would want the sender email DL (Distribution List) to be configurable. Think of these settings like an ASP.NET web.config file.

In this article, lets see what are the options to store configuration data.

Creating a hidden configuration screen :

An easy way of setting configuration values is just to create a hidden screen and put your configuration values in text input controls. In this way, you can change application settings without editing code.

  • Create a ‘Settings Screen’ and make it as the last screen, so that it’s easily found.
    • I’ve create a simple ‘Settings Screen’ with a text input control ‘txtEmailDL‘.
  • We will restrict the ‘Settings Screen’ screen to the end users by making sure no logic/formula on the App takes Users to this screen. This way the screen accessible only when the app is edited, and Makers or Admin can go to this screen and configure values.
  • Now, lets see how to read the configuration data and use it across the App.
  • I’ve created a flow which expects ‘EmailDL’ parameter from the Canvas App.
  • On my Canvas Apps ‘Main’ screen, I’ve a button which triggers the flow by passing the Email DL value. Here I am reading the txtEmailDL control value from my ‘Settings Screen’ and pass it to the flow.
  • This way yo can read the txtEmailDL control value from ‘Settings Screen’ across all the screens of Canvas application.
Drawbacks of this approach:
  • You must republish the app to change values and make them persist.
  • Because values persist in the app, you must create a process that updates these values before you export the app in preparation for a move to another environment.

Store the configuration data in external source (Dataverse):

Keep in mind that Dataverse requires a premium connector and since you are using Dataverse you will need a premium license. To use this approach:

  • Create a new Dataverse table to store configuration values. Because the values persist outside the app, they can be modified at any time without redeploying the app.
  • As an example, create a table with a custom ‘Data’ column and keep configuration settings required for your Canvas app in json format.
  • Every time you open Canvas App, read the configuration from Dataverse.
Drawbacks of this approach:
  • This approach requires a call-back to Dataverse connector evertytime you open the Canvas Apps. Therefore, there will be a slight effect on performance.

Hope you got some beginner understanding of how to store configuration data and consume in Canvas Apps. If you are a beginner, I highly recommend go through coding standards.

šŸ™‚

C# Basics | Why Interfaces?

I often get this question “Why Interfaces”, can’t I simply implement logic just with Class from C# beginners?.

Well, If you search this questions over internet, you get the following overwhelming response:

In C#, interfaces are a way to specify a contract that a class must implement. They allow you to define a set of methods that a class must implement, without specifying how those methods should be implemented. This is useful for several reasons:

  1. Interfaces allow you to create a common set of methods that can be used across multiple classes, even if those classes have very different implementations.
  2. Interfaces allow you to write code that is more flexible and adaptable, because it is not tied to a specific implementation of a class.
  3. Interfaces can be used to model real-world concepts in your code, such as the concept of a “drawable” object that can be drawn to the screen.
  4. Interfaces can be used to create a level of abstraction between different parts of your code, which can make it easier to understand and maintain.

Overall, interfaces are a powerful feature of C# that can help you write more flexible, reusable, and maintainable code.

Why Interfaces in C#?

In this article, I will try to explain a very basic use of Interface out of many other benefits.

Scenario:

Assume that you are building a Shopping Cart functionality for a Car Show room, which ships both Electric and Gas Cars and you want build functionality to add cars to the Cart and Ship them.

That’s the scenario and I will demonstrate this scenario with a simple C# console project.

Implementation:

We will first start with defining ‘Entity Model’ and then move on to Cart functionality.

Entity Model :
  • As we know that ‘Electric Car’ and ‘Gas Car’ contain both common and different features, So I decided to go with two classes ElectricCar and GasCar.
  • Class ‘ElectricCar‘ looks as below:
  • Class ‘GasCar‘ looks as below:
  • If you notice, “FullChargeTimeInHours” property is in ‘ElectricCar‘ but not in ‘GasCar‘ and “CapacityInLiters” property is in ‘GasCar’ but not in ‘ElectricCar‘.
  • Lets implement a simple ‘Cart’ functionality by:
    • Add items to Cart
    • And ship them using ‘Ship()’ function

Cart Logic (No Interface):
  • Add a new function AddElectricCars() which returns list of Electric Cars.
  • Add a new function AddGasCars() which returns list of Gas Cars.
  • Now call AddElectricCars() and AddGasCars() and loop through Cars and invoke Ship() function.
  • If you observe, both ‘ElectricCar‘ and ‘GasCar‘ classes have same properties and function (i.e., Ship) except one property, we had to implement 2 Carts logic.
  • Now lets see how this can be simplified using Interfaces.

Cart logic (using Interface):
  • Create a new ‘ICar’ interface with common properties and function between ‘ElectricCar‘ and ‘GasCar‘.
  • Implement ‘ICar’ interface in ‘ElectricCar‘ class.
    • Notice that I’ve defined ‘FullChargeTimeInHours’ property which is specific to ‘ElectricCar‘ with in the Class.
  • Similarly implement ‘ICar’ interface in ‘GasCar‘ class.
    • Notice that I’ve defined ‘CapacityInLiters’ property which is specific to ‘GasCar‘ with in the Class.
  • Now lets see the magic. We can have a single Cart which handles both ‘ElectricCar‘ and ‘GasCar‘.
  • Add just one ‘AddCars()’ function which returns list of ‘ICar’.
  • If you execute the code, the output looks as below:
  • That’s the flexibility we get with interfaces. I hope now you can relate the statement “Interfaces allow you to create a common set of methods that can be used across multiple classes, even if those classes have very different implementations.” with our Cars example.

You can download the whole code from here. I will continue this C# basics with more simple examples.

šŸ™‚

Categories: CRM

Plugin Registration Tool | Connect to environment directly by skipping discovery

November 23, 2022 Leave a comment

If your Dynamics 365 tenant has more than 20 environments and you are tired of selecting the right environment by scrolling all over, this tip is for you.

In Plugin Registration Tool (PRT) there is an option to skip discovery during login and directly connect to your environment. Lets see how to do that.

Steps to configure Skip Discovery in PRT:

  • Go to the folder where you have downloaded the Plugin Registration Tool.
  • Open the “PluginRegistration.exe.config” xml file in an editor of your choice.
  • Under <appSettings> , uncomment the “SkipDiscovery” key.
  • Should be as below once you uncomment.
  • Save the “PluginRegistration.exe.config” file and open the Plugin Registration Tool.
  • On the ‘Login’ pane, provide credentials and make sure you uncheck “Display list of available organizations”.
  • Click ‘Login’ and you get a ‘Enter environment instance url‘ popup.
  • Provide the ‘Instance url’ of your environment to connect.
  • Click ‘Ok’ and the Plugin registration tool will directly connect to your environment thus skipping the environments discovery.

  • To get the Instance url
    • Connect to Maker Portal.
    • From ‘Settings->Session details’
    • Copy the ‘Instance url’.

šŸ™‚

[Step by Step] Power Apps | Show pop ups in Canvas App

November 15, 2022 Leave a comment

In this article lets see how to show pop-ups in Canvas Apps using Container controls. I am going to explain this topic with two different examples. A ‘Single Popup’ and ‘Dual Popup’.

Single Popup in action:

Dual Popups in action:

Now that you got an idea of the two examples, lets go ahead and learn how to build them.

Step by Step to show single popup:

  • Create a new Canvas App.
  • Add a button ‘Demo Single Popup’ to the screen to show popup.
  • To display a popup, we would need 2 Container controls.
    • First container will bring the gray out affect speeded across the screen.
    • Second container will hold the display content and acts as popup pane.
  • So add the 1st Container on the screen and spread it across the screen.
    • I’ve named the Container as ‘cont_One’.
  • In the “Fill” property of Container (i.e., cont_One), set the value as RGBA(169, 169, 169, .75)
    • RGBA(169, 169, 169, .75) gives gray out affect. You may also use your own color combination.
  • Now add the 2nd Container, by selecting the 1st Container (i.e., cont_One). Make sure you select ‘cont_One’ before adding the second container.
    • I’ve named the2nd Container as ‘cont_Two’.
  • Place the 2nd Container (i.e., cont_Two) middle of the screen and set the background color.
  • Its time to add pop up content. So, select ‘cont_Two’ and add the controls. I’ve added a Label and Button controls as shown below.
  • Now that we got the layout ready, its time to implement hide/show of popup logic.
  • As we need to show popup only on ‘Demo Single Popup’ button click, set a Boolean variable by name ‘ShowPopup‘ on ‘OnSelect’ of ‘Demo Single Popup’ button.
    • Formula : UpdateContext({ShowPopup : true});
  • Now select 1st Container (i.e., cont_One) and set ‘Visible’ as ‘ShowPopup‘ variable which we defined in the previous step.
  • As the popup should be closed on click of ‘Close’ button on 2nd Container (i.e., cont_Two), select the ‘Close’ button and on ‘OnSelect’ event, set the ShowPopup to ‘false’.
    • Formula : UpdateContext({ShowPopup: false});
  • That’s it. Play the App and you should see popup on click of ‘Demo Single Popup’ button and should close on click of ‘Close’ button.

Step by Step to show dual popup:

In the dual popup scenario, everything remains same as we did for single popup and additionally we will add a 3rd Container. Lets get started.

  • Repeat the steps you did during single popup.
    • There is a slight change than what we did in single popup demo in terms of controls.
    • I’ve added ‘Rating’ control instead of label.
  • Now that we added ‘cont_One’ and ‘cont_Two’, to get the dual popup, select ‘cont_One’ and add a new Container and name it as ‘cont_Three’
  • Place the ‘cont_Three’ on top of ‘cont_Two’ and add controls as shown below.
  • We got the layout ready, its time to implement hide/show of popup logic as below.
    • On click of ‘Demo Dual Popup’ button on main screen
      • Show ‘cont_One’.
      • Show ‘cont_Two’
      • Hide ‘cont_Three’.
    • On click of ‘Rate Us’ button of ‘cont_Two’
      • Show ‘cont_One’.
      • Hide ‘cont_Two’.
      • Show ‘cont_Three’.
    • On click of ‘Close’ button of ‘cont_Three’
      • Hide ‘cont_One’.
      • Hide ‘cont_Two’.
      • Hide ‘cont_Three’.
  • Don’t worry, if the above conditions scares you. Its easy to implement. Its how we did by defining ‘ShowPopup‘ variable in showing single popup example. Additionally we would need another variable ‘ShowDualPopup‘ for dual popup.
  • On ‘OnSelect’ event of ‘Demo Dual Popup’ button, set ‘ShowPopup‘ variable as ‘true’ and another variable ‘ShowDualPopup‘ as ‘false’.
    • Formula : UpdateContext({ShowPopup : true, ShowDualPopup:false});
  • Now select 1st Container (i.e., cont_One) and set ‘Visible’ as ‘ShowPopup‘ variable. (Refer screen from single popup example if you need help).
  • Now select 3rd Container (i.e., cont_Three) and set ‘Visible’ as ‘ShowDualPopup‘ variable.
  • As we need to show ‘cont_Three’ only on click of ‘Rate us’ button of ‘cont_Two’, on ‘OnSelect’ of ‘Rate us’ button set the ‘ShowDualPopup‘ variable to ‘true’.
    • Formula : UpdateContext({ShowDualPopup : true});
  • Important point to note is that, we dont need logic to Hide/Show ‘cont_Two’ as it gets visible when ‘cont_One’ is visible and it gets hidden when ‘cont_Three’ is visible as ‘cont_Three’ is top of ‘cont_Two’.
  • Finally, as we need to hide all the popups (i.e., cont_One and cont_Three) once you click the ‘Close’ button on ‘cont_Three’, on ‘OnSelect’ of ‘Close’ button set both ShowPopup and ShowDualPopup variables to ‘false’.
    • Formula : UpdateContext({ShowPopup:false,ShowDualPopup :false})
  • That’s all needed for dual popups. Play the App and you should see dual popups.

šŸ™‚

[Code Snippet] PowerShell | Azure DevOps | Query Variable Group using API

In Azure DevOps, Variable groups store values and secrets that you might want to be passed into a YAML pipeline or make available across multiple pipelines.

Variable Group is a collection of variables with Name and Value pair.

Below is my variable Group ‘BillingSystemDictionary’ with 3 variables in my DevOps organization ‘RajeevPentyala0011’ and project ‘Demo’ (These details are required in PowerShell script).

In DevOps pipeline scenarios, you may need to fetch the variables under a variable group. Following is the PowerShell script which calls DevOps API and fetch variables by variable group name.

    # Form API authentication Header
    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add("Authorization", "Bearer $(System.AccessToken)")
    $headers.Add("Content-Type", "application/json")

    # Pass Variable Group Name and read variables
    $variableGroupName = "BillingSystemDictionary"
    # 'projectid' pattern is https://dev.azure.com/{organization_name}/{projectname}
    $projectid = "https://dev.azure.com/RajeevPentyala0011/Demo"

    $variableGroupGetUrl = "$projectid/_apis/distributedtask/variablegroups?groupName=$variableGroupName*&queryOrder=IdDescending&api-version=6.0-preview.2"

    $queryResponseObject = Invoke-RestMethod -Uri $variableGroupGetUrl -Method GET -Headers $headers
 
    # $queryResponseObject will be of type pscustomobject
    # To fetch the variable value of "isactive"
    $variableName = "isactive"
    $variableValue = $queryResponseObject.value.variables.$variableName.value
    Write-Host "$variableName value is $variableValue"

šŸ™‚

Categories: CRM, DevOps Tags: , , ,

PowerĀ PlatformĀ | Data source environment variables

Recently, I got a deployment (ALM) specific query from my SharePoint colleague who was exploring Power Platform’s Canvas Apps.

Query:

  • SharePoint team got 3 Sites (i.e., Dev/QA/Prod) and they also use 3 different Power Platform environments for Development, QA, and Production.
  • On Development environment, a Canvas App was built connecting to ‘Dev’ SharePoint site.
  • When the ‘Canvas App’ moved to QA and Production environments using Solution import, it must connect to the ‘QA’ and ‘Prod’ SharePoint sites.
  • Following diagram depicts the topology.

Solution:

  • It’s pretty a common scenario and one option would be post solution import to QA/Prod environments, reestablish the Connection reference manually. This option is time consuming and not intuitive.
  • Other recommended option is “Data source environment variables”. We will see the ‘How’ part in next section.

Data source environment variables:

  • As we know, Environment variables store the parameter keys and values, which then serve as input to various other application objects.
  • Environment variables are now much simpler to work with and can storeĀ parameters required to connect to data.

In this article, lets see how to create and consume Data source environment variables in Canvas App.

Configure Data source environment variables:

Create Environment variables:

In this article, I am using SharePoint site to connect from Canvas App.

  • Create a SharePoint site if not exists already and add a list using native ‘Issue Tracker’ template (You can also use any List of your choice).
  • From Power Apps maker portal, connect to Dev environment and create a new solution.
  • Create a new ‘Canvas App’ from the Solution.
  • Now, from Canvas App, go to ‘File-> Settings’, enable the setting toĀ Automatically create environment variables when adding data sources.
  • Add a SharePoint data source and configure the Site and List.
  • Once you add the ‘SharePoint’ data source, you would notice a banner message, indicates Environment Variables were auto created.
  • Click on the ‘Manage them here’ will redirect you to the Solution where you can access the auto created ‘Environment Variables’.
  • That’s all needed to create Environment Variables.

Configure Environment variables during Solution Export and Import:
Exporting Solution:
  • Before exporting the solution, select one of the Environment variables and choose ‘Edit’ and select ‘Remove from this solution’.
    • This is step is important. You willĀ notĀ be prompted for new values during solution import if the environment variables already have either a default value or value present, if not chosen the ‘Remove from this solution‘.
  • Repeat this step for other Environment variables.
  • Export the solution.
Importing Solution:
  • Select the target environment (I.e., QA in my case) and choose import the Solution.
  • You will get following ‘Connections’ pane which will allow you to configure to the QA SharePoint site.
  • You will be redirected Connections screen to establish connection to QA SharePoint site. Once you establish connection, it looks as below.
  • Go back to Solution import process and map the new connection configured in above step.
  • In the next step of import, system will ask you to provide values for the Environment variables (i.e., Site, List).
  • You would not get above Connection reference and Environment Variables panes, if you have not chosen the ‘Remove from this solution‘ option.

This approach eliminates manual step of reestablishing connection post solution import to Target environment.

Important Points:

  • ‘Data Source Environment’ variables doesn’tĀ require querying environment variables via Dataverse connector orĀ require premium licenses.
  • The Environment variables can be unpacked and stored in source control using DevOps Power Platform tools.
  • We can also use ‘Pre-existing’ data source Environment variables by creating a new ‘Environment Variables’ of ‘Data Type’ of ‘Data source’.
    • Use this option, if you don’t want auto creation of Environment Variables (i.e., By enabling the setting toĀ Automatically create environment variables when adding data sources).

Refer docs for more details.

šŸ™‚

Categories: CRM

[Step by Step] Model-driven apps | In-app notifications

Using in-app notification feature (Preview) we can notify Users with in the Model-driven apps. In this article lets learn how to enable the feature and use the in-app notifications with different options step by step.

Enable In-app notifications feature:

  • Connect to Power Apps Maker Portal.
  • Open the ‘Model Driven App’ using ‘Edit in preview’ option.
  • In the App Editor, select ‘Settings -> Upcoming’ and enable theĀ In-app notifications (Preview) as below.

Create a Test User:

  • To test the In-app notifications, create a new user account. This User acts as recipient of notification.
    • Note: If you already have more users in your environment, skip this step and use one of the existing Users as recipient.
  • I’ve created an User named ‘Test User 1’ to send the notifications to.
  • Open the Model driven app in another browser using the Test User account.
  • Next copy the ‘Test User 1’ GUID by opening the User from ‘Advanced Find’. We will use this GUID while creating notification.

As we completed pre-requisites, its time to create notifications.

Creating our first notification:

  • Notification features uses an OOB table called “appnotification”.
  • We create a record in ‘appnotification’ table which turns out to be a notification for targeted User.
  • Each notification row is meant for a single user, identified by theĀ OwnerĀ column value.
  • If a notification needs to be sent to multiple users, a record needs to be added for each recipient.
  • The sender controls the recipient through theĀ OwnerĀ column.

Following is code snippet is using ‘Client API’ to create a basic notification.

function showBasicNotification() {
    // GUID of User (i.e.,Test User 1 in my case) whom you want to send the Notification to.
    var systemuserid = "0758fd55-c2ca-ec11-a7b5-00224808dd66";
    var notificationRecord =
    {
        "title": "Welcome",
        "body": "Welcome to the world of app notifications!",
        "ownerid@odata.bind": "/systemusers(" + systemuserid + ")",
        "icontype": 100000000, // info
        "toasttype": 200000000 // timed
    }
    // Create notification record
    Xrm.WebApi.createRecord("appnotification", notificationRecord).
        then(
            function success(result) {
                console.log("notification created with ID: " + result.id);
            },
            function (error) {
                console.log(error.message);                
            }
        );
}
  • Register the showBasicNotification() function on one of the form jscript events (i.e., On Load/On Save/Field_OnChange).
  • For this blog post, I’ve registered script on ‘On Load’ event.
  • Use Browser ‘DevTools’ (F12) to check the successful execution of function.
  • Up on executing the script, end user (i.e., Test User 1) would get a notification as below.

Notification with Action(s):

  • Using “data” tag we can create notifications that include actions, custom body definitions, and custom icons.
  • Following code snippet contain 2 actions (i.e., 2 URLs to navigate to) in Notification.
    • ‘actions’ is an array.
function showNotificationWithMultipleActions() {
    // Notification with multiple actions as center dialog 
    var systemuserid = "0758fd55-c2ca-ec11-a7b5-00224808dd66";
    var notificationRecord =
    {
        "title": "Different Search Options",
        "body": "This is to inform you that you can use following search options",
        "ownerid@odata.bind": "/systemusers(" + systemuserid + ")",
        "icontype": 100000000, // info
        "data": JSON.stringify({
            "actions": [
                {
                    "title": "Bing",
                    "data": {
                        "url": "https://bing.com",
                        "navigationTarget": "dialog"
                    }
                },
                {
                    "title": "Google",
                    "data": {
                        "url": "https://google.com",
                        "navigationTarget": "dialog"
                    }
                }
            ]
        })
    }
    Xrm.WebApi.createRecord("appnotification", notificationRecord).
        then(
            function success(result) {
                console.log("notification created with multiple actions: " + result.id);
            },
            function (error) {
                console.log(error.message);
            }
        );
}
  • Up on execution, End User gets a notification with 2 navigation actions as below.

Notification with a custom Title and Body:

  • TheĀ dataĀ field supports overriding the Title and Body simple strings with a limited subset of markdown based.
  • Below is the supported markdown.
Text StyleMarkdown
Bold**Bold**
Italic_Italic_
Bullet list- Item 1\r- Item 2\r- Item 3
Numbered list1. Green\r2. Orange\r3. Blue
Hyperlinks[Title](url)
  • Newlines can be included with the body usingĀ \n\n\n\n.
  • Following is a code sample using ‘Markdown’ to customize Title and Body.
    • Under ‘actions’ tag, url is pointing to an existing record.
function notificationWithCustomTitleAndBody() {
    var systemuserid = "0758fd55-c2ca-ec11-a7b5-00224808dd66";
    var notificationRecord =
    {
        "title": "Example of Custom Title and Body",
        "body": "Maria Campbell mentioned you in a post.",
        "ownerid@odata.bind": "/systemusers(" + systemuserid + ")",
        "icontype": 100000004, // mention (Displays @ symbol)
        "data": JSON.stringify({
            "title": "[Potential Prospect](?pagetype=entityrecord&etn=raj_prospect&id=48f5d750-cbca-ec11-a7b5-00224808dd66)",
            "body": "Here is a [Potential Prospect](?pagetype=entityrecord&etn=raj_prospect&id=48f5d750-cbca-ec11-a7b5-00224808dd66)",
            "actions": [
                {
                    "title": "View record",
                    "data": {
                        "url": "?pagetype=entityrecord&etn=raj_prospect&id=48f5d750-cbca-ec11-a7b5-00224808dd66"
                    }
                }
            ]
        })
    }
    Xrm.WebApi.createRecord("appnotification", notificationRecord).
        then(
            function success(result) {
                console.log("notification created with custom title and body: " + result.id);
            },
            function (error) {
                console.log(error.message);
            }
        );
}
  • Up on execution End User receives notification as below.

Notification with a custom Icon:

  • Within the notification, setĀ iconTypeĀ toĀ CustomĀ and in the body, includeĀ iconUrlĀ with a value pointing to a web resource.
    • “icontype”: 100000005, // custom
    • “data”: “{ ‘iconUrl’: ‘/WebResources/cr245_AlertOn’}”
  • The icon can be either an SVG or PNG file type.
  • Following is the ‘notificationRecord’ object.
var notificationRecord = 
{
  "title": "Welcome",
  "body": "Welcome to the world of app notifications!",
  "ownerid@odata.bind": "/systemusers(" + systemuserid + ")",
  "icontype": 100000005, // custom
  "data": "{ 'iconUrl': '/WebResources/cr245_AlertOn'}"
}
  • Notification with Custom icon looks as below.

Key points on Notification usage:

  • If you don’t specify “ownerid@odata.bind” in ‘notificationRecord’ object, notification will go to the User who created Notification.
  • Notification Polling:
    • In-app notifications uses polling to retrieve notifications periodically when the app is running.
    • New notification are retreived at start of the model-driven app and when a page navigation occurs as long as the last retreival is more than one minute ago.
    • If a user stays on a page for a long duration, new notifications will be retrieved.
  • Notifications appear in the notification center until the recipient dismisses them or they expire. By default, a notification expires after 14 days but your administrator can override this setting
  • You can change in-app notification behavior by settingĀ Toast TypeĀ to one of the following values.
Toast TypeBehaviorValue
TimedThe notification appears for a brief duration (the default is four seconds) and then disappears.200000000
HiddenThe notification appears only in the notification center and not as a toast notification.200000001
  • You can change the in-app notification icon by settingĀ Icon TypeĀ to one of the following values.
Icon TypeValueImage
Info100000000Info Icon
Success100000001Success Icon
Failure100000002Failure Icon
Warning100000003Warning Icon
Mention100000004Mention Icon
Custom100000005

šŸ™‚

Categories: CRM

Dynamics 365 and Microsoft Power Platform | Release planner

As the Dynamics Release Wave 1 2022 is being deployed this month, if you are planning for an upgrade of your existing system, Release planner tool (BETA) helps you to organize and plan for New and Upcoming features.

  • To get started, first create an account. Alternately you can connect using your Work Account.
  • Pick the feature you want to try add that to your plan by clicking ‘+ To my plan’.
    • Click ‘Learn more’ to understand about the feature.
  • Once you add the Features, go to ‘My Release Plans’ for collated list.
  • Refer this article by Microsoft FastTrack Team on how to plan and approach the products release wave upgrades.

šŸ™‚

Categories: CRM, Dynamics 365 Tags:

[Step by Step] Using JSLint extension in VSCode

In this article, lets see how to Install and use JSLint extension in VSCode.

What is JSLint:

  • JSLint is a JavaScript program that looks for problems in JavaScript programs. It is a code quality tool.
  • JSLint takes a JavaScript source and scans it. If it finds a problem, it returns a message describing the problem.

Install JSLint extension in VSCode:

  • From the VSCode ‘Extensions’, search for ‘JSLint’ and Install.
  • Next, we need to install ‘jslint’ Globally by running ā€˜npm install -g jslint’ command from Terminal.
  • All the required files gets installed and Terminal looks as below.

Run JSLint on a JavaScript File:

  • Open the JavaScript file, which you want to validate in VSCode.
  • Open the Terminal and run ‘jslint {file_name}’ command. In my case, its ‘jslint HelloWorld.js’.
  • Script violations will be listed in Terminal as below.

šŸ™‚

Categories: JScript Tags: ,