Monthly Archives: January 2019

Power Apps Components – let’s experiment!

 

Well, if there is an experimental feature, let’s experiment!

image

https://docs.microsoft.com/en-us/powerapps/maker/canvas-apps/create-component

Having read through that page, I thought “wow.. can I create some kind of confirmation dialog using those components?” (Hint: if you are wondering how that worked out, scroll down to the bottom to see the recording)

That was a crazy idea, I can readily admit it now, but it did not seem that crazy at the time.

Here is how it went..

First of all, you need to take a few steps:

  • It is an experimental feature, so you have to be working in the “Preview” region (this feature won’t be available in your regular region)
  • And, then, you need to enable components in the app properties (under the “preview” settings)

If you look at the link above, you’ll see how it’s all supposed to be set up, so here I just wanted to emphasize those two steps.

Once I had components enabled for the application, I figured I’d do something like this:

  • There would be a screen
  • There would be a button on that screen
  • There would be a component with a couple of buttons (Cancel/Ok)
  • There would be a message label in that component
  • And the component would be hidden by default
  • So, when the users clicks that button on the screen, I’d like the component to show up and display a custom message so that the user could choose “OK” or “Cancel”, and, then, something else would happen on the main screen.

 

Would not that be cool? I could use the same component for different screen to confirm various delete actions, for example..

It did not take long to realize, though, that components do not share context variables with the parent screen, they do not share global variables with the rest of the application, and they don’t have any kind of “OnSelect”, “OnDisplay”, “OnVisible” events. They are encapsulated in their own context which seems to be very different from what it normally looks like.

Actually, if you try to invoke UpdateContext function in the component, you will get an error from the IntelliSense:

image

Although, as you can see from the same screenshot “Set” will work just fine there. Except that it won’t be touching application global variables – those will be some kind of component-specific variables.

So how was I supposed to organize the sequence of “events”? Here is what I knew:

  • I could hide and show my component on the screen using “Visible” property.
  • I could also adjust X & Y coordinates so that the confirmation message would show up in the middle of the parent screen
  • I could create input/output parameters for the component to pass values in and out
  • However, since , at this point, PowerApps components are not exposing any events, there seem to be no way to easily respond to the click of the “OK”/”Cancel” buttons

 

And the solution was? Timers! Mind you, it’s not an ideal solution. But it did get me very close to what I wanted to do.

Here is how my component looks like:

image

There are two buttons, there is a message label, and there is a timer.

There are two input properties: Message (Text) and NavigateOnClose (Screen). And there is one output property: Result (Number)

In the Time “OnTimerEnd” event, the component is setting DlgResult variable to 0:

image

And the time itself is configured this way:

image

In the “OnSelect” event of the “OK” button, the same variable is set to 2:

image

Finally, in the “OnSelect” event of the “Cancel” button, the same variable is set to 1:

image

You’ll also notice that both Cancel and OK buttons will use NavigateOnClose property to Navigate away from the component.

Component’s result property will be sources from the DlgResult variable:

image

But what’s the purpose of the timer?

It will simply reset DlgResult variable to 0 every 587 milliseconds(it’s not a magic number.. it’s just something to hopefully avoid collisions with the other timer – you’ll see it below). Problem is, I have to reset that variable somehow(otherwise, every time I show this component, it’ll already have a result value corresponding to either “Cancel” or “OK”), and I don’t have access to that variable from the main screen. Yet I don’t have any other event to use in this case.

Now off to the main screen:

image

There is my component, there is a button to show it, and.. there is another timer!

Component’s visibility is source from the variable:

image

X and Y properties of the component are sourced from the variables, too:

image

image

When the button is selected, I’ll set ConfirmDlgVisible to true, and I’ll also adjust X & Y coordinates:

image

In the OnVisible property of the screen, I am hiding the dialog:

image

And, finally, what’s that timer is doing? It’s checking “result” property of the component. Yep, periodically. If you have followed me this far, you may still remember there was another timer that’s actually resetting the result, so the idea is that the timer on the screen should be checking “Result” frequently, and the other timer should be resetting it not so frequently (but, still, frequently enough to reset the result before the confirmation message is required again).

So, here is how this timer is set up:

image

And here is what’s happening in the OnTimerEnd:

image

Basically, it’s all about checking the result and hiding the dialog. I could add another If condition there to verify if the value of the result property corresponds to the “OK” button and do something if it does (as in, I could call Remove on some data source)

So.. Let’s just hide the timers (set Visible to “false” on both of them) and see how everything looks like. I’ve also added a label to the component to create a visual border:

image

As you are watching the recording below, notice how there are different numbers showing up just above the button (they will be 0, 1, or 2). That’s a label linked to the component’s “result” property.

powerappsdialogcomponent

BTW, if you were watching carefully, you’ve probably noticed how the first time I clicked “OK” there two timers actually ran into one another, so the click was not processed correctly. Had to click “OK” twice that time. It was an interesting experiment, though, which just proves there are things we can do with the Canvas apps which, maybe, we were not even meant to doSmile

Tricky Application ID-s

When looking at the application designer, we can see application ID in the link:

image

It is the same appid that will be added to the url when you open your application in Dynamics:

image

However, try adding that application(and the corresponding sitemap) to a solution, then export the solution, and have a look at the customizations.xml:

image

You’ll see the name of your application, but you won’t see the ID. You should probably see where this is going at this point, but let’s do a test.

Delete your application sitemap, and, then, delete the application from your Dynamics instance. Publish all customizations. Make sure the application is not there anymore. Re-import the solution exported above back to your Dynamics instance.

Your application will be back, but it will have a completely different ID:

image

Why would it even matter? Mostly, because there can be multiple applications in the Dynamics instance, and you may want to start adding application ID-s to the links you are sending by emails or using in the reports. And, if you follow some kind of application lifecycle methodology, you will likely have a dev environment where your application ID will be different from the same application ID in production.

So, before you start adding those ID-s to the workflows/scripts/flows/plugins, or anywhere else, you may need to figure out a way for getting application ID by application name somehow. If you need to use it in a workflow, you might create a custom configuration entity, store appID in the entity field, and use a custom workflow activity to get that entity. You might use a custom action instead (in this manner: http://missdynamicscrm.blogspot.com/2014/05/crm-2013-custom-action-as-configuration.html). You might probably just use a custom workflow activity to query app ID by name through FetchXml.. or do the same in the javascript through WebAPI.

Just don’t use the ID directly or you’ll have to re-configure the workflows/scripts/etc every time you deploy them in production as part of your solutions.

The magic of reflow, or the story of two grids

 

You would think an MVP should know.. Ha.. Tell me about it.

So, just to illustrate why I was scratching my head earlier today – there are two grids on the screenshot below, they were both just added to the form, there were no further customizations to them. And, yet, they kind of look different, don’t you think?

image

Of course the example above is not exactly how I came across this behavior. It’s just that I finally got to work with the Unified Interface long enough to realize something is off.. way off.. and what you see above is just a result of the research that happened after. And you may already know all that, in which case just have a bit of fun reading the rest of this post.

See, earlier today I suddenly realized that, when looking at the contact form, I did not see all the columns I would expect to see in the opportunity subgrid. Actually, I’ve been working with that form for quite a while, so the fact that this realization did not jump at me earlier is a big kudos to the unified interface. It just looks and works, well, naturally.

That was the end of my work day, even if it were only midday for everyone else. Since, after that, I just could not help but start researching.

Turned out thigs are not exactly obvious, but the following few links helped a great deal:

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/customize/specify-properties-for-unified-interface-apps

https://survivingcrm.com/2018/07/card-forms-and-list-views-in-unified-interface/

And this link, in turn, did add some confusion:

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/customize/create-design-forms

See, there is a “Card Form” in addition to the form types mentioned at the link above. And there is that “reflow” concept.. Once put together, it all explains the difference between the two grids you see on the screenshot above.

Long story short, here is how it works, it seems(this applies to read-only grids):

  • By default, a readonly grid will reflow into a “list” once there is not enough space to display the whole grid. I’m actually not certain on what’s not “enough”, but.. those are the finer details
  • By default (again) that reflowed list view will display a couple of columns from the entity. And, again, I am not sure if those are always the same or if they are different from entity to entity
  • But here is the thing.. you are in control!

 

If you go to the subgrid properties, you will normally see something like this:

image

So click that “Add Control” link, choose Read Only Subgrid control, and add it:

image

It seems to be a little strange way of doing things. Adding a read-only subgrid when there is, already, a read-only subgrid?

However, for that newly added subgrid control you’ll see a few more options:

image

And that’s the key to it. First of all, you can choose reflow behavior. Do you want the grid to always show up as a list? As a grid? Or do you want it to reflow? Pick and choose:

image

You also get to choose what will be showing up in the list view – this is where “Card Form” type gets into play. Remember how, when adding a new form to the entity, you can choose a “Card Form”?

image

This is exactly the type of form that will be displayed in the “list” view. Card forms have some limitations – looks like they only support up to 5 controls, they don’t support any kind of complications (other subgrids, quick view forms, sections, etc), but that’s just a side note.

One note about choosing the card form for the grid, though. When doing it, make sure to choose correct entity. As in, if doing it for the opportunity subgrid, choose Opportunity. You can surely choose “Account” or something else: image

But that will lead to an error when the list is being rendered:

image

And that’s about it. Not sure if you learned anything from this post, but I definitely did learn a thing or two earlier today. And the takeaway is – reflow is absolutely awesome.. even if a little under-documented. Hope you like it, too!

April’19 release notes – is it, actually, a bit of a short-term roadmap?

There are lots of “new and planned” features mentioned in the April’19 release notes:

https://docs.microsoft.com/en-us/business-applications-release-notes/April19/

But, it seems, those release notes are not just “release” notes – they are a bit of a roadmap, too.

Have a look at the corresponding section for the Customer Service, for example:

https://docs.microsoft.com/en-us/business-applications-release-notes/April19/service/planned-features

A lot of features will be delivered before or after April:

image

And, also, if you look at the list above, you’ll see that some features will not be delivered in the GA yet – they’ll be in Public Preview. 

Interesting that Microsoft took down the original Dynamics roadmap site some time ago and came up with a new roadmap experience here:

https://dynamics.microsoft.com/en-ca/roadmap/customer-service/

A lot of links from the new roadmap site are pointing to the release notes now..

I think this is all fine, though, – it’s great to know what the release plan is, and, apparently, there are lots of goodies coming our way in that release. It’s just worth keeping in mind that there seem to be no single release date for all the features mentioned in the notes(even thought the majority of them are still planned for April), so, when planning, you might want to watch those dates to make sure you are not expecting a feature to show up in April when it’s actually planned for a later date.

Getting model-driven app record id in the embedded canvas app

 

While prototyping my image upload canvas application for the contact form the other day, I ran into something that is probably just a quirk of the preview implementation, but you may want to be aware of this behavior when doing something similar in the meantime.

Imagine that you had your canvas app working with some other data source, such as SharePoint list. You might need to identify an item in that list depending on the ID of the record in the model-driven app, and, then, you might want to put your canvas app form in the new/edit mode depending on whether the item exists. Technically, you should be able to do something like this to identify the record id (MOdelDrivenFormIntegration is a special hardcoded name for the model-driven data source):

First(ModelDrivenFormIntegration.Data).ContactId

And, then, you should be able to use LookUp/Filter functions on the SharePoint datasource (assuming you store record ID-s in a separate column there, for instance).

It seems, though, that First(ModelDrivenFormIntegration.Data).ContactId will always be empty if you try accessing that value in the Screen->OnStart/OnVisible

The workaround I found was to add a Timer with 1 second delay. In the OnTimerEnd event everything is working just fine:

image

Maybe there is a better option? Let me know.

Using a Canvas app with Dynamics CE to upload an image

 

You probably know that we can extend entity forms with the canvas apps – this feature has been in the preview for a while now:

https://docs.microsoft.com/en-us/business-applications-release-notes/october18/powerapps/extend-dynamics-365-entity-forms-with-embedded-canvas-apps

It would be interesting to find some useful application for this new functionality, so I figured why don’t I use it to add “image upload” area to a form?

Here is what I ended up with:

powerimage

Quite frankly, it took a while. A few hours.. But, also quite frankly, it took less than it might have taken me if I had to actually do some coding there. Although, this whole solution is not without its own limitations, so there are pros and cons, but, as you can see above, at the very least it’s viable.

Here is how it’s been set up:

  • There is a list in sharepoint, so those files are stored as attachments on the list
  • That list has an extra column (RecordId, string). That’s what my PowerApps application is using to identify the list item related to the currently open contact record in Dynamics

 

On the application side, I have my main screen and a form right on that screen:

image

You can see that there is, also, a Timer control. Somehow, I cannot really use filter/lookup functions in the OnStart/OnVisible of the screen control but it works perfectly when done in the timer.

So the timer (which will run only once) is doing this:

image

It will set a variable, and, then, depending on whether a sharepoint list item exists, it will either call EditForm or NewForm.

My form “DATA” properties are set like this:

image

I’m using SelectedContactId, but I have to use a LookUp there, too, since, otherwise, the form does not get refreshed properly on the updates (Could have used a variable.. but the variable needs to be refreshed when a file is added/removed)

Attachments card has two controls. There is an attachment control which I’m using to add files, and there is an Image control which I’m using for the preview of the image. On the screenshot below, you’ll see how Image property of that control is set:

image

And, finally, whenever a file is added/removed, I need to submit the form and refresh it. So, I’m doing exactly the same in the attachment control OnRemoveFile and OnAddFile events:

image

So how is this new file linked to the record in Dynamics? Remember in my sharepoint list I have “recordId” column – – you’ll see I’m using it on the screenshots above to do a LookUp on the Files datasource. That RecordId is always set to the ID of the record, but the control itself is not visible on the form (no point displaying the guid there):

I think it took me more time to figure out how to work with all these screens/controls/events/etc than to actually write an app for this particular use case, and, yet, it only took a few hours. Not bad, it seems?

And just a couple of notes for the conclusion:

 

Not sure how to end this post.. Happy Power Platforming, I guess?Smile

The twists of duplicate detection

 

There is an interesting twist with the duplicate detection in Dynamics which kind of makes sense once you realize this is how it works, but it may not be obvious at first.

image

Imagine that you have duplicate detection rules configured for a certain entity, and most of your users have business-unit access to that entity. Which means that, in reality, those duplicate detection rules will normally work within each business unit, but somebody having organization-wide permissions will still see duplicates (when those duplicates are created in different business units).

Then imagine that you need to load the same set of data into two different business units. You would think it’s easy – log in as a system administrator, use excel import, and, while importing, assign newly imported records to a team (or to a user) in the target business unit.

That’s the assumption I made the other day, and it turned out to be a wrong one. When running the import, Dynamics will look for the duplicates first, and it will do the assignment only after that. So, as a system admin, I’ll only be able to import those records into one business unit, and, then, while trying to import into another one, I’ll start getting duplicate detection errors.

Fine, you may say.. so why don’t we add a “match” condition for the owning business unit to each of the duplicate detection rules involved in this process?

image

This is another interesting one. If we do this, it seems that duplicate detection rules just stop working at all. You don’t need to run a data import to test this – the rules will stop working even for the records you’ll be creating manually. Why?

Honestly, I am not sure, but, from my vague recollection of how the data is populated behind the scene, I think “Owning Business Unit” field is not populated immediately  on create of the record (it’s kind of a calculated field.. Once a record is assigned to an owner, Dynamics will look at that owner record to calculate the value of the business unit field)

What’s the solution, then? It seems the only way to make it work in the above scenario is to create a user account, to put that user account into the destination business unit, to import the records under that user account, and to remember to assign newly imported records to a different team or user in that business unit(without the last step, which can be done as part of the import, all those imported records will keep following the user account to other business units). Once it’s done, we can move that user account to a different business unit and repeat the process.

What the heck is a reference panel?!

(Update) this seems to be old news because of this older post: https://community.dynamics.com/crm/b/crminogic/archive/2017/12/20/reference-panel-section-in-dynamics-365-v9-0    No navigation icons on the screenshots there, though.. hm..

 

While looking at the Health Care Accelerator solution earlier today, I noticed this strange navigation panel on the right:

image

Have never seen it before, so I tried clicking some of those items. Lo and behold, they are perfectly clickable:

image

So, I went to the designer.. That part of the form looked like a regular section with grids:

image

But was it? Unlike your other sections, this one is somewhat unique:

image

I can’t change the name, and I can’t even set some of of the regular properties. Hm..

Can I re-create a similar section somewhere else? Turned out I can, though I am not sure how supported it is.

Here is how to do it – you’ll probably have to mess with customizations.xml, so I’m assuming you know how to work with it:

  • Create a new solution
  • Add your entity
  • Add a form you want to update
  • Make sure you only have subgrid controls on the form you want to update (remove all other input controls)
  • Make sure you are using a one-column section
  • Export your solution and extract the contents
  • Open customizations.xml
  • Find the section and add ref_pan_ prefix to the section name
  • Within that section, replace classid attribute of all subgrid controls with this id: “02D4264B-47E2-4B4C-AA95-F439F3F4D458”

 

Save the file, re-package your solution, and see what happens. For example, in my case I got this kind of navigation for the recent cases/recent opportunities/entitlements:

image

What does it all have to do with the “reference panel”? This is how those sections are called, it seems. For example, if you don’t replace subgrid control id above, you’ll get an error that will be explaining that only some specific controls can be used in the reference panels etc.

PS. You probably noticed that I did not get the icons right above.. Not sure why yet, may need to get back to it.

 

Dynamics login errors

I see the error below relatively often, since it’s not extremely unusual to see a user that was created without giving that user any roles in Dynamics (or, maybe, that user was moved to another business unit and lost his/her roles in the process):

image

The error is absolutely clear – we just need to assign roles to the user.

What turned out to be quite a bit more confusing is the HTTP 404 error I saw this morning when trying to access Dynamics under one of the test accounts:

image

“No webpage was found for the we address: https://…crm3.dynamics.com

Well, of course there was a webpage since I was able to open that page under my regular user account. How come?!

The problem turned out to be with the business unit of that test user account. The user account had all the roles, it was an active account in Dynamics, so, when looking at the user account, everything looked perfectly fine.

The business unit, however, was disabled. I am not sure why it was disabled (guess that’s what test accounts are for.. somebody was testing something), but the end result is: you can see this error message if your user account is linked to an inactive business unit in Dynamics 

What’s wrong with those security roles?

You know how security roles in Dynamics are duplicated for each business units, right? So you have a role in the root BU, and there is a copy of that role in each of the child business units.

So what would you be thinking if there were a role in the root business unit for which there would be no corresponding role in the child business unit?

For example, on the screenshot below, you can see how all other roles are displayed in pairs (one per business unit); however, those highlighted roles are unique:

image

It all becomes clear once “parent role” column is added to the view:

image

Somehow, my “Test Role” in the child business unit has a parent role that’s named differently. There is an easy fix – I just have to update parent role name (flip it back and forth) – everything gets synched after that:

image

So how come?

Turned out this is something that may happen during solution import – in my case, the role was originally imported through a managed solution. Then it was updated in the source and re-imported again. Somehow, once the role was imported, the display name of that role got updated only in the root business unit.

Technically, nothing gets broken when this happens. But, of course, it the role name is mentioned in some kind of user setup instructions, those instructions become rather confusing.

PS. And, btw, the credit for figuring out most of this(well, to be fair for creating the issue, tooSmile ) goes to Richard Lund from MNP.