Azure Functions - Seamlessly Connecting Time Cockpit

Sunday, May 1, 2016 by Rainer Stropek

Image source:, Creative Commons License

In nearly every time cockpit implementation project, we have to integrate time cockpit with upstream and downstream systems like CRM, accounting, billing, etc. Additionally, customers want to automate workflows like handling working time violations or vacation requests. In the past, we typically used Azure WebJobs for that. Recently, Microsoft announced an improved successor: Azure Functions. In this blog article we introduce Azure Functions and show how they can be used with time cockpit.

Background Information

The original intent of Azure WebJobs was to make it simple for web site developers to automate background processing. Imaging you develop your company's website and you want to automatically create small thumbnail images from uploaded high-res pictures. Azure WebJobs were created for tasks like that. You can create them in various programming languages (e.g. C#, Node.js, batch scripts) and they have a scheduler built-in.

However, Azure WebJobs don't necessarily process data of the web site they are hosted in. Essentially, they are just pieces of code that can read, process, and write data from any location. Being part of the Azure App Service product, WebJobs have a free pricing tier for applications that don't need much memory and processor time. If all you need is to transfer data from one SaaS system (e.g. time cockpit) to another SaaS system (e.g. billing), you will need only very few resources. Therefore, free WebJobs were the perfect tool for the job - until Azure Functions came out recently.

Let's look at an example. Like some of our customers, we use Zendesk for handling customer support. A scheduled Azure WebJob could care for regularly polling Zendesk using its RESTful Web API. It could find detect new support tickets and create them in time cockpit using time cockpit's Web API.

Note that Azure AppServices support accessing on premise systems via Hybrid Connections. You can find an example in our blog article Integrating On-Premise Resources Into Time Cockpit.

Another use case for a WebJob could be sending out notification emails e.g. in case of a budget overrun. A scheduled Azure WebJob could use time cockpit's RESTful web API to regularly search for critical projects. It could then use an email services like e.g. Mandrill to send notifications.

You can find an example for a script sending out notification emails in in our blog articles Warning Emails in Case of Budget Overrun.

Enter Azure Functions

As you can see, Azure WebJobs are a very useful and versatile tool. However, they have some drawbacks, too. Here are some examples:

  • WebJobs were originally intended as helpers for background processing in the context of a web app. It feels somehow strange that you have to create a web app just to get to a WebJob. WebJobs often don't come to people's minds when they don't want a website but just a way of connecting two SaaS applications.
  • You have to develop a WebJob's code in a separate editor or development environment. Then, you have to package it in a ZIP file. That ZIP file can be uploaded to your Azure Web App. This is an unnecessarily complex workflow. Wouldn't it be nice to have an online editor where you can just write your script directly in the browser?
  • Today, many SaaS solutions offer Webhooks. They can call downstream systems via HTTP whenever data is changed. With that, integration solution do no longer have to poll. They get actively called whenever something important happens. WebJobs offer some functionality in that direction, but it is far from perfect.

In reaction to these drawbacks, Microsoft recently announce a brand new Azure Feature: Azure Functions. They solve all the problems mentioned above.

Although the final pricing of Azure Functions has not been announced yet, Microsoft has already made it clear that there will be a free tier again. So just like with WebJobs in the past, you will get small integration scripts for free with Azure Functions, too. Read more about pricing of Azure Functions.


Enough theory, let's look at an example. Note that you need an Azure subscription if you want to follow along. Although you have to enter a credit card to prove that you are a real person, Azure functions are free. You will net get charged as long as you just use free services. You can even protect yourself from unpleasant surprises by setting up a spending limit for Azure.

Setting up Azure Functions

Start here with Azure Functions:

Once you create your first function as shown above, Azure will create a new App Service called AzureFunctions-WestEurope. It is a regular Azure App Service so you can configure, monitor and maintain it as usual.

You are new to Azure App Services? I recently did a workshop about it at the .NET Summit in Munich. Feel free to use the slides of my Azure App Services workshop as a starting point for exploring this great Azure service.

Creating Your First Function

In our example, we create a timer-based function. It is called regularly based on a time schedule that you can define. Timer functions are the easiest way to start with Azure Functions. Once you master them, move on to more elaborate scenarios like Webhooks or queue-based system integrations.

Let's start by creating a new function from scratch:

Next, we select the appropriate template. As you can see, there are lots of templates available that make it easier for you to start. As mentioned above, we are using a timer functions to begin with. The programming language in this example will be C#:

Note that the schedule is defined based on a Cron expression. There are many Cron expression builders available on the web (e.g. Cronmaker).

Sample Code

The good news is that you don't need to write a complete C# application for Azure Functions. It uses C# Scripts instead (came recently with Visual Studio 2015 Update 1; read more about C# Scripting). Of course, the code of the function depends on your specific needs. However, here is a sample script querying time cockpit's Country table and writing the result to the function's log. You can use it as a starting point to create your time cockpit integration script.

#r "System.Configuration"
#r "Newtonsoft.Json"

using System;
using System.Configuration;
using System.Text;
using Newtonsoft.Json; 

const string timeCockpitBaseUrl = "";

public static string Base64Encode(string plainText) => Convert.ToBase64String(Encoding.UTF8.GetBytes(plainText));

public static async Task Run(TimerInfo myTimer, TraceWriter log)
    string timeCockpitAuth = ${body}quot;{ConfigurationManager.AppSettings["tcUser"]}:{ConfigurationManager.AppSettings["tcPassword"]}";
    using (var client = new HttpClient())
        var queryObject = new { query = "From C In Country Select C" };
        using (var request = new HttpRequestMessage
                RequestUri = new Uri(${body}quot;{timeCockpitBaseUrl}/select"),
                Method = HttpMethod.Post,
                Content = new StringContent(JsonConvert.SerializeObject(queryObject), Encoding.UTF8, "application/json")
            request.Headers.Add("Authorization", ${body}quot;Basic {Base64Encode(timeCockpitAuth)}");
            using (var response = await client.SendAsync(request)) 
                log.Verbose(await response.Content.ReadAsStringAsync());

Handling Secrets

Whenever you access time cockpit (same is true for many other systems), you need to authenticate using user and password, a token or something similar.

Never write such security-critical setting directly in your code!

You should store such secrets in your function's Application Settings instead. Here is where you can find them:

Here you see how you enter time cockpit user and password for our sample script:

Run Your Function

That's it. You can run your function manually or wait until the scheduler starts it.


Azure Functions are a great way of automating SaaS integration scenarios. Whenever you used WebJobs for that in the past, consider Azure Functions in the future.

Questions regarding integrating time cockpit with your systems? Feel free to contact us at We would be happy to help!

comments powered by Disqus