Monthly Archives: February 2019

Unconventional intro to the Canvas Apps

Canvas Apps tutorials / samples are often using the same approach. They will show you how to create an application that is relying on the Gallery and Form controls and walk you through the basic usage of those controls. Here is an example:

https://docs.microsoft.com/en-us/powerapps/maker/canvas-apps/customize-layout-sharepoint

Those are very powerful controls and you can achieve a lot just by using them. And there is certainly a lot to discuss. But, after playing with Canvas apps for some time, I’m now realizing that it would be really helpful from the beginning if my initiation into the Canvas apps happened differently.

As if, if I saw then, even though it’s not the main use case, that it’s possible to do things completely outside of the realm of those three controls:

image

As is perfectly demonstrated in this youtube video:

https://www.youtube.com/watch?v=0-ZWqs_emQA

Imagine this futuristic scenario: you had never driven a car, and, then, you got one which has an autopilot, so you don’t even need to know how to drive it – you just need to tell it where to take you. You are happily using the car, it’s taking you where you need to go, but, then, you start noticing that there are cars around which are doing some fun things.. They can go faster or slower, they can really maneuver, and there are people in them apparently doing something when all you can think of doing is just sitting in the chair. Oh, wait.. can these cars actually do more somehow? Did you miss something? What happens if you turn off the autopilot?

This is the kind of feeling I got about the Canvas apps some time ago. The tipping point was when Scott Durow made a post on his PowerFlappy application https://community.dynamics.com/crm/b/develop1/archive/2018/09/29/powerflappy-canvas-app-power-apps-for-c-and-javascript-developers.. I mean, I can’t imagine anyone REALLY creating this kind of games in PowerApps other than for fun – it’s not so much a gaming platform. But it’s the ability to do more than I thought was possible that made me thinking.

I sort of had to rethink my understanding of the canvas apps. It’s probably still not quite complete, but there is one thing I’m pretty certain about – there should be an alternative learning route, which is “from bottom up”.

That said, all the information is already available there, it’s more a question of looking at it in different order.

Let’s see, then, if I can map out that alternative route by asking some questions and providing relevant links for the answers.

1. What are some of the main Canvas Apps concepts?

  • There is no classic coding – don’t even try to reuse your .NET development skills. And no, code libraries cannot be created in the Canvas Apps.
  • There is a set of connectors you can work with. Connectors provide tables and actions
  • There is a set of controls you can use on the screens. Among other controls, there is a timer control, a text box, a label, and more.
  • We need to think “functions” (more specifically, always think which function you can use from those available)
  • In the function calls, you can only set values for variables and collections, but not for the controls. BUT you can source control values from variables.

 

2. What are some of the operations you can do with external data?

You can use a few functions, such as Patch or Remove, to manipulate data in the datasource.

You can also use functions like Filter, Lookup, or Search to query data from the datasource.

You can do it all wherever you want in the Canvas App as long as you can call a function in that place.

3. Where can you call a function?

All controls have properties and events. You can use functions to set the properties or to respond to the events. You can make multiple functions calls there, and you need to get used to the syntax, but still:

image

4. How can you use variables?

There are global and local variables. We can use variables in the function calls; we can use variables to set control property values; and we can set variable values anywhere a function call is possible:

image

Keep in mind we cannot directly set control property value just like we would set a variable value in the function call. So, the way it works is:

-We would instruct our app to source control property value from a variable

image

And, then, we would use Set or UpdateContext call to update that variable somewhere else. Update value will automatically apply to the control, too.

5. How do you navigate between various screens?

That’s what Back and Navigate functions are for

6. Do you have to use Gallery or Form controls to create a Canvas App?

Absolutely not. You will need a screen for sure, but which controls you put on that screen is totally up to you. You want to use a Gallery control since there is a list of records you need to display there? Great. You don’t need to display a list, so there is no need to the Gallery control? That works, too. You don’t even have to connect to an external datasource for that matter if the app is only supposed to do some things locally (for example, measure conversions between different measurement systems?)

7. So what am I trying to say here?

Compared to many other folks, I’ve only done very little “development” with Canvas Apps so far, and, really, I’ve started once it turned out we can embed those apps into Dynamics forms. But, when I first tried to do a Canvas app, I was thinking in terms of Gallery and Form controls I mentioned at the beginning. They are very useful, indeed, but they are imposing certain structure on your application, and I doubt I’d be able to do what I wanted to do if I just stuck to them. For example, my recent Photo ID prototype is not using either of those controls, and, yet, I can still manipulate the data easily.

So, really, if you are just starting to work with the canvas apps, make an effort to look beyond those basic samples and you’ll likely see that there is much more you can do (even if it still all feels a bit foreign to somebody more accustomed to the classic .NET/JavaScript development)

Why do you see what you see when you log into Dynamics through the root instance url?

The answer is not “because it is what it is”! There is certainly more to it.

I just created a new user and gave it a couple of roles:

image

This use is supposed to see Customer Service Hub (Unified Interface) and Customer Service (Web)applications.

Plus there is that default web application which is normally called “Dynamics 365 – custom” and which is usually available to everyone.

So, I logged in as that new user, and, as expected, here is what I saw:

image

Can I make it so that my new user lands directly in his/her application instead?

Well…Let’s try something. Let’s go to https://admin.powerplatform.microsoft.com as an administrator, and, under this particular environment Settings->Behavior let’s set classic mode to “Off”:

image

Then let’s try logging in to Dynamics under that test account again. You’ll be looking at a different screen – Dynamics is not suggesting classic mode by default anymore:

image

What if we disabled those two web applications on the screenshot above? It’s a little tricky since we can’t disable “Dynamics 365 – custom” application for any particular role – we can only disable it for all roles:

image

Anyway, let’s do it (using the admin user of course).

And let’s also remove permissions from the “Customer Service App Access” role for the “Customer Service” web application.

This is where some magic starts happening.. Our test user has access to only one application, which is Customer Service Hub application. And, that’s the application which opens up right away when/if I navigate to the root instance url:

image

Just for the sake of experiment – if I give my test user access to the Sales Hub application, here is what the user will see when he tries opening root url for the instance:

image

So, to recap.. Here is how it seems to work:

image

Might not be an eye opener, but might still be good to know if you are trying to set up default application for those users who will only have access to one app.

Implementing photo id functionality in Dynamics with the embedded canvas app

This post is nothing but a relatively boring technical walkthrough.. Which is as promised in the previous (hopefully not so boring) teaser post

Before you continue with this one, you may want to do some reading on how embedded canvas apps can be added to the model driven apps.

I would suggest a few links if you are just starting to look into it:

 

Either way, there are 3 key concepts involved in this prototype:

1. Captured images are stored directly in Dynamics in a multiline text field

You might say this is not optimal, and I would agree. But that takes away the need to figure out where to store those images, and, at the same time, allows me to display such images in the Word Template (see this link btw)

Here is how the field is defined:

image

What if I wanted to store file data somewhere else? Technically, the problem is not so much where to store it, but whether I can easily use those stored images in the Word Template (or in the SSRS report), since, in the end, I’ll need to produce a printer-ready “photo id”. Either way, at this point I did not want to mess with Sharepoint (have a look here: https://blogs.perficient.com/2018/10/08/store-powerapp-camera-photos-in-sharepoint-or-onedrive/ ), so I figured I’d take the easy route.

2. There is a Word Template that’s using that field

image

That’s pretty straightforward – page size is set to match standard ID width/height, there are no margins, and that picture content control is linked to the new_imagedata field

3. There is a Canvas application that’s embedded into the contact form

I am assuming you know the basics of creating an embedded canvas app by this moment (if not, have a look at those links above), so I’ll spare you from those details.

Here is how the app looks like:

image

All initialization happens in the Timer1.OnTimerEnd. This is where ContextPicture is initially set from the new_ImageData field, and, also, where SelectedContactId is initialized with the ContactId:

image

Camera control is set up with the stream rate – this is to use a button to capture images (rather than to do it through Camera OnSelect):

image

PictureButton is there, but it’s right under the “Open Camera” button (don’t be confused with how it looks like on the screenshot) – this button will set ContextPicture from the camera stream, and it will hide the Camera:

image

OpenCamera button will display the camera:

image

Image1 will be displaying ContextPicture:

image

Finally, depending on whether the camera is visible or not, Image1 control and those 3 buttons will change their visibility as required. For example:

image

That’s about it. In other words:

  • When the app is loaded, Camera control will be hidden initially
  • So Image1 control will be visible
  • Once OnTimerEnd happens (1 second after load), it will initialize the image and contactId, so Image1 control will be displaying current image at that point
  • Once the user decides to take a picture, they’ll click “Open Camera” button to bring up the Camera
  • Once the camera is there, “Picture Button” and “Save Button” will be visible and “Open Camera” button will be hidden
  • Once the user clicks “Take a Picture” button, new image will be displayed in the Image1 control. Image1 control will be visible and Camera2 will be hidden
  • Finally, the user might decide to save that image, at which point the image will be sent back to Dynamics through the Contacts dataset

 

How does it work with the “Save” button, though? Here is a screenshot:

image

As I mentioned in the other post (see those links above), when working with the Base64 images in the Word Templates, I have to remove that data:image.. prefix. That’s exactly what Substitute function is for. And, then, there is a Patch function that’s updating a record in the Contacts data source. I have added that one to my canvas app separately so I’d be able to update the contact record.

And that’s about it.. Once the picture has been taken, I just need to download the template:

image

Then open the document and send it to printer.. Here we go:

image

One last bit – you may want to consider setting Camera->DisplayMode property depending on whether the Camera is visible or not. Otherwise, the camera just goes on and stays activated till the app is closed:

image

 

 

Tricky Base64 Images in Dynamics reports/word templates

 

I think at least half of my posts should start with “I was pulling my hair out, and then..”

Image result for pulling my hair

(Like the picture? Here is the source)

If you ever tried creating a printer-ready screen in Dynamics that would, among other things, display a Base64 image stored in a field, you might know the feeling.

There are two possible options out of the box, it seems:

  • We can use an SSRS report
  • We can use a Word Template

However, here is what I was observing when trying to download a word template that would display my Base64 image:

image

And, in the SSRS, I was observing different things, but, in the end, no images would be displayed (I think I’ve also seen “Errors” in that column, but I could not reproduce those now):

image

Here is the thing, though. I was using a PowerApp to create those images through a Camera control, so, if you look at the screenshots above, you’ll notice how there is a prefix added to the Base64 string which identifies the type of that string: data:image/gif;base64

I did not know that was the problem – for that matter I did not even think twice about that part.

Until I ran (not even sure how – somewhat by luck) into this awesome thread on the community forums where Wouter Madou provided all the explanations needed to make this work:

https://community.dynamics.com/crm/f/117/t/234072

Short version – just remove that data:image/gif;base64 from the string. Picture content control in the templates does not seem to understand that prefix.

That took care of the Word templates, though I am still unable to display those images in the SSRS report. Well, I can actually display them in the Visual Studio when previewing the report, but not directly in Dynamics for some reason.

On the flip side, I also had a web resource on the form that would be displaying the same image in an iframe. That web resource was using the technique described here to display the image, and this is where the prefix is, actually, required (so, in other words, once I’ve removed the prefix, my web resource could not display the image anymore). That’s the lesser evil, though, since I can just add the prefix through javascript.

Well, that’s enough of hair pulling for now, and I can get back to wrapping up my PhotoID prototype – will be using a Word Template for ID printing.

Camera capabilities, or how to add photo id capturing to a contact screen in Dynamics

 

It would be a challenge these days to find a single person who does not have any picture id at all. Driver licences, health cards, passports, access cards.. Those id-s are everywhere – I probably have to carry at least 2-3 every day, and there are a few more I have to carry occasionally.

All these id-s are always linked to the clients/contacts/employees/citizens – basically, to the individuals. So it’s not, really, such a far-fetched scenario for an organization (private or government) to come in and say: we have Dynamics, we have records of all those individuals we are working with stored in Dynamics,  can we use Dynamics to issue photo-ids?

The answer is probably “yes”, but this functionality does not necessarily come right out of the box.

There are two distinct scenarios:

  • We can use external camera software and just integrate it with Dynamics to some extent
  • We can use native camera capabilities in Dynamics/Power Apps

 

The first scenario has always been available, and there is probably a whole range of possible solutions.

The second scenario has become increasingly available in the last few years – we actually have different options now, and I tried to summarize them in the table below:

image

SDK scenario does not necessarily fall into the “native capabilities” category. But, technically, one might create an HTML5 snippet, embed it in the model-drive application form, and use the camera that way. Or, possibly, one might create an ActiveX control. Or a custom mobile application.

The other 3 are, really, “out of the box” though each of them comes with a few caveats.

Entity images (https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/image-attributes) won’t really work for the “photo id” scenario. There is  size limitation (144×144) which makes them good for the small avatar-type of images, but they are not good at all for the id-s. However, there is nothing you need to do to make them work.. Just open Dynamics on your phone, open the contact record you want to update the image for, click on the image, and the camera will start.

The next in line is Xrm.Device.captureImage (https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/clientapi/reference/xrm-device/captureimage) This one would work fine if it were available in the web client, and it’s not.

What about the Power App approach? Actually, it works just fine. There is that limitation on the image resolution, but it might be ok for the photo ID applications.

For example, here is the kind of photo id capturing screen we might have in Dynamics if we used a Canvas App:

Not that bad for a couple of hours of work? Well, of course ignoring a day or two it took to figure out how to make it work:) And I will explain how this screen was implemented in the next post..

Canvas Apps: a context variable vs a global variable – who wins?

Yesterday, I was scratching my head trying to figure out why a value I stored in a variable was not displayed correctly in the text box.

Turned out I was doing this kind of thing:

image

I was setting a context variable in one place, and I was setting a global variable in another. Both variables had the same name. Then I was using that variable for a text control:

image

Interesting, by the way, that context and global variables can have the same name without causing an error. But, if you were to guess, which value do you think would be displayed in the text control in this scenario?

The answer is – it’s the context variable that’ll be displayed there.

Why? Quite frankly, I may not be able to explain what’s happening behind the scene in the Canvas Apps.. Would be great if we could debug them somehowSmile But the best intuitive explanation seems to be that context variables are “closer” to the place than global ones, so I’ll just stick to that.

The end result, though, is that this whole scenario is not extremely obvious. There are no warnings, there are no errors.. everything is supposed to work, but it does not, and you are getting a wrong value (or, worse, an empty value) from a variable.

Well, if you find yourself observing those symptoms, check the scope of your variables and make sure you are not mixing global and context scopes. It might be exactly the problem.

Office365 authentication for the SDK & XrmToolBox

 

One thing about Dynamics which I love and hate at the same time is that I’m constantly getting challenged. In the old days we had an on-premise system where the updates were rare, where we had access to the database, and where, to a certain extent, we were in control. At least it sometimes felt like this (and it’s such a nice memory, so let’s just pretend we never had to deal with the Generic SQL errors)

Things have changed, though, and Dynamics is now part of the huge online ecosystem which goes far beyond Dynamics or PowerPlatform. There are different concepts, principles, applications, and technologies involved there, and it’s almost impossible to know all of them.

However, and this is where that love-hate cliché comes into play, if you are working with Dynamics these days, you are almost inevitably getting exposed to the other parts of this ecosystem.

Anyway, if you think this post was too abstract so far, here is how my morning started today:

  • XrmToolBox was not connecting to the Dynamics instances
  • Deployment automation scripts were throwing errors

And, yet, Dynamics was working just fine in the browser or when we tried PluginRegistration tool

Besides, XrmToolBox and some console applications (which were using SDK) were connecting just fine to the Dynamics instance hosted in another tenant.

Have I mentioned that it was all working yesterday?

Having done a few more tests, we decided that it’s probably Office365 authentication that was not working anymore.

https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/xrm-tooling/use-connection-strings-xrm-tooling-connect

image

But why? Of course there were voices claiming Microsoft did a silent update..

This is where I should probably clarify that it is a relatively big environment, and not everyone working with Dynamics would have global administrator permissions. In other words, we don’t always know what’s happening in this tenant outside of Dynamics.

Turns out there are settings in the Azure Active directory we did not even know about. They were updated the night before by the tenant admins, and that affected our ability to use Office365 authentication.

Here is another link:

https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/block-legacy-authentication

And here is a screenshot:

image

Yes, it turns out that it’s possible to disable Office365 authentication through the conditional access policies in the Azure Active Directory.

Once required exclusions were added there, everything went back to normal and we had XrmToolBox and other tools are working now.

And the takeaway? Well, just keep in mind that Office365 authentication falls into the category of legacy authentication methods, and, so, it can be disabled through the conditional access policies. So if you want it to work for the time being, and if you have conditional access policies set up as per the link above, you’ll need to make sure those policies implement all required exclusions.

PS. Why did we have to use Office365 authentication in the first place? Normally, we have multi-factor authentication enabled for the users. So we were looking at how to bypass the MFA for our tools(would not be very convenient if we had to go over the MFA process every time we wanted to prepare a nightly build, for example), and it turned out Office365 authentication ignores MFA. Which is, probably, one reason it is considered “legacy” from the policy standpoint.

Alphabetical filtering: the same but different

When you are working with the grids in Dynamics, the last line shows up as a list of letters from A to Z, so you can click one of the letters and that will quickly apply a filter to the grid.

What kind of filter, though?

After some digging around earlier today, it turned out the answer depends on whether you are using Unified Interface or whether you are using Classic Interface.

Classic interface is filtering by the first ordered column

image

Unified Interface is filtering by the first (ordered or not) column.. or so I thought until Feb 15

image

What you see below is my original interpretation (things have changed – keep reading):

This means the behavior is slightly different between those two interfaces, although, it’s probably not such a big issue. Unless you are used to the way alphabetical filtering used to work before, you just need to know how it works in the Unified Interface since that’s the one to stay.

Besides, it may actually be a more straightforward approach. When sorting is applied to multiple columns in the grid, alphabetical filtering becomes a bit confusing since it only applies to the first sorted column, so it’s just more nuances for the users to keep in mind.

Added on Feb 15: but what about the screenshot below?

image

There is no First or Last name in the view, and, yet, some record does show up there once I’ve selected “F” for the filter. The only explanation is that the contact has this kind of full name:

image

It seems what’s really happening is that Unified Interface applies filtering on the entity primary field, even there is no column for that field in the grid.

Well.. Wondering if there is still more to it.

HTTP Connector Support for Data Loss Prevention Policies

With the recent update, HTTP Connector Support has been implemented so we can add HTTP Connector to the DLP policies now. This is different from HTTP with Azure AD, btw, and this may affect you if you are using HTTP Actions in the flows.

For all the finer details, have a look at the post below:

https://flow.microsoft.com/en-us/blog/introducing-http-and-custom-connector-support-for-data-loss-prevention-policies/

Here is just a summary of what it is about:

HTTP Connector Support

The HTTP actions and triggers up to this point have not been considered connectors. Due to customer feedback, we decided to go ahead and re-categorize those items so they could be subject to DLP to offer customers a greater level of flexibility and control over their environments.

We have added the option to support these triggers/actions when a policy is created or modified using the PowerShell cmdlets or given Flow Templates. More specifically, you can now manage:

  • HTTP (and HTTP + Swagger)

  • HTTP Webhook

  • HTTP Request

Activating or deactivating somebody else’s workflow when you are not a System Admin

 

We were investigating the option of using non-interactive user account for automated deployment, and it was all going great until we ran into the error below while importing the solution:

“This process cannot be activated or deactivated by someone who is not its owner. If you contact support, please provide the technical details.”

image

Actually, I remember having seen this error before. As in, a few years ago it would be normal to see it. Then it went away somehow, so, normally acting as a System Administrator, I have not seen it for a while. Apparently, what we saw this time had something to do with the permissions granted to our non-interactive account – it was set up as System Customizer.

So, just in case you run into it and to save you some time, here is the permission you’ll need to add to the System Customizer role in this scenario – took us a bit of testing to figure it out:

clip_image002

(I also noticed that it may take a minute to “apply” this “Act on Behalf of Another User” permission.. then it all starts to work)