Remove Flow Ribbon Button

Remove Flow Ribbon Button

Hey D365’ers! Welcome to {{ quirk.works }}, a blog series where we try to solve a Dynamics 365 or Power Platform problem with unconventional solution. For our first part of the series, let’s try to remove the Flow ribbon button.

So you want to remove the Flow ribbon button?

Yes sir, we don’t want our users to see it as per our requirements document.

Tried removing it with Ribbon Workbench?

Ribbon buttons are easy to hide/show using the Ribbon Workbench. Just select the ribbon button, right click, and click Hide.

Hide also the rest of the ribbon button sub-menu.

And there you go. What? It’s not hidden isn’t it?

Here’s a {{ quirk.works }}

There is a quirk with how the Flow ribbon button can be removed.

Click the cog icon on the upper right side of the screen and click Advanced Settings.

Go to Settings > Administration

Go to System Settings.

Open the Customization tab. There you have it, select No from the option Show Microsoft Flow on forms and in the site map. Click the OK button and we’re all set.

Conclusion

Not every ribbon button can be hidden using the Ribbon Workbench, sometime you have to look out of the XrmToolBox. Just playing with some puns, no offense meant for these great tools as I admire these awesome works from Scott and Tanguy. Until our next {{ quirk.works }}, stay-tuned D365’ers. I’ll keep you posted.

 

PowerApp Admin Tools

I’ve been working on XrmToolBox Tools for a bit now, both speaking and posting on the huge number of cool tools and how we can build our own. I’m still working on a few XrmToolBox related projects, but when I started diving into Power Apps, I immediately wondered if I could replicate some Tools in Canvas or Model Driven Apps. Wouldn’t it be cool if we could build out a suite of some administrator or developer tools as Power Apps?

In my post Building XrmToolBox Tools, Part 2, we build an example Tool that allows admins to view the list of Users with a Security Role assignment. It’s a relatively simple tool but it can be pretty useful if you need a quick check on a Role for migrations, troubleshooting, etc. This seemed like as good a candidate as any for a new ‘Admin Tool’ Power App.

Security Role Member Manager!

The proposed functionality for the tool is pretty simple: provide a list of Security Roles in the system, and when the user selects a Role, show the list of assignments. This was meant to be written in about an hour, so that was the extent of the capabilities. Since we have a bit more time, we can add some features. How about we display the list of Teams that have the selected Role assignment and allow Adding or Removing a User or Team to the selected Role.

These requirements are a pretty good candidate for a Canvas App. We can build this using the following components:

  • Common Data Service (CDS) connector – provides the list of Security Roles
  • Office 365 Users Connector – provides the user picture
  • Gallery – bound to the Security Roles list
  • Gallery – bound to the list of Users related to the Security Role
  • Gallery – bound to the list of Teams related to the Security Role

The main screen layout and functionality is also fairly simple. Bind the main grid to to the Security Roles list, and on the select event, bind the secondary lists to the related Users and Teams. No real code behind, just some simple data binding to galleries.

Here is the initial main screen for the Power App:

Security Role Member Manager

Some challenges, some solutions

With the XrmToolBox Tool, I wrote some code to retrieve Security Roles and and User Security Role assignments using the standard SDK Query Expression methods. The list of Security Roles was a simple Retrieve Multiple while the User Role Assignment is a many-to-many relationship.

The many to many is where I stumbled a bit. When I select my Security Role, I want to retrieve the Users and Teams which are both many-to-many relations to Security Roles. The CDS connector does not list the join table as an Entity, so I couldn’t simply add a new Data Source for User or Team and filter by the selected Role. Fortunately, support has been added for many-to-many relationships in the CDS connector. Here is an excellent blog post on the feature by Greg Lindhorst, Principal Program Manager at Microsoft: Relate records in Many-to-Many relationships

So to render the list of Users and Teams, I can bind the galleries using a simple formula. The main screen gallery from which you select a Security Role is named ‘Security Roles List’. So the User and Teams gallery Items property can be set using these simple formulas respectively:

'Security Roles List'.Selected.Users
'Security Roles List'.Selected.Teams

As you can see in Greg’s post, adding and removing Users and Teams are fairly easy too. To remove a User from the selected Security Role, we need a single line formula added to our gallery button:

Unrelate('Security Roles List'.Selected.Users, ThisItem)

That statement passes the selected Security role and the currently selected User to the Unrelate formula, and we’re done!

Next Steps

I plan on a follow up post with a bit more functionality. For example, I like the inline model for selecting a User shown in the post by Greg above, but I think selecting multiple Users and Teams works better. Another nice feature will be to distinguish between Business Units. Right now, this pulls all Security Roles for the entire organization.

This sounds like an obvious one, but I also plan on adding a confirmation dialog before removing the User or Team from a Security Role. This was a bit more complicated than I had expected, so I will write up more detail on how this will be implemented.

As I was working on this sample Power App, I came across a great post User Admin PowerApp (Part 4) by d365Cooky that proposes a similar tool, but for managing Security Roles for a selected User. I like the idea of embedding this into Dynamics 365 CE. By the way, I saw the link via Guido Preite’s dynamicsweekly.com newsletter. If you have not already signed up for this, get to it!

I’ll post notes on all these updates with more detail on how it was built, including the full solution for download in a follow up post.

Powerful stuff!

I feel like I have said that a LOT recently! In a relatively short time, I built a functioning Power App that will allow administrators to manage the Security Role Users and Teams. I put this together in a few hours, including some reading on the CDS connector capabilities and designing a few screens. All of this was done using the existing connectors and no custom code outside of the standard Canvas App formulas.

This is not as complex a tool as you may find in the XrmToolBox, and I am definitely going to continue any contribution I can to the XrmToolBox! But I think this once again demonstrates how the Power Platform allow us to provide low code/no code solutions to your users.

In the meantime, as always, any comments, suggestions, or questions are appreciated!

Dynamics 365-CE Approval Dialogues Using Canvas-apps

There are scenarios where we need to configure approvals in Dynamics 365, for example, mark an account as a premium customer after approval or qualify leads after approval etc. We used dialog control to capture approval request and comments but, now dialog controls are depreciated and not advised to use for new projects.

As per Microsoft’s initial announcement

Dialogs are deprecated and are replaced by mobile task flows (available as of the December 2016 update), and business process flows. Both task flows and business process flows will continue to evolve to make the transition easier.

But either tasks flow or business process flow was not a perfect replacement for Dialog. Knowing this pain from users, Microsoft has now modified the announcement.

Dialogs are deprecated, and should be replaced by business process flows or canvas apps

Even though I knew canvas apps can be now embedded in model-driven apps, I hadn’t thought of this option until I came across this new announcement, so tried replicating my approval dialogues with a canvas app and it works fine. Pheww!!!! 🙂

For testing purpose, I replicated the dialogue for creating approval request for the Account entity.

  1. created a canvas app to create an approval request.
This sample app changes account status to pending verification and captures the comments in one custom field.

2. Now we need to call this app from account form, obtain the app ID from app details section.

select app details to get the App GUID

3. I need to call this canvas app as a popup when the user clicks a button. I created a custom button for account entity-> added a JavaScript as button action to call an HTML web-resource and embedded my canvas app in this HTML I-frame.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<html><head>
<title>Approval</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style="padding: 0px; font-family: arial; overflow-wrap: break-word;" onload="LoadPowerApp()">
<center>
<iframe id="Approval" width="800" height="600"></iframe>
</center>
<script id="myScript">
function LoadPowerApp()
{
var AccountID = window.parent.opener.Xrm.Page.data.entity.getId().slice(1, -1);
document.getElementById("Approval").src=url;
}
</script>
</body>
</html>

I know you have many questions now. "https://web.powerapps.com/webplayer/iframeapp?source=iframe&appId=/providers/Microsoft.PowerApps/apps/56123673-f45c-4b96-b9e6-ece1b0a8069a&ID="+AccountID;

This is the key and I will breakdown it into parts “https://web.powerapps.com/webplayer/iframeapp?source=iframe&appId=/providers/Microsoft.PowerApps/apps/APP GUID&CUSTOM PARAMETER NAME=”+PARAMETER VALUE

App GUID I explained in step 2, now regarding a custom parameter, I deliberately didn’t mention it when we discussed the app creation and kept for this section. When we open this canvas from an account form(like we start a dialogue) the app needs the record GUID to update the account status

I have used form control in the canvas app and filtered the item using the ID Parameter.

4. Now try your button and you can see the magic.

You can download the sample APP from TDG Power Apps bank.

Please note this is a basic app I tried for testing purpose and needs many improvements to use in a live project. you are always welcome to discuss with on this app.

Hope this helps….. 🙂

D365UG Bristol

Man, oh MAN! I am just on the train back from Bristol after attending their first 365 User Group. and it was AWESOME!

First up, big props to the organisers @lubo @dbarber @xrmjoel @robpeledie @leembaker for doing such an amazing job. The venue was great, the food was too (including vegan options :-)) and the swag bags were epic.

But more importantly, the speakers were amazing.

First up, Mark Smith did a fantastic presentation to explain the (seemingly unexplainable) Common Data Model, which is something that sits on the CDS and exists to make sense of your data so that it is usable and, more importantly, means you can build apps faster. Considering he knew nothing about the CDM 5 days ago, this was a great presentation which goes to show how quickly you can assimilate information when the data is available in a usable format (see what I did there *winks*)

Second up was @scott-durowdevelop1-net showing us how much the Power Platform has changed in such a short space of time, and why that’s such a good thing, enabling access to a much wider audience and giving rise to things like the Citizen Developers who can effect such great change in an organisation, and how we all need to embrace change and be adaptable.

And finally, @themarkchristie with an entertaining presentation on how he bought headphones at the Microsoft store and @lubo busted them 5 minutes later – but not to worry, Virtual agent was able to help him raise a support ticket through Forms Pro, which then could be assigned to someone in Field Service, leading to the headphones being fixed (whilst being worn by Mark Smith).

I learned a lot about how to better use the tech we have openly available to us in a more inventive way, and how to work with the community to find answers to stuff that you are struggling with.

I love these community events and I hope to attend each and every one that I can.

Again, big thanks and well done to the organisers.

Love to all

Alison

(Me when I won a Flic button from @themarkchristie)

How to set Sharepoint document location in a field dynamically in Dynamics 365

So, I recently had this requirement to put the SP document location in a field and show it on the Contact form. And I had to do it OOTB way. After some time of playing around with the D365 workflow, I found a way to do it. Yay! 🙂

First, make sure to

  1. Enable Server-side Sharepoint Integration.
  2. Enable document management for your desired entity.
  3. Take note of the absolute URL of your Sharepoint directory. It looks something like this: https://contoso.sharepoint.com

Once you have Sharepoint side set up, let’s do some config! 🙂

  1. Create a field where you would like the link to appear on. In this case, I created a single line of text field with format URL and put it on the form.

2. Create a workflow. The important thing to note here is that the workflow should run on the Document Location entity.

3. Create a step to update the record of whichever entity you enabled document management on. In my case, it is Contact.

4. Inside the workflow designer, select the field you created on Step 1 and paste the URL of your sharepoint directory and add a “/” character.

5. Once you’ve done that, select this field from the Form Assistant and it on the field after the “/”.

6. Once you’ve mapped the field from Step 5, add another “/” character.

7. Select this field from the Form Assistant and add it after the second “/” character.

8. Select Save & Close and activate your workflow.

9. Now this link will be added dynamically on the form 🙂

 

5 ways to insert images in Dynamics 365 email templates

 

Disclaimer: Some of these methods are unsupported, so please check Microsoft documentation for updates.

1. The old school copy paste.

1.You need an image that is hosted on a public-facing website. Simply go to that image, right click, and select Copy Image. Works in IE, Chrome, Edge, and Firefox. The image must be rendered in browser view.

2. Open a new email template window, hit ‘Ctrl + V’ to paste the image. Your image should now be visible.

2. Upload your image in a file repository online (OneDrive/Dropbox/Google Drive)

Another secure way is to upload your image to your preferred file repository, make the file public, and embed it in your email template.

  1. Simply get the direct link to the image you have uploaded.
  2. Open the image in browser view, right click and select Copy Image.

3. Open a new email template window, hit ‘Ctrl + V’ to paste the image. Your image should now be visible.

3. Base64

If you do not want to upload your image to a site, you can encode your image using Base64.

1. Use an Image to Base64 converter. I personally use this website but it’s up to you, you can use MS Flow if you want 🙂

2. After you’ve converted the file, copy the Base64 code. Enclose it with an <img> tag. Select the text and copy and paste it to your email template.

3. When you insert a template into you email, the image should render properly.

4. Clickable images

If you want your image to point somewhere on the web, then you would want to make use of a few friendly HTML tags.

Example:

<a href=”https://dynamics.microsoft.com/en-us/”>
<img border=”0″  src=”https://mspoweruser.com/wp-content/uploads/2016/10/Microsoft-Dynamics-365-logo.jpg”></a>

  1. Just copy the snippet above and replace the href tag to whatever URL you want the image to direct to.
  2. Open a new Email Template window, paste the HTML snippet. Select Save & Close. 

3. When you try your new email template, the clickable image should work properly.

5. Image slices

This is a bit beyond this post, but this is a common issue especially if you want to send out marketing emails. I would just like to share what I know.

  1. Open your image in Photoshop, make your desired slices using the slice tool.

2. Once your slices are ready, right click on a selected slice, then select Edit Slice Options.

3. Enter URL/target depending on where you want the slice to direct to.

4. Once you’re set, select Save for Web and Devices and then select Preview.

5. Copy the generated HTML script and replace the img src tag to the direct link of the image.

6. Paste it on your new email template. Select Save & Close.

7. When you try your new email template, the image slices should be rendered properly. 🙂

Opening Dynamic CRM Entity Form by passing Query String

Photo by Luca Bravo on Unsplash
One of the awesome features of the Power Platform is its extension capabilities. We often talk about integrating Power Platform using web services, azure services or plugins but we overlook the platform client side capabilities. The Dynamics platform allows interacting with resources using Addressable elements. URL addressable elements enable you to include links to Dynamics 365 for Customer Engagement apps forms, views, dialogs, and reports in other applications. In this manner, you can easily extend other applications, reports, or websites so that users can view information and perform actions without switching applications.

Requirement

I had a requirement to open an Account entity form based on the Account Telephone number. The Dynamics platform allows only to open the entity record in edit mode only by passing the entity ID. However, my requirement was to open the entity form based on the telephone number.

Considerations

  • Opening a form in edit mode is possible only if we know the ID (or GUID) of the record. If you pass any other query string like telephone, employeeno or etc.  you will receive 500-internal error.
  • You will need an HTML webresource as intermediate component to resolve your query string and in my case telephone to the entity ID and then open the form in edit mode by passing ID.
  • The only query string name you can use to pass to the organization URL is “data”. If you use any other query string name such as employeeId, contactid and etc. will lead you to the 500-Internal Server Error.
  • You will need to use GlobalContext by calling getGlobalContext method in your web resource. The getQueryStringParameters method is deprecated. You will need to find another way to get the value of your query string. I used Andrew Butenko post to extract query string. A big shout out to Andrew Putenko. At the same time a big shout out to Jason Lattimer for his great CRMRestBuilder.

Solution

I used an HTML webresource, with a Javascript function to extract and resolve query string and then call OpenForm function to open the form.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Web Resource</title>
    <script src="ClientGlobalContext.js.aspx" type="text/javascript"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"> </script>
    <script>
        function Onload() {
            var queryString = location.search.substring(1);
            var params = {};
            var queryStringParts = queryString.split("&");
            for (var i = 0; i < queryStringParts.length; i++) {
                var pieces = queryStringParts[i].split("=");
                params[pieces[0]] = pieces.length == 1 ? null : decodeURIComponent(pieces[1]);
            }

            var phone = params["data"];//formContext.data.attributes["data"];
            var req = new XMLHttpRequest();
            req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v9.1/accounts?$select=accountid&$filter=telephone1 eq '" + phone + "'", true);
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("Prefer", "odata.include-annotations=\"*\",odata.maxpagesize=1");
            req.onreadystatechange = function () {
                if (this.readyState === 4) {
                    req.onreadystatechange = null;
                    if (this.status === 200) {
                        var results = JSON.parse(this.response);
                        for (var i = 0; i < results.value.length; i++) {
                            var accountid = results.value[i]["accountid"];
                            OpenForm("account", accountid);
                        }
                    } else {
                        Xrm.Utility.alertDialog(this.statusText);
                    }
                }
            };
            req.send();           
        }

        function OpenForm(entity, id) {
            var entityFormOptions = {};
            entityFormOptions["entityName"] = entity;
            entityFormOptions["openInNewWindow"] = true;
            entityFormOptions["entityId"] = id;
            Xrm.Navigation.openForm(entityFormOptions).then(
                function (success) {
                    console.log(success);
                },
                function (error) {
                    console.log(error);
                });
        }
</script>
</head>
<body>
<script>Onload();</script>
</body>
</html>

Underhood of Dynamics 365 Portal Profile Page

Photo by Emanuel Villalobos on Unsplash
In the part 1 of the series, I shed light on some of planning and analysis activities involved in a Portal project. From this part, I will be writing about some common portal project requirements and the way I have addressed those requirements.

Site Settings

One of the most basic portal configurations happen in Site Settings. Site Settings contain some global configuration used by portal framework. The complete list of portal site settings can be found here. However, there are some settings are deprecated since this link is taken from ADXStudio product and there are some settings that you will not find in the given link and I am listing down those settings in the below table:
Setting Description
Search/Enabled A true or false value. If set to false will disable the search functionality from the portal so you will not see the magnifier sign on the primary navigation
DateTime/DateFormat The format you want to show dates in your portal. For example, for British datetime format, I use d/M/yyyy
profile/forcesignup A true or false value. If set to true will force user to update their profile after signup. It means portal will redirect the user to the Profile page after successful signup
Authentication/Registration/TermsAgreementEnabled A true or false value. If set to true, the portal will display the terms and conditions of the site. Users must agree to the terms and conditions before they are considered authenticated and can use the site.
Authentication/Registration/ProfileRedirectEnabled A true or false value. If set to false and profile page is disabled on the Portal, then Redeem Invitation workflow doesn’t work properly and keeps redirecting user to same page in place of home page.

From <https://support.microsoft.com/en-au/help/4496222/portal-capabilities-for-microsoft-dynamics-365-version-9-1-4-29-releas

Authentication/Registration/LoginButtonAuthenticationType If a portal only requires a single external identity provider, this allows the Sign-In link on the primary navigation to link directly to the sign-in page of that external identity provider
Authentication/Registration/OpenRegistrationEnabled A true or false value. If set to true allows any anonymous visitor to the portal to create a new user account.
Profile/ShowMarketingOptionsPanel A true or false value. If set to false, it hides the marketing preferences area in the contact profile

Profile page

Profile page is a custom aspx page which displays Contact entity’s “Profile Web Form” on the profile page. If you want to change the fields on this page, you must modify “Profile Web Form” on the contact entity. In addition of fields on the “Profile Web Form”, the profile pages show Marketing Preferences. Marketing Preferences can be enabled or disabled by using Profile/ShowMarketingOptionsPanel site setting.

Customising Profile Page

Profile page is a special page which you cannot customise using Entity forms and Metadata. An ordinary web page like a case form in portal rely on “Entity Forms”. The case of Profile page is different. The Profile page does not rely on Entity forms, but it re-writes the request to “Profile.aspx”. So, in case if you want to change the form behavior or add validation to fields on the screen, you will need to come with a different approach.

Scenario:

  1. The mobile phone on the profile should be in the format xxxx-xxx-xxx
  2. The profile page should be editable if the contact has NO active cases
  3. The profile page should be read-only if the contact has active cases

Implementation:

  1. Deactivate the existing Profile web page
  2. Create a new Entity Form called “Editable Profile Entity Form” interfacing “Profile Web Form” in Edit mode
  3. Create a new Entity Form called “Read-only Profile Entity Form” interfacing “Profile Web Form” in Read-only mode
  4. Create a new Web Template called “Profile Web Template” – We will talk about this template in details later
  5. Create a new Page Template named “Profile”
  6. Open the Profile Page template and set the following values
    1. Type=Web Template
    2. Entity Name= Web Page (adx_webpage)
    3. Web Template = Profile Web Template (created in the step 4)
  7. Create a new Web Page named “Profile”.
    1. The profile page’s partial URL must be “Profile”
    2. Set the parent page to “Home”.
    3. Set the Page Template to the Profile Template (created on the step 6)
  8. Open the Profile Web Template and add the following liquid template:

For adding the breadcramp, add the following liquid

{% block breadcrumbs %}
{% include 'Breadcrumbs' %}
{% endblock %}

For adding the title to the page, add the following liquid

{% block title %}
{% include 'Page Header' %}
{% endblock %}

For adding side navigation, add the following liquid

{% block aside %}
{%include "side_navigation_portal" %}
{% endblock %}

The main form will be in the Main Block

<div class="col-sm-8 col-lg-8 left-column">
{% block main %}
{% endblock %}
</div>

Now the below code is the magic behind meeting the requirement:

Use FetchXML to check if there are any active cases related to the contact:

{% fetchxml my_query %}
<fetch version="1.0" output-format="xml-platform" mapping="logical"returntotalrecordcount="true" distinct="false">
<entity name="incident">
<attribute name="name" />
<attribute name="status" />
<attribute name="createdon" />
<filter type="and">
<condition attribute="parent_contact" operator="eq" value="{{User.Id}}" />
<condition attribute="status" operator="eq" value=0 />
</filter>
</entity>
</fetch>
{% endfetchxml %}
  1.  The FetchXML block must be enclosed in the {%fetchxml my_query%} where my_query is holding the result of the query
  2. If you want to check the total records returned by the query, you must use returntotalrecordcount=true otherwise you will always get -1 in count of your records
  3. The total count of result of the query will be accessed by my_query.results.total_record_count

The final piece of code in the page template will be the following

{% if my_query.results.total_record_count > 0 %}
{% entityform name: 'Read only - Profile Entity Form' %}
{% else %}
{% entityform name: 'Editable - Profile Entity Form' %}
{% endif %}

With this simple if/else statement you can control the behavior of the profile page.

Validating Mobile phone

Since we are using Entity Forms to show profile information, we can use Entity Form Metadata to control behavior of fields on the form. To ensure our mobile number is always in xxxx-xxx-xxx format, do the following:

  1. Open Editable – Profile Entity Form
  2. From related records, go to “Entity Form Metadata”
  3. Add a new metadata record with the following properties:
  4. Type: Attribute
  5. Attribute Logical Name:  Mobile Phone (mobilephone)
  6. Find Validation section down the form and add Validation Error Message
  7. Use the ^\d{4}\s\d{3}\s\d{3}$ as regular expression to ensure the mobile phone is in the xxxx-xxx-xxx format
  8. You can tick the “Is Field Required” to make the field required on the screen

 

Converting Dynamics’s Geolocation To SQL Geolocation Using Microsoft Flow And Azure Function

Background

One of the awesome features of the Azure Search service is the ability to search information based on location. Azure Search processes, filters, and displays geographic locations. It enables users to explore data based on the proximity of a search result to a physical location. This feature is powered by SQL Server Geolocation data type. Since SQL Server 2008, developers are able store geospatial data in SQL server using Geolocation fields. Geolocation fields allow querying data with location based queries. To facilitate the Azure Search service to search within CRM accounts and contact, I had to pushed my account and contact searchable information to SQL server hosted in Azure. To copy information from Dynamics to Azure SQL server, I used Microsoft flow. Everything worked good except, copying CRM longitude and Latitude to SQL Server.

The problem

The problem with copying longitude and latitude to SQL server Geolocation field is the compatibility. When you try to insert longitude and latitude fields to Geolocation you encounter casting error.

The solution

  1. The solution I used to tackle this problem is making use of Azure Function and converting Longitude and Latitude to Geolocation type in the Azure function and return the response before the Insert action in the flow. See the below steps:
  2. Step 1 is self-explanatory.
  3. The step “CC Contact” extracts the Contact name (or any lookup name property) from a lookup.
  4. The “Http” step, calls the Azure Function to converts the CRM longitude and Latitude to SQL Geolocation field
  5. The “Insert Row” step, inserts our data to SQL server row.
Microsoft Flow
Microsoft Flow

The Azure Function

The Azure function is a very simple function. You will need to import Microsoft.SqlServer.Types Nuget package and use the below code:
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();  
       Coordinates data = JsonConvert.DeserializeObject<Coordinates>(requestBody);  
       SqlGeography point = data.GetGeography();  
       return ( ActionResult ) new OkObjectResult ( $"{point}" );  
 public class Coordinates  
   {  
     public double Longitude { get; set; }  
     public double Latitude { get; set; }  
     public SqlGeography GetGeography ( )  
     {        
       try  
       {  
         return SqlGeography. Point ( Latitude , Longitude , 4326 );  
       }  
       catch ( Exception ex )  
       {  
 // Log ex and handle exception  
         throw ex;  
       }  
     }  
   } 

 

 

Implementing Enterprise Search In Power Platform

Photo by Anthony Martino on Unsplash
Photo by Anthony Martino on Unsplash
Providing good search capabilities is a key feature in modern business applications to support usability and end user satisfaction. We have seen how the search capabilities of the Dynamics platform has evolved from providing “Quick Search” and “Advanced File” to “Relevance Search”. The goal of the platform search features has been to support users to find the relevant information they need in the quickest and easiest form. These search features are out-of-the-box and easy to enable/configure/use. As the platform progresses to offer richer features to users and enable them to search better, the demand for richer and better search techniques grow, and we see instances where the platform capabilities cannot meet user demands with its out-of-the-box capabilities. Before going further about advanced search scenarios, you can read about the platform out-of-the-box search capabilities in this official documentation. In this article I share why we may decide to implement a search solution of our Dynamics solution using Azure Search Service.
In enterprise implementations, business applications are not the only systems used in the organization. We often see call center agents and sales representatives need to obtain their required information from various systems to service customers. Searching users in every system is a cumbersome job which may cause setbacks in end-user adaption. Integrating Dynamics with Azure search offers consolidation of search operations in one specialized search service with ability to connecting to various data sources and apply modern search techniques to find the most relevant data. A practical example of this scenario can be seen in one my recent experiences where the organization users had to search for user information in CRM, SharePoint, Sybase and a pool of CSV files.

Customized Search experience

To facilitate more user adoption, using customized search techniques are highly favorable. In all modern search engines, we see use of “Auto complete”, “Suggestions” and “highlighting” features which can be added to the Dynamics solutions search experience. Displaying search results by support of “Document Preview”, “Document Opening in a customized containers”, “Facets”, “Filter” and “Sorting” are examples that enhance your Dynamics solution’s capabilities.

Customized Search Behavior

The true power of search is demonstrated with different pieces of information are linked together to make sense of a bigger picture. Extracting words and sentences from documents including images and pdf files, extracting key phrases, people names, location names, languages and other custom entities with the help of AI is another unique feature that you can add to your Dynamics’s search capabilities. Another amazing search capability you can have in your Dynamics implementation is the ability to search based on geolocation information, i.e. you can search for all your partner network from CRM or get the location of your field service force. The beauty of implementing your own enterprise search lies in the fact that you can search information in your data stores and link them using AI to generate knowledge and better insight to your data.

Customized Search Result

Another need for customized search in your Dynamics solution to the ability to refine your search result profile. When you use AI in your search, the system gives you the power to see how relevant search results are to your search keywords. And by knowing this you can refine your search profiles to generate a different result for the same keywords. This way you train the AI engine to work better for you and enable users to get more accurate search results.
Architecture

Dynamics integration with Azure Search service can be integrated in the following pattern:

 

  1. Integration through web resources: These web resources will host a web application acting as a client to the search service. The web resource can be a HTML file or an iFrame hosted on forms. The important point in this approach to ensure cross-origin settings in the client application and writing your html in a secure way and according to the best practices.
  2. Integration through custom power platform controls. You may build your own custom control which sends REST requests to the Azure Search and display results by consumes REST responses. The custom control can call Azure Search services using Actions or direct REST calls to Azure Service.
  3. Azure Search works based on indexes and your first step is to push your CRM searchable data to Azure Search indexes. This can be done using Microsoft Flow, Microsoft App Logics, custom solutions or Azure Data Factory. I have used all these tools in my implementations, and you can opt to any of these tools based on your requirements.
  4. Once the data is in your data store, you can create your indexes in the Azure Search. You can go for separate indexes for each data source or combine multiple data sources in one index. Each approach has its own requirements which will need to be met either in your client web application or a separate azure compute resource. Once indexing is done, you can make use Azure Search Rest API directly or using Azure API management to expose your search service to your Dynamics solution.
Summing these all up, you see as business application products get more sophisticated and organizations move from data to big data, engineers now must look for innovative approaches to implement Dynamics Solutions. Microsoft Azure along with Dynamics platform offers necessary tools to solution architects to design such solutions.

Virtual Entities 0x80040203 Invalid Argument Error

I stumbled upon this issue after creating a custom virtual entity data provider. Ivan Ficko has a great tutorial on this here.

The subgrid displayed records perfectly fine in the old web client, but in UCI i received the below error message “0x80040203 Invalid Argument”. After some search and only finding a single post regarding this with no answers, i decided to take matters into my own hands! Digging through my  browsers console i managed to find additional information regarding this error. Inspecting the  exception, i found the message “entity name is invalid”.

Continue reading

Custom views on lookup wont work without name field

Quick tip here, when setting a custom view on a lookup in the form designer:

pic1

Always ensure that the name attribute is on the view too, even if it won’t be displayed.

pic2

I had noticed that my search results were not working at all when I had typed in the lookup field. After an hour of troubleshooting, I added the name field onto the view and voila! Search and the control, in general, started behaving.