asp.net-corepower-automateazure-queues

How can I generate Microsoft Teams approvals using an Azure .NET Core webapp


I want to convert a PowerAutomate-heavy workflow using MS Teams approvals to an ASP.NET Core application.

Is there a way to create approvals without the need for PowerAutomate?


Solution

  • No, there is no way currently to create approvals without using PowerAutomate.

    I was still able to create a .NET app using MS Teams approvals by converting all the logic to .NET, but had to create a separate PowerAutomate workflow for generating approvals.

    My basic flow is:

    1. .NET pushes a message to an approval-requests Azure queue containing info to be displayed in the approval
    2. PowerAutomate workflow has a trigger for new messages in the approval-requests queue, gets triggered
    3. PA pops the message from the queue, parses as JSON
    4. PA gathers list of people from a sharepoint/AAD group, concatenates the emails together
    5. PA uses concatenated email list to start and wait for an approval
    6. PA pushes result of approval to the approval-responses queue
    7. .NET background task pops messages from the approval-responses and does its app logic based on the result.

    preview

    This page is helpful for getting started with .NET background tasks. However, it mentions that the Timer class doesn't wait for previous execution to finish. Instead, I just use a new thread that calls Sleep in an infinite loop while calling a Tick method that handles polling and blocking execution of workflows with a positive approval result.

    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    
    namespace app.Services
    {
        // https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-6.0&tabs=netcore-cli
        public class WorkflowFulfillmentService : IHostedService
        {
            private readonly ILogger<WorkflowFulfillmentService> _logger;
            private readonly WorkflowClient _workflowClient;
            private CancellationToken _cancellationToken;
            private Thread _thread;
    
            public WorkflowFulfillmentService(
                ILogger<WorkflowFulfillmentService> logger,
                WorkflowClient workflowClient
            )
            {
                _logger = logger;
                _workflowClient = workflowClient;
            }
    
            public Task StartAsync(CancellationToken cancellationToken)
            {
                _logger.LogInformation("Starting workflow fulfillment service.");
                _cancellationToken = cancellationToken;
                // _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
                _thread = new Thread(new ThreadStart(this.DoWork));
                _thread.Start();
                return Task.CompletedTask;
            }
    
            private async void DoWork()
            {
                while (true)
                {
                    if (_cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                    else
                    {
                        Thread.Sleep(5000);
                    }
                    await _workflowClient.Tick();
                }
            }
    
    
            public Task StopAsync(CancellationToken cancellationToken)
            {
                _logger.LogInformation("Stopping workflow fulfillment service.");
                return Task.CompletedTask;
            }
        }
    }
    

    Then in Startup.cs

                services.AddHostedService<WorkflowFulfillmentService>();