Wednesday, November 27, 2019

How to specify BindingRedirects in Azure functions app settings via ARM template in automatic provisioning scenarios

If you face with famous problem with Newtonsoft.Json version mismatch in Azure functions (when Azure functions SDK requires one specific version and e.g. OfficeDevPnP requires other – you get error in runtime that Newtonsoft.Json.dll of version x.x.x.x is not found). There is solution for this issue posted here: Performing a binding redirect in Azure Functions. With this solution we have to add new app setting for Azure function which is string representation of JSON array:

{
    "BindingRedirects": "[ { \"ShortName\": \"Newtonsoft.Json\", \"RedirectToVersion\": \"11.0.0.0\", \"PublicKeyToken\": \"30ad4fe6b2a6aeed\" } ]"
}

It works but if you use automatic provision of Azure functions using template json file (see Azure Resource Manager template functions) and will want to specify it there like this:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "BindingRedirects": {
            "type": "string",
            "defaultValue": "[{ \"ShortName\": \"Newtonsoft.Json\", \"RedirectToVersion\": \"12.0.0.0\", \"PublicKeyToken\": \"30ad4fe6b2a6aeed\" }]"
        }
    }
}

you will see the following error:

Error occured when try to create Function app (error code 1):
Error: Code=InvalidTemplate; Message=Deployment template language expression evaluation failed: 'The language expression '{ "ShortName": "Newtonsoft.Json", "RedirectToVersion": "12.0.0.0", "PublicKeyToken": "30ad4fe6b2a6aeed" }
' is not valid: the string character '{' at position '0' is not expected.'. Please see https://aka.ms/arm-template-expressions for usage details.

The problem here is that BindingRedirects app setting use square brackets which at the same time are used by ARM template engine for specifying calculated values. Solution for this problem is to escape square brackets by double them i.e. instead of [ use [[ and instead of ] use ]]. Final version will look like this:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "BindingRedirects": {
            "type": "string",
            "defaultValue": "[[{ \"ShortName\": \"Newtonsoft.Json\", \"RedirectToVersion\": \"12.0.0.0\", \"PublicKeyToken\": \"30ad4fe6b2a6aeed\" }]]"
        }
    }
}

After that provision of ARM template for Azure functions will go well.

Monday, November 25, 2019

Authentication when publish nuget package to internal Azure packages feed

If you  want to use Azure packages feed for storing internal packages of your organization (https://{tenant}.pkgs.visualstudio.com) you will have to use nuget client as usual and authenticate yourself against Azure packages feed using your Azure AD credentials. However by default nuget.exe doesn’t support Azure authentication: it will ask you to enter username and password inside console Windows which will fail (it will just ask you to enter username and password again and again).

In order to enable Azure AD authentication with nuget client you will need to install authentication provider first. This page contains instructions how to do that: Azure Artifacts Credential Provider. Basically you need to download installcredprovider.ps1 PowerShell script to local machine and run it with “-AddNetfx” param:

installcredprovider.ps1 -AddNetfx

Note that “-AddNetfx” switch param is mandatory in most cases – otherwise credentials providers will be added only to .Net core and won’t work in regular Windows console client or PowerShell window.

After it will be done when you will run command to publish nuget package to Azure:

nuget push -Source "MySource" -ApiKey az PackageName.nupkg

it should show standard authentication popup window where you will be able to enter your Azure AD credentials. And after that publish to Azure nuget packages should succeed (of course if you have permission to push packages to this feed).

Tuesday, November 12, 2019

Why you should be careful with /groups/{id}/photo and /users/{id}/photo endpoints in MS Graph or unintentional getting photos of big sizes in Graph

As you probably know we may retrieve groups and users photos via Graph API using the following endpoints (see Get photo):

GET /users/{id | userPrincipalName}/photo/$value
GET /groups/{id}/photo/$value

Note however that Graph stores photos of different sizes:

The supported sizes of HD photos on Office 365 are as follows: 48x48, 64x64, 96x96, 120x120, 240x240, 360x360, 432x432, 504x504, and 648x648.

and if we use default /photo endpoint it will return biggest available photo, i.e. 648x648. Depending on your scenario it may not be what you actually need as if you just need to display group logo or group member photo smaller images e.g. of 64x64 pixels size will be enough. And if you work with big photos of 648x648 size and reduce its size by css – page size may be very big and browser memory consumption will be much bigger:

So instead of using default /photo endpoint in MS Graph you may consider using of endpoints which return photo of specified smaller size:

GET /groups/{id}/photos/64x64//$value

or with Graph client library in .Net app:

var stream = Task.Run(async () =>
{
 var photo = await graphClient.Groups[groupId].Photos[Constants.GRAPH_IMAGES_CACHE_PHOTO_ID].Content.Request().GetAsync();
 return photo;
}).GetAwaiter().GetResult();

This code will return small image which may be more appropriate for your scenario:

Compare also sizes for big 648x648 image and small 64x64 image: 10Kb vs 2Kb.

Thursday, November 7, 2019

Quick way to upload user photo for making it available through Graph API /user/{id}/photo endpoint

If you want to test fetching of users photos via Graph API you may need to upload this photos so they will become available through Graph endpoints (see Get photo):

GET /me/photo/$value
GET /users/{id | userPrincipalName}/photo/$value
GET /groups/{id}/photo/$value

Of course you may do that programmatically using PUT requests like shown here:

PUT /me/photo/$value
PUT /users/{id | userPrincipalName}/photo/$value
PUT /groups/{id}/photo/$value

but if you need to do it quickly without developing tool for that you may use standard UI and upload photo from user’s Delve profile page:

1. Click icon with your account in top right corner and select My Office profile:

2. You will be redirected to your accounts Delve profile page:

3. On this page click “Upload a new photo” icon and upload photo of the user.

After that it will be possible to get users photos via Graph endpoints including photos with different sizes.