How YOU can build a Serverless C# .Net Core API in no time, with bindings and a Database 
Tags: dotnet, tutorial, webdev, serverless
Published: 2019-09-13 16:49:40

---
title: How YOU can build a Serverless C# .Net Core API in no time, with bindings and a Database 
published: true
description: Learn the basic concepts of Serverless in .Net Core and how to do a CRUD against a database
tags: dotnet, tutorial, webdev, serverless
cover_image: https://thepracticaldev.s3.amazonaws.com/i/d4si8c2zkxuzp4r3rfhc.jpg
canonical_url: https://softchris.github.io/pages/dotnet-serverless-database.html
---

Follow me on [Twitter](https://twitter.com/chris_noring), happy to take your suggestions on topics or improvements /Chris

This article is part of [#ServerlessSeptember]( https://dev.to/azure/serverless-september-content-collection-2fhb). You'll find other helpful articles, detailed tutorials, and videos in this all-things-Serverless content collection. New articles are published every day — that's right, every day — from community members and cloud advocates in the month of September.


> Serverless is great in many ways. 

> Your first impression of Serverless might be that it's saving you money. You've realized that you have some code that can run seldom and you've moved that and made Azure functions out of it. Great, you're already happy at this point, who doesn't like more resources? Then you discover something else that's equally great or even greater. Because it lives in the Cloud it can take to all your services in the Cloud with almost no configuration. How come it's this easy? It's made easy cause we are using something called *bindings*. So let's talk about Serverless and why and how bindings are part of the success story that is Serverless



In this article we will cover:

- **Serverless**, what is it, why would we want to use it?
- **Core concepts**, let's cover bindings and trigger
- **Demo**, let's build something using Bindings and Databases and show how easy it is 

## Resources

- [Sign up for a free Azure account](https://azure.microsoft.com/en-us/free/?wt.mc_id=servsept_devto-blog-chnoring)
If you want to build Logic Apps and Azure Functions you will need an Azure account, it's free.

- [Triggers and bindings](https://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings?wt.mc_id=devto-blog-chnoring)

- [Great example page for using Triggers and bindings in different languages](https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-cosmosdb-v2#input---c-examples?wt.mc_id=devto-blog-chnoring)

- [Great article on CosmosDB and Azure Functions](http://dontcodetired.com/blog/post/Reading-Azure-Cosmos-DB-Data-In-Azure-Functions)
Great article, great blog in general

- [LEARN module for working with bindings and Triggers](https://docs.microsoft.com/en-us/learn/modules/chain-azure-functions-data-using-bindings/?wt.mc_id=devto-blog-chnoring)

## Serverless

> Serverless is on everyone's lips right now. Serverless this Serverless that. Why is that?

Part of the reason is that Cloud nowadays has become the default hosting platform, no more server rooms *almost*. The Cloud is really someone else server room but the bottom line is that you don't have to care. There are so many things the Cloud helps with, security, reliability, backup, scalability and most of all the ability for other things that live in the Cloud to talk to each other. 

>  So why is that great? 

Most companies have a ton of services that together makes out the IT landscape they call a business. Getting all or most of these services to talk to each other is an all-consuming task or at least it requires a lot of resources. Most Clouds today are really good at connecting these services within the Cloud and even cross Cloud. 

> So where does Serverless fit in?

Serverless has arrived after many steps of cloud evolution in which we first decided to NOT manage the hardware anymore. Then we decided that we didn't want to deal with app servers. So we arrived at the point where we just wanted to focus on code, code, and nothing but the code. That meant a whole new platform was born or FaaS, function as a service. With the arrival of Serverless, we realized something else. We started to realize more and more we only wanted to pay for actual code execution and that's just what Serverless offers - fully managed and pay for what you use.

> That's not why we read this article though?

Correct, we are here to learn about how to integrate Serverless functions with other things using something called *bindings*. 



## Core Concepts

There are three major concepts we need to understand when it comes to integration and Serverless, those are

- **Triggers**, this is how our function can be invoked. What causes an invocation could be everything from an HTTP call, new database entry to a new message on a queue and even more other things. The Point is, triggers are what *starts* our function.
- **Input binding**, this a connection to some kind of data source. The point is to read data from this data source. This could be everything from an Excel document, Database or a Queue
- **Output binding**, this is us creating a connection to a database with the explicit intent of wanting to change data. Typically we get access to a record that we can populate and this record goes into the data source to typically update or create new data

There, now we know the most important concepts that we need to know to get started.

## Demo

Ok so what are we building? Well, to showcase how great Serverless let's try to connect with at least two things. That means we will need to build/provision:

-  **Database**, we will provision a CosmosDB Database
- **Azure Function App**, of course, we will need to build an Azure Function App that connects with our database

### Database

This step is pretty straight forward. What we need to do is log in to the Azure Portal. You do have an account right? If not, create a free one here [Free Azure account](https://azure.microsoft.com/en-gb/free/?wt.mc_id=devto-blog-chnoring)

Here are all the steps we need to take:

1. **Provision** our Database
2. **Set up** the database and add sample data



**Provision our Database**

Ok, so we have logged in to the portal. Now let's provision a database like so:

![](https://thepracticaldev.s3.amazonaws.com/i/xigs7t567fu6c68381ui.png)

Thereafter we need to enter some information about our database. Below we have indicated all the mandatory fields we need to fill in. Ensure you select `API` as `Core(SQL)` and also ensures you have picked a `Location` that's close to you for best response times.

![](https://thepracticaldev.s3.amazonaws.com/i/uzw4wwwxp8cdho5fn7rm.png)

Lastly, hit `Review + Create` at the bottom. This should trigger provisioning. A few minutes later your resource/database should be ready for use.

**Set up the database**

Now our resource has been provisioned and it's ready for use to configure it. The first thing we are going to do is to add a Container.

> What is a container?

Glad you asked :) A container is what actually will hold our data or entities. The container itself contains something called *documents*.

To create the container we select `Data explorer` from the left menu and then click `New Container`, like so:

![](https://thepracticaldev.s3.amazonaws.com/i/8sjzdb4xcue9cs8rar9n.png)

Next step is to fill in all the details needed to create a container. 

It will ask you to fill in the following fields:

- **Database id**, you can give it whatever name you want, I choose to name it **database-chris**
- **Throughput**, give it the value **1000**
- **Container id**, this is the name of the collection. A collection holds a list of documents. Every document is like a row in a table, with table and collection being roughly the same thing. Give it the name **Bookmarks**
- **Partition key**, The partition key specifies how the documents in Azure Cosmos DB collections are distributed across logical data partitions. What does that even mean? It means this database scales in the Cloud. We tell it how to scale and how to use a technique used *sharding* to do so. Give the value **/id**

The form will look like this:

![](https://thepracticaldev.s3.amazonaws.com/i/hrcdcez6fm9h5qyecovv.png)

**Add sample data**

Ok now the database is set up and we can start filling it with some data. So the next step is to click our `Collection` bookmarks and then `Items`. Thereafter click `Net Item` to insert a record in our collection, like so:

![](https://thepracticaldev.s3.amazonaws.com/i/ukbh9x0rq8015gztwtap.png)

As you can see to the right it has opened up a textarea that we can use to insert data. Let's change that to the following:

```
{
    "id": "docs",
    "url": "https://docs.microsoft.com/azure"
}
```

and click `Save`. Add a few more records like so:

```
{
    "id": "portal",
    "url": "https://portal.azure.com"
}
```

and a last one:

```
{
    "id": "learn",
    "url": "https://docs.microsoft.com/learn"
}
```

### Azure Function app

Ok, then we have a database, a data source. Now it's time for us to build an Azure Function app and an Azure Function and really demonstrate how easy it is to connect our data source. We will do the following:

1. **Scaffold** an Azure Function app and an Azure Function
2. **Set up** a connection to the database
3. **Read** from our database and thereby learn about input bindings
4.  **Write** to our database and thereby learn output bindings

**Prerequisites**

To be able to scaffold our Azure Function app we need a few things installed namely

- [Azure Core Tools](https://github.com/Azure/azure-functions-core-tools#installing)
- Azure Functions extension for VS Code, [Extension](vscode:extension/ms-azuretools.vscode-azurefunctions)
- A free Azure Account or an existing one if you have that,  [Free account](https://azure.microsoft.com/free/?wt.mc_id=twitter-social-chnoring)

>  Ok, all setup?

Good, let's continue! :)

**Scaffold an Azure Function App**

Open up VS Code. Select `View/Command Palette` (Ctrl + Shift + P on Windows, CMD + Shift + P on Mac). 

Start typing for `Azure Function: Create new Project` and select it. 

- Select the current folder
- Select C# as language
- Select HttpTrigger for our first function
- Give it the name `Bookmarks`
- You name the namespace anything you want but let's go with `Company`.
- Choose the authorization type `Function`

A window will popup to `restore dependencies`. Click that or if you miss it head to the terminal and type `dotnet restore`. This is so it downloads all the dependent library that it has specified.

Ok then. We have gotten ourselves a function called `Bookmarks`, it resides in the `Bookmarks.cs`, like so:

![](https://thepracticaldev.s3.amazonaws.com/i/9elzk1f0kjmrn7dm4vqs.png)

Let's open up `Bookmarks.cs` shall we?

```csharp
// Bookmarks.cs
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Collections.Generic;

namespace Company
{
    public class Bookmark 
    {
        public string Id { get; set; }
        public string Url { get; set; }
    }
    public static class Bookmarks
    {
        [FunctionName("Bookmarks")]
        public static async Task<IActionResult> Run(
          [HttpTrigger(
            AuthorizationLevel.Function, 
            "get", 
            "post", 
            Route = null)
          ] HttpRequest req,
            ILogger log
            )
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            return name != null
                ? (ActionResult)new OkObjectResult($"Hello, {name}")
                : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
        }
    }
}

```

What we are most interested in is the top of our function, let's zoom in on that:

```csharp
[FunctionName("Bookmarks")]
public static async Task<IActionResult> Run(
  [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
  ILogger log
) { /* function body */ }
```

We can see that the attribute `FunctionName` is used to determine that we are dealing with a function and that it's called `Bookmarks`. Then we can see that we have an attribute `HttpTrigger` that says it can be triggered by an HTTP call. 

### Adding CosmosDB input binding

Ok, so how do we add CosmosDB to this? Well, there are two ways:

1. **Add the CosmosDB attribute** to our `Bookmarks.cs` file and then install the correct NuGet package from the terminal to ensure everything compiles

2. **Add a function with a CosmosDB trigger**, this will install the needed dependencies and will also trigger a storage dialog that makes you choose a storage account, the name of your database and your collection

Let's try out the first option. First, let's open up a terminal and type:

```
dotnet add package Microsoft.Azure.WebJobs.Extensions.CosmosDB
```

Now we are ready for the next step which is to add an input binding to our `Bookmarks.cs` file. 

To do that we will use an attribute class called `CosmosDB`. We need to give it some values namely

- **database name**,  this is what we named our database so that's **database-chris**
- **collection name**, we named our collection **Bookmarks**
- **connection string**, as for connection string, this is something we can find in our Azure Portal. Go to your resource click **Keys** in the menu and then copy the value displayed in **PRIMARY CONNECTION STRING**

Now, database name and collection name are things we can add in the code, like so:

```csharp
// excerpt from Bookmarks.cs

[FunctionName("Bookmarks")]
public static async Task<IActionResult> Run(
  [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
  [CosmosDB("database-chris", "Bookmarks", ConnectionStringSetting ="CosmosDB")]IEnumerable<Bookmark> bookmarks
  ILogger log
) { /* function body */ }
```

So above we have added the attribute class `CosmosDB` and *decorated* the parameter `bookmarks`. We can see that `bookmarks` is of type `IEnumerable<Bookmarks>`

> where does the type `Bookmark` come from?

That's a type we need to create, either in `Bookmarks.cs` or it's own file, but it needs to have the following shape:

```csharp
public class Bookmark 
{
  public string Id { get; set; }
  public string Url { get; set; }
}
```

It has the properties `Id` and `Url` to match the shape it has in the database.

Looking further at the code, we give `ConnectionStringSetting` the value `CosmosDB`

>  where does it come from? 

It comes from a file `local.settings.json` and its `Values` property, like so:

```json
{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "CosmosDB": "value of primary connection string"
  }
}
```

**Trying it out**

Let's first set a debugger  on the first row of our function in `Bookmarks.cs`. 

In the menu of VS Code select `Debug/ Start Debugging`. 

![](https://thepracticaldev.s3.amazonaws.com/i/yamon2cfp0gzfzjxuios.png)

Go to the browser and input `http://localhost:7071/Bookmarks` and your breakpoint should be hit, like so:

![](https://thepracticaldev.s3.amazonaws.com/i/qigybiof4aegyrkxiwcv.png)

As you can see our `bookmarks` variable is populated with data, we are talking to the database and it is giving us data, success :)

**Limiting our response**

Now the above is great, we get data back from the Database. However, we might have millions of records in there, how do we limit our response? 

 That's easy to do, we need to add two parameters to our `CosmosDB` attribute, namely:

- Id
- PartitionKey

It's worth learning about partition keys. So have a read here [Partition keys for CosmosDB](<http://www.anderbakk.com/designing-a-partition-key-for-cosmos-db/>)

Ok, so what we will do is to add a new function that will be able to take a `query` parameter from our trigger and use that to query CosmosDB. So add the following function:

```csharp
[FunctionName("GetBookmark")]
public static IActionResult GetBookmark(
  [HttpTrigger(AuthorizationLevel.Function, "get", Route=null)] HttpRequest req,
  [CosmosDB(
  "database-chris",
  "Bookmarks",
  ConnectionStringSetting = "CosmosDB", 
  Id = "id",
  PartitionKey = "{Query.id}"
)]Bookmark bookmark, 
  ILogger log
)
{
  return (ActionResult) new OkObjectResult(bookmark);
}
```

Now start up our application and run the following URL in the browser `http://localhost:7071/api/GetBookmark?id=portal`. This will ensure that our CosmosDB is queried for `id` with the value `portal`. The result should be this:

![](https://thepracticaldev.s3.amazonaws.com/i/mbm0y7r21vq0d8kv17i0.png)

### Output bindings

We used input bindings to read from a database. Output bindings are used to write to a database. Let's look at two different scenarios. 

- **Create**, we will take query parameters from our trigger and use those to create an entry in our database
- **Update**, We will take an existing entry and update that

**Create**

Ok then, what's needed to create an output binding? Well, it's almost nothing. The only thing we need is a new parameter in a function of type `out`, like so:

```csharp
out dynamic bookmark
```

Let's create a new dedicated function though and call it `CreateBookmark` and define it like so:

```csharp
[FunctionName("CreateBookmark")]
 public static IActionResult CreateBookmark(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route=null)] HttpRequest req,
        [CosmosDB("database-chris","Bookmarks",
            ConnectionStringSetting = "CosmosDB")]out dynamic bookmark,
            ILogger log
    ) {
        string id = req.Query["id"];
        string url = req.Query["url"];

        bookmark = new { id = id, url = url };

        return (ActionResult)new OkObjectResult("created");
    }
```

Now fire up the program and enter a URL like so `http://localhost:7071/api/CreateBookmark?id=devto&url=dev.to%2Fsoftchris`  in the browser. That's it, this should create new entry. Don't believe me? Have a look at your database in the portal:

![](https://thepracticaldev.s3.amazonaws.com/i/zlmv0pmxq6axcqdfhsw8.png)

**Update**

Well, because this is CosmosDB. This means that if there is a pre-existing record with that id value if will simply be replaced. However, that might not be what you had in mind. If you only wanted to update certain properties I recommend the following approach:

1. **Use** an input binding to retrieve an existing record
2. **Copy** the values from that input record to the output binding
3. **Copy** whatever values you get from a trigger to the output binding

That's it, that's the two update scenarios we have.

## Summary

We've learned about input bindings as well as output bindings. We learned that input bindings allowed us to read from the database and output bindings allowed us to create or update data. Additionally, we've learned how to provision a CosmosDB database and connect to it using an attribute class called CosmosDB. It's definitely possible to have CosmosDB as a trigger as well but that will be another article :)