Do you wanna build a snowman? (pt. 1)

Joost van Dam

Blog
02 juni 2022

Hoe maak je een custom connector voor Power Apps?

Wat te doen wanneer Power Apps tekort schiet? Een verhaal over sneeuwpoppen.

Het Microsoft Power Platform heeft het maken van business apps enorm versimpeld. Power Apps biedt een breed scala aan mogelijkheden die in vele vraagstukken een oplossing kunnen bieden. Echter biedt het platform niet voor álle uitdagingen de middelen om tot een oplossing te komen. Een voorbeeld hiervan is het automatisch genereren van een (technisch) schema om deze vervolgens als afbeelding beschikbaar te maken. In dit soort gevallen maken we vaak gebruik van een zogenaamde Custom connector. We doen dit door in Microsoft Azure een zogenaamde Application Programming Interface (of API) te ontwikkelen die de technische schema’s kan genereren.

Om dit technische onderwerp enigszins luchtig te houden, illustreren we dit door een sneeuwpop te genereren. In deel #1 van deze blog bouwen we een API die een sneeuwpop kan genereren. In deel #2 integreren we deze API binnen een Power App waarmee we de sneeuwpop configureren en het resultaat tonen. We laten zo zien hoe je een duurzame modulaire oplossing bouwt die zoveel mogelijk low code is. Dus: do you wanna build a snowman?

First things first

Je vraagt je misschien af: waarom een sneeuwpop? Hoewel de winter pas net voorbij is heb ik de sneeuwdagen gemist. Het is daarnaast lang geleden dat ik een sneeuwpop gemaakt heb. Tenslotte is een sneeuwpop goed op te delen als een ‘schema’, bestaande uit gestapelde onderdelen zoals een hoed, een neus en knopen.

De opbouw van de API

We beginnen met het opstellen van een definitie van de sneeuwpop: hoe ziet de data eruit die tussen de Power App en de te bouwen API in Azure uitgewisseld wordt? Vervolgens bekijken we hoe die data omgezet kan worden naar instructies voor het genereren van de afbeelding. Tenslotte sluiten we af met het daadwerkelijk genereren van de afbeelding.

Het datamodel

Het datamodel is de definitie waarmee de generator begrijpt wat de buitenwereld ervan verwacht. Daarnaast is het voor ons een manier om de gebruiker keuzes te laten maken. Het beantwoordt vragen als hoe groot de sneeuwpop moet zijn of welke kleur de neus is (oranje natuurlijk). Voor onze sneeuwpop zijn de volgende regels van toepassing:

  • Een sneeuwpop bestaat uit drie type onderdelen: een basis, een lichaam en een hoofd;
  • Het lichaam kan uit meerdere lichaamsdelen bestaan;
  • De basis en het hoofd zijn een speciaal lichaamsdeel;
  • Ieder lichaamsdeel heeft een radius;
  • De basis kan knopen en/of voeten hebben;
  • Het hoofd kan een mond en/of een hoed hebben;
  • Standaardlichaamsdelen kunnen knopen en/of armen hebben.

Een veel gebruikte standaard voor het uitwisselen van data tussen API’s is het JSON-format (lees hier meer). Hieronder zie je hoe een sneeuwpop in dit format uitgedrukt kan worden, met bovenstaande regels in het achterhoofd:

{
      "snowman": {
            "bottom": {
                  "buttons": true,
                  "feet": true,
                  "radius": 100
            },
            "body": [
                  {
                  "buttons": true,
                  "arms": true,
                  "radius": 50
                  }
            ],
            "head": {
                  "mouth": true,
                  "hat": true,
                  "radius": 30
            }
      }
}

Het datamodel omzetten naar instructies

De service Azure Functions biedt een bijzonder goedkope en schaalbare manier om kleine applicaties efficiënt binnen Microsoft Azure te hosten. We gebruiken dit dan ook om een kleine applicatie te bouwen die de sneeuwpop voor ons genereert. Allereerst transformeren we het datamodel naar instructies voor de afbeelding generator.

Dit doen we door ieder onderdeel uit het datamodel om te zetten naar een bijbehorende klasse. Dit is een abstracte omschrijving van de mogelijkheden en eigenschappen die het onderdeel heeft in de code. Iedere klasse is een afleiding van de klasse “SnowmanPart”, waarin eigenschappen en mogelijkheden die alle onderdelen gemeen hebben staan. Doorgaans visualiseren we deze klassenstructuur door middel van een klassendiagram, zoals hieronder is te zien.

Het klasssendiagram

Dit doen we door ieder onderdeel uit het datamodel om te zetten naar een bijbehorende klasse. Dit is een abstracte omschrijving van de mogelijkheden en eigenschappen die het onderdeel heeft in de code. Iedere klasse is een afleiding van de klasse “SnowmanPart”, waarin eigenschappen en mogelijkheden die alle onderdelen gemeen hebben staan. Doorgaans visualiseren we deze klassenstructuur door middel van een klassendiagram, zoals hieronder is te zien.

In de klasse “SnowmanPart” is de basis gedefinieerd van het omzetten van het datamodel naar een instructie. Laten we in de simpelste duiken, een lichaamsdeel:

public virtual SnowmanPart Render(int verticalOffset, int width)
{
      var centerX = width / 2;
      // 1. Bepaal het midden
      var centerY = verticalOffset - Radius.Value;
      var center = new PointF(centerX, centerY);

      var shape = new EllipsePolygon(center, Radius.Value);
      // 2. Definieer de vorm en kleuren
      var fill = Color.White;
      var border = Color.Black;
      var borderThickness = 2;
      var index = 1; // determines the layer to draw on

      // 3. Bouw de instructie
      var instruction = new RenderInstruction(shape,
            fill, border, borderThickness, index);
      // 4. Voeg de instructie toe aan de lijst met instructies voor dit onderdeel
      parts.Add(instruction);
      return this;
}

Door de instructies in een lijst te stoppen kunnen afgeleide klassen (zoals het hoofd) instructies toevoegen voor de neus of de hoed. Dat ziet er als volgt uit:

De afbeelding genereren

Zodra de API een verzoek binnenkrijgt zet het de JSON data om in de zojuist genoemde klassen, wat een collectie objecten oplevert. Door daarna de render methode aan te roepen bouwt de collectie van objecten een collectie van renderinstructies op. Zoals te zien in de afbeelding hierboven bestaat een renderinstructie uit een vorm, een rand, een vulkleur en een index. De index bepaalt in welke laag de vorm aangemaakt moet worden. Om de instructies om te zetten in een .png gebruiken we een opensource 2d graphics library, ImageSharp.

De API beschikbaar maken

Met een methode om inkomende datamodellen van sneeuwpoppen om te zetten in .png afbeeldingen zijn we er bijna. De afbeelding moet nog teruggestuurd worden naar de aanvrager. Dit doen we door de afbeelding op te slaan in het geheugen van de Azure host, het stuk geheugen uit te lezen in een lijst van bytes, en de bytes terug te sturen. De aanvragen (bijvoorbeeld een Power App) kan deze bytes terug omzetten tot een afbeelding.
In versimpelde code ziet dat er als volgt uit:

byte[] output;
// Reserveer geheugen
using (MemoryStream stream = new())
// Maak een teken object aan
using (IDrawer drawer = _drawer())
{
            
            // Teken, en sla op in geheugen
            await drawer.Draw(drawing).SaveAsync(stream);
            // Kopieer inhoud geheugen naar bytes
            output = stream.ToArray();
}
// Stuur bytes terug en specificeer dat het om .png gaat
return new FileContentResult(output, asPNG); 

De afbeelding genereren

Zodra de API een verzoek binnenkrijgt zet het de JSON data om in de zojuist genoemde klassen, wat een collectie objecten oplevert. Door daarna de render methode aan te roepen bouwt de collectie van objecten een collectie van renderinstructies op. Zoals te zien in de afbeelding hierboven bestaat een renderinstructie uit een vorm, een rand, een vulkleur en een index. De index bepaalt in welke laag de vorm aangemaakt moet worden. Om de instructies om te zetten in een .png gebruiken we een opensource 2d graphics library, ImageSharp.

Tenslotte publiceren we de Azure Function achter een Azure API Management laag, waarin we onder andere kunnen configureren wie er op welke manier toegang kunnen krijgen tot de API.

Het resultaat
DO YOU WANNA BUILD A SNOWMAN?

Zelf proberen? Dat kan!

  1. Vraag allereerst een testsleutel aan via marketing@shared.nl;
  2. Ga naar https://snowmandemo.azurewebsites.net/api/swagger/ui;
  3. Vul de sleutel in binnen de ‘authorize’-popup;
  4. Definieer je sneeuwpop (of gebruik het voorbeeld van de sneeuwpop definiëren)
  5. Geniet van je sneeuwpop!

Take aways

Met de technologieën die ons vandaag de dag beschikbaar gesteld worden, kunnen we ontzettend veel, maar niet alles. Het Microsoft Power Platform maakt het bouwen van Businessapps een mogelijkheid voor een breder publiek. Dit heeft als keerzijde dat complexere applicaties steeds lastiger worden om te bouwen. Met maatwerk in de cloud kunnen complexe taken weggenomen worden van het Power Platform, waardoor de mogelijkheden alleen maar groeien en de complexiteit niet hoeft toe te nemen. Zo heb je de zowel de voordelen van snelle low code ontwikkeling alsook de flexibiliteit van complexer, modulair en herbruikbaar maatwerk.

Hoe cool de sneeuwpop ook is die we generen; het komt natuurlijk niet in de buurt van het gemak en het plezier van het echte ding maken. Hoe lang het duurt in Nederland tot we weer die kans krijgen durf ik niet te zeggen. Gelukkig is het gebruik van deze Cloud based ‘image creation service’ oneindig te versimpelen met het Power Platform. Hoe? In pt #2 van deze serie lopen mijn collega’s er in detail doorheen.

Meld je aan voor onze nieuwsbrief

Better business dankzij inspiratie, tips, best practices, klantverhalen en meer.


Joost van Dam

02 juni 2022

Meer inspiratie

Contact

Je naam
Dit veld is bedoeld voor validatiedoeleinden en moet niet worden gewijzigd.
Shared BV

Vasteland 12G
3011 BL Rotterdam

+085 833 0011 info@shared.nl
Sluiten
Privacyverklaring

Privacyverklaring Shared

Shared, gevestigd aan Vasteland 12G, 3011 BL Rotterdam, is verantwoordelijk voor de verwerking van persoonsgegevens zoals weergegeven in deze privacyverklaring.

Contactgegevens: Website: https://www.shared.nl
Adres: Vasteland 12G, 3011 BL Rotterdam
Telefoon: +31 85 8330011

Persoonsgegevens die wij verwerken Shared verwerkt je persoonsgegevens doordat je gebruik maakt van onze diensten en/of omdat je deze gegevens zelf aan ons verstrekt. Hieronder vind je een overzicht van de persoonsgegevens die wij verwerken:

  • Voor- en achternaam
  • Telefoonnummer
  • E-mailadres
  • IP-adres
  • Gegevens over jouw activiteiten op onze website
  • Internetbrowser en apparaat type

Bijzondere en/of gevoelige persoonsgegevens die wij verwerken Onze website en/of dienst heeft niet de intentie gegevens te verzamelen over websitebezoekers die jonger zijn dan 16 jaar, tenzij ze toestemming hebben van ouders of voogd. We kunnen echter niet controleren of een bezoeker ouder dan 16 is. Wij raden ouders dan ook aan betrokken te zijn bij de online activiteiten van hun kinderen, om zo te voorkomen dat er gegevens over kinderen verzameld worden zonder ouderlijke toestemming. Als je ervan overtuigd bent dat wij zonder die toestemming persoonlijke gegevens hebben verzameld over een minderjarige, neem dan contact met ons op via gerritjan@shared.nl, dan verwijderen wij deze informatie.

Met welk doel en op basis van welke grondslag wij persoonsgegevens verwerken Shared verwerkt jouw persoonsgegevens voor de volgende doelen:

  • Je te kunnen bellen of e-mailen indien dit nodig is om onze dienstverlening uit te kunnen voeren.
  • Shared analyseert jouw gedrag op de website om daarmee de website te verbeteren en het aanbod van producten en diensten af te stemmen op jouw voorkeuren.
  • Shared volgt jouw surfgedrag over verschillende websites waarmee wij onze producten en diensten afstemmen op jouw behoefte.

Geautomatiseerde besluitvorming Shared neemt geen besluiten op basis van geautomatiseerde verwerkingen die aanzienlijke gevolgen kunnen hebben voor personen.

Hoe lang we persoonsgegevens bewaren Shared bewaart je persoonsgegevens niet langer dan strikt nodig is om de doelen te realiseren waarvoor je gegevens worden verzameld. Wij hanteren de volgende bewaartermijnen voor de volgende (categorieën) van persoonsgegevens:

  • Persoonsgegevens: 26 maanden

Delen van persoonsgegevens met derden Shared deelt jouw persoonsgegevens met verschillende derden als dit noodzakelijk is voor het uitvoeren van de overeenkomst en om te voldoen aan een eventuele wettelijke verplichting. Met bedrijven die je gegevens verwerken in onze opdracht, sluiten wij een verwerkersovereenkomst om te zorgen voor eenzelfde niveau van beveiliging en vertrouwelijkheid van jouw gegevens. Shared blijft verantwoordelijk voor deze verwerkingen. Daarnaast verstrekt Shared jouw persoonsgegevens aan andere derden alleen met jouw nadrukkelijke toestemming.

Cookies, of vergelijkbare technieken, die wij gebruiken Shared gebruikt functionele, analytische en tracking cookies. Een cookie is een klein tekstbestand dat bij het eerste bezoek aan deze website wordt opgeslagen in de browser van je computer, tablet of smartphone. Shared gebruikt cookies met een puur technische functionaliteit. Deze zorgen ervoor dat de website naar behoren werkt en dat bijvoorbeeld jouw voorkeursinstellingen onthouden worden. Deze cookies worden ook gebruikt om de website goed te laten werken en deze te kunnen optimaliseren. Daarnaast plaatsen we cookies die jouw surfgedrag bijhouden zodat we op maat gemaakte content en advertenties kunnen aanbieden.

Bij jouw eerste bezoek aan onze website hebben wij je al geïnformeerd over deze cookies en hebben we je toestemming gevraagd voor het plaatsen ervan.

Je kunt je afmelden voor cookies door je internetbrowser zo in te stellen dat deze geen cookies meer opslaat. Daarnaast kun je ook alle informatie die eerder is opgeslagen via de instellingen van je browser verwijderen. Zie voor een toelichting: https://veiliginternetten.nl/themes/situatie/cookies-wat-zijn-het-en-wat-doe-ik-ermee/

Op deze website worden ook cookies geplaatst door derden. Dit zijn bijvoorbeeld adverteerders en/of sociale media-bedrijven. Hieronder een overzicht:

  • Google Analytics & Ads
    • Naam: _ga & _utma
    • Functie: Analytische cookie die websitebezoek meet
    • Bewaartermijn: 24 maanden
  • LinkedIn
    • Naam: _ligc
    • Functie: Analytische cookie die websitebezoek meet
    • Bewaartermijn: 24 maanden
  • Hotjar
    • Naam: _hjSessionUser_14
    • Functie: Analytische cookie die websitebezoek meet
    • Bewaartermijn: 24 maanden

Gegevens inzien, aanpassen of verwijderen Je hebt het recht om je persoonsgegevens in te zien, te corrigeren of te verwijderen. Dit kun je zelf doen via de persoonlijke instellingen van jouw account. Daarnaast heb je het recht om je eventuele toestemming voor de gegevensverwerking in te trekken of bezwaar te maken tegen de verwerking van jouw persoonsgegevens door ons bedrijf en heb je het recht op gegevensoverdraagbaarheid. Dat betekent dat je bij ons een verzoek kan indienen om de persoonsgegevens die wij van jou beschikken in een computerbestand naar jou of een ander, door jou genoemde organisatie, te sturen.

Wil je gebruik maken van je recht op bezwaar en/of recht op gegevensoverdraagbaarheid of heb je andere vragen/opmerkingen over de gegevensverwerking, stuur dan een gespecificeerd verzoek naar gerritjan@shared.nl.

Om er zeker van te zijn dat het verzoek tot inzage door jou is gedaan, vragen wij jou een kopie van je identiteitsbewijs bij het verzoek mee te sturen. Maak in deze kopie je pasfoto, MRZ (machine readable zone, de strook met nummers onderaan het paspoort), paspoortnummer en Burgerservicenummer (BSN) zwart. Dit ter bescherming van je privacy. Shared zal zo snel mogelijk, maar in ieder geval binnen vier weken, op jouw verzoek reageren.

Shared wil je er tevens op wijzen dat je de mogelijkheid hebt om een klacht in te dienen bij de nationale toezichthouder, de Autoriteit Persoonsgegevens. Dat kan via de volgende link: https://autoriteitpersoonsgegevens.nl/nl/contact-met-de-autoriteit-persoonsgegevens/tip-ons

Hoe wij persoonsgegevens beveiligen Shared neemt de bescherming van jouw gegevens serieus en neemt passende maatregelen om misbruik, verlies, onbevoegde toegang, ongewenste openbaarmaking en ongeoorloofde wijziging tegen te gaan. Als jij het idee hebt dat jouw gegevens toch niet goed beveiligd zijn of er aanwijzingen zijn van misbruik, neem dan contact op met onze klantenservice of via gerritjan@shared.nl. Shared heeft de volgende maatregelen genomen om jouw persoonsgegevens te beveiligen:

  • Gebruik van beveiligde verbindingen (SSL/TLS)
  • Regelmatige beveiligingscontroles en updates
  • Strikte toegangscontroles voor medewerkers en systemen

Deze privacyverklaring is voor het laatst aangepast op 11-06-2024.