We walk you through how to set up a Dataverse Search API and connect it to Canvas apps in this step-by-step blog.
Recently, I had a client interested in building a Power App Canvas app for mobile devices that would take some of the more routine aspects of their Dynamics sales process and provide their salespeople with an easier way to do some of the tasks associated with capturing customer information.
However, this particular client’s users didn’t like using Dynamics, and they wanted to streamline this process for them without needing to use the Dynamics mobile app. Canvas apps to the rescue!
One Search to Rule Them All – Using Dataverse Search
When I started this project, I admittedly didn’t have a deep knowledge of Dynamics. As a part of the app, the client wanted a single search interface whereby users could search across Contacts, Accounts, Leads and Opportunities, and have those presented in one pane of glass. My immediate thought was to simply use an input control and a gallery to display the results, but with Galleries, they really want a single data schema and data source in order to display information.
With these tables, the data schema was decidedly different across each of them. After doing some digging, I realized my best option was to use the Dataverse Search (formally Dynamics Relevance) API. With this being my first real exposure to that API, I immediately went to see if anybody else has ever done this type of work before, and I came across this blog.
This particular solution relied on using a Canvas app and then calling a Power Automate flow to retrieve the results from the Dataverse Search API. While it certainly performed the job, what I also found was the lag between clicking the button in the Canvas and the Power Automate returning results would be unacceptable for my client. So, I figured, why not just let Power Apps query it directly?
Please Mr. Postman
My first step into understanding how to query the Search API and return the results I needed was to read the documentation out on Microsoft’s site. This information provided me with the necessary syntax to query the API with a POST command. From here, I knew I wanted to test it to make sure I could get results returned.
This is where Postman comes into play. Microsoft also provides a tutorial on how to connect to the Dataverse Search API using Postman, especially around authenticating to service, which I found invaluable. By following that tutorial, you’ll be ready to try out a simple query.
In my case, I had some test data with my name in Dynamics, so I did a search on it. If everything is working properly, you should see a response like the one below:
{
“search”: “Jo Karnes”
}
In that search, I simply tested it with a search term query, in this case “Jo Karnes”. This particular search would scan across all of the Dynamics tables I configured to search through Dataverse Search (see here for instructions on how to configure tables for this), but the requirement for this app was to only return results across four specific tables. We need to specify those tables in the Body of our request. We can do that by defining those entities as shown below:
{
“search”: “Jo Karnes”,
“entities”: [“account”, “contact”, “lead”, “opportunity”]
}
Now, my results should only return results from those four tables, and we’ve successfully tested a search query to the API. Now we need to get our Canvas app to do the same thing.
Creating Custom Connectors for Power Apps
Did you know that Dynamics licensing allows you to create Custom Connectors for Power Apps? Power Apps licensing can be quite confusing sometimes, but if you have certain Dynamics licensing, you can use custom connectors (unlike the Power Apps license included in Office 365). The specific licenses you’ll want to have for this are either a PowerApps per App or per User license or one of these Dynamics Licenses:
Let’s Configure Authentication First
We’re ready to create the custom connector our Power App will use to connect to the Dataverse Search API. But first things first, we need to add an Azure AD app registration for the API. This will allow us to use delegated permissions to Dynamics so the logged-in user in Power Apps can pass their credentials from Power Apps to the API seamlessly.
Microsoft has provided a guide for creating this app registration here. Once you’ve created the App registration, save the ClientID, DirectoryID and the Client Secret to Notepad, we’ll need these values when creating the custom connector.
You’ll also want to get the endpoint for your Dynamics environment. This will be in this format: https://<environment>.crm.dynamics.com/.
You can find the exact endpoint of your environment by going to https://admin.powerplatform.microsoft.com/, clicking on the environment where you want to search, and you’ll see the Environment URL in the details:
Now that we have all of this information, it’s time to create our custom connector. Head over to make.powerapps.com, click on Data, and then click on ‘Custom Connectors’.
From here, we’re going to want to ‘Create from Blank’.
On the General tab, you can define an icon, and a description, but the most important thing on this screen is the host url. This will be the environment name we captured above. When it’s entered in, click on the Security tab.
For Security, we have a few things to define. First, change the authentication type to “OATH 2.0”, then select the Azure Active Directory Identity provider. From here, populate the ClientID, Client Secret and Resource URL. The Client ID and Secret can form our Azure AD app registration, and the Resource URL is the Environment path, but with https://. When complete, click on the Definition tab.
When we get to Definition, the first thing we want to do is to create a new Action. You can name this anything you want, I just kept mine as RelevanceSearch for the Summary, Description and Operation ID. Next, we’ll want to import a sample for the Request. From here we can define what a typical request would look like. For the Verb, choose POST, for the URL, the format of the URL will be: https://<environment url>/api/search/v1.0/query.
For the Headers, we need to add the following Headers and values into the Headers box:
Content-Type application/json
Accept application/json
OData-Version 4.0
OData-MaxVersion 4.0
And finally, for the Body, we’ll pass in an example JSON request. For this sample, I’ve included the “entities” definition, as our requirements was to limit our results to just those four tables:
{ “search”: “Jo Karnes”, “entities”: [“account”, “contact”, “lead”, “opportunity”]}
When finished, click on “Import”.
Next, we’ll want to define the response. This is the schema Power Apps expects to get back from the API. The easiest way to get the return schema is to copy and paste it from a response in Postman. Just copy the entire response and paste it into the “Import from Sample” section for the custom connector.
NOTE: For whatever sample response you use from postman, make sure to include results from all entities you defined. This way, if you have custom fields that should be returned by these entities, they’re included in the response and PowerApps will recognize them.
Once you’ve imported the Response, you may get a validation error. You can safely ignore this, I haven’t seen any impact when returning data.
Finally, you can choose to test the connector, of you can just click on “Create connector” to save the connector.
NOTE: When you save the connector, on the Security tab, you will see the Redirect URL that has been defined for the Connector. Verify that the same Redirect URL is defined on the Azure AD App Registration, or you may encounter an authentication error.
Let’s Make an App
Now that we’ve defined our custom connector, we can create a Power App to use to search. Our first step is to create a blank Canvas app and add the custom connector.
Next, add two controls. The first is a Text Input box and the second is a Blank Vertical Gallery. See the example below.
Now, we need to modify the “OnChange” value of the Text Input box. This way, any time we type in a search, it will communicate with the API to get our results (NOTE: the “OnChange” value will only execute when the Text Input box loses focus. It might be helpful to add an icon people can “select,” which will then move focus off of the Input box). We’re going to set a variable called varRelSearchResults, which will pass the Text from our Text Input box to the API and collect all of the results into a variable.
Change the “Items” property of the gallery to varRelSearchResults. Now you can add any controls you want to display on to the template of the Gallery to show your results.
Conclusion
I hope this is something you may find useful, especially if you have want to be able to connect to custom API’s for Dynamics.