Quantcast
Channel: Mavention
Viewing all 715 articles
Browse latest View live

Top 5 aangekondige nieuws features voor jouw moderne intranet

$
0
0

De moderne SharePoint sites in Office 365 zijn volop in ontwikkeling. Op de jaarlijkse Ignite conferentie heeft Microsoft weer mooie aankondigingen gedaan. In deze blog geven we je onze top 5 features voor de nieuwsvoorziening op jouw intranet. Laat je alvast inspireren want, naast het ‘goedkeuren van content’, komen de andere features eind 2018 beschikbaar.

Goedkeuren van content

Een grote wens bij onze opdrachtgevers was de mogelijkheid om content vóór het plaatsen op het intranet goed te keuren. Bijvoorbeeld om een inhoudelijke- of spellingcheck te doen. Die functionaliteit is er nu. Je kunt een goedkeuringsmechanisme op je site instellen dat werkt op basis van Microsoft Flow. Als de Flow aangezet is verschijnt er bij het maken van een nieuwsbericht de button ‘Verzenden voor goedkeuring’ rechts bovenin het scherm. Na indienen krijgen de goedkeurders een notificatie via Outlook.


Targeten van doelgroepen

Je hebt straks meer controle over welke nieuwsberichten er op je homepage verschijnen. Je kunt dan namelijk nieuwsberichten targeten naar specifieke doelgroepen. Publiceer nieuws naar een specifiek bedrijfsonderdeel (Human resources) of bijvoorbeeld locatie (Rotterdam). Dit zorgt ervoor dat medewerkers content zien die daadwerkelijk relevant is voor hen. Het mooie van deze functionaliteit is dat je als content redacteur op één centrale locatie nieuws kunt opvoeren, en vanuit daar aangeeft wie wat moet zien. Deze ‘audience targeting’ functionaliteit, komt beschikbaar voor nieuwsberichten, pagina’s en andere highlighted content webparts.


@mentions in comments

Op dit moment kun je al reageren op nieuwsberichten in SharePoint. Straks kun je in die reactie ook iemand @mentionen. Een @mention zorgt ervoor dat de betreffende persoon in jouw organisatie een notificatie krijgt en zo als het ware in de discussie getrokken wordt. @Mention bijvoorbeeld iemand die een antwoord kan geven, of iemand waarvan jij weet dat die een mening over het onderwerp heeft. Zo stimuleer je de dialoog binnen de organisatie.

 

Creëren van pagina designs

Het is straks mogelijk om één of meerdere pagina designs voor je nieuwsberichten op het intranet te maken. Deze pagina designs kun je selecteren als je een nieuw bericht maakt. Denk bijvoorbeeld aan een design met of zonder plaatje of een design met een specifieke kolomindeling. Het gebruiken van de pagina designs scheelt je als redacteur een hoop tijd: je hoeft niet elke keer een pagina vanaf scratch in elkaar te klikken. Het zorgt daarnaast ook voor consistentie en herkenbaarheid, bijvoorbeeld als je je branding guidelines in het design verwerkt.

 

Opmaak van je titel aanpassen

Je hebt straks meer mogelijkheden om de titel van je nieuwsberichten op te maken. Zo kun je een gekleurd blok over de header leggen en kun je de publicatiedatum, auteur, en labels tonen. Verder maak je je nieuwsberichten op deze manier visueel aantrekkelijker en zorg je dat lezers de belangrijke informatie snel kunnen scannen.

 

Kijktips modern intranet

Wil je meer weten over de nieuwe features voor moderne intranetten en nieuws? Kijk dan deze Ignite sessies terug:

 

 

The post Top 5 aangekondige nieuws features voor jouw moderne intranet appeared first on Mavention.


Big O: When algorithms get complex

$
0
0

Have you ever asked yourself when writing a piece of code if it could perform faster? The answer is most likely: yes. Programming is not only about writing functional blocks. Speed and code efficiency are directly connected to user satisfaction, even if you do not see it right away on your screen. Most frameworks allow you to iterate through collections like its nothing. Until… The collections meet each other.

Track your algorithm speed

An iteration is nothing more than an algorithm running itself for a couple (or dozens) of time. The speed of this algorithm depends on the size of the collection (the amount you run through an iteration), which can be pretty relative. In order to keep track of this speed there’s something called the Big O Notation. It’s kind of like the Big Mac Index, but then without the burger.

Big O

The Big O Notation basically tells how long an algorithm takes to run. It can be used for any programming language and is a way to use math to keep track of… Math. Big O keeps track of how quick the runtime grows. We cannot assume the tested algorithm is always used on the same hardware, therefore we cannot trust runtime speed itself. The growth of runtime however is the same for each set of hardware. The growth of the runtime is measured in ‘n’ which can be described as the size of the collection or input. As ‘n’ gets larger and larger, we could expect the execution to be slower. For simple inputs, lets say we are iterating one collection, we use O(n). Where n is relative to the input. For iterating a collection within a collection we use O(n^2). N is squared because of its nested property. Iterating a collection within a collection within a collection? As you may have guessed: O(n^3). Sounds cool right?

Why use it?

Big O could be hard to understand at the start due to its abstract and mathematical notation. But the more you get used to it, the more you will use it without thinking about it. When it becomes part of your programming routine, your code will definitely benefit from it. How will your code benefit from a mathematical analysis? Well, it makes you think about how fast the code runs, why it runs at that speed and if you could do it better. Surely your code will be happy to get some more attention.

Examples

private static void iterateSimpleCollectionSample(int[] numbers){
    for(int i=0; i< numbers.Length; i++){
        Console.WriteLine("Number: "+ numbers[i]);
    }
}
private static void iterateSimpleCollectionSample2(int[] numbers){
    foreach(var number in numbers)
	{
        Console.WriteLine("Number: "+ number);
    }
}

private static void iterateSimpleCollectionSample3(int[] numbers){
    foreach(var number in numbers)
	{
        Console.WriteLine("Number: "+ number);
    }
    for(int i=0; i<numbers.Length; i++){
        Console.WriteLine("Number: "+ numbers[i]);
    }
    int n =0;
    while(n<numbers.Length){
        Console.WriteLine("Number: " + numbers[n]);
        n++;
    }
}

All three methods above use O(n). The third method which uses three different iterating methods is described as O(3n) which is basically O(n) because it’s still linear. So far; not really that exciting. How about some nested loops?

private static void nestedIterationSample1(int[] numbers){
	List<int> reversed = new List<int>();
    for(var j = numbers.Length-1; j > 0; j--){
		reversed.Add(numbers[j]);
	}
    foreach(var number in numbers)
	{
        Console.WriteLine("Number: "+ number);
        foreach(var reversedNumber in reversed)
		{
            Console.WriteLine("Product: " +  number * reversedNumber);
        }
    }
}

That looks more like a situation you might encounter. Because this method uses one nested iteration it runs in O(n^2). If the array of integers contain 10 numbers it will loop 10*10 times. Imagine if the list contains a thousand numbers! And most importantly; what if a third loop is to be added in the nested loop?

Big O is not always the right way to keep track of runtime growth. For instance: What if we’re iterating through a list of people and we’re looking for ‘Mike’. It is possible Mike is the first one in the list, or the last. If Mike would be the first in the list the algorithm would run at O(1), if not it will run at O(n). In these cases it is not entirely sure how fast the runtime will grow, so it is best to consider O(n) as the runtime growth. 

private static void findPersonInList(string[] people){
    for(int i = 0; i<people.Length; i++){
        if(people[i] == "Mike"){
            Console.WriteLine("Found him at " + i);
        }
    }
}

 

Conclusion

While developing Mavention Workspace we continuously think about code efficiency and performance. Lots of data requires lots of data manipulation and iterations. Big O can be usefull to help understand how efficient iterations are.  It’s better to have O(n) than O(n^x). Therefore optimizing functionality could help speeding up performance. Instead of a double iteration it’s better to split them apart to create a O(n) friendly environment. And if that’s not possible; atleast you thought about code optimization!

The post Big O: When algorithms get complex appeared first on Mavention.

DIWUG Ignite 2018 Recap

$
0
0

Another year another Ignite, so from the 24th till the 28th of September 2018 I was in Orlando for the MSIgnite. So it only made sense to do a DIWUG Ignite recap almost three weeks later. As usual the Ignite was all about the community and all the new stuff that is coming. With 755 sessions on Microsoft 365 and SharePoint and almost 400 hours of recorded materials on those topics doing a recap in 45 minutes was quite challenging.

Ignite Lookbook

In order to inspire everyone with the new capabilities with Modern SharePoint Microsoft released a lookbook. This lookbook contains some beautiful graphics and can help you to convince anyone that Modern SharePoint looks awesome! It contains samples of different options regarding Hub sites, Communication sites and team sites. Each image can be achieved with almost Out of the Box designs. Some of the web parts and options are not yet in first release but during the Ignite Microsoft announced each and every option they show here to be present before the end of the year. A pretty awesome way to start my slides with. You can

Ignite Lookbook image

You can download the Lookbook or visit the SPDesign website for guidance. During the Ignite itself Microsoft also published an overview of most of their announcements in a Book of news. While it does not contain all updates or announcements it served me to get some overview of the updates outside of Microsoft 365 and helped to get a quick overview of things in Azure.

DIWUG Slides

Most of the presentations given by the Product Teams contained a nice overview slide with their roadmap and what is coming. So during my preparations for the DIWUG I downloaded almost all slide decks and sifted through them to get those roadmap slides. Each slide in the presentation is marked with the session number so you can easily find them yourself. I would say that the following ten sessions can help you stay up to date.

  • BRK2136
  • BRK3360
  • BRK3090
  • BRK2102
  • BRK2103
  • BRK2104
  • BRK2105
  • BRK3314
  • BRK3316
  • BRK2064

DIWUG slides download

You can download my DIWUG slides here! If you want a quick overview that dives into a different format you should checkout the slides Cameron Dwyer shared for his Ignite 2018 Sydney User Group session. I had a blast presenting and I hope the slides can help you share the awesome stuff that is coming! Do not hesitate to ping on twitter if you have questions!

Blog overview

As some of you rather read then download slides or watch recordings, you can use the following overview of blogposts that where released during the Ignite and contains most of the important announcements:

Originally posted at: https://www.cloudappie.nl/diwug-ignite-2018-recap/

The post DIWUG Ignite 2018 Recap appeared first on Mavention.

3 levels of CSS-selectors to select all elements

$
0
0

Style-facts part3

This chapter in the series of StyleFacts is about how you can select your element-‘weapon of choice’: The selector. You will see how selectors can be specified for the right cascading effect. You will learn how to overwrite selectors and how to apply selectors on element indirectly by pseudo-selectors. We can select elements. We can select behavior of elements, by selecting the state. We can even select elements that are not really there. That’s where you will reach the last level of selectors the pseudo-element. Let’s see which level of selection is most suited to apply your styles: the selector, pseudo-selector or the pseudo-element selector.

Like most of you might have experienced, writing styles is a balancing act between writing too specific style selectors (which only target one thing) and selectors that are too global (which mess up every thing they hit.)

.page-container div

This for instance. Where ‘div’ is the most widely used element targeting a random ‘div’ within a global class, will target every ‘div’-element on your page. Selecting every class and element along your way to the target, will be the opposite scenario. This is not an efficient way to target the item to be styled. It gives you massive stylesheets that target very little each time.

Types of selectors:

So which type of selectors are there? In styling we have 5 types of selectors. I listed them for you in the preferable order of use:

Class

.class-selector {}

The most preferable selector in my opinion, it targets elements with the class specified after the dot.

Element

element-selector {}

The element-selector weaker then the use of a class-selector and target element types directly.

Attribute

element[attribute="selector"] {}

It is weaker(less specific) then the use of an element-selector and is written between brackets ‘[]’.

Universal

element > * {} /* universal selector*/

Is not specified to an element or a class. It’s a powerful selector, so be careful to use in a global way. it’s presented by an asterix.

ID

#idSelector {}

Strongest selector out there which can be used. This is also it’s problem. If you use a ID-selector in a combination selection. It can overpower a lot of similar combinator descent selections. This is a nice bridge to combinators. It is combining the types of selectors above into a selection.

 

Combinators:

When you combine classes, they will become more specific. This way you can target classes that are nested deeper in your template, without effecting other elements. There are four ways to combine selectors into a combinator: By Descendent, Child, Sibling and General Sibling Combinator. The most known and most used is the Descendent Combinator:

Descendant

.parent-class .descendant-class

This is where a (parent) element and an element in a (few) more nested level is combined in one selector.
The nested level selector does not necessarily need to be a child element of the element targeted by the parent selector. This is how you can skip levels of explicit selectors to get to your target selector, through ‘unique’ landmarks within your template.

Child

.parent-class > .child-class

While it is not necessary to specify direct child elements as selector, this can be enforced in CSS by chaining the combinator with a chevron (arrow) to the right. This will target all the children with specifics of your second selector.

Sibling

.parent-class + .sibling-class

Since CSS2 arrived we are able to target sibling and general sibling elements with combinators. The sibling selector, with the ‘+’ in the example above, is to target the direct next sibling element of the previous chained selector (element). To target all siblings with the next chained selector a ‘~’ can be used. Like in the example below:

General sibling

.parent-class ~ .general-sibling-class

We learned which types of selectors there are: class, element, attribute, universal and ID-selector. We know how to combine them: via descendent, child or general-/sibling. So we are ready to move on to the selectors which can target elements inexplicit. The so called pseudo-selectors.

 

Pseudo selectors

Pseudo selectors enable you to select element inexplicit based on state or location. For Example: if you want the second child of an element with a certain selector. Another example is selecting an element only when hovered upon. There are many pseudo selectors and every month new ones are added as experimental CSS3 selectors. To check availability, go to www.caniuse.com and enter the selector you want to use to check if the most used browsers support it already.

state

We can divide pseudo-selectors in 2 groups: based on targeting location, or based on a specific state of an element. To illustrate the state group we can view pseudo-selectors in action ‘<a>’ link element. See what I did there? 🙂
Below you can see an example of a few common link pseudo-selectors, ‘:hover’, ‘:link’, ‘:visited’:

.link-element:link {}
.link-element:visited {}
.link-element:hover {}

In de the codepen you can see this in action by clicking, hovering or visiting the link. All these different colors and appearance of the link are specified separately. Most of these interactive elements in html come with there browser default styling. Without the styling they would be white on a white background and therefor not visible. many more pseudo-selectors are available to define the state of an element. For instance the ‘:focus’-state when you click on a input field, or the ‘:checked’ state if you select a checkbox or radio button. The full list of pseudo-classes can be found here.

location

The second group of pseudo(-class)-selectors are the selectors to specify the location of the element. You might know the ‘:first-child’ pseudo-selector. This targets the first child of a selected element. So if you have:

.list > div:first-child {} /* selects the first child in the list */

This will select the first child in the element with the [class]-class. It’s possible to target the last child in a similar way. You can do this by defining ‘:last-child’. For every child in between a new pseudo-selector was created. The so called ‘:nth-child’-selector. This selector gives you the possibility to select one or more child elements. You can even write equations in attributes to select different sequences of child elements. Let me clarify this with an example:

.list > div:last-child {} /* selects the last child in list */
.list > div:nth-child(odd) {} /* selects the odd children in list */
.list > div:nth-child(7) {} /* selects the 7th child in list */
.list > div:nth-child(4n+1) {} /* selects child 1,5,9,etc in list */

This kind of selecting can be handy in list or tables in which all elements and rows are of the same elements. It does not matter if the elements are specified with a class. You can target them either way. In the codepen you can find an example of the nth-child targeting. I made you a sort of nth-child hovering memory game :). Can you find all color duo’s by looking at the selectors?
I mentioned that you can add a mathematical equation into the ‘nth-child’-selector. Let’s take ‘4n + 1′ for example. You might recognize this from math-class at high school. It is similar to 4x +1. It selects each fourth child and then shifts the selection by one. Selecting the next element. This means 1 (4 x 0 +1), 5 (4 x 1 +1), 9 (4 x 2 +1) and so on… here’s a detailed blog about the ‘nth-child’-selector.

 

Pseudo- elements

Let’s move on to pseudo-elements. These where introduced in CSS3 to add decoration to elements semantically correct. For instance adding a icon to a button without adding an empty ‘i’-tag or adding targeting a placeholder element that is a invisible element belonging to the ‘input’-element. You can see this selector as ‘selecting a part of an element.’ Normally you would create a new element to do this but now you can target it being part of its original element.
Let’s see the pseudo-element in action:

  .selector-class::before {
    content: "x";
    position: absolute;
    display: block;
    top: 0;
    left: 0;
    width: 30px;
    height: 30px;
    background-color: gray;
  }

You can find a full set of pseudo-element-selectors here. What more magical things you can do with pseudo-elements we will discuss in a later chapter of this blog.

karate kid element selection

karate kid element selection

You now know what selector you can use in which situation. Where to use the type of selectors, where to use combinators, where to use pseudo-elements and where you can use pseudo-elements. You know the specificity of selectors. The elements selector is the strongest. Then classes. Then pseudo and attributes. You are now ready to select any element on the page.

Like with driving a car, writing elegant CSS-selectors comes by experience in writing styles and playing around with branding. The template will be your canvas. Try to use selectors in new learned ways to see what possibilities you have. You will discover many things you would normally solve with Javascript.

StyleFacts part 1

StyleFacts part 2

If you have questions about selector or you have a great addition to this blog please let me know in the comments! Thanks for reading. The next blog will be about responsive design.

The post 3 levels of CSS-selectors to select all elements appeared first on Mavention.

SPSBE Slides: Deploying in a Cloud First World

$
0
0

Deploying in a Cloud First World; continuous integration and continuous deployment. Topics you see arising more and more when developing for Office 365. So with the development model maturing and Office 365 introducing new options for us as developers Octavie and I decided to do a session on how we do our deployments at Mavention. One of the advantages of living in Europe is the amount of SharePoint Saturdays we have near, so we tried our luck at the SharePoint Saturday Belgium and got selected to do a presentation!

Deploying in a Cloud First World

We are thrilled to have done a nice session based on the following abstract:

So you’ve built something awesome for Office 365 and now you want to have it deployed? Is the IT department giving you a hard time? In this session we show you a lot of Developer and IT Pro better-together demo’s how to get your solution in the right place the right way. So while Office 365 and Azure provide you with large scale options, we show how to keep control of your DTAP scenarios in the cloud. You get real world insights in how you can set up your multiple environments and manage your deployments, making sure you stay in control!

Slides and code

To get an overview of all presentations just head to Slideshare and of course our slides are available as well:

As promised during our session we also made our code samples available. A whole lot of these samples can be found on blogs by Octavie (or mine for that matter). All samples used are pushed to GitHub. You can get all the code for our demo’s in the script folder:

  • DEMO SPA ARM – Simple SPA sample based on ARM template deployment with Environment variable
  • DEMO SPA GEO ARM – Simple Geo redundant SPA sample based on ARM template deployment with Environment variable
  • DEMO SPFx Deployment – Simple SPFx package deployment and site provisioning with PNP PowerShell.

The SPFx sample with custom gulp tasks is based on Elio Struyfs gulp task to change environment settings in SharePoint Framework projects and can be used to showcase how to deploy to different environments.

Feel free to reach out to us if you have any questions or would like to se more.

Originally posted at: https://www.cloudappie.nl/spsbe-slides-deploying-in-a-cloud-first-world/

The post SPSBE Slides: Deploying in a Cloud First World appeared first on Mavention.

Test de levensvatbaarheid van je idee met een design sprint

$
0
0

Begin september faciliteerde Mavention een design sprint bij Mavim. Mavim biedt meer dan 1.000 organisaties een platform dat bedrijfstransformaties en continue verbeterinitiatieven helpt te effectueren. In het kader van ‘de toekomst is de Cloud’ was de initiële opdracht van het team om hun applicatie Mavim platformonafhankelijk en browser-based te maken. Maar hoe begin je daarmee? Moet je alles een-op-een overnemen? Er zit 20 jaar historie in hun applicatie. Of is dit een mooi moment om een verbeterslag te maken? Met een design sprint kun je razendsnel je ideeën testen.

Focus op de ideeën

Als facilitator zorg ik dat het team heel breed en algemeen begint en zo steeds gerichter naar de juiste oplossing toewerkt. Bij design sprints is er geen discussie, iedereen gaat naar aanleiding van de eerste verhalen en vraagsessies zelf ideeën bedenken. Die plakken we, anoniem, op een flipover of whiteboard en dan gaan mensen stemmen. Op die manier maakt het idee van de marketingman met de ‘snelle praatjes’ net zoveel kans als het idee van de introverte computernerd. Zo focus je op de ideeën, niet op de presentatie.

Kijken naar de sprintvragen

Na de eerste vraagsessie gaan we zaken als langetermijndoelen neerzetten. Groot denken mag. Zo kan een doel zijn: over twee jaar willen wij de Netflix van het procesmanagement zijn. Dan gaan we ook kijken naar de sprintvragen: wat zijn de vragen die we beantwoord willen hebben als het product klaar is. Bij Mavim kwam al snel de volgende sprintvraag naar voren: kunnen we een product neerzetten waarmee we onze doelgroep kunnen verbreden? Wat als je een versie maakt met alleen de essentials? Dan kun je het product misschien nog breder uitrollen.

Enorm veel whiteboards met post-its

Zo heb je na een ochtend en een deel van de middag enorm veel whiteboards met post-its om je heen staan. Dan beginnen we met het uitdenken van ideeën. Allereerst kijken we of de verzamelde informatie in een userflow gezet kan worden: de gebruiker begint hier, doet dan x en daarna y en komt via z bij het einddoel. Dan bepalen we op welk stuk we ons in eerste instantie gaan richten.

Afzijdig van de inhoud

Als facilitator hou je je afzijdig van de inhoud. Je zorgt dat het energielevel optimaal is, de snacks ruim aanwezig en het engagement hoog. Wanneer je merkt dat mensen wat geremd zijn, doe je wat oefeningen om het creatieve proces op gang te krijgen. De bedoeling is dat mensen zich vrij voelen en niet bang zijn om fouten te maken.

Innovatie vanuit de gebruiker

Mavim is een softwarebedrijf. Die hebben legio techneuten in huis. Deze sessie hebben we expres met zo min mogelijk techneuten gedaan. Een grote ‘omdenk-actie’: bij veel traditionele softwareclubs komt innovatie uit de technische hoek. Met deze sessies denken we vanuit de gebruiker en gaan we daarna pas kijken wat de juiste oplossing is. Dat kan het prototype van een technische oplossing zijn, maar er kan ook iets totaal anders uitrollen. Misschien komt er wel een marketingfolder uit die vertelt wat het product gaat zijn. Het eindproduct van een designsprint is niet per definitie een applicatie.

Design sprints als onderdeel van projectmethodiek

Zo kunnen design sprints onderdeel worden van een projectmethodiek. Om zeker te weten dat je iets gaat bouwen dat zinvol is, kun je je ideeën eerst toetsen met design sprints. In vier dagen heb je een prototype – of iets anders – en kun je direct testen of iets werkt en of je op de goede weg zit.

Enthousiasme en waardevolle feedback

Bij Mavim is het team op de vierde dag van de design sprint hun prototype gaan testen met vijf eindklanten. Heel spannend, maar het concept is goed ontvangen door alle vijf de klanten. Ook was er waardevolle feedback. Zo vonden drie van de vijf bijvoorbeeld de samenwerkfunctie overbodig en zouden ze liever gebruikmaken van Microsoft Teams. In eerste instantie is dat even balen; het team dacht tenslotte dat het een goed idee was. Maar nu zijn ze er na een halve dag werk achter gekomen; wat als ze er na zes maanden achter zouden zijn gekomen?

Meer weten?

Ook nieuwsgierig hoe je in jouw organisatie design sprints kunt inzetten? Een facilitator nodig of een partner nodig die je helpt het prototype te vertalen naar een technisch ontwerp? Neem vrijblijvend contact met ons op.

 

The post Test de levensvatbaarheid van je idee met een design sprint appeared first on Mavention.

A beginner’s guide to binary search

$
0
0

Searching. One of the most crucial activities performed on datasets. Think of a world with lots of data, but no possibility to filter relevant info for yourself. Sounds pretty stone-age right? Thankfully we have lots of options to perform the craziest search queries on huge datasets. These options are available to us for quite some time, and we got used to perceiving lots and lots of data. In this digital age we tend to thrive for the most efficient ways to gather data, but besides that: we want it fast. So how do we search through data in a quick way? In this technical blogpost I will shine my light on one of the most underrated searching methods: Binary searching. It is one of the quickest ways to retrieve data, but it has its downsides.

Binary searching – The basics

As the name gives away binary searching is a about 0 and 1: yes or no, true or false. This method doesn’t aim to look for an array item by looping through an array and waiting for it to bounce back a result. Instead it uses something what looks like a “warmer, colder”-kind of approach. But then without the “colder”. Imagine playing a game of hide and seek and you get to ask the person that is hiding to shout their name every 5 seconds. You’ll get their location in no time!
Binary searching loops through an array by looking for an item and asking the array if it is nearing it. To summarize the method in one sentence:

“Search an array by splitting it in half – each iteration.”

Let’s say we have an array of 10 integers and we’re looking for the number 2. Normally we would have to loop through the entire array until the iteration finds ‘2’. For this number it will take 3 iterations to get to number 2 (3rd position in the array) but it could also take 11 loops if the number is 10. Binary searching tries to optimize the efficiency of searching this array. Instead of looping through the entire array it splits the array in half each time. It does this by determining a minimum and a maximum. Both variables will change each iteration until the number is just between the two, at which the number has been found.

Binary searching – Code example

In the below example I have created a binary searching method which retrieves an array of integers and a number that it needs to find. It defines a leftIndex (the index of the minimum position it needs to look at) and a maxIndex (which is always the length of an array minus one). It will iterate with the condition that the minimum index plus one needs to be smaller than the maxIndex. This will prevent us from looping outside of the array (in case we’re looking for number 11). Inside the loop we define between what positions we need to check. Then we split that up by dividing by 2. Finally we will define the current position we’re looking at which is the minimum plus the (max) position of the divided variable (lookTill). We check its value with the given number and decide if it is bigger than or smaller than the current value. Inside the if else statement we basically tell our method to move to the left or to the right by determining the minimum and maximum look up positions.
However, if the current number is the number we’re looking for there is no need to iterate any further!

private static bool FindNumberNormallyInArrayBinaryStyle(int number)
    {
        int leftIndex = -1;
        int maxIndex = nums.Length-1;
        while (leftIndex + 1 < maxIndex)
        {
            nonRecursiveBinaryAttempts++;
            int lookBetween = maxIndex - leftIndex;
            int lookTill = lookBetween / 2;
            int lookAt = leftIndex + lookTill;
            long currentValue = nums[lookAt];

            if (currentValue > number)
            {
                maxIndex = lookAt;
            }
            else
            {
                leftIndex = lookAt;
            }
            if (currentValue == number)
            {
                return true;
            }
        }
        return false;
    }

Binary searching – To recurse or not to recurse

The above example demonstrates how to use binary searching without using recursion. But perhaps we could make this code cleaner, more efficient or just way more awesome by using recursion (another recursion example here)!  The below code shows how to make it recursive.

private static bool FindNumberRecursivelyInArrayBinaryStyle(int number, int leftIndex, int maxIndex)
    {
        if (leftIndex + 1 < maxIndex)
        {
            recursiveBinaryAttempts++;
            int lookBetween = maxIndex - leftIndex;
            int lookTill = lookBetween / 2;
            int lookAt = leftIndex + lookTill;
            long currentValue = nums[lookAt];

            if (currentValue > number)
            {
                maxIndex = lookAt;
            }
            else
            {
                leftIndex = lookAt;
            }
            if (currentValue == number)
            {
                return true;
            }
            else
            {
                return FindNumberRecursivelyInArrayBinaryStyle(number, leftIndex, maxIndex);
            }
        }
        else
        {
            return false;
        }
    }

Binary searching – But.. IS it faster?

So we now know how to make a binary searching method. But does it do the trick? Is it worth creating your own searching method instead of using general methods like .Where, .filter, .any or using brute force techniques like foreach and while(i<nums.Length). I have created a demo console application that shows the execution speed per techniques. I have tested 5 techniques:
– Binary search with recursion
– Binary search without recursion
– Old-school style (for looping)
– Searching with a lambda expression (general)
– Linq style searching (C# only)

The results? See below. Or try it out using the dotnetfiddle I have created here.

Finding number 90 in an array with numbers between 0 and 9999999. Recursive binary style takes 23 loops, 0.0026 milliseconds. Non-recursive binary style takes 23 loops, 0.0008 milliseconds. Old-school style takes 91 loops, 0.0008 milliseconds. Lambda style finished in 42.0569 milliseconds. Linq style finished in 33.912 milliseconds.

Here we have given the program the number 90 to find. This number is pretty close to the start of the array. No wonder that the old-school/brute-force method works pretty quick (It runs with O(91). The two binary searches are also quick. But looping an array 90 times apparently gives us no reason to pick binary search as iteration method.Finding number 5050505 in an array filled with numbers between 0 and 9999999. Recursive binary style loops 22 times, 0.0026 milliseconds. Non recursive binary style loops 22 times, 0.0017 milliseconds. Old-school style loops 5050506 times, 22.5992 milliseconds. Lambda style finished in 34.9058 milliseconds. Linq style finished in 35.2623 milliseconds.

The number 5050505 is further away from the start of the array than the previous test. And we can clearly see the difference: 22.5992 milliseconds for Old-School looping and 0.0017-0.0026 milliseconds for binary searching! Finding number 99999999 in an array filled with integers between 0 and 9999999. Recursive binary style loops 24 times, 0.0031 milliseconds. Non recursive binary style loops 24 times, 0.0017 milliseconds. Old-school style loops 10000000, 37.0759 milliseconds. Lambda style finished in 35.3435 milliseconds. Linq style finished in 35.149 milliseconds.

What about a number that does not exist in the array? This means the brute force loop will run through the array nums.Length-1 times. The array is filled with numbers between 0 and 9999999. Adding another 9 shows us that the binary searches are way quicker than the other three methods.

The reason why Lambda and Linq show slow results are simple. Methods like .find and .where or using data query structures with Linq pretty much do the same as brute force looping: iterating the entire list. The real benefit in using lambda and linq is readability and clean code. Linq contains lots of overheads. But sure; it’s perfect if you want to retrieve data in complex structures. What Linq really does when using a data query like I used in my code is transforming it into a more complex lambda expression. That’s why both lambda and linq approaches are quite similar in results.

Conclusion

I hope you have enjoyed this quick tour into binary searching. As I tried to emphasize in my last post about runtime growth, it’s a requirement that every programmer should think about the why’s and when’s on using filter/search algorithms. As we have seen in the examples lambda en native linq are pretty much the same. And I can tell you; using linq with lambda will give us no significant performance boost. If we have a small array the brute force approach is just as efficient as using a binary search. But, if we have a large list of numbers its better to use a binary search. Recursive or non-recursive I hear you say? As we have seen it’s pretty much the same. But if you’re really interested in the tiniest of milliseconds I’d say go for a non-recursive method. Recursive methods are most fun when using nested data. Keep in mind however that binary searching methods only work in sorted arrays!

Questions? Or do you have suggestions? Be sure to mail me by using the mail button under my avatar!

The post A beginner’s guide to binary search appeared first on Mavention.

Gebruikersbijeenkomst Make 5.0

$
0
0

 

Op dinsdag 11 december om 12.00 uur praten we onze relaties graag bij over de laatste ontwikkelingen en nieuwe features in Mavention Make tijdens onze jaarlijkse gebruikersbijeenkomst.

Tijdens deze middag zullen onze product manager Robert Jaakke en onze CTO en Microsoft MVP Albert-Jan Schot een deep dive demonstratie geven van alle nieuwe en verbeterde functionaliteiten van Make 5.0. Daarnaast delen we tijdens deze bijeenkomst ook onze plannen voor de toekomstige releases en kunnen de bezoekers vragen stellen aan ons product team.

Aan bod komen onder andere de volgende onderwerpen:

  • Een mooie functionaliteit dat Make klaarmaakt voor de toekomst: de mogelijkheid om, naast SharePoint sites en Office 365 Groepen, ook Teams te provisionen op basis van templates.
  • Een mechanisme waarmee sites en Teams eenvoudig kunt valideren ten opzichten van templates en eventuele verschillen kunt identificeren en herstellen.
  • Optimalisatie in gebruikersvriendelijkheid.
  • Onze Roadmap voor 2019.

 

Bedenk jij samen met ons de features voor Make 5.5?

We laten ons graag inspireren met de ideeën vanuit de markt en we ontwikkelen Make graag in co-creatie met onze relaties. Op 11 december krijgen de bezoekers van de sessie kans om eigen ideeën en suggesties met het product team te delen. Welke functionaliteiten zijn voor jullie belangrijk in Make 5.5? Waar lopen jullie organisaties tegenaan met betrekking tot provisioning van sites, groepen en teams? Jullie input helpt ons in de verdere ontwikkeling van Mavention Make.

Agenda van deze middag:

Datum: 
11 december 2018

Programma:
12:00 -13:00                Lunch
13:00 -15:00                Make 5.0 – nieuwe features en toekomst visie & brainstorm Make 5.5
15:00 – 15:30             Koffie pauze
15:30 -16:30                Make spreekuur

Locatie:
Kantoor Mavention (Caballero Fabriek)
Saturnusstraat 60, unit 39
2516 AH, Den Haag

Wil jij bij dit evenement aanwezig zijn? Schrijf je dan hier in! (Registratie verplicht)

 

The post Gebruikersbijeenkomst Make 5.0 appeared first on Mavention.


AppSettings in your SPFx solutions

$
0
0

With the SPFx framework you can make really cool web parts and extensions for SharePoint. In this blog I want to show you a little trick that can help develop your solutions. An easy way to set up an App settings file in your solution.

We came up with this solution when we were developing our last project that included a solution with 4 web parts. These web parts had a few variables that were used across all four. There were some configuration settings as well like an API address and API ID. Especially configurations are annoying, because every time you switch between development environment and production you need to switch those configurations. The lazy developer that I am I would like to do that with the least bit of effort and not change these configurations at a gazilion places throughout my solution.

This idea was basically copied from the way the SPFx framework and generator uses language files. When you generate a new SPFx project with the Microsoft generator. In your web part folder you get a folder ‘loc’ with two files: ‘en-us.js’ and ‘mystrings.d.ts’. These files define certain localized values of variables. If you add more language files besides the en-us one that is provided you get multi-lingual support for your solution.

In these files you can create a module with a set of variables. In your webparts you can import the module that is exported. The variables from the module can then be used as a typed instance throughout your solution and then values are inserted.

We are going to use this setup to create an appSettings file for our solution. In your webparts folder create a file called: appSettings.js with content like this:

define([], function() { return { "StringValue": "The answer to life the universe and everything:", "NumberValue": 42, "BooleanValue": true } });

And then an AppSettings.d.ts file next to it with this content:

declare interface IAppSettings { StringValue: string; NumberValue: number; BooleanValue: boolean; } declare module 'AppSettings' { const appSettings: IAppSettings; export = appSettings; }

Then we have to add a reference to this file in the config.json(found at the top level in the folder ‘config’) file with the localized resources. There should already be a reference to the language file in the localized resources, just add your appSettings file there:

"localizedResources": { "AppSettingsBlogWebPartStrings": "lib/webparts/appSettingsBlog/loc/{locale}.js", "AppSettings": "lib/webparts/appSettings.js" }

If you have given your appSettings a different name or placed it in a different position, adjust accordingly. (tip: just run gulp serve on your project and look for it in the lib folder if you are not sure how to reference it)
Then the final step is to import the module wherever you want to use it. You can import it anywhere with the follow statement:

import * as appSettings from 'AppSettings';

The module is then available for that class or component, including typings. You can always add more variables by adding them to the file and they will become available. My main component now looked this:

import * as React from 'react'; import * as appSettings from 'AppSettings'; import styles from './AppSettingsBlog.module.scss'; import { IAppSettingsBlogProps } from './IAppSettingsBlogProps'; export default class AppSettingsBlog extends React.Component<IAppSettingsBlogProps, {}> { public render(): React.ReactElement<IAppSettingsBlogProps> { return ( <div className={ styles.appSettingsBlog }> <div className={ styles.container }> <div className={ styles.row }> <div> <p>String value: {appSettings.StringValue}</p> <p>Number value: {appSettings.NumberValue}</p> <p>Boolean value: {appSettings.BooleanValue}</p> </div> </div> </div> </div> ); } }

The result looks this:

The post AppSettings in your SPFx solutions appeared first on Mavention.

Nu ook Microsoft Teams uitrollen met Mavention Make

$
0
0

Nu ook Microsoft Teams uitrollen met Make

De gebruikers van Mavention Make ervaren de voordelen van het automatisch uitrollen van SharePoint sites en Office 365-groepen met behulp van sjablonen al geruime tijd. Eén van de wensen die ons productteam regelmatig ontvangt, is de mogelijkheid tot het uitrollen van Teams met behulp van sjablonen.

Microsoft heeft onlangs de Graph API uitgebreid waardoor het nu mogelijk is om Teams aan te maken. Het productteam van Mavention heeft hier gelijk op ingespeeld!

In het nieuwe Mavention Make 5.0 kunnen onze klanten ook Teams uitrollen op basis van sjablonen. Deze kunnen uiteraard je branding en documentbibliotheken bevatten, maar ook kanalen en ondersteunende applicaties zoals OneNote en Planner.

Daarnaast worden in de nieuwste versie van Mavention Make ook alle acties rondom SharePoint sites, Office 365-groepen en Teams bijgehouden zodat je een geschiedenis in je omgeving opbouwt. Hiermee kun je uiteindelijk je omgeving valideren ten opzichte van eerdere sjablonen en eventuele verschillen identificeren en herstellen.

Kortom Mavention Make 5.0 biedt je belangrijke verbeteringen en nieuwe functionaliteiten waarmee jij en je collega’s efficiënter, veiliger en effectiever aan de slag kunnen met Office 365!

Meer weten?
Bekijk de Mavention Make productpagina

of stuur een email naar info@mavention.nl

 

The post Nu ook Microsoft Teams uitrollen met Mavention Make appeared first on Mavention.

Using PowerShell DSC in ARM Templates

$
0
0

In one of my previous posts I introduced Azure Resource Manager templates, aka ARM templates. These templates are great for deploying and configuring Azure Resources like virtual networks, virtual machines, Azure websites, Azure key vaults, etc. But sometimes you need a little bit more automated configuration that goes beyond ARM template functionality. A good example is provisioning a Virtual Machine with additional components like Active Directory, DNS or even SQL Server instances. In this article I’ll introduce PowerShell Desired State Configuration (DSC) and how to use it with your ARM templates.

PowerShell DSC

DSC is a feature/extension of PowerShell (from version 4.0 and up). As the name says, you can create a configuration (a declarative PowerShell script) that defines the desired state of a Virtual Machine. This way you can maintain consistency across devices. For example, you can create a configuration that your virtual machine running Windows Server needs to have IIS installed. This can be achieved by ensuring the Windows features Web-Server and Web-Mgmt-Tools:

Configuration MyWebServerCfg {

    Import-DscResource -ModuleName PsDesiredStateConfiguration

    Node 'localhost' {

        # The first resource block ensures that the Web-Server (IIS) feature is enabled.
        WindowsFeature IIS {
            Ensure = "Present"
            Name   = "Web-Server"
        }

        # The second resource block ensures that the Web-Mgmt-Tools feature is enabled.
        WindowsFeature IIS-Tools {
            Ensure    = "Present"
            Name      = "Web-Mgmt-Tools"
            DependsOn = "[WindowsFeature]IIS"
        }

    }
}

Every time you execute this configuration, your machine will be in the desired state of having IIS installed. As you can see in this example I have defined 2 DSC resources based on WindowsFeature. The second one is even depending on the first one, which means that the feature will be installed and enabled after the first one has finished. That’s cool, isn’t it? With each DSC resource you can set properties with required values.

I won’t be explaining writing and using PowerShell DSC in too much details, but you can find good resources over here:

Custom PowerShell DSC Resources

Of course, PowerShell DSC also has a great community and they have lots of custom DSC resources available for you. Please take a look at Github and the PowerShell Gallery for some awesome DSC resources!

Wouldn’t it be cool to create some Azure VMs, install and configure a Windows Active Directory Domain, set up DNS, install SQL Server and a SharePoint farm? I think that’s awesome. And yes, the community has some really cool custom DSC Resources available for you to use.

Using DSC Resources in your project

Before you can use the custom DSC resources, you need to install the package. However, when you deploy an Azure VM with a ARM template, then you have a challenge installing that package on the newly created VM while deploying the ARM template. Another approach is to download the source branch of the DSC resource and add it to your project. In my case I have created a folder DSC and added several custom DSC resources to that folder:

image

Then I create my custom DSC configuration scripts, that need to be executed on one of more Azure VMs. In my case I created a ProvisionDC.ps1 that configures several windows features to enable Active Directory Domain Services, DNS, provisions the attached Azure DataDisk, creates some folders, adds several OUs and user accounts, etc. The other configuration scripts provisions SQL Server instances, adds the VM to the domain, provisions Firewall Rules, etc..

The question is now: how to get these scripts on the Azure VM and execute them?

Azure VM Extensions

To answer the previous question, you can use Azure VM Extensions. There is a PowerShell DSC extension that you can use in your ARM template. I have defined a resource of type extensions and this resource is part of my VM resource.

image

Take a look at the following snippet from my ARM template:

"resources": [
    {
        "name": "CreateADForest",
        "type": "extensions",
        "apiVersion": "2016-03-30",
        "location": "[parameters('location')]",
        "dependsOn": [
            "[resourceId('Microsoft.Compute/virtualMachines', variables('vmDCName'))]"
        ],
        "properties": {
            "publisher": "Microsoft.Powershell",
            "type": "DSC",
            "typeHandlerVersion": "2.19",
            "autoUpgradeMinorVersion": true,
            "settings": {
                "ModulesUrl": "[concat(parameters('locationScripts'), '/ELB_DSC.zip', parameters('locationScriptsSasToken'))]",
                "ConfigurationFunction": "ProvisionDC.ps1\\ProvisionADDomainController",
                "Properties": {
                    "DomainName": "[parameters('domainName')]",
                    "AdminCreds": {
                        "UserName": "[parameters('adminUsername')]",
                        "Password": "PrivateSettingsRef:AdminPassword"
                    }
                }
            },
            "protectedSettings": {
                "Items": {
                    "AdminPassword": "[parameters('adminPassword')]"
                }
            }
        }
    }
],

In the properties I define that this extension is of type PowerShell DSC. In the Settings I have a reference to a ZIP file. This ZIP file is stored in an Azure Storage Account. When this Azure VM Extension is deployed by the ARM template, this ZIP file gets downloaded and unzipped on disk in the VM. Then it executes the script ProvisionDC.ps1 and the configuration named ProvisionADDomainController. This is configured by the property ConfigurationFunction. And yes, you can also supply parameters to the configuration. In my case I supply DomainName and the Administrator Credentials.

Uploading your DSC zip file

How does the ZIP file get it in the Azure Storage Account? Well, you could do it manually, but I like automating stuff. Within the PowerShell script that deploys the ARM template, I also have created some PowerShell script to create the ZIP file and upload it to the Azure Storage account:

function Prepare-DSCScripts()
{
    $zipFileName = "ELB_DSC.zip"
    $sourcePath = Join-Path $PSScriptRoot "..\DSC\*"
    $destinationPath = Join-Path $PSScriptRoot $zipFileName

    if( Test-Path $destinationPath ) {
        Remove-Item -Path $destinationPath -Confirm:$false
    }

    Write-Host "`tCompressing to file $zipFileName " -NoNewline
    Compress-Archive -Path $sourcePath -DestinationPath $destinationPath
    Write-Host -f Green "[Done]"
}

function Upload-DSCScripts( $context )
{
    $containerName = "scripts"

    $containerState = Get-AzureStorageContainer -Name $containerName -Context $context -ErrorAction SilentlyContinue
    if ($null -eq $containerState) {
        $container = New-AzureStorageContainer -Name $containerName -Context $context
    }
    
    $fileName = "ELB_DSC.zip"
    Write-Host "`tUploading $fileName " -NoNewline
    $blob = Set-AzureStorageBlobContent -File $fileName -Container $containerName -Blob $fileName -Context $context -Force
    Write-Host -f Green "[Done]"
}

From here I provide a final location of the script and a SASToken to the final ARM template that deploys the VM and DSC extension.

So, what happens on the VM?

During the deployment of the DSC extension, the ZIP gets downloaded and unzipped on the disk. That looks like this:

image

The PowerShell DSC extension is installed in C:\Packages\Plugins and your custom DSC Resources and configuration scripts are unpacked in a subfolder named DSCWork. From there, your configuration is executed where it uses the custom DSC resources that are compiled in a MOF file located in the subfolder ProvisionADDomainController.

And with that, your ARM template will be deployed successfully ending up with very much completed provisioned Azure VMs.

image

Summary

Extending your ARM templates with the PowerShell DSC extension gives you a powerful and flexible way of provisioning your Azure VMs. It is possible to completely deploy your SharePoint infrastructure unattended. And if you set up your scripts wisely you can even support DTAP environments this way!

Originally posted at: http://blog.octavie.nl/index.php/2018/11/23/using-powershell-dsc-in-arm-templates

The post Using PowerShell DSC in ARM Templates appeared first on Mavention.

Gratis whitepaper: In 3 stappen naar adoptie van Office 365

$
0
0

In 3 stappen naar adoptie van Office 365

Onze businessconsultants Alex Verheij en Floor de Wit zijn geïnterviewd over hun expertise met betrekking tot adoptie van Office 365.
In dit interessante whitepaper worden handvatten gegeven hoe je ervoor kunt zorgen dat je medewerkers Office 365 omarmen.

Hoe zorg je voor een succesvolle vernieuwing van je digitale werkplek?

Download de whitepaper hier:  In 3 stappen  naar adoptie van Office 365

The post Gratis whitepaper: In 3 stappen naar adoptie van Office 365 appeared first on Mavention.

Microsoft Graph API: How to change images

$
0
0

Mavention Workspace has the ability to easily change the image of a group (or as we like to call them: Workspace). This will set the new image visible on all platforms including Microsoft Teams (if it is a Teams workspace), Outlook and SharePoint. This sounds like an easy to write code-module. And when I began writing the module, I thought just the same. However, there are some tricky parts in communicating with the Graph API if you want to send files. In this blog I will elaborate on how to upload images using the Microsoft Graph API.

Graph API endpoint

In order to upload or replace an image and make it available on all platforms we have to update the values that already exist . The endpoint we are looking for is described here.

As you can read in the documentation there are some permissions that have to be set according to your needs:

  •  User.ReadWrite -> For the profile picture of the signed in user
  •  User.ReadWrite.All -> For the profile picture of any user in the organization, on behalf of the app’s identity
  •  Group.ReadWrite.All -> For the profile picture of a group
  •  Contacts.ReadWrite -> For the photo of a contact

For uploading a group image this endpoint will do:

PUT /groups/{id}/photo/$value

Call the Graph API

This is where the tricky parts starts. We have to give some value to the endpoint, and as you can read in the Microsoft Docs it cannot be a Base64 string, which would be a lot easier. Instead, the endpoint expects binary data of the image. But how to convert a Base64 string to binary data? It’s easy to say a Blob will do some magic. But then again; how to put this huge string into a Blob?

Firstly the base64 string has to be gathered from the uploaded file. Once a file is selected using a simple <input type=”file”/> we can access the data. This can be done with the following code:

var file = document.querySelector('#fileInput').files[0];

public uploadImage() {
    getBase64String(file).then(base64Image => {
        const groupId = 'The group ID here';
        const request = {
          method: 'PUT',
          url:  'https://graph.microsoft.com/v1.0//groups/' + groupID + '/photo/$value',
          responseType: 'application/json',
          data: base64Image
        };

        this.$http(req).then(result => {
          // Image has been set
        }, (err) => {
          // Image has not been set
        });
    });
  }

public getBase64String(file: any) {
    return new Promise((resolve, reject) =&gt; {
        const reader = new FileReader();
     reader.readAsDataURL(file);
    reader.onload = () =&gt;
        resolve(reader.result);
        reader.onerror = error =&gt; reject(error);
    });
}

 

On this page I have found a way to convert Base64 strings to binary data and return a blob which we can send to the Graph API endpoint. The answer of Jeremy also contains information that helps you understand what is actually going on in the function. However, this function will not work if you are calling it with a base64 string that is gathered by something like this:

var file = document.querySelector('#fileInput').files[0];

This is because the file is rendered with ‘data:image/{imageType};base64/’ infront of it. So in order to directly gather the base64 string from an HTML element we have to remove this part of the string. This can be done by replacing:

var byteCharacters = atob(base64Image);

With:

var byteCharacters = atob(base64Image.replace(/^data:image\/(png|jpeg|jpg);base64,/, ''));

Performance

As you can read in Jeremy’s answer he has roughly tested the performance of the b64toBlob function.
I have tried to test it abit further. As you can see on the same page of Jeremy’s answer another developer used 1024 as sliceSize, where as Jeremy used 512. So, what is the exact difference? And why split the length anyways?  Obviously the performance speed differs per machine, but just for the sake of reference I performed some tests.
I have used four slicesizes to see how it affects performance speed. For each sliceSize I uploaded three different images. One of a few kB, one of 1.94Mb and one of 3.91Mb. 4Mb is the maximum size the endpoint accepts, so that makes +/- 2Mb a nice average.

No slices

When using no sliceSize, or set sliceSize to base64Image.length we get the following results:
We can see some exponential time difference between the three images, which is expected.

File size: 10.66Kb, String length: 14570, Execution time: 0.8139msFilesize: 1.94Mb, string length: 2710978, execution time: 53.123779ms

File size: 3.91Mb, String length: 5468183, Execution time: 144.135ms

Slicesize 512

Let’s see how Jeremy’s recommendation works out.
We see that files around 2Mb are slower than when using a sliceSize of base64Image.length. However, large files seems to be quicker!

File size: 10.66Kb, String length: 14570, Execution time: 1.090087ms File size: 1.94Mb, String length: 2710978, Execution time: 79.64013ms

File size: 3.91Mb, String length: 5468183, Execution time: 119.24121ms

Slicesize 1024

Let’s see how that other suggestion turns out.
Clearly this slicesize is faster than the previous two sizes.

File size: 10.66Kb, String length: 14570, Execution time: 0.883056msFile size: 1.94Mb, String length: 2710978, Execution time: 58.1508789ms

File size: 3.91Mb, String length: 5468183, Execution time: 98.963134ms

Slicesize 2048

We see that doubling the slicesize has a positive effect between 512 and 1024. Can we speed it up even more when doubling 1024?
I guess this is where we have to draw the line. 1024 Is faster than 2048, so we can assume that
4096 won’t be faster than 1024.

File size: 10.66Kb, String length: 14570, Execution time: 0.80712ms File size: 1.94Mb, String length: 2710978, Execution time: 67.643066ms

File size: 3.91Mb, String length: 5468183, Execution time: 108.047851ms

Conclusion

Setting an image for users, groups or contacts is doable via the Graph API. It’s the conversion from base64 to binary data that can be a bit difficult. The documentation is clear on what the endpoint expects, but does not state a way how to convert a file to binary. As for performance; if you think your users will use large files between 2.5 and 4Mb consider using the sliceSize of 512. For small to average files using the total length of the base64 string will do no harm and can even speed things up. Here’s a quick tip for you: How about first checking the filesize and set the slicesize accordingly?

I hope this blog has helped you. If you have questions or comments feel free to mail me!

See you next blog 😉

The post Microsoft Graph API: How to change images appeared first on Mavention.

Eén overzicht van alle SharePoint sites, Office-365-groepen en Teams? Jawel, het kan!

$
0
0

Office 365, het is een zegen. Althans, dat vinden wij. Maar soms ben je het overzicht volledig kwijt. Je zoekt bepaalde informatie en hebt geen idee meer waar het stond. Was het een SharePoint-site, een Office-365-groep, een communication site of in MS Teams? En als administrator zie je soms helemaal door de bomen het bos niet meer. Welke groups zijn er, welke teams, welke sites? Welke zijn actief en welke totaal niet? Wie is de eigenaar en wie zijn de leden?

Onze handen jeukten

Wij zagen dat veel eindgebruikers en administrators met deze vragen worstelden. Als club die erin gelooft dat technologie in dienst van de mens moet staan jeukten onze handen natuurlijk. Daar moesten we iets mee! Net voor deze zomer zijn we hard aan de slag gegaan en we zijn er dan ook trots op dat we nu Mavention Workspace kunnen lanceren. In één klap een duidelijk overzicht van al je workspaces – lees: SharePoint-sites, Office-365-groepen en Teams – om zo nog efficiënter te werken in Office 365, of dat nu is op PC, laptop, tablet of mobiel.

Alles bij elkaar in een handig overzicht

Binnen Mavention Workspace worden alle workspaces als kaartjes op een duidelijke overzichtspagina getoond. Die kaartjes zitten vol slimme functies. Zo kun je op ‘Leden’ klikken en direct zien welke collega’s ook meewerken in een project of lid zijn van de Office-365-groep. Maar je kunt ook vanaf een kaartje direct naar de bestanden van de workspace gaan, naar de gesprekken van de bijbehorende group of naar de planner. Zo klik je direct naar alle productiviteitstoepassingen die aan een workspace zijn gekoppeld. Met één klik gelijk toegang tot alle relevante content. Op de overzichtspagina kun je ook direct naar My Workspaces – alle workspaces waar jij lid van bent – of naar je Favoriete Workspaces. Binnen All Workspaces kun je door je bedrijfsworkspaces bladeren om deel te nemen aan interessante workspaces.

Zoek, filter en vind gericht wat je zoekt

Met Mavention Workspace is het ook mogelijk om te zoeken naar een workspace of je SharePoint-sites, Office-365-groepen en Teams te filteren. Filter je bijvoorbeeld op de locatie of land van een bepaald project, dan zie je alle projecten die op die locatie of in dat land uitgevoerd worden. Zo kun je ook filteren op afdeling of een thema als innovatie of duurzaamheid. Daarna kun je verder filteren op bijvoorbeeld sector, sitetype of status. Zo kom je precies in de juiste workspace terecht. Als beheerder bepaal je de hoofdcategorieën van de workspaces en als eigenaar van de SharePoint-site, Office-365-groep of Teams kun labels toevoegen waarop gebruikers kunnen filteren. Zo zorg je ervoor dat jouw workspace beter gevonden wordt.

Het creatieproces versimpeld

Vanuit Mavention Workspace kun je ook een nieuwe workspace aanmaken, of dat nu een SharePoint-site, Office-365-groep of in Teams is. De beheerder heeft ingesteld van welk type deze workspaces kunnen zijn, de gebruiker bepaalt de titel, de members en geeft meteen labels mee zoals bijvoorbeeld locatie, project, sector, afdeling, taal of werkbedrijf. De SharePoint-site, Office-365-groep of Teams worden aangemaakt – al dan niet nadat het goedkeuringsproces is doorlopen – en de workspace staat direct in het overzicht van Mavention Workspace. Door Mavention Workspace te koppelen aan ons product Mavention Make kun je ervoor zorgen dat tijdens het creatieproces de juiste apps, lijsten, pagina’s, webonderdelen en de juiste huisstijl worden toegevoegd aan je workspace. Zo combineer je de kracht van twee producten: het een zorgt voor overzicht en het ander zorgt voor een consistente look and feel en de juiste governance.

Meer weten?

Mavention Workspace maakt het leven net iets makkelijker: minder klikken, meer overzicht. Nieuwsgierig hoe je Mavention Workspace in jouw organisatie optimaal kunt inzetten? Je bent van harte welkom voor een kop koffie of thee bij ons in de Caballero Fabriek in Den Haag. Bel even met 070 – 820 02 31 of neem contact op via het contactformulier en we regelen een afspraak!

Erik Rutters

The post Eén overzicht van alle SharePoint sites, Office-365-groepen en Teams? Jawel, het kan! appeared first on Mavention.

Responsive design: The things you need to know to make one

$
0
0

Style-facts part4

Responsive design was a buzzword a few years ago and now it is expected to be the fundament of every self respecting website. But since it is a purely styling concept we see many developers struggling to implement it. This is a guide to the basic concept and mathematics behind responsive design grids.

We need to make the site responsive, let’s use bootstrap… Well if you put a class here and there it kind of aligns. But what is this ‘row’-class and why is it breaking my design? Wouldn’t it be cleaner to only use a grid?

Well… Yes. It would be and there are some options: You can use alternative grids to bootstrap (which is way more than you need) like ‘Susy’. Susy provides a more clean and nowadays more efficient way of defining your columns per device. Although the documentation isn’t that clear the examples are pretty explanatory. The other option is to write it yourself. Which could be a nice exercise to get into SCSS mixins and media queries. I will explain the grid by walking you true a 12 column grid. This is the most commonly used.

Why might one ask? This has a practical reason. 12 can be divided by 12, 6, 4 ,3, 2. These splits are a huge advantage when you are trying to split up your page in different ways for several window sizes. If you don’t have to switch between grids that even more of a plus. You can occasionally use a 10 column grid, for instance when you have a 5 column layout. This might be the only exception not to use a 12 col grid.

Responsive design: Columns and Gutters

In a 12 column grid, your grid has 12 columns. I here you thinking: ‘Well yes… it’s called a 12 column grid, duh…’. I say this because it’s often mistaken that the grid would vary on smaller devices. This is not the case. On tablet the grid has 12 columns and the grid on mobile phone has 12 columns too. Only difference is that width of the screen is split fewer times. The number of columns stays the same.

Let me give you an example. We have a set of cards on phone, tablet and a desktop screen. By default the card is the full 12 columns. That’s 0 splits. Why? Because we design mobile first. This is best practice. Besides that, you can imagine it is easier to give things more room, then squashing more stuff in less space. That’s why we start designing on the smallest screen. The card might use half the screen. It’s one split into 6 columns and 6 columns. Finally we split the width again as we make cards that are a quarter of the width.

Gutters

We don’t always want the card to be x the column width. This would mean that if you place multiple cards next to each other they would look stuck together. We wouldn’t want that and that’s where grids gutters come in. The gutter width defines the space between columns.

Columns with a gutter can be calculated by:

c = number of columns
g = gutter width

(100% / 12 * c) - (g / 2 * 2) 

Why the / 2 * 2? Writing down only ‘g’ might confuse some of you when there are gutter on both sides of the column. The column next to it has the same thing. So the actual gutter width is a half gutter. This makes the equation some what deceiving when only writing down ‘-g’. That said, we might have encountered an issue. When placed in a row our gutter provide us with the problem that the outer gutters misalign our grid with the object that are full width above and following or grid.

Gutter Correction

To fix this the complete grid equation is (when using 2 cards stretching a number of columns) this:

c = number columns 
g = gutter width
 
((100% / 12 * c) - (g / 2 * 2) + (100% / 12 * (12 - c)) - (g / 2 * 2)) - g

We remove the outside 2 half gutters. Bootstrap fakes this by giving it’s container ‘.row’ a margin-left and margin-right of -(g / 2)px. My personal opinion is that this is not a clean solution to the problem. I would suggest a removal of the left margin on the first card-column and a removal of the right margin on the 2nd / last column. In a more than 2 column situation my solution would cause a slight inexact split. This can be solved by redistributing the width gained by the first and last column over the columns evenly.

It’s a choice between complexity and best practice.

Classes? Mixins?

The ‘c’ in the equation is the number you might recognize from the bootstrap class ‘col-xs-6’. the ‘xs’ is the media query where the size ‘6’ applies. So if we wanted to make a mixin for this it could look something like this:

$gutter: .5rem;
$cols: 12;
$media: (
  xs: 512px, 
  sm: 768px, 
  lg: 1024px,
  xl: 1200px
);
 
@mixin column($cols, $gutter) {
  @each $name, $value in $media {
    @media screen and (min-width: $value) {
      @for $i from 1 through $cols {
        $width: calc((100% / 12 * $i) - ($gutter));
        .col-#{$name}-#{$i} {
          width: $width;
          margin: 0 calc($gutter / 2);
        }
        // add push/ pull function for indenting and pulling column where you see fit. It's a little advanced for this chapter ;)
        // disclaimer: this mixin might need some tweaking.
      }
    }
  }
}

You now know how a responsive grid is used and calculated. A grid is the same on all devices but the span of your card-column over a number of grid-columns may vary. Adding gutters between your columns makes your design look a lot nicer but it has it’s downsides and complexities. It is not as hard as it look to define your own grid. If you find it to complex to make a responsive grid yourself, there are options like ‘Susy’. These standalone grids provide a good alternative to using bootstrap for a grid alone. Thanks for reading this column! And if you have questions or comments, please leave them in the comment section or in my mail :).

 

 

Want to know more about styling? Read the other blogs in this series about styling:
Part 3: https://www.mavention.nl/blogs-cat/3-levels-of-css-selectors-to-select-all-elements/
Part2: https://www.mavention.nl/blogs-cat/shaping-elements-and-its-surrounding/
Part1: https://www.mavention.nl/blogs-cat/2-basics-you-need-to-know-to-position-elements/

The post Responsive design: The things you need to know to make one appeared first on Mavention.


Make design magic with borders and shadows

$
0
0

Style-facts part5

Soon or late everybody would like to have some spaceships on their webpage. Just A little magic to accentuate their artistical and technical capable side. Borders and shadows can provide some of this styling magic and that is why we will explore the world of borders and shadows by making UFO’s. Let’s make alien space ships!

In this Blog you will learn how to use borders and how make blocks into circles or ellipses. Besides this, we will have a look at box-shadows and the way to make it a little magic.

Borders

To decorate the edge of your block in ancient times, the digital community came up with borders. Nowadays we can do a lot with borders. We can have dashed, dotted and even images decorating the border of your block. In this part of the StyleFacts we will cover the basics of borders. Not the images part.
A border consist of three parts: width, type and color. The width is defined in pixels. This is the easy part. The type of the border is a name and the most commonly used types are: solid, dashed, and dotted. For a complete overview of border-styles please visit w3schools. The color can be set by any form of color definition: rgb, rgba, hex or name. This looks like this:

border: 8px dotted yellow;
box dotted border

Box dotted

Border-radius

Every one knows that UFO’s are round, so we will be needing some styles to make an ellipse. We can do this by defining the border-radius of the block. This can be set in any unit you like. So if we make the border-radius of our disc 50% it will become an actual ellipse. And provide our UFO with magical lights on the edge we change our border style to dotted and increase the with to make the dots bigger.

What’s a UFO without a glass dome on top of it!? Let’s make one! We can’t just put an ellipse on top of it. That would look kind of weird. We need a trick to make border on the bottom more flat. We can do this by defining the border this way:

border-radius: 50%/25%;
border-top-left-radius: 60%;
border-top-right-radius: 60%;
Ellipse with dome on it

Ellipse with dome on it

Shadows

Now we have our awesome spaceship, we need to come of the background. Because spaceships hover! We need some shadow under this magical thing. Shadows take at least 5 parameters. The first for the x positioning of the shadow, the second for y, the third for the size of the blurred part of the shadow and fourth for the solid part of the shadow. The fifth is the color your shadow needs to be. It can be red, we could pretend our UFO had lights at the bottom, but most of the time in real life shadows are not red…

red shadow lights

red shadow lights

It’s time to beam up stuff! UFO’s abduct people and cows. So let’s make a beam! We need a green triangle shape, to make a light beam. Unfortunately triangles are not really basic shapes in CSS. So we need some CSS-wizardry to make triangles. Imagine a block without width or height. Now imagine it has a big fat border of 20px.
This would make a block 40px x 40px. You imagined that correctly. Now imagine you make all borders transparent but the bottom one. What does that leave us? Yes, a triangle. Let’s fix our UFO up with a triangle beam!

triangle beam!

triangle beam!

We have created magic!
Here’s the codepen.
You are now able to make some pretty spacy stuff on your own site or app. Some shade and some funky rounded borders. The possibilities are endless! You are now an open-sorcerer with borders and shades. Want to share more tips and tricks you found exploring borders? Please leave a comment! Questions? Please send me a message.

 

Here are the other parts of these blog series:

Part 4:  https://www.mavention.nl/techblog/how-to-make-a-responsive-grid/
Part 3: https://www.mavention.nl/blogs-cat/3-levels-of-css-selectors-to-select-all-elements/
Part2: https://www.mavention.nl/blogs-cat/shaping-elements-and-its-surrounding/
Part1: https://www.mavention.nl/blogs-cat/2-basics-you-need-to-know-to-position-elements/

The post Make design magic with borders and shadows appeared first on Mavention.

Zelf verbeteringen doorvoeren met Power

$
0
0

De digitale transformatie is in volle gang. Iedere organisatie gebruikt of is zich aan het oriënteren op het gebruik van cloud platformen als Office 365. Je wilt slimmer samenwerken en sneller kapitaliseren op de aanwezige kennis in de organisatie. Je wilt snel kunnen inspelen op veranderingen in de markt en een beweeglijke organisatie creëren. Tegelijkertijd zijn dit grote veranderingen in cultuur, werkwijzen en processen, waar organisaties niet altijd klaar voor zijn. Soms wil je zelf kleinschalig iets starten met de middelen die je tot je beschikking hebt. Hoe kun je zorgen voor impact binnen jouw organisatie, zonder een groot verander- of implementatietraject in te gaan? Binnen deze blog geef ik antwoord op deze vraag door verschillende ontwikkelingen aan elkaar te verbinden.

Business agility

Het kan je bijna niet ontgaan zijn. In de ICT- sector is al jaren een schaarste aan talentvolle developers en de verwachting is dat dit in de toekomst alleen maar toeneemt. Developers zijn nodig om (maatwerk) software te ontwikkelen om te voorzien in een behoefte. Doordat er een tekort is aan developers zie je gepeperde rekeningen verschijnen voor iedere aanpassing, ieder verzoek en iedere aanvulling op nieuwe of bestaande functionaliteit. Daarbij neemt het ontwikkelen van software vaak veel tijd in beslag, waardoor je soms weken of maanden moet wachten tot je écht aan de slag kunt.

Als organisatie, opererend in een competitieve en snel veranderende markt, of als medewerker, opererend in een complexere wereld, kun je geen maanden wachten op de juiste ICT ondersteuning voor jouw werkzaamheden. Business agility vraagt dat je wendbaar bent en snel kunt reageren op veranderingen in de markt of wijzigingen op de werkvloer. Als de ondersteuning dan achterblijft is dat inefficient. We krijgen dan ook vaak de vraag, kan dat niet sneller?

De no- en low-code revolutie

Ja beste opdrachtgever, dat kan sneller! Er is een revolutie gaande in de IT sector, die bovenstaande problemen, het tekort aan developers en lange oplevertijden, oplost. Door software niet van A tot Z te ontwikkelen, maar op basis van modules aan elkaar te verbinden, is in zeer korte tijd een applicatie te ontwikkelen. Er zijn verschillende platformen beschikbaar waar minuscule bouwblokken aangeboden worden, die je met elkaar kunt combineren en/of koppelen met externe databronnen en applicaties. Hier is geen of weinig development kennis voor nodig, omdat gewerkt wordt op basis van een model of op basis van point-and-click. Business medewerkers met affiniteit voor processen en software ontwikkeling kunnen hiermee direct aan de slag om zelf applicaties te ontwikkelen.

Citizen development

Deze business medewerkers, die op deze manier nieuwe bedrijfsapplicaties maken, noemen we ‘citizen developers’. Citizen developers zijn er in enorme aantallen. Denk bijvoorbeeld aan de business analist, business consultant, proceseigenaar of lean-expert. De citizen developer heeft affiniteit met ICT en heeft bijvoorbeeld in het verleden al de grenzen opgezocht van Excel en/of Access modellen, waar verder niemand iets van begreep. In die zin is het bouwen van een applicatie met bouwblokken niet heel anders dan complexe applicaties of formules opbouwen in Excel en Access. Iedereen met procesmatig inzicht kan dus direct aan de slag om (een gedeelte van) het proces te digitaliseren en automatiseren. Binnen jouw organisatie heb je dus ongetwijfeld de mogelijkheid om in korte tijd innovatieve applicaties neer te zetten.

Microsoft Power Platform

Microsoft 365 biedt een scala aan applicaties waar je met relatief weinig kennis bovenstaande mogelijk maakt. In het Power Platform van Microsoft zitten applicaties als Flow, Power BI en PowerApps. Met PowerApps creëer je applicaties waarin content uit verschillende Office 365 applicaties combineert. Dit is van de drie de meest krachtige en uitgebreide applicatie, waarmee je zelf applicaties kan bouwen zonder te coderen. Microsoft noemt het zelf een point-and-click aanpak, waarbij op basis van een sjabloon de data gepresenteerd wordt. Met Excel-achtige expressies kan vervolgens de logica opgebouwd worden. Flow zorgt vervolgens voor de triggers en interactie tussen de applicaties en stelt je in staat om taken uit te voeren op de verschillende applicaties binnen Microsoft 365 en daarbuiten. Met Power BI kun je vervolgens gemakkelijk een BI dashboard opbouwen om de data te visualiseren.

Met het Microsoft Power Platform zijn teams en afdelingen dus in staat om snel een bedrijfsproces te automatiseren. Mocht je hier meer over willen weten neem dan contact op met mij.

The post Zelf verbeteringen doorvoeren met Power appeared first on Mavention.

Reactiemogelijkheid per document in een SharePoint bibliotheek

$
0
0

Mijn opdrachtgever heeft de wens om een extra kolom toe te voegen aan een SharePoint documentenbibliotheek. Deze kolom moet de mogelijkheid bieden om een reactie te geven op elk kwaliteitsdocument van de organisatie. Als je op de link in deze kolom klikt, opent een pop-up met daarin een tekstveld voor de reactie. De documenteigenaar krijgt vervolgens een email met deze reactie, de persoon die deze reactie heeft geplaatst en een link naar het betreffende document.

JS-Link

Ik heb dit gerealiseerd met behulp van een JS-Link in de documentenbibliotheek.
Deze mogelijkheid vind je in de eigenschappen van het webonderdeel, onder ‘Diversen’.

js-link

Hierin plaats je een link naar het js-bestand, bijvoorbeeld:
~site/SiteAssets/scripts/JSLinkRenderAsHyperlink.js

 

Script

Dit script ziet er als volgt uit:

(function () {
var nameFiledContext = {};
nameFiledContext.Templates = {};
nameFiledContext.Templates.Fields = {
"ID": { "View": nameFiledTemplate }
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(nameFiledContext);
})();

// The pop-up
function openReactieDialog(pageUrl) {
var options = {
url: pageUrl,
title: 'Geef een reactie',
allowMaximize: false,
showClose: true,
width: 700,
height: 400
};
SP.SOD.execute('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', options);
}

// This function applies the rendering logic
function nameFiledTemplate(ctx) {
return "<a href='#' onclick='openReactieDialog(\"https://*.sharepoint.com/sites/Kwaliteitshandboek/Lists/Reacties/newform.aspx?DocID=" + ctx.CurrentItem.ID + "\"); return false;'>Geef reactie</a>";
}

Ik gebruik de ID-kolom en plaats daar de link naar de ‘newform.aspx’ van een reactielijst in. Deze link opent als een pop-up door de functie ‘openReactieDialog’. De reactie zelf wordt opgeslagen in een standaard SharePointlijstje.

SharePoint Designer Workflow

Wat nu alleen nog nodig is: de email naar de documenteigenaar. Dit heb ik gerealiseerd met een eenvoudige good-old SharePoint Designer workflow op de reactielijst.

spd workflow

Ik definieer een aantal variabelen en verstuur vervolgens een email naar de documenteigenaar.
De plaatser van de reactie krijgt een CC van deze email.

“Beste document eigenaar,

[%Huidig item:Gemaakt door%] heeft de volgende reactie geplaatst op het kwaliteitshandboekdocument “[%Variabele: docnaam%]”:

*************** Reactie ***************
[%Huidig item:Reactie%] ****************************************”

Mocht je hier meer over willen weten neem dan contact op met mij.

The post Reactiemogelijkheid per document in een SharePoint bibliotheek appeared first on Mavention.

WOFF files returns HTTP 404 in Azure Web Sites

$
0
0

After deploying a site to Azure App Services I noticed a lot of 404 errors while monitoring the request in Application Insights. All of the .woff  and .woff2 files returned a 404 error. So it looked like not all of the font files where deployed.

Application Insights 404 errors

But when I checked the fonts folder with the Kudu fil explorer I saw that all the fonts where deployed and I was enabled to download them from Kudu. So it has to be something different.

After some investigation it turns out to be an Azure App Service ‘issue’. Azure App service doesn’t actually have a MIME type configured out of the box for .woff and .woff2  files, so it will simply return a 404 on every call. We didn’t noticed this while developing because your local IIS express service does have MIME types configured for .woff and .woff2 files.

To allow Azure App Service to serve these files we need to update the web.config file. In the <system.webSever> section create a  <staticContent> tag. Foreach file extension we want to add create a <mimeMap> entry.  This entry has two properties:

  • A unique file name extension that is specified by the fileExtension attribute, for example, “.txt”, “.png”, etc.
  • A MIME type for the file name extension that is specified by the mimeType attribute, for example, “text/plain”, “image/jpg”, etc.

<system.webServer>
<staticContent>
<mimeMap fileExtension="woff" mimeType="application/font-woff" />
<mimeMap fileExtension="woff2" mimeType="application/font-woff" />
</staticContent>
</system.webServer>

After these changes to the Web Config the woff and woff2 files have a configured MIME type and will be served to the client.

The post WOFF files returns HTTP 404 in Azure Web Sites appeared first on Mavention.

Mapping a collection of interface based objects

$
0
0

While building an API endpoint we had the requirement to handle a collection of objects based on an interface. This seemed relatively simple task but took more time then anticipated due to the JSON serialization and deserialization behavior.

When using a console application, you will get an error on deserializing a collection of interface types. The message will tell you “Could not create an instance of type x. Type is an interface or abstract class and cannot be instantiated”. When you are using an API and the input for the collection is for example the post data you will not get such an exception, you would just get an empty collection.

Doing a quick google search got me half way to the solution via the stackoverflow post: https://stackoverflow.com/questions/12638741/deserialising-json-to-derived-types-in-asp-net-web-api which was indicating to create a new class based on the JsonConverter. Using the accepted answer as a starter lead me to some more changes to be able to use it on objects where one of the properties is the problematic collection instead of the complete content as described in the post.

To demo this without needing to explain all surrounded business logic a sample of high school / alumni sports teams is used.

The API controller endpoint did not ask for a base class as is described in the post but an object that had a collection of classes as input:

// POST api/values
public void Post([FromBody]IEnumerable<Team> value)

The sample team object has the following properties:

public class Team
{
    public string Name { get; set; }
    public Sport Sport { get; set; }
    public ICollection<IPerson> Players { get; set; }
}

When calling the Post API endpoint to create a new team the team would always have zero players. The default JsonConverter could not create objects based on the IPerson class, but instead of throwing an error like the console application it returned an empty collection.

In the sample code there can be an Alumni or a Student class present in the collection of players. To simplify the demo code, we added a string to each class to determine what the type is. A sample of the Alumni class is:

public class Alumni : IPerson
{
    public string FirstName { get; set; }
    public Sport FavoriteSport { get; set; }
    public string PersonType => "Alumni";
}

To fix the deserialization we created the abstract class from the stackoverflow post. We created a PersonConverter class that implemented the abstract class and added the following code to the Create overload method to identify what kind of IPerson object was being deserialized:

protected override IPerson Create(Type objectType, JObject jObject)
{
    switch (GetPersonType(jObject))
    {
        case "Alumni":
            return new Alumni();
        case "Student":
        default:
            return new Student();
    }
}

The GetPersonType method checks if the property PersonType is available in the object and returns the value when available, or null when the property is not present. We choose to default to students when the property is not present.

To be able to activate this logic we needed to decorate the interface with an attribute to link it to the custom JsonConverter, there are no changes needed in the Team, Alumni or Student classes.

[JsonConverter(typeof(PersonConverter))]
public interface IPerson

After adding the custom JsonConverter to the IPerson interface the API did not have an empty collection anymore but objects of the correct typed, ready to be handled by the business logic.

The post Mapping a collection of interface based objects appeared first on Mavention.

Viewing all 715 articles
Browse latest View live