Share via


Azure Cosmos DB: A Simple Project Using Cosmos DB And Azure App Service

In my previous article, I talk about  Azure Cosmos DB. In this post, I will describe in simple steps how you can deploy a web app with an Azure Cosmos DB on the back end.

Prerequisites 

  • Azure Cosmos DB account with SQL API
  • Azure Web App Service
  • Visual Studio 2015 or Higher

Install Document DB NuGet Package

Back to top

NuGet is a tool that helps developers to download compiled DLL’s  “packages”  for their solutions. In the image below, I download the Microsoft.Azure.DocumentDB package which I use it for the demo project.

Web.config Configuration (Connect to Azure Cosmos DB)

Back to top

On Solution Explorer, select Web.config and add the following values, endpoint, authKey, database, collection.


<appSettings>
  <add key="webpages:Version" value="3.0.0.0" />
  <add key="webpages:Enabled" value="false"  />
  <add key="ClientValidationEnabled" value="true"  />
  <add key="UnobtrusiveJavaScriptEnabled" value="true"  />
<!--Copy the value from the URI field.  -->
  <add key="endpoint" value="https://cloudopszone.documents.azure.com:443/"/>
<!--Copy the value from PRIMARY OR SECONDARY KEY field.  -->
  <add key="authKey" value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>
<!--Copy the value from PRIMARY CONNECTION STRING field.  -->
  <add key="database" value="cloudopszone"/>
<!--Copy the value from PRIMARY CONNECTION STRING field.  -->
  <add key="collection" value="AdventureWorksData"/>
</appSettings>

Repository Configuration

Back to top

A repository works intermediary between business access layer and data access layer of the Web application. Below we can see the C# code that I used to create the WebAppCosmosDB.Repository.


namespace WebAppCosmosDB
{
    public class  MvcApplication : System.Web.HttpApplication
    {
        protected void  Application_Start()
        {
 AreaRegistration.RegisterAllAreas();
 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
 RouteConfig.RegisterRoutes(RouteTable.Routes);
 BundleConfig.RegisterBundles(BundleTable.Bundles);
 CosmosDBRepository<Employee>.Initialize();
        }
    }
}
 
namespace WebAppCosmosDB.Repository
{
    public class  CosmosDBRepository<T> where T : class
    {
        private static  readonly string  DatabaseId = ConfigurationManager.AppSettings["database"];
        private static  readonly string  CollectionId = ConfigurationManager.AppSettings["collection"];
        private static  DocumentClient client;
  
        public static  void Initialize()
        {
 client = new  DocumentClient(new  Uri(ConfigurationManager.AppSettings["endpoint"]), ConfigurationManager.AppSettings["authKey"]);
 CreateDatabaseIfNotExistsAsync().Wait();
 CreateCollectionIfNotExistsAsync().Wait();
        }
  
        private static  async Task CreateDatabaseIfNotExistsAsync()
        {
 try
 {
     await client.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(DatabaseId));
 }
 catch (DocumentClientException e)
 {
     if (e.StatusCode == System.Net.HttpStatusCode.NotFound)
     {
         await client.CreateDatabaseAsync(new Database { Id = DatabaseId });
     }
     else
     {
         throw;
     }
 }
        }
  
        private static  async Task CreateCollectionIfNotExistsAsync()
        {
 try
 {
     await client.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId));
 }
 catch (DocumentClientException e)
 {
     if (e.StatusCode == System.Net.HttpStatusCode.NotFound)
     {
         await client.CreateDocumentCollectionAsync(
  UriFactory.CreateDatabaseUri(DatabaseId),
  new DocumentCollection { Id = CollectionId },
  new RequestOptions { OfferThroughput = 1000 });
     }
     else
     {
         throw;
     }
 }
        }
  
        public static  async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> predicate)
        {
 IDocumentQuery<T> query = client.CreateDocumentQuery<T>(
     UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId))
     .Where(predicate)
     .AsDocumentQuery();
  
 List<T> results = new  List<T>();
 while (query.HasMoreResults)
 {
     results.AddRange(await query.ExecuteNextAsync<T>());
 }
  
 return results;
        }
  
        public static  async Task<IEnumerable<T>> GetItemsAsync()
        {
 IDocumentQuery<T> query = client.CreateDocumentQuery<T>(
     UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId))    
     .AsDocumentQuery();
  
 List<T> results = new  List<T>();
 while (query.HasMoreResults)
 {
     results.AddRange(await query.ExecuteNextAsync<T>());
 }
  
 return results;

Controllers Configuration

Back to top

Controllers, responsibility is to control the way that interacts a user with an MVC App, for example, a user sends a request to a Web App and the controller define the response to send back.
Let’s take a quick look at the controller C# code.

public class  EmployeeController : Controller
{
    // GET: Employee
    public async Task<ActionResult> Index()
    {
        var items = await CosmosDBRepository<Employee>.GetItemsAsync();
        return View(items);

Models Configuration

Back to top

Models are used to represent data from a database to the Web interface on an ASP.Net project. For example, on the C# code below we can see the fields that will project on the Web App.


public class  Employee
{
    [JsonProperty(PropertyName = "BusinessEntityID")]
    public string  BusinessEntityID { get; set; }
  
    [JsonProperty(PropertyName = "Title")]
    public string  Title { get; set; }
  
    [JsonProperty(PropertyName = "FirstName")]
    public string  FirstName { get; set; }
  
    [JsonProperty(PropertyName = "MiddleName")]
    public string  MiddleName { get; set; }
  
    [JsonProperty(PropertyName = "LastName")]
    public string  LastName { get; set; }

Views Configuration

Back to top

Actually, a View is a page that is used from a Web App. This is not a page that point to a path on a hard disk but is mapped to controller actions.
On the C# code below we can see the View for my example.

@model IEnumerable<WebAppCosmosDB.Models.Employee>
  
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
  
<h2>Index</h2>
  
<table class="table">
    <tr>
        <th>
 @Html.DisplayNameFor(model => model.BusinessEntityID)
        </th>
        <th>
 @Html.DisplayNameFor(model => model.Title)
        </th>
        <th>
 @Html.DisplayNameFor(model => model.FirstName)
        </th>
        <th>
 @Html.DisplayNameFor(model => model.MiddleName)
        </th>
        <th>
 @Html.DisplayNameFor(model => model.LastName)
        </th>
        <th></th>
    </tr>
  
@foreach (var item in Model) {
    <tr>
        <td>
 @Html.DisplayFor(modelItem => item.BusinessEntityID)
        </td>
        <td>
 @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
 @Html.DisplayFor(modelItem => item.FirstName)
        </td>
        <td>
 @Html.DisplayFor(modelItem => item.MiddleName)
        </td>
        <td>
 @Html.DisplayFor(modelItem => item.LastName)
        </td>
    </tr>

Conclusion

Back to top

Microsoft continues to be next to Development teams and helps them by providing cloud services like Azure Cosmos DB and App Services. In this post, I tried to show how easy is for someone to sit down and write few lines of  C# code and be able to integrate them easily into their projects.

You can easily calculate the cost of these services by using Azure Pricing Calculator.