Veel lezers zullen wel bekend zijn met een van de populaire front-end frameworks/libraries, zoals Angular, React, Vue.js, Blazor of een van de vele andere. De manier om hier snel professionele oplossingen in te ontwikkelen is ook flink verbeterd in de afgelopen jaren.
De afgelopen tijd ben ik ook aan de slag geweest met het Power Platform, en dan met name Power Apps, Power Automate & de Dataverse integratie. Deze combinatie van oplossingen stelt ontwikkelaars, en mensen van ‘de business’ in staat om snel oplossingen te maken.
Het Power Platform van Microsoft staat bekend als een low-code/no-code platform en dat is het ook. Het staat zelfs op de landing pagina:
Omdat dit het enige platform is met een set tools met weinig code die je teams nodig hebben om flexibel te blijven en oplossingen te bouwen die je bedrijf vooruithelpen. Microsoft Power Platform is vanaf het begin opgebouwd met het oog op sterke beveiliging, beheer en naleving en biedt de ruimte om te groeien.
Bron: https://powerplatform.microsoft.com/nl-nl/what-is-power-platform/
Dit klinkt niet heel aantrekkelijk voor een ontwikkelaar, want ‘wij’ vinden het vaak veel leuker om zelf een hele oplossing te maken, denk aan integraties, schermen, communicatie, componenten, beveiliging, etc. En in veel gevallen doen we dit dan ook ‘beter’ als in een low-code/no-code platform.
Het woord ‘beter’ staat tussen aanhalingstekens met een reden. Want hoewel we de oplossingen vaak wel 100% op maat kunnen maken voor een specifieke klant, betekent dit vaak wel veel ontwikkelwerk, zelf alles moeten testen, bugs oplossen, etc. Dit kan redelijk in de papieren lopen voor wat betreft tijd en geld.
Of de uiteindelijke oplossing dan nog steeds ‘beter’ is, in vergelijking met een oplossing die, bijvoorbeeld, in het Power Platform is gemaakt valt te bezien. Vaak kun je daarmee met relatief weinig moeite toch een nette oplossing maken welke goed genoeg voor het vraagstuk dat de business opgelost wil zien.
Het aantal connectoren, voor nagenoeg iedere populaire service, dat standaard is te gebruiken is ook immens. Dit betekent dat je niet meer zelf een integratie met bijvoorbeeld SAP, Dynamics of Azure Service Bus hoeft te ontwikkelen, maar dit out-of-the-box kunt gebruiken. De connectoren zijn goed te vergelijken met degene die ook in Azure Logic Apps gebruikt kunnen worden.
Mocht het zo zijn dat jouw connector voor een service er echt niet tussen staat, of je hebt echt maatwerk nodig, dan staat het vrij om zelf een connector te maken & publiceren in de publieke of private store.
Binnen het Power Platform wordt ook een database aangeboden, genaamd Dataverse. Dit kun je zien als SQL Server on steroids. In de basis draait het op een SQL Server, maar er zijn veel toevoegingen op gemaakt, waardoor het ideaal geschikt is om gebruikt te worden binnen het Power Platform. Dataverse is volledig gemanaged, is relatief eenvoudig te beveiligen, role-based-access-control is ingebouwd, en schaling wordt automatisch geregeld.
Er is zelfs een speciale Dataverse versie voor Teams gemaakt:
Make working in Microsoft Teams more productive and collaborative with Dataverse for Teams—a low-code data platform built into Teams. Remove friction for users having to switch between multiple services and apps with an end-to-end experience. Create secure, integrated solutions with Microsoft Power Apps and support your workforce with intelligent bots using Microsoft Power Virtual Agents.
Bron: https://powerplatform.microsoft.com/en-us/dataverse/
Mocht jouw organisatie dus geen licentie hebben om gebruik te maken van het Power Platform, dan is dit een (gratis) optie om toch aan de slag te gaan.
Natuurlijk zullen niet alle wensen van klanten, of de business, kunnen worden ingewilligd met standaard componenten. In het geval dat er een stuk functionaliteit ontbreekt en per se moet worden geïntegreerd in een applicatie, dan zijn er verschillende mogelijkheden om dit op te lossen. Een daarvan is het ontwikkelen van een PCF-component (https://docs.microsoft.com/en-us/power-apps/developer/component-framework/overview). Hiermee worden ontwikkelaars in staat gesteld om custom code componenten te maken, gemaakt met HTML, CSS & TypeScript. Het gebruik maken van dit type componenten is ideaal in het geval dat er kleine stukken functionaliteit moet worden toegevoegd aan een Power App.
Het maken van dit soort componenten wordt niet verder in dit artikel behandeld, maar mocht je hier interesse in hebben, dan kan ik van harte de documentatie pagina’s die hierover gaan aanbevelen.
Veel applicaties die in het Power Platform worden ontwikkeld kunnen door zogenaamde ‘citizen developers’ worden gemaakt, dat is dan ook de kracht dat iedere medewerker binnen een organisatie iets voor zichzelf, of een team, in het werkproces kan automatiseren of vereenvoudigen.
Naar mijn mening is het wel zo dat het fijn is dat een ontwikkelaar betrokken is bij de ontwikkeling van (belangrijke) applicaties, om zo een beter te onderhouden & testen applicatie neer te zetten. Een ontwikkelaar heeft vaak meer ervaring met zaken als beveiliging, performance, onderhoudbaarheid en versiebeheer. Als dit goed wordt opgepakt, dan zitten er grote voordelen aan het gebruik van Power Apps (en het Power Platform in z’n algemeenheid) ten opzichte van op maat ontwikkelde applicaties/platformen.
Mocht je het nog niet hebben gedaan, dan zou ik aanraden om een ‘Hello World’-achtige applicatie te maken met Power Apps en een integratie met Dataverse. Dit kan zowel met de volledige- als wel de Teams-variant. Bonuspunten voor het toevoegen van een Power Automate flow!
Zodra de Power App is ontwikkeld kan die worden toegevoegd als een nieuwe tab in Teams. Door de optie Power Apps te selecteren zal er een pop-up verschijnen waar alle gepubliceerde Power Apps kunnen worden geselecteerd binnen de organisatie
Een veelvoorkomend voorbeeld dat men vaak maakt is een To Do applicatie, zo heb ik ook een ‘Action Management’ applicatie ontwikkeld met daarin verschillende Power Automate flows en een geïntegreerd Power BI dashboard.
De basis voor deze applicatie kan binnen enkele uren worden opgezet en daarmee kunnen gebruikers direct aan de slag. Zeker met de verschillende Power Automate flows is het mogelijk om integraties met externe systemen toe te voegen zonder daar een expert voor hoeven te zijn.
Natuurlijk kun je deze Power App ook prima los starten, maar het grote voordeel om dit binnen Teams te doen, is dat de applicatie ook gebruik kan maken van de context waar die in draait (welk team, deelnemers in het team, kanalen, etc.). Deze informatie wordt in de querystring van de Teams-tab meegestuurd en kan eenvoudig worden gebruikt in de applicatie in bijvoorbeeld een `appConfig` variabele.
With( { tmpGroupID: Param("groupId"), tmpChannelId: Param("channelId"), tmpTeamId: Param("teamId") }, If ( !IsBlank(tmpGroupID), Set( appConfig, { TeamsData: { GroupId: tmpGroupID, ChannelId: tmpChannelId, TeamId: tmpTeamId } } ) ) );
Een ander bijkomend voordeel, vanuit een gebruiker perspectief, is dat deze persoon minder vaak hoeft te switchen tussen applicaties, wat de productiviteit ten goede kan komen. Het namelijk mogelijk om vanuit de Power App een chat te starten met collega’s en gelijktijdig door te werken.
Mijn korte antwoord is: JA!
Maar zoals iedereen weet zijn er geen absolute antwoorden in onze wereld. Het antwoord zal sterk afhangen van de use-case en wensen van de gebruikers/business.
Wel is het zo dat het relatief eenvoudig is om een, eenvoudige, applicatie op te zetten. De applicaties kunnen ook prima met verschillende APIs communiceren en desgewenst kan er voor deze APIs met enkele klikken een Custom Connector worden gemaakt. Op deze manier hoeven ontwikkelaars minder bezig te zijn met het maken van de zoveelste CRUD-applicatie in hun carrière en bezig te houden met interessantere vraagstukken, zoals schaalbaarheid, beveiliging, performance, etc.
Dat begrijp ik!
In de afgelopen jaren dat ik bij verschillende klanten projecten heb mogen uitvoeren heb ik geleerd dat er geen een klant gelijk is en ieder bedrijf vaak wel iets ‘raars’ in het werkproces heeft dat je nog niet eerder bent tegengekomen. Dit is niet erg en maakt ons werk, naar mijn mening, des te meer interessant!
Vaak is het wel dat dit ‘ene’ unieke stuk in het werkproces vaak maar een klein onderdeel is van het grotere geheel. Daarom denk ik dat je vraagstukken van de business wel voor 80%, of misschien wel 90%, de applicaties met een Power Apps kunt oplossen, al dan niet met kleine PCF-componenten.
Voor de resterende functionaliteit kan dan nog een zelf ontwikkelde applicatie worden gemaakt. Hier kan ervoor worden gekozen om een applicatie te ontwikkelen met Angular, React, Vue.js, etc., maar er is ook een minder bekende optie, namelijk een Native Teams applicatie. Dit kan een hele logische keuze zijn, aangezien alle andere applicaties (Power Apps) ook binnen Teams kunnen worden gehost.
Is dit heel anders als het hosten van een webapplicatie in een `Web`-tab binnen Teams? Nee, niet heel anders, maar het heeft wel enkele voordelen zoals de integratie met Azure Active Directory & M365, de applicatie als een ‘package’ kunt aanbieden en er standaard gebruik kan worden gemaakt van de Fluent UI (https://docs.microsoft.com/en-us/fluent-ui/web-components/) welke ook door Teams zelf wordt gebruikt. Standaard wordt er ook gebruik gemaakt van Blazor, dus is het relatief eenvoudig aan te leren voor .NET ontwikkelaars.
Sinds Visual Studio 2022 is er de optie om de Microsoft Teams development tools te installeren. Het is aan te raden deze optie te gebruiken, want het installeert ook de Teams App project template.
Deze template geeft als optie om een Teams Application te maken met zowel `Tab`- als `Bot`-functionaliteiten. Het maken van een Bot is iets dat niet in dit artikel wordt behandeld, maar is zeker interessant! De ‘Get started quickly…’ in de documentatie (https://docs.microsoft.com/en-us/microsoftteams/platform/toolkit/visual-studio-overview) geeft een goed overzicht wat er voor een snelle start gedaan moet worden.
Het belangrijkste vind ik dat de Teams applicatie goed wordt geconfigureerd in Azure & M365. Hier kan de optie voor worden gebruikt `Teams Toolkit -> Configure Microsoft Teams app`.
Deze optie zorgt er onder andere voor dat er een App Registration wordt aangemaakt in Azure Active Directory en de benodigde properties in het bestand `appsettings.Development.json` van het project worden gevuld met het `ClientId`, `ClientSecret` en `OAuthAuthority`.
De App Registration in Azure Active Directory gedraagt zich verder hetzelfde als een reguliere, dus ook hier is het mogelijk om API Permissions aan te vragen voor de applicatie, applicatie rollen toe te voegen, etc.
Wanneer er een native Teams applicatie wordt gemaakt is er een grote kans dat er ook al Power Apps zijn ontwikkeld binnen de organisatie. Deze Power Apps maken waarschijnlijk ook gebruik van Dataverse als repository. Het ligt voor de hand dat de native Teams applicatie ook toegang moet krijgen tot deze data. Standaard is dit niet geregeld en moet deze toegang nog worden toegevoegd.
Het toevoegen van deze toegang kan worden gedaan op de `API permissions`-blade van de zojuist gegenereerde App Registration. Hier moet de toegang tot `Dynamics CRM` worden toegevoegd, zoals is te zien in de afbeelding.
Let op dat de `Grant admin consent for [organization]` wel moet worden verleend. Mocht dit niet worden gedaan, dan zullen de gebruikers een fout te zien krijgen bij het verlenen van hun ‘consent’ aan deze applicatie.
Niet iedereen binnen de organisatie heeft voldoende rechten om deze ‘admin consent’ te activeren, dus let daarop!
Nadat de applicatie volledig is geconfigureerd is het eindelijk tijd om te ontwikkelen!
Het standaard project template heeft een voorbeeld applicatie welke in staat is om data over de ingelogde gebruiker op te halen vanuit Azure Active Directory. Dit is mogelijk, omdat de gebruiker al in Teams is ingelogd en de applicatie de `User.Read` autorisatie heeft op de Microsoft Graph.
Omdat er ook data uit Dataverse moet worden verkregen, of toegevoegd, moet er door de gebruiker ook toegang worden verkregen tot deze bron. Het is hiervoor noodzakelijk om het Web API endpoint van de betreffende omgeving te verkrijgen. Deze kan in Power Platform worden gevonden onder `Settings -> Developer Resources`.
Om te kunnen lezen en schrijven kan het eigen account van de gebruiker worden gebruikt, want het is in Dataverse heel goed mogelijk om rechten toe te kennen op tabellen en kolommen.
In de applicatie dienen we nu alleen de Web API endpoint te definiëren en de scope (`user_imporsonation`).
private string dynamicsResource = "https://[thePowerPlatformEnvironment].api.crm4.dynamics.com/"; private string dynamicsScope = "user_impersonation";
In de Teams applicatie kan er de `TeamsUserCredential` worden geïnjecteerd.
@inject TeamsUserCredential teamsUserCredential
Er kan nu een `LoginAsync` worden uitgevoerd met de benodigde scopes, waardoor de gebruiker consent kan geven om de Teams applicatie voor de geconfigureerde resources.
await teamsUserCredential.LoginAsync(new[] { _scope, dynamicsResource + dynamicsScope });
Zodra het consent is verleend is het mogelijk om de gebruikersgegevens uit de AAD te lezen, maar ook de bekende gegevens uit Dynamics/Power Platform.
var dynamicsToken = (await teamsUserCredential.GetTokenAsync(new TokenRequestContext(new string[] { dynamicsResource + dynamicsScope}), new System.Threading.CancellationToken())).Token; var httpClient = HttpClientFactory.CreateClient(); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", dynamicsToken); var whoAmIResponse = await httpClient.GetAsync(dynamicsResource + "/api/data/v9.2/WhoAmI"); if (whoAmIResponse.IsSuccessStatusCode) { JObject body = JObject.Parse(whoAmIResponse.Content.ReadAsStringAsync().Result); Guid userId = (Guid)body["UserId"]; _dynamicsUserId = userId.ToString("D"); } else { ErrorMessage += "Web API call failed"; ErrorMessage += "Reason: " + whoAmIResponse.ReasonPhrase; }
Het aanroepen van het `WhoAmI`-endpoint is goed om te valideren dat de connectie goed is opgezet. Een interessantere call is om bijvoorbeeld te zoeken naar de top 3 accounts van het bedrijf, gesorteerd op omzet. Ook dit kan met een vergelijkbare call worden verkregen.
var dynamicsToken = (await teamsUserCredential.GetTokenAsync(new TokenRequestContext(new string[] { dynamicsResource + dynamicsScope}), new System.Threading.CancellationToken())).Token; var httpClient = HttpClientFactory.CreateClient(); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", dynamicsToken); var accountsResponse = await httpClient.GetAsync(dynamicsResource + "/api/data/v9.2/accounts?$select=name,revenue&$orderby=revenue desc&$top=3"); if (accountsResponse.IsSuccessStatusCode) { var topAccountsWithRevenue = await JsonSerializer.DeserializeAsync<Models.Dataverse.Accounts.WithRevenue.Rootobject>( await accountsResponse.Content.ReadAsStreamAsync()); _accountCollection.Clear(); _accountCollection.AddRange(topAccountsWithRevenue.value); } else { ErrorMessage += "Web API call failed"; ErrorMessage += "Reason: " + accountsResponse.ReasonPhrase; }
Redelijk veel code, en te veel om over te typen. De volledige oplossing is dan ook beschikbaar op GitHub: https://github.com/Jandev/TeamsAppWithDataverseApiConnection
Ik vind van wel.
Het snel kunnen ontwikkelen, beschikbaar maken en valideren van een oplossing bij eindgebruikers heeft veel voordeel. Zo kan er sneller worden geschakeld en gevalideerd of de gemaakte oplossing(en) voldoen.
Mocht het nodig zijn om toch een stukje maatwerk (component of Teams applicatie) te ontwikkelen, dan behoort dat ook tot de mogelijkheden, maar zal eerder een uitzondering zijn. En het staat natuurlijk nog steeds vrij om een volledig losstaande applicatie naast de overige applicaties te ontwikkelen, omdat dat simpelweg de beste keuze voor de betreffende use-case is.
Het is alleen goed om te weten wat de (on)mogelijkheden binnen het Power Platform zijn, zeker met de aanwezige Teams integratie. Het zorgt ervoor dat wij ontwikkelaars ons minder druk hoeven te maken met ‘saaie’ CRUD-schermen en de focus meer gelegd kan worden op het verbeteren en automatiseren van processen en de cross-cutting concerns.