Implementing the API using Azure Functions — Part 6
This is the 6th article of an article series which we’ll be creating an API using Azure functions.
Let’s jump right into it.
Create an Azure functions project
and when the next dialog appears which asks about the nature of the azure function which you are creating select “empty” as shown below,
We will be using the functions V2 environment where you can develop using .NET Core 2. All the Azure functions need a storage account and “Storage Emulator” is the storage when you are developing locally (you can always change it to an existing storage account or even create a new one from there and assign that account)
Once it gets created you’ll see a couple of files created. The local.settings.json
is where we’ll be adding the configuration settings which we’ll require. Please add the below content in your local.settings.json
file.
- AzureWebJobsStorage — As explained earlier when we develop we can easily use this account. It emulates a storage account in Azure.
- FUNCTIONS_WORKER_RUNTIME— Azure functions can be implemented using many languages. Since we are using .NET the value is “dotnet”.
- FunctionAppEnvironment — this is a custom setting. This is to identify the environment which the function is operating on. When we are developing locally it will be “development” but once we publish it to Azure it will be “production”. The setting of the values are done in the portal when we deploy.
- KeyVaultUrl — We are using AKV to store connection strings securely in Azure. In the local environment (development) we’ll keep it empty but when we deploy we’ll add the URL to the key vault which we’ll be creating.
- FunkyBankConnectionStringKey — In the “development” environment this will actually represent the connection string to your local database. But when we deploy to Azure this will have the value to the “key name” where we store the actual connection string securely in AKV.
local.settings.json file should not be source controlled. Because it’s the local environment and, it represents the config values which you need to set in the portal anyway.
Before we move further let’s install some nuget packages which we’ll be using. In the application we have many classes and interfaces scattered across many projects. It’s time to introduce IoC. I am using AzureFunctions.Autofac
as the dependency injection framework. Also because we are using AKV for secure access there are a few nuget packages which we need to install as well. Please install the below packages using Nuget.
- AzureFunctions.Autofac — 3.0.6 is the latest at the writing of this.
- Microsoft.Azure.KeyVault — 3.0.3 is the latest at the writing
- Microsoft.Extensions.Configuration.AzureKeyVault — 2.2.0 is the latest at the writing
- Microsoft.Azure.Services.AppAuthentication — 1.0.3 is the latest at the writing
If you want to get more information about how to use
AzureFunctions.Autofac
Jason Robert’s excellent article on this would be the best or, visit their documentation
Personally I don’t like one class configuring the entire application’s dependencies. I would like to give that responsibility to each module which have dependencies to be registered. So I have created “bootstrapper” classes in each project.
ApiBootstrapper
This resides in the FunkyBank.CustomersApi
. Because this is the executing assembly, this is where registrations for dependencies begin. Depending on the environment (development or production) where the function executes it registers it’s own dependencies and passes the ContainerBuilder
instance to the next layer — which is the FunkyBank.Services
.
ServicesBootstrapper
This is where we register the dependencies in the services layer and, once it’s done it passes it to the data access module.
DataAccessBootstrapper
This is where dependencies for the data access layer is registered.
Now we have wired all the dependencies in a consistent and a manageable way. Let’s go and create those Azure functions now.
I’ll explain the GetCustomersFunction
Azure function, because it’s quite easy to start with and to show how the dependencies are injected. The approach will be the same, for the other Azure functions.
GetCustomersFunction
- Right click the
FunkyBank.CustomersApi
project and click “New Azure Function”. Then select “HttpTrigger” template and select “anonymous” as for “access rights” as shown below,
Then change the code as shown below,
- Decorate the class with
DependencyInjectionConfig(typeof(ApiBootstrapper))
— this is how Autofac identifies to initiate the dependency registrations in the IoC container. - Decorate what you want to inject with the
Inject
attribute. As you can see on line #27 how theICustomerService
is injected.
The implementation is pretty straight forward because we have already implemented the functionality in the data access and in the service modules.
Notice how the
route
is set. When this is set the function need to be accessed through a specific route only and, this is how the API will be accessed from the external parties.
CreateCustomerFunction
Will be used to create a customer.
UpdateCustomerFunction
Used to update a customer.
DeleteCustomerFunction
Used to delete a customer.
GetSpecificCustomerFunction
Used to retrieve a specific customer by id.
All done, we have now created an API using Azure functions. But how can we deploy this to Azure? We’ll use Azure DevOps to setup a project and create build and release pipelines in there to get this done smoothly. We’ll use the Azure resources which we created in Part 2, where the release pipeline will use to deploy the code into.
Well hold on…how about database migrations? Didn’t we want that to be a part of the solution and to be a part of the deployment as well?
Exactly, before we jump into the exciting times of seeing the application which we built on Azure let’s get the database migrations sorted.
Please read the next article which I’ll be explaining how the database migrations are done through “DbUp”
Thanks!