Azure Function Isolated mode and ConnectionString set up for CosmosDB

240 views Asked by At

I built a .net 8 V4 Azure function app that uses both cosmos db triggers and bindings to read and write data to cosmos db. Locally, the app works fine because I have set up the connection string local.setting.json. However, when I upload the code to Azure, the functions run but it does not communicate with my cosmos db. In the portal, I added the connection string through Environmental variables, and then connection strings, but it did not work. Please one can help to solve this issue.

    public CosmosDBFunction(ILogger<CosmosDBFunction> logger,
        IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory.CreateClient();
        _logger = logger;
        _cosmosClient =
        new CosmosClient("AccountEndpoint=<Connection>");
        
    }
    
    [Function(nameof(Function))]
    public static async Task<string> RunOrchestrator(
        [OrchestrationTrigger] TaskOrchestrationContext context)
    {
        ILogger logger = context.CreateReplaySafeLogger(nameof(CosmosDBFunction));
        logger.LogInformation("----Function Started-----");
    
    
        string pagesToLinks = await context.CallActivityAsync<string>(
        nameof(somefunction));
        
        string linksToClins = await context.CallActivityAsync<string>(
        nameof(somefunction));
        
        string Blinks = await context.CallActivityAsync<string>(
            nameof(somefunction));
    
        logger.LogInformation("----Function Finished-----");
        return "Operation Is Completed";
    }

[Function(nameof(SomeFunction))]
[CosmosDBOutput(databaseName: "X", containerName: "Y",
      Connection = "ConnectionNameSavedInLocal.Setting.json"
     , CreateIfNotExists = true, PartitionKey = "/dd")]
public async Task<string> ScanLinksAndInsertIntoLinksContainer
    ([ActivityTrigger] string name,
    [CosmosDBInput(
    databaseName:"ss",
    containerName:"pt",
    Connection = "ConnectionNameSavedInLocal.Setting.json"
    )]
    List<todo> todos,
    FunctionContext executionContext){}

Host.json
{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      },
      "enableLiveMetricsFilters": true
    },
    "extensions": {
      "cosmosDB": {
        "connectionMode": "Direct",
        "userAgentSuffix": "MyDesiredUserAgentStamp"
      }
    }
  }
}

local.setting.json

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolate

d",
    "CosmosConnection": "AccountEndpoint=https: <ConnectionString>"
  }
  
}

In portal I checked the tab Connection String and it looks like this

[
  {
    "name": "CosmosConnection",
    "value": "AccountEndpoint= 
             <ConnectionString>",
    "type": "DocDb",
    "slotSetting": false
  }
]
3

There are 3 answers

6
Pavan On

when I upload the code to Azure, the functions run but it does not communicate with my cosmos db.

  • Initially I am also getting same issue. After adding the cosmosdb connection string in appsettings of function app working as expected.
  • Make sure the key must be same in Local and portal appsettings. and check the binding in integration.
  • I have created a function with runtime stack .net 8.0 Isolated and added cosmosdb Input and output binding in the code. The below function executed successfully and when added the Items in cosmosdb container.
namespace FunctionApp130000
{
    public static class Function1
    {
        [Function(nameof(Function1))]
        public static async Task<List<string>> RunOrchestrator(
            [OrchestrationTrigger] TaskOrchestrationContext context)
        {
            ILogger logger = context.CreateReplaySafeLogger(nameof(Function1));
            logger.LogInformation("Saying hello.");
            var outputs = new List<string>();

            // Replace name and input with values relevant for your Durable Functions Activity
            outputs.Add(await context.CallActivityAsync<string>(nameof(CosmosTrigger1), "Tokyo"));
            outputs.Add(await context.CallActivityAsync<string>(nameof(CosmosTrigger1), "Seattle"));
            outputs.Add(await context.CallActivityAsync<string>(nameof(CosmosTrigger1), "London"));

            // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
            return outputs;
        }

        [Function(nameof(CosmosTrigger1))]
        [CosmosDBOutput("%sampledb%","%user%", Connection ="CosmosDBConnection", CreateIfNotExists = true)]
        public static async Task<string> CosmosTrigger1([ActivityTrigger] string name, [CosmosDBInput(databaseName: "sampledb",containerName: "user", Connection = "CosmosDBConnection")] List<Todo> todos,
            FunctionContext executionContext)
        {

            ILogger logger = executionContext.GetLogger("SayHello");
            logger.LogInformation("Saying hello to {name}.", name);
            foreach (var todo in todos)
            {
                // Do something with each todo item
                logger.LogInformation("Processing todo item: {id}, {name}", todo.Id, todo.Name);
            }
            return $"Hello {name}!";
        }

        [Function("Function1_HttpStart")]
        public static async Task<HttpResponseData> HttpStart(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
            [DurableClient] DurableTaskClient client,
            FunctionContext executionContext)
        {
            ILogger logger = executionContext.GetLogger("Function1_HttpStart");

            // Function input comes from the request content.
            string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
                nameof(Function1));

            logger.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId);

            // Returns an HTTP 202 response with an instance management payload.
            // See https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-http-api#start-orchestration
            return client.CreateCheckStatusResponse(req, instanceId);
        }
    }

    public class Todo
    {
        public string? Id { get; set; }
        public string? Name { get; set; }
    }
}

local.settings.json:

{
    "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "CosmosDBConnection": "your-cosmosdb conn-string",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
  }
}

enter image description here

I have published the above function into azure portal successfully. check below: enter image description here

Check the binding of cosmosdb connection like below:

enter image description here

  • when adding items in cosmosdb trigger getting traces in Invocation details of function. check below:

enter image description here

2
user23536253 On

I have the same issue on .net 8 V4 isolated Azure function app that uses cosmos db triggers. Works locally every time, when deployed it fails to trigger.

I can see storage exceptions in kudu logs:

 "functionAppContentEditingState": "Unknown"
}
2024-03-05T12:08:06  PID[4860] Error       3/5/2024 12:08:06 PM Encountered exception while validating SAS URI System.Exception:Azure storage account must be configured     at DaaS.Storage.AzureStorageService.ValidateStorageConfiguration(String& storageAccount, Exception& exceptionContactingStorage)
2024-03-05T12:08:06  PID[4860] Error       3/5/2024 12:08:06 PM Invalid storage configuration System.Exception:Azure storage account must be configured     at DaaS.Storage.AzureStorageService.ValidateStorageConfiguration(String& storageAccount, Exception& exceptionContactingStorage)

I have tested storage connection string locally and works fine, feels like an SDK issue to me.

0
redar ismail On

I solved the issue. In the Azure portal, there is a tab called Environment Variables, once you click on that you will get two different tabs one called App Settings and Connection Strings. I was saving my connection string inside connection string tab, and that was the reason my app was not working. I added the connection string in the App Setting tabs, the application started working as expected. I am not sure why the connection string is there. This is very confusing and it took a couple of days to figure it out.