Introduction
The HTTP trigger lets you invoke a function with an HTTP request. These HTTP triggers let you build a serverless API and respond to the webhooks.
In case you haven’t read my previous article, I would recommend you to read it here.
You can find the source code here.
Attributes
| Attribute Property | Description |
| Route | It defines the route template on which the endpoint is listening. The default value of the route is set to api/<FunctionName>. |
| AuthorizationLevel | Azure Function protects your HTTP trigger using Authorization keys. Authorization Level comes with three flavors – Anonymous: No key is required. – Function: A specific function key is required. This is the default value if none is specified. – Admin: A master key is required. |
| Methods | This is used to define HTTP verbs for the functions. |
Coding
Let's begin by creating a new Azure Functions project by select the trigger type as HTTP.
Add Nuget package
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Design
- Microsoft.EntityFrameworkCore.Tools
- Microsoft.Azure.Functions.Extensions
Add the entity Model,
- public class Employee {
- public int Id {
- get;
- set;
- }
- public string Name {
- get;
- set;
- }
- public int Age {
- get;
- set;
- }
- public double Salary {
- get;
- set;
- }
- public string City {
- get;
- set;
- }
- public string State {
- get;
- set;
- }
- }
Next, I’ll create a plain context for the data model to interact.
- public class EmployeeContext: DbContext {
- public EmployeeContext(DbContextOptions < EmployeeContext > dbContextOptions): base(dbContextOptions) {}
- public DbSet < Employee > Employees {
- get;
- set;
- }
- }
Write Function code to inject context
To inject the EmployeeContext in our HTTP Function, we first need to register the context in configure method of the FunctionStartUp.
- [assembly: FunctionsStartup(typeof(HttpTriggerVerify.Startup))]
- namespace HttpTriggerVerify {
- public class Startup: FunctionsStartup {
- public override void Configure(IFunctionsHostBuilder builder) {
- string SqlConnection = Environment.GetEnvironmentVariable("SqlConnectionString");
- builder.Services.AddDbContext < EmployeeContext > (x => x.UseSqlServer(SqlConnection));
- }
- }
- }
- public class HttpTriggerVerify {
- private readonly EmployeeContext employeeContext;
- public HttpTriggerVerify(EmployeeContext employeeContext) {
- this.employeeContext = employeeContext;
- }
- [FunctionName("HttpTriggerVerify")]
- public IActionResult GetEmployees(
- [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req, ILogger log) {
- log.LogInformation("C# HTTP trigger function processed a request.");
- var employees = employeeContext.Employees.ToList();
- return new OkObjectResult(employees);
- }
- [FunctionName("SaveEmployee")]
- public async Task < ActionResult > SaveEmployeeAsync([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req ILogger log) {
- string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
- var data = JsonConvert.DeserializeObject < Employee > (requestBody);
- await employeeContext.Employees.AddAsync(data);
- await employeeContext.SaveChangesAsync();
- return new OkResult();
- }
- }
In this example, we are using two functions
- GetEmployees: Get all the employees from the DB
- SaveEmployee: Insert the employee related information to DB
Here, I am using the Authorization level as Anonymous for simplicity purposes.
Executing EF Core Migration
Now, run the EF core migration by using the below commands.
- //For Mac
- dotnet ef migrations add InitialContext
- For Windows
- add-migrations InitialContext
After running the migration command, an error is thrown suggesting it's unable to find the project dll in the netcoreapp folder. But, you can find the project dll file inside the netcoreapp’s bin folder.
Unfortunately, the design time tools like EF core migration expect the dll’s to be present in the root of build target. To make the EF core migration happy, we need to add post build event to copy the dll to the root of build target.
- <Target Name="PostBuild" AfterTargets="PostBuildEvent">
- <Exec Command="cp "$(TargetDir)bin\$(ProjectName).dll" "$(TargetDir)$(ProjectName).dll"" />
- </Target>
Again after running the migration script, EF core is now complaining about not being able to find the desired context. We can fix it by using IDesignTimeDbContextFactory<T>.
- public class EmployeeContextFactory: IDesignTimeDbContextFactory < EmployeeContext > {
- public EmployeeContext CreateDbContext(string[] args) {
- var optionsBuilder = new DbContextOptionsBuilder < EmployeeContext > ();
- optionsBuilder.UseSqlServer(Environment.GetEnvironmentVariable("SqlConnectionString"));
- return new EmployeeContext(optionsBuilder.Options);
- }
- }
After running the migration script, everything seems to be working perfectly! Now, update the database with the latest migration
- //For Mac
- dotnet ef database update
- //For Windows
- update-database
Now, I can see Employee table is being added to the DB.
Finally, we have managed to put all the code changes in place. Run the application and verify the GetEmployees and SaveEmployee methods are working as expected.
I hope you like the article. If you found this article interesting then kindly like and share it.

Paras SuriPosted Oct 29, 2020, 8:41 AM
Hi Anup, Thanks for the above article. I am using TimerTrigger instead of http trigger as I had different scenario. On adding IDesignTimeDbContextFactory<T>. it has solved migration script error problem for me. But on running Add-Migration command again it is showing me the following error. Have you came across the error below? ystem.ArgumentNullException: Value cannot be null. (Parameter 'connectionString') at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName) at Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseSqlServer(DbContextOptionsBuilder optionsBuilder, String connectionString, Action`1 sqlServerOptionsAction) at Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseSqlServer[TContext](DbContextOptionsBuilder`1 optionsBuilder, String connectionString, Action`1 sqlServerOptionsAction) at FunctionAppDemoOTP.Models.BankContext.BankContextFactory.CreateDbContext(String[] args) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContextFromFactory(Type factory) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_1.<FindContextTypes>b__9() at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType) at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action) Value cannot be null. (Parameter 'connectionString') My local.settings.json file has the following settings { "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet", "ConnectionString": "Server=(localdb)\\mssqllocaldb;Initial Catalog=SampleDB;Trusted_Connection=True;MultipleActiveResultSets=true" } } And here is my startup.cs file. It has the following code. public class Startup : FunctionsStartup { public override void Configure(IFunctionsHostBuilder builder) { string SqlConnection = Environment.GetEnvironmentVariable("ConnectionString"); builder.Services.AddDbContext<BankContext>(options => options.UseSqlServer(SqlConnection)); } public class BankContextFactory : IDesignTimeDbContextFactory<BankContext> { public BankContext CreateDbContext(string[] args) { var connectionString = Environment.GetEnvironmentVariable("ConnectionString"); var optionsBuilder = new DbContextOptionsBuilder<BankContext>(); optionsBuilder.UseSqlServer(connectionString); return new BankContext(optionsBuilder.Options); } } }
Teja RPosted Aug 6, 2020, 6:11 AM
Hi Anup, Is it possible to use existing tables in the database and just do an insert using EF core with Azure Functions (C#)?
kiran guptaPosted Jul 15, 2020, 10:46 PM
Hi Anup, Thanks for the above article. Quick question: We have a queue trigger azure function. We are injecting dbContext say EmployeeContext in a different class EmployeeRepository. EmployeeRepository will create/update/get entities. This EmployeeRepository is injected in to Queue trigger Azure function. If we don't use using statement or dispose the EmployeeContext once we add/update, is there a possibility with the sql connections or dbContext instances running out?