FunctionNewbie
FunctionNewbie

Reputation: 31

Migration NET 8 isolated process using Microsoft.Azure.WebJobs.QueueAttribute

I'm encountering multiple trigger errors while migrating my Azure Functions to the .NET 8 Isolated process model. I've been troubleshooting to the best of my ability, but haven't been able to pinpoint the exact cause(s).

To provide more context, here's some additional information (if applicable):

I'd greatly appreciate any insights or suggestions you might have to help me resolve these trigger errors and successfully complete the migration.

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Azure.Functions.Worker.Extensions.Storage;
//using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Microsoft.WindowsAzure.Storage.Queue;

namespace ClientService
{
    public static class ClientService
    {

 [Function("SaveClientToQueue")]
 [OpenApiOperation("saveclient", "SaveClient")]
 [OpenApiRequestBody("application/json", typeof(SaveClientQueueRequest))]
 [OpenApiResponseWithBody(HttpStatusCode.OK, "application/json", typeof(void))]
 public static async Task SaveClientToQueue([Queue("%SaveClientStorageQueue%", Connection = "StorageQueueConnectionString")] CloudQueue cloudQueue, ILogger log)
 {
    
      try
  {

      var saveClientRequest = await req.ReadFromJsonAsync<SaveClientQueueRequest>();
 
      var saveClientMessageAsJson = JsonConvert.SerializeObject(saveClientRequest);
      log.LogInformation($"HTTP Trigger Save client request received : {saveClientMessageAsJson}");

      var cloudQueueMessage = new CloudQueueMessage(saveClientMessageAsJson);
      await cloudQueue.AddMessageAsync(cloudQueueMessage);

      log.LogInformation($"Message added to Queue: {cloudQueue.Name} , SaveClientMessage: {saveClientMessageAsJson}");

      return req.CreateResponse(HttpStatusCode.OK);
  }
  catch (Exception ex)
  {
      
      log.LogError("An error happened while adding message to save client queue: " + JsonConvert.SerializeObject(await req.ReadFromJsonAsync<SaveClientQueueRequest>()), ex);

      throw;
  }

 
        [Function("SaveClientFromQueue")]
        public static async Task SaveClientFromQueue([QueueTrigger("%SaveClientStorageQueue%", Connection = "StorageQueueConnectionString")] CloudQueueMessage saveClientQueueMessage, ILogger log)
        {
            
            try
            {
                var saveClientMessage = JsonConvert.DeserializeObject<SaveClientQueueRequest>(saveClientQueueMessage.AsString);
                log.LogInformation($"C# QueueTrigger SaveClientFromQueue function processing started for message: {saveClientQueueMessage.AsString}.");                
            }            
            catch (CustomerRegistrationException ex)
            {
                var messageJSON = saveClientQueueMessage.AsString;
                log.LogError($"Error processing SaveClientFromQueue Message: {messageJSON}, DequeueCount: {saveClientQueueMessage.DequeueCount }, Exception Message: { ex.Message}, Exception: {ex}");
                throw;
            }            
            catch (Exception ex)
            {                
                var messageJSON = saveClientQueueMessage.AsString;               
                log.LogError($"Error processing SaveClientFromQueue Message: {messageJSON}, DequeueCount: {saveClientQueueMessage.DequeueCount }, Exception Message: { ex.Message}, Exception: {ex}");
            }
        }

 }

 [Function("KeepAliveFunction")]
 public static void KeepAliveFunction([TimerTrigger("%KeepAliveSchedule%")] TimerInfo timerInfo,  FunctionContext functionContext)
 {
     if (timerInfo.ScheduleStatus is not null)
     {
         var log = functionContext.GetLogger("KeepAliveFunction");
         log.LogInformation("Keep alive triggered for client service");
     }
 }

    }
}

No luck in finding correct solution and need guidance on how to migrate and properly implement this in the NET 8 isolated process.

Upvotes: 2

Views: 2252

Answers (1)

Pavan
Pavan

Reputation: 1381

  • The package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues must be installed.

The dotnet 8.0 isolated model must have packages below:

.cs proj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.0" />
    <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
      <PackageReference Include="Azure.Storage.Queues" Version="12.12.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues" Version="5.0.1" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
  </ItemGroup>
</Project>
  • Instead of using CloudQueue, use a parameter type that represents the message payload, such as string, CloudQueueMessage, or a custom class representing your queue message.
  • Change the function parameter to match the type of message you expect from the queue. If you want to process the message payload directly, use a type that represents your message payload, such as string or a custom class.

The below code is to migrated to dotnet 8.0 isolated. check below:

Code:

using System;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace ClientService
{
    public class Function1
 {
     private readonly ILogger<Function1> _logger;
     private readonly QueueClient _queueClient;

     public Function1(ILogger<Function1> logger, IConfiguration configuration)
     {
         _logger = logger;
         var connectionString = configuration["StorageQueueConnectionString"];
         var queueName = configuration["SaveClientStorageQueue"];
         _queueClient = new QueueClient(connectionString, queueName);
     }

     [Function("SaveClientToQueue")]
     public async Task<HttpResponseData> SaveClientToQueue(
         [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
     {
         _logger.LogInformation("HTTP trigger function processed a request.");

         try
         {
             var requestBody = await req.ReadAsStringAsync();
             var saveClientRequest = JsonConvert.DeserializeObject<SaveClientQueueRequest>(requestBody);
             if (saveClientRequest == null)
             {
                 var badRequestResponse = req.CreateResponse(HttpStatusCode.BadRequest);
                 await badRequestResponse.WriteStringAsync("Invalid request payload.");
                 return badRequestResponse;
             }
             var saveClientMessageAsJson = JsonConvert.SerializeObject(saveClientRequest);

             await _queueClient.CreateIfNotExistsAsync();
             await _queueClient.SendMessageAsync(saveClientMessageAsJson);

             _logger.LogInformation($"Save client request received: {saveClientMessageAsJson}");

             var response = req.CreateResponse(HttpStatusCode.OK);
             await response.WriteStringAsync("Client saved successfully.");
             return response;
         }
         catch (Exception ex)
         {
             _logger.LogError("An error occurred while processing the save client request.", ex);
             var response = req.CreateResponse(HttpStatusCode.InternalServerError);
             await response.WriteStringAsync("An error occurred while processing the request.");
             return response;
         }
     }

        [Function("SaveClientFromQueue")]
        public static void SaveClientFromQueue(
            [QueueTrigger("%SaveClientStorageQueue%", Connection = "StorageQueueConnectionString")] string saveClientQueueMessage,
            ILogger log)
        {
            try
            {
                var saveClientRequest = JsonConvert.DeserializeObject<SaveClientQueueRequest>(saveClientQueueMessage);
                log.LogInformation($"C# QueueTrigger SaveClientFromQueue function processing started for message: {saveClientQueueMessage}");

                // Your processing logic here
            }
            catch (Exception ex)
            {
                log.LogError("An error occurred while processing the message from the save client queue.", ex);
                throw;
            }
        }

        [Function("KeepAliveFunction")]
        public static void KeepAliveFunction(
            [TimerTrigger("%KeepAliveSchedule%")] TimerInfo timerInfo,
            ILogger log)
        {
            if (timerInfo.ScheduleStatus is not null)
            {
                log.LogInformation("Keep alive triggered for client service");
            }
        }
    }

    public class SaveClientQueueRequest
    {
        // Define your request properties here
    }
}

  • In SaveClientToQueue, replaced CloudQueue parameter with IAsyncCollector<string> to output messages to the queue.

Output:

enter image description here

enter image description here

Upvotes: 1

Related Questions