Http Trigger #Azure functions with CosmosDB SQL API #serverless
Examples how to get routing parameters with SQL API working for Cosmos DB in Azure functions.
Published 17th of October 2018
Version .net 4.7
All these example are used in the back end of this app Find an Episerver Partner with Certified Developers
Http Trigger Function apps
Example 1: Getting data from Cosmos DB with SQL API and routing parameter then deserializing the data to custom object.
Test URL: https://gosso-epiworld.azurewebsites.net/api/GetDevs/CmsCert/Gosso Systems AB
Route = “GetDevs/{type}/{company}” and then using {type} in SQL:
[DocumentDB(Manager.DatabaseName, “devs”, ConnectionStringSetting = Manager.DbConnString, SqlQuery = “SELECT top 1 * FROM c where c.type={type} and c.count>0 order by c._ts desc”)]
using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Azure.WebJobs.Host; using Newtonsoft.Json; namespace EpiWorldFunctions.CertifiedDevs { public static class GetDevs { [FunctionName("GetDevs")] public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "GetDevs/{type}/{company}")]HttpRequestMessage req, string company, string type, [DocumentDB(Manager.DatabaseName, "devs", ConnectionStringSetting = Manager.DbConnString, SqlQuery = "SELECT top 1 * FROM c where c.type={type} and c.count>0 order by c._ts desc")] IEnumerable<object> documents , TraceWriter log) { Manager.DbDocument deserializedDbDocument = JsonConvert.DeserializeObject<Manager.DbDocument>(documents.FirstOrDefault()?.ToString()); if (company == "Unknown") deserializedDbDocument.Devs = deserializedDbDocument.Devs.Where(item => item.Company=="") .Select(x => x) .ToList(); else if (company!="everyone") deserializedDbDocument.Devs = deserializedDbDocument.Devs.Where(item => System.Net.WebUtility.HtmlDecode(item.Company).Contains(company)) .Select(x=>x) .ToList(); string message = $"type: {type} | company: {company} | returns: {deserializedDbDocument.Devs.Count}"; log.Info(message); System.Diagnostics.Trace.WriteLine(message); return req.CreateResponse(HttpStatusCode.OK, deserializedDbDocument, "application/json"); } } }
Business logic (Manager) and structs:
using Microsoft.Azure.WebJobs.Host; using System; using System.Collections.Generic; using System.Linq; using System.Net; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace EpiWorldFunctions { public class Manager { public const string DbConnString = "AzureWebJobsDocumentDBConnectionString"; //this file is set in local.settings.json public const string DatabaseName = "databasename-not-collection"; public enum DevType { Emvp = 0, ComCert = 1, CmsCert = 2 } public struct DbDocument { [JsonProperty("date")] public DateTime Date; [JsonProperty("devs")] public List<Developer> Devs; [JsonProperty("count")] public int Count; [JsonProperty("type")] public string Type; } public struct Developer { [JsonProperty("name")] public string Name; [JsonProperty("company")] public string Company; [JsonProperty("url")] public string Url; } } }
Example 2: Getting data from Cosmos DB with SQL API and routing parameter then deserializing the data to custom object. Grouping devs by Company
Test URL: https://gosso-epiworld.azurewebsites.net/api/GetCompanies/ComCert/
using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Azure.WebJobs.Host; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; namespace EpiWorldFunctions.CertifiedDevs { public static class GetCompanies { [FunctionName("GetCompanies")] public static HttpResponseMessage Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "GetCompanies/{type}/")] HttpRequestMessage req, string type, [DocumentDB(Manager.DatabaseName, "devs", ConnectionStringSetting = Manager.DbConnString, SqlQuery = "SELECT top 1 * FROM c where c.type={type} and c.count>0 order by c._ts desc")] IEnumerable<object> documents, TraceWriter log) { if (documents.Count() == 0) return req.CreateResponse(HttpStatusCode.NoContent, "[]", "application/json"); Manager.DbDocument deserializedDbDocument = JsonConvert.DeserializeObject<Manager.DbDocument>(documents.FirstOrDefault()?.ToString()); var list = deserializedDbDocument.Devs.GroupBy(item => item.Company) .Select(group => new {company = group.Key, count = group.Count()}) .OrderByDescending(x=> x.count).ThenBy(x => x.company) .ToList(); TimeSpan span = DateTime.Now.Subtract(deserializedDbDocument.Date); var returnObj = new {date = span.Hours, companies = list}; log.Info($"Logmessage type: {type} | returns: {list.Count}"); System.Diagnostics.Trace.WriteLine($"System.Diagnostics.Trace.WriteLine type: {type} | returns: {list.Count}"); return req.CreateResponse(HttpStatusCode.OK, returnObj, "application/json"); } } }
Example 3: Get a subsequence of the data from cosmos, retrieve and return a smaller json for statistics.
Used here: https://devblog.gosso.se/find-an-episerver-certified-dev-company/certification-over-time/
Test url: https://gosso-epiworld.azurewebsites.net/api/GetStatsByDate/ComCert/
using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Azure.WebJobs.Host; namespace EpiWorldFunctions.CertifiedDevs { public static class GetStatsByDate { [FunctionName("GetStatsByDate")] public static async Task<HttpResponseMessage> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "GetStatsByDate/{type}/")]HttpRequestMessage req, string type, [DocumentDB(Manager.DatabaseName, "devs", ConnectionStringSetting = Manager.DbConnString, SqlQuery = "SELECT c.date, c.count FROM c where c.type={type} and c.count>0 order by c._ts desc")] IEnumerable<object> documents, TraceWriter log) { var docs = documents.ToList(); log.Info("C# HTTP trigger function processed a request. Found documents: " + docs.Count); return req.CreateResponse(HttpStatusCode.OK, docs, "application/json"); } } }
Tip: Local diagnostics with System.Diagnostics.Trace.WriteLine(message);
Further reading and testing
SEO Terms
- Serverless Cosmos db example
- Using routing in function app
About the author
Luc Gosso
– Independent Senior Web Developer
working with Azure and Episerver
Twitter: @LucGosso
LinkedIn: linkedin.com/in/luc-gosso/
Github: github.com/lucgosso