I am trying to execute a Timer triggered function via the Azure Portal but I get a 403 Forbidden error:
My networking settings on the Function App:
So it should be available and the appservice itself is running. I have created a new Function App with the default settings on Azure but still get the 403 error. Is there any other setting in Azure that I should set manually to be able to execute the function?
Program.cs
var host = new HostBuilder()
.ConfigureAppConfiguration((context, config) =>
{
var builtConfig = config.Build();
if (context.HostingEnvironment.IsDevelopment())
{
config.AddUserSecrets<Program>();
}
})
.ConfigureFunctionsWebApplication()
.ConfigureServices((context, services) =>
{
var configuration = context.Configuration;
var connectionString = configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
services.ConfigureFunctionServices();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddAutoMapper(typeof(Program));
var mapperConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new ConfigureAutoMapper());
});
})
.Build();
host.Run();
Function test:
public class FunctionTest
{
private readonly ILogger _logger;
public FunctionTest(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<FunctionTest>();
}
[Function("FunctionTest")]
public void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer)
{
_logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
if (myTimer.ScheduleStatus is not null)
{
_logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
}
}
}
I successfully executed the Timer trigger function after updating the below code to retrieve configuration details from local.settings.json
, which allowed it to directly access the connection string.
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
var connectionString = configuration["DefaultConnection"];
Program.cs :
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using AutoMapper;
using Microsoft.AspNetCore.Identity;
using Microsoft.Azure.Functions.Worker;
namespace FunctionApp16
{
public class Program
{
public static void Main(string[] args)
{
var host = new HostBuilder()
.ConfigureAppConfiguration((context, config) =>
{
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
if (context.HostingEnvironment.IsDevelopment())
{
config.AddUserSecrets<Program>();
}
})
.ConfigureFunctionsWebApplication()
.ConfigureServices((context, services) =>
{
var configuration = context.Configuration;
var connectionString = configuration["DefaultConnection"];
if (string.IsNullOrEmpty(connectionString))
{
throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
}
services.AddApplicationInsightsTelemetryWorkerService();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var mapperConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new ConfigureAutoMapper());
});
IMapper mapper = mapperConfig.CreateMapper();
services.AddSingleton(mapper);
})
.ConfigureLogging(logging =>
{
logging.AddConsole();
})
.Build();
host.Run();
}
}
}
FunctionTest.cs :
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
namespace FunctionApp16
{
public class FunctionTest
{
private readonly ILogger<FunctionTest> _logger;
public FunctionTest(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<FunctionTest>();
}
[Function("FunctionTest")]
public void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer)
{
_logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
if (myTimer.ScheduleStatus is not null)
{
_logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
}
}
}
}
local.settings.json :
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "<StorageConneString>",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"DefaultConnection": "<sqlConneString>"
}
}
I added the DefaultConnection in the Function app > Environment variables > App settings as shown below.
Azure Function app Output :
The Timer trigger function ran successfully as shown below.
Invocations :