Thursday, January 27, 2022

Creating a CosmosDB Azure Function in 5 Minutes

What is an Azure Function?

When talking about cloud solutions, there are many choices. A web application can be deployed using a typical virtual machine or the PaaS (Platform as a Service) solution of an Azure web app. Sometimes a quick function is all you need, and a large application is overkill. This is where an Azure Function comes into play.   With an Azure Function, we can implement a web end point that can be called by other Azure services or create a typical http endpoint. These functions can can be coded directly in the browser for a quick way to roll up an endpoint. In addition to this, there are integration features where you can setup triggers, integrate data sources, and choose the output option for the function all without code. 

Azure Functions work well with a microservice architecture. Functions are well suited for keeping your code to one domain and avoiding a sprawling application into other domains. They are meant to fit a very specific action and it makes it difficult to go beyond that specific action. Also, with the ability to trigger the function from various methods setting up an event bus that will react and trigger the function when necessary.

Example of a function setup.

Create an Azure Function in 5 minutes

Setup CosmosDB

In this example, we are going to create a function that returns some data from a CosmosDB. For our function to be configured using integrations, we need to make sure we are using a SQL backed Cosmos DB. We can still use Azure Functions to connect to other NoSQL databases, but it will be the traditional connection, such as BSON.
 


In the newly created Cosmos DB, we need to create a new container. For this example, a simple Product database will be used. Our container will use the following model, and we will use Product ID for our partition key.


public class GetTestItem
{
    public string id {get;set;}
    public string ProductId {get;set;}
    public string manufacturer {get;set;}
    public string description {get;set;}
}





Here is an example of some data inserted into our newly created database.


Setup Azure Function

With the data source created, the next step is to setup the Azure function. 


With our app created, next we need to setup a trigger. For this example, I am going to call it GETALL for demonstration purposes. Proper REST Url would be "Products". When creating the function, we are also going to select "Development in Portal", and "Anonymous" for authorization. Finally, this will be an HTTP trigger.

In our new function, click "Integration". This will bring up our menu to configure the function.



In our integration screen, a new input needs to be created. This will bring up a message for creating a connection to the Cosmos DB database. Just follow the steps to select your Cosmos DB connection. The "Document Parameter Name" is the name we will use to reference in our function.








Going back to our integration screen, select the function. Now pull up the run.csx. This is where we will write our code to manipulate the Cosmos DB data. The biggest changes will be in the constructor of our function.



public static async Task Run(HttpRequest req, ILogger log)

In the constuctor, we will add a collection that will represent our SQL collection. You will notice in the code below, that the connection string now has an IEnumerable name Products to represent the input we declared in in the integration screen. Once this is added our function will connect to the database and pull all items from our container with no code. The example below will just write back all the data as a response to the request.


#r "Newtonsoft.Json"

using System.Net;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;



public class Product
{
    public string id {get;set;}
    public string ProductId {get;set;}
    public string manufacturer {get;set;}
    public string description {get;set;}
}

public static async Task Run(HttpRequest req, 
                IEnumerable Products,
                ILogger log)
{
    try
    {
    log.LogInformation("C# HTTP trigger function processed a request.");

    return new OkObjectResult(Products);
    }
    catch (Exception ex)
    {
                log.LogError($"Couldn't insert item. Exception thrown: {ex.Message}");
                return new StatusCodeResult(StatusCodes.Status500InternalServerError);
    }
}


That's it. Our function app is ready and will show all items for our Cosmos DB with very little coding.

Bonus! Setup an additional call to get item by id

It is pretty impractical to display all items from our database. So how can we add a query to our integration to pull the data we need. If you notice, on the bottom of our input integration screen there is a SQL query section. To setup a query function, let's go back and create a new function GetById.  An additional function can be added from the Azure portal in the function settings. We will use the same settings from our GET app We will have it be anonymous and use the designer. Once the new function is created, go to the integration screen and create the input. fill out the database name and collection name from the previous step. This time, a SQL query will be added at the bottom. The query will select the top item where id = id


SELECT TOP 1 * FROM d where d.id = {id}



In our SQL query you will find the parameter {id} which will represent the data we are wanting to pass to the query. So to get our id parameter we will want to update the request's route to include the id. To do this, open up the Trigger in our integration menu to get the edit screen for adding a route.




In the route template we will add our parameter {id} to the route. For this example I will have GetByID/{id} to show what I am actually doing, in a production environment this route would be something like Products/{id}.





Now in our new function app, we will open the function and go to our run file. I will add the new parameters for ID and my SQL database to the constructor. Since i have a query setup, my SQL collection will now be filtered, in this case contain the one item with the id passed to the function.



#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public class Product
{
    public string id {get;set;}
    public string ProductId {get;set;}
    public string manufacturer {get;set;}
    public string description {get;set;}
}

public static async Task Run(HttpRequest req, 
string id,
 IEnumerable Products,
  ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");
    log.LogInformation(id.ToString());
    log.LogInformation(Products.First().ProductId);
}

That's it, we have setup two Azure functions for pulling data from Cosmos DB without ever opening Visual Studio.

C#, C sharp, machine learning, ML.NET, dotnet core, dotnet, O365, Office 365, developer, development, Azure, Supervised Learning, Unsupervised Learning, NLP, Natural Language Programming, Microsoft, SharePoint, Teams, custom software development, sharepoint specialist, chat GPT,artificial intelligence, AI

Cookie Alert

This blog was created and hosted using Google's platform Blogspot (blogger.com). In accordance to privacy policy and GDPR please note the following: Third party vendors, including Google, use cookies to serve ads based on a user's prior visits to your website or other websites. Google's use of advertising cookies enables it and its partners to serve ads to your users based on their visit to your sites and/or other sites on the Internet. Users may opt out of personalized advertising by visiting Ads Settings. (Alternatively, you can opt out of a third-party vendor's use of cookies for personalized advertising by visiting www.aboutads.info.) Google analytics is also used, for more details please refer to Google Analytics privacy policy here: Google Analytics Privacy Policy Any information collected or given during sign up or sign is through Google's blogger platform and is stored by Google. The only Information collected outside of Google's platform is consent that the site uses cookies.