Update your Microsoft Teams notifications via an Azure Function

In my latest post, I’ve shown you how you can use Azure Functions in your Microsoft Teams flow to handle errors in your environment. This stuff works great in a couple of projects I’ve worked on, but what would be even more awesome is to reply to a message in Teams when an action has completed after a button is pressed.

Well, replying & modifying the original message with a status update is quite possible and I’ll show you how in this post.

How do I send a reply to Microsoft Teams?

In the image below you can see a message having posted on my Teams channel and a reply is posted.

reply on teams message

This reply has been sent from my Azure Function. If you want to do this, you need to send a HttpResponseMessage with a status code 200 and a specific header value. This header value is CARD-ACTION-STATUS and the value will be the message which you will see in the reply.

The code for this will look something similar to the following.

public static async Task<HttpResponseMessage> Run(
	[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
	ILogger log)
{
	// Do your stuff...

	var result = new HttpResponseMessage
	{
		Headers =
		{
			{ "CARD-ACTION-STATUS", $"Timeout of `{request.Timeout}` miliseconds has expired."},
		},
		StatusCode = HttpStatusCode.OK
	};


	return result;
}

That’s all there is to it in order to send a single reply to your message.

So you also mentioned updating the original message?

Yeah, I did!

From your Azure Function (or any other API) it’s possible to change the original message. Updating the message might make sense in a couple of scenarios. The one scenario where we’re using it for is to remove the button(s) in the message, therefore limiting the ‘action’ only to a single use.

While our services are set up to be idempotent, we don’t want to spam the API with useless requests, so removing the button makes sense in our case.

In order to do this, you need to add another header to your response message, named CARD-UPDATE-IN-BODY and set the value to true. This tells the client (Teams) there’s an update for the card in the body of the response message.

If you want to use this, it makes sense to create a new card with data that’s useful after an action has been executed. The eventual code will look pretty similar to the following snippet.

public static async Task<HttpResponseMessage> Run(
	[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
	ILogger log)
{
	// Do all of your stuff...

	var result = new HttpResponseMessage
	{
		Content = new StringContent(GetContent(request.Timeout)),
		Headers =
		{
			{ "CARD-ACTION-STATUS", $"Timeout of `{request.Timeout}` miliseconds has expired."},
			{ "CARD-UPDATE-IN-BODY", "true" }
		},
		StatusCode = HttpStatusCode.OK
	};
	result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");

	return result;
}

Over here I’m creating a new Content property with the update of the card. I do have to make clear it’s a full replacement of the original message. Therefore, you have to create a completely new MessageCard. For me, the content of the new MessageCard looks pretty much like the following piece of JSON.

{
	"@type": "MessageCard",
	"@context": "https://schema.org/extensions",
	"summary": "Testing the timeout",
	"themeColor": "0078D7",
	"sections": [
		{
			"activityImage": "https://jan-v.nl/Media/logo.png",
			"activityTitle": "Timeout test",
			"activitySubtitle":"Testing, testing...",
			"facts": [
				{
					"name": "Timeout (miliseconds):",
					"value": "1000"
				}
			],
			"text": "The response has returned with a timeout of 1000 miliseconds.",
		}
	]
}

In Microsoft Teams this will appear like the following screenshot.

updated message and response

The message gets an Updated status, which makes it clear for all users this isn’t the original message.

Erroneous statements on other sites / posts

So if you stumbled on this post while searching for this functionality in a search machine, you probably know it’s hard to find anything useful on the matter. While doing research on this I also saw a post stating the response message has to be returned within 5 seconds in order for Microsoft Teams to process it and show the reply and/or updated message in the channel.

From my experience, I can tell you this isn’t true (at the moment). I’ve tested this timeout function with delays up to 30 seconds and the functionality still works properly as you can see on the image below.

response with 30 seconds

Closing up

If you want to evaluate the complete code there’s a GitHub repository called ServerlessDevOps where I’m doing all of the code updates and trying out new stuff & integrations with Microsoft Teams and Azure Functions.

So, is this something you might consider using in your own projects and keeping your DevOps workplace happy? I’d love to hear it and if you’re missing something which you want to be highlighted in future posts.


Share