October 18, 2019

PCF Gallery - 5 months after

Today (18 October 2019) I added the 100th to PCF Gallery.

All the controls listed inside PCF Gallery can be downloaded, and the source code is available inside their GitHub repository or in the blog post linked inside the page. The majority of the controls is for Model-driven apps, some of them can be added also to Canvas apps and there are also a couple created specifically just for Canvas apps.

There is no doubt the PowerApps Component Framework is one of the most interesting capabilities landed recently inside the Power Platform world, at least for developers!

When I wrote the post announcing the launch of PCF Gallery, I optimistically wished that soon it would list dozen of controls. After few months, thanks to the contributions from more than 40 authors, PCF Gallery is a beautiful showcase of the possibilities offered by the PowerApps Component Framework.

A big thanks to the whole PCF Community!

July 19, 2019

New SDK released with support for new regions (France, US Gov DoD, China)

A week ago thanks to a question on Dynamics Community Forums (link) and to Daniel Cai that spotted the crm12 inside the url, I became aware that a new region for Dynamics 365/PowerApps (located in France) was introduced, however the SDK was not able to connect to this new region as it was not updated yet.

Yesterday the SDK Team released an update to several NuGet packages (link), from the changelog:
Added support for France and New US Geo's

Microsoft didn't update yet the official documentation page but you can check in the next days if you need the exact Discovery Url (especially for the new US region, for the France one you just need to use crm12)

Meanwhile I was testing the new Plugin Registration Tool, I noticed they also introduced a new region in China, strangely the changelog didn't mention this.

Hope it helps!

June 14, 2019

My first PCF Control

After launching PCF Gallery I finally created my first PCF control: Custom Url Control.

The idea behind this control is to display a custom url using record values as parameters.
In my screenshot I implemented a google search using the phone number, but the possibilities are infinite: you can implement a shipment tracking, a link to your reporting engine, open an sms gateway webpage, just one click away!

The control has several settings: It supports up to 3 fields to fetch their values, the url link, the text and some styling options
I didn't want to force the use of a specific placeholder so they are also customizable.
And now the setup example:
  1. First of all I added an additional Phone field (telephone1) to the form and I attached my control to it
  2. The placeholder is the string used inside Url Link and Url Text to replace the value from the Source Field
  3. As I want to display the name inside the Url Link I bounded Source Field 2 to Name (name) field and I used the default placeholder __VALUE2__
  4. For this example I didn't need a third parameter so I left Source Field 3 empty
  5. Inside the Url Link I inserted https://www.google.com/search?q=__VALUE__ in this way __VALUE__ will be replaced with telephone1 value
  6. Inside the Url Text I inserted Search __VALUE2__ Phone Number, in this way __VALUE2__ will be replaced with name value
  7. Url CSS has a default value, to make the links looks similar to Dynamics UI
  8. Inside Font Awesome Icon I inserted the classes required to show a Font Awesome Icon (version 5), I set the search icon, if for example you wanted the UPS one, you need to insert fab fa-ups
  9. Font Awesome Icon Style is to set the style property of the icon, in my case I wanted to change the color
I hope you like this control and find it useful.

May 20, 2019

PCF Gallery website launched!

If you are Dynamics 365 Developer (or I should say Power Platform Developer) you are probably aware of the trending topic of the last weeks: PCF.

What is PCF? PCF stands for PowerApps Component Framework, a new way to create custom controls for model-driven apps (more info at Microsoft Docs).

PowerApps Component Framework (also called in the past CCF Custom Control Framework) is an interesting concept to enhance the UX of our apps, it has been in private preview for a very long time and currently is in public preview.
Despite its preview state, many developers started to create controls and to avoid dispersion I decided to create a website to collect the amazing controls created by the Power Platform community, this website is PCF Gallery (https://pcf.gallery).

I created the site the other day so it's a bit empty right now, but I am sure soon it will list dozen of controls. If you created a control or you found a control and want it to be listed please contact me (by Twitter or email).
PCF Gallery has also an Ideas forum (thanks Nick Doelman for the suggestion) where people can submit their idea for new controls, hopefully developers can use them to build new controls for the community.
What are you waiting for? Click on the logo to get started!

March 28, 2019

Update user’s calendar in Field Service schedule board

Configuring the work hours for a user is straightforward from the Dynamics 365 UI, a couple of clicks and you are done. However in the last years we saw an increase of Field Service projects, hence the necessity to automatize the creation and the update of user's works hours.
C# code to update the calendar entity has been around from CRM 2011, like this one:
Sample code to update user’s calendar programmatically (work hours) in CRM 2011

The code linked above works perfectly when you see the work hours inside the user calendar, however they don't appear inside the Field Service schedule board. How can we make sure the work hours appear everywhere?

Nearly 50 lines of code to create a work hour entry are (at least to me) a bit excessive, but this is the way Dynamics work. I tried to simplify the code by renaming the variables and adding the code necessary for the work hours to appear inside the schedule board.
// we start with the user Id
Guid userId = Guid.Empty; // instead of Guid.Empty here we should have the real user Id

// we retrieve the calendarid from the user entity
Entity user = service.Retrieve("systemuser", userId, new ColumnSet("calendarid"));
Guid userCalendarId = user.GetAttributeValue("calendarid").Id;

// we retrieve the calendar record in order to get the Business Unit and the Calendar Rules
Entity userCalendar = service.Retrieve("calendar", userCalendarId , new ColumnSet("businessunitid"));
Guid calendarBusinessUnitRef = userCalendar.GetAttributeValue("businessunitid");
EntityCollection calendarRules = userCalendar.GetAttributeValue("calendarrules");

// we create a new calendar record (inner)
Entity innerCalendar = new Entity("calendar");
innerCalendar["businessunitid"] = calendarBusinessUnitRef;

// Field Service Schedule Board: we must define the type as Inner Calendar
// https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/types-calendars
innerCalendar["type"] = new OptionSetValue(-1);

Guid innerCalendarId = service.Create(innerCalendar);

// we create a calendar rule for the whole day we want to edit
Entity dayRule = new Entity("calendarrule");
dayRule["duration"] = 1440; // 24 hours in minutes
dayRule["effort"] = 1.0;
dayRule["extentcode"] = 1;
dayRule["pattern"] = "FREQ=DAILY;COUNT=1";
dayRule["rank"] = 0;
dayRule["timezonecode"] = 110; // 110 is (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
// GetAllTimeZonesWithDisplayNameRequest can be used to retrieve all the timezones with their code
dayRule["starttime"] = new DateTime(2019, 3, 28, 0, 0, 0, DateTimeKind.Utc);
dayRule["innercalendarid"] = new EntityReference("calendar", innerCalendarId);

// Field Service Schedule Board: we must also define the calendarid reference to the user calendar
dayRule["calendarid"] = new EntityReference("calendar", userCalendarId);

// we attach it to the Calendar Rules of the user

// we update the user calendar to refresh the calendar rules collection
Entity updateUserCalendar = new Entity("calendar", userCalendarId);
updateUserCalendar["calendarrules"] = calendarRules;

// we define the calendar rule containing our work hour 
Entity exactCalendarRule = new Entity("calendarrule");
exactCalendarRule["duration"] = 120; // 2 hours in minutes
exactCalendarRule["effort"] = 1.0;
exactCalendarRule["issimple"] = true;
exactCalendarRule["offset"] = 480; // 8 hours in minutes from start time (12:00)
exactCalendarRule["rank"] = 0;
exactCalendarRule["subcode"] = 1;
exactCalendarRule["timecode"] = 0;
exactCalendarRule["timezonecode"] = 110; // same timezone as the day rule
exactCalendarRule["calendarid"] = new EntityReference("calendar", innerCalendarId);

// we add the calendar rule to a collection
EntityCollection innerCalendarRules = new EntityCollection();
innerCalendarRules.EntityName = "calendarrule";

// we update the inner calendar with the new calendar rules 
innerCalendar["calendarrules"] = innerCalendarRules;
innerCalendar["calendarid"] = innerCalendarId;

In the end to changes were necessary to make the work hour visible inside the Field Service schedule board:
  1. We must define the type for the Inner Calendar
  2. We must reference the user calendar inside the calendar rule the the whole day
I didn't discover this by myself but with the help of Microsoft support, hope it helps.

January 14, 2019

getText API behavior changed

Some days ago I was upgrading some JavaScript files to v9 and I noticed one of the scripts was not working correctly.
The specific code was using the getText function in order to retrieve the label of an optionset field. The getText function used to return an empty string in Dynamics instances prior to CRM 2016, but in recent versions it returns null. If you need to handle the label in your code (like showing some alerts) the check should be like this one:
function checkOptionsetLabel(context, fieldName) {
    var selectedLabel = context.getAttribute(fieldName).getText();
    if (selectedLabel != null) {
        // ...
Also the official documentation has been updated to highlight the return value. Hope it helps!

December 31, 2018

Dynamics Weekly and recap of (my) 2018

If you were hoping to read (after long time) a technical post from me, I am sorry but you need to wait a bit longer :)
In this post I will write about Dynamics Weekly (first part) and what I have been up to during 2018 (second part), let's start.

Dynamics Weekly is my newsletter regarding Dynamics 365 CE, I started it in the end of 2017 and it's going well.

A chart of the subscribers: (click to zoom)

This chart shows 2 things:
  1. There is a steady increase of the subscribers, that's nice
  2. I am terrible at promoting the newsletter, because except the initial grow (maybe due to my spamming on Twitter and LinkedIn) the final count is relatively low
I want to tell how Dynamics Weekly started. Back in December 2017 I realized that due to my commitments (both work and personal) I was not able to keep track of all the news, Dynamics is my work but I also like it and it's pity if I miss the cool stuff.
I already knew that the 2018 would have been the same, so I needed a way to force myself to check the Dynamics world. A weekly newsletter is a good way to summarize the content published during the last days, also having the email in my inbox allows me to search for specific posts that I vaguely remember just using few keywords.

Most of the time I am able to collect the newsletter material during the week, sometimes I do the Sunday evening before the send. But Keep Dynamics Weekly running is useful to me and to the subscribers, in the last year I received many messages of appreciation, thanks to all of you.
Of course Dynamics Weekly would not exist without all the contributors in the Dynamics communities, I am honored to know some of them and the time and energy they spend creating all kind of content is way more important than mine spent on preparing the newsletter.

And now the second (brief) part of this post. How was my 2018? to be honest not great, it really drained me of energy and the final reward was very small. But I met new friends, I learned new things (not related to Dynamics) and I am positive 2019 will be a better year.

PS: 19 January I will join the "Dynamics Power! 365 Saturday London" event, see you there.