Sunday, November 5, 2017

Website with App experience using Ionic

We may already be in the heydays of mobile Apps, but you will still run into companies that want an App-experience for their (internal) products. For the cases in which you don't need any native phone capabilities and don't want to add an App into the Google or Apple stores there recently has been added (by Google) a new development paradigm called: Progressive Web Apps (PWA). PWAs are web sites (that run on the internet) that behave like a real App on a mobile phone (in the chrome browser on Android phones).
The Progressive Web App
.. is installed as an App so it shows in the Apps section of Android
.. has a nice icon on your android homescreen
.. starts with a splash screen
.. runs full screen.
.. can be used offline.

This blog demonstrates how you can build (from a sample solution) and deploy such a PWA to Azure websites. 
This has already been documented in other places better than I can do it so I will link to those places for further investigation, but write the steps to perform the deployment here aswell.
You can see the end result here https://jwiersem-ionic-conferenceapp.azurewebsites.net . If you open that URL on an android phone, you will get a popup allowing you to install the App on your phone.

I will use the Ionic framework sample of their conference app, Visual studio 2017, an Azure account and a recent Android phone in order to build and deploy a working (sample) PWA.

First, as written on http://ionicframework.com/getting-started/ :
  1. Install NodeJS
  2. Open a Command window and install cordova and ionic with the command npm install -g cordova ionic
  3. In a directory of your choosing, create a new app with the command ionic start. This starts a menu that asks for a name for your project, fill it in and when you're asked which template to start from select the Conference app. This is a completely fleshed out and functioning ionic app.
  4. Change directory into the folder you created for the App and test the app by running the command ionic serve. Or connect your Android phone via USB cable and run ionic cordova run android. The latter will run your app on your phone with one command.
  5. Note the WWW folder of this app. All the necessary files are added here during building the project and the index.html can be opened in a browser and it will work as a desktop app.
  6. Now you have a working cordova app. But we wanted a PWA! What to do?
  7. In order to use your (well not your code, but you downloaded it fair and square!) code as a PWA, follow this article from Josh Morony.
  8. Do this:
    1. In index.html comment back in the script that loads servicework.js
    2. Also in index.html, remove the loading of the script cordova.js.
    3. Run the command: ionic cordova build --prod
    4. And you're done!
  9. But wait, didn't we need an Azure account for something? Yessir, we want to really test the PWA as a website in Azure. In order to deploy it easily and quickly we need to follow a few more steps.
  10. Open Visual Studio. Then click File -> Open --> Website. Select the WWW folder of your ionic app.
11. You need to do one more thing in order to get your PWA live. Right click your www folder and select Add -> Add new item. Select Web configuration file here. In the web.config file (you should be familiar with that btw!) add the following section inside <configuration>
<system.webServer> 
    <staticContent>
      <mimeMap fileExtension=".js" mimeType="application/javascript" />
     <mimeMap fileExtension=".json" mimeType="application/json" />
     <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
     <mimeMap fileExtension=".woff2" mimeType="font/woff2" />
  </staticContent>
</system.webServer>
You need to add this to the webconfig, otherwise the required files for your PWA will not be served by the Azure website.
12. Right click www again and now click Publish Web App and deploy to an Azure App service.
13. Your PWA is live! Visit the httpS URL with chrome on your Android phone, and you will get a popup asking it you want to install it as an App.
14. You now have a website with the added advantages detailed in the beginning of this article.
Full screen PWA on your phone.


NB: Once you installed the PWA on your phone and the delete it from your homescreen, you won't soon get another popup on the website. But maybe you want to demo the process to someone else later... To get the popup back follow these steps on your phone:
1.       Open Android Chrome.
3.       Click Enable

4.       Click Relaunch Now

PWA Popup in Chrome on Android phone

Azure Function with PnP - Missing Microsoft.IdentityModel.Extensions.dll

Let's say you want to build a Azure Function for site provisioning in SharePoint Online. You think, I could use the .Net PnP library for that! And you're right. However, I ran into the problem of a missing dll when trying to authenticate to SharePoint using App-only credentials.
It turns out the the Nuget packages for PnP are missing a dependency that is present on your developer environent but not with the Azure App service you deploy the Function to.
The file that is missing is Microsoft.IdentityModel.Extensions.dll.
This file is available in C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.IdentityModel.Extensions\v4.0_2.0.0.0__69c3241e6f0468ca

In order to get the Azure Function working, add this file in a folder in your Azure function solution. Then click on it and in the properties window select Embedded resource for Build action and Copy always for Copy to output directory. This will make sure the dll is copied into the bin folder of the App service and that it is loaded when the Azure Function starts.

Hopefully this article helps someone in fixing this issue when using PnP in Azure Functions!

Wednesday, August 23, 2017

SharePoint Online: New web service to scale images

I guess I was still in my wintersleep in Februari when this was released, but there is a new webservice available in SharePoint Online for rendering optimal-sized images for any device/screen resolution (image renditions don't work well for this )

You can use this in order to minimize the amount of bits sent to your users, especially for mobile users. Or you could use it to minimize the risk of terrible performance when a content editor adds a 6MB image to your site.

The location is https://yourtenantname.sharepoint.com/_layouts/15/getpreview.ashx . This location is virtual so the service exists in any site collection (NB. so also at https://yourtenantname.sharepoint.com/sites/yoursite/_layouts/15/getpreview.ashx )

If you read the following posts you can learn how to use it with a Path query variable pointing to the URL of the image or with three guids that identify the image file.

Image renditions available - this article also contains the available resolution codes.

Generate thrumbnail from URL in SharePoint

This is an example URL: https://MYTENANT.sharepoint.com/_layouts/15/getpreview.ashx?path=https%3A%2F%2FMYTENANT.sharepoint.com%2Fsites%2FJurgenCommSiteTest%2FSiteAssets%2FSitePages%2FTest-nieuws%2F627-large_9051a70d15cd9b67ba2097efb9e6c74c488d7267.jpg&resolution=6

Note the Path query variable that holds a URL encoded locator of the file and the Resolution which should be a value from 0 to 6.

So you can easily use this new webservice in your display templates or other (JavaScript) code to allow a user a fast download of an optimal size image.




Wednesday, August 9, 2017

Run asynchronous code on schedule with Azure WebJobs

This short post describes how you can have a scheduled Azure WebJob that runs an asynchrouns method.

The problem with this scenario is that the WebJob, which is just a regular console application, cannot have an asynchronous Main method. So you need a way around that. Next to that you would to be able to trigger that method with a schedule.

In my solution I use a Settings.job text file that is in the root folder of the WebJob (Set copy to out put directory to 'Copy Always' in the properties of the file in Visual Studio.
The contents of the file contain JSON with a cron expression like so:
{
    "schedule": "0 0 6/12 * * *"
}
This is set to every twelve hours starting from 6:00. So far so good, and nothing you probably havent seen before or in other blogs.

Now suppose you used the Visual Studio template to generate the WebJob Project. This creates the main Program.cs file and also a Functions.cs file. The Functions file is meant for you to register yor methods that serve as triggers. I tried using the TimerTriggered function like below, but the result wasn't that good. If you Run and block the JobHost in the Program.cs (as is done in the VS template), this means that your job will always show a running state and the timertrigger will go off, but only if it's within the time out period of the webjob which is 120 seconds. So that is a crap solution.

Instead, define a manual trigger with the tag [NoAutomaticTrigger]. We will call this method from the Main method. Notice that this method is asynchronous. I use code in there to fetch from a API and save back to a different service that I already wrote and that is asynchronous.

public class Functions
    {
        public static async Task TimerTriggered([TimerTrigger("0 0 6/12 * * *")] TimerInfo timer, TextWriter log)
        {
            await Functions.RunJob(log);
        }

        [NoAutomaticTrigger]
        public static async Task ManualTrigger(TextWriter log)
        {
            await Functions.RunJob(log);
        }

Now, code your Main method in Program.cs to call and await the method, using the JobHost.CallAsync method inside a Task.Run delegate.

class Program
    {
        static void Main()
        {


            var host = new JobHost();
            Task aTask = Task.Run(() => host.CallAsync(typeof(Functions).GetMethod("ManualTrigger")));

            aTask.Wait();          
        }
    }

The solution is to use the Task class to run and await the asynchronous method. With the JobHost.CallSync you can call the method in another class. Parameters like the TextWriter are passed by the JobHost.