Blog Technology Stack


Published: 11 September 2017
Author: Jared Holgate
Category: Blog
Tags: Blog,Technology Stack,CosmosDB,ASP.NET Core,C#,Bootstrap,Markdown,Azure App Service

Intro

This article goes into a bit of detail about the technology behind iteration one of this blog. I used the blog to test out some technology stacks I've not had chance to try yet.

So, I choose Azure CosmosDB (DocumentDB API) for the persistence. I choose ASP.NET Core 2.0 for the framework, I've been using ASP.NET MVC and ASP.NET Core 1.0 and 1.1 already, but ASP.NET Core 2.0 has some impressive new features, seems a lot leaner and the new Razor page syntax is awesome.

As mentioned, my front end skills are lacking when it comes to design, so I wanted to try my hand as using Bootstrap a bit more and understanding how I leverage it's capabilities.

Azure CosmosDB

CosmosDB is a database that can be scaled horizontally and across different data centers (globally distant data centers). It has near real time replication of data. It uses the familar DocumentDB API to interact with it, but you can also choose to use the MongoDB API. There are also a couple of other new API's that I haven't delved into yet. It's obviously massively overkill for my 3 page blog, but wanted to give it a try.

I'm not going to go into much detail here, as you can just read the Microsoft site and it will explain it a lot better than I can.

It's a key value (NoSQL) database.

Setting it up literally took a few seconds. I'm using the C# DocumentDB client Microsoft.Azure.DocumentDB to interact with it. Adding the nuget package and following the online tutorial I got start very quickly. Then I tried to implement my use case and hit my first gotcha. Partitioning.

For larger databases it makes sense to partition on a well distributed property to make access fast. For my use case it seemed a bit much. I tried creating a collection via the Azure UI and it forces you to define a partition. I tried doing it that way and then querying with the sample code that immediately fell over because I wasn't supplying the partition value.

So after a bit of investigating I realised that deleting my collection and creating via the API meant that I can create one without a partition.

var collection = new DocumentCollection {Id = "CollectionName");
await _client.CreateDocumentCollectionAsync(
            UriFactory.CreateDatabaseUri("DatabaseName"),
            collection,
            new RequestOptions {OfferThroughput = 1000});

If you do want a partition you can define it in the code like so;

var collection = new DocumentCollection {Id = "CollectionName", PartitionKey = new PartitionKeyDefinition {Paths = new Collection<string> { "PartitionKeyName" }}}

That was the main stumbling block, from there it was pretty plain sailing. The example code contains a bunch of CRUD operations. I wanted have a CreateOrUpdate method rather than separate Create and Update methods. You can see here that I'm simply getting the count of documents at the moment. This obviously won't work if I ever delete a document. Originally i used Max(), but this didn't work for anything higher than 10, as it always brings back 9 as being higher than 10. My next refactoring job is have a separate collection with a single document to store the current ID;

 public async Task<T> CreateOrUpdateItemAsync(T item)
    {
      Document result;
      if (string.IsNullOrWhiteSpace(item.Id))
      {
        var maxId = _client.CreateDocumentQuery<long>(UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId), "SELECT VALUE COUNT(0) from c").AsEnumerable().FirstOrDefault();
        
        var newId = (maxId + 1).ToString();
        item.Id = newId;
        result = await _client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId), item);
      }
      else
      {
        result = await _client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(_databaseId, _collectionId, item.Id), item);
      }

      if (string.IsNullOrWhiteSpace(result.Id))
      {
        throw new Exception("Unable to save or update the Item...");
      }
      return item;
    }

As you can see here, you can pass SQL syntax and well as lambdas to the API, making it very flexible.

I think that's enough for now. I'll post the whole repository code at the end of the article as an attachment.

ASP.NET Core 2.0

This is about as straight forward as it gets. File => New Project... Add a reference to the repository and get writing some controllers. You get the idea.

It's clean, it's simple, it's stable, it's fast. Go ahead and use it.

The best part of ASP.NET Core 2.0 is the markup syntax, it's much nicer than using HTML helper tags, here are some examples;

<a asp-controller="Article" asp-action="Edit" asp-route-id="@Model.Article.Id">[Edit]</a>
<a asp-controller="Article" asp-action="Read" asp-route-title="@article.Title.Replace(" ", "-")">@article.Title</a>

 <form asp-action="CreateOrUpdate">
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
      <input asp-for="Id" type="hidden"/>
      <div class="form-group">
        <label asp-for="Title" class="control-label"></label>
        <input asp-for="Title" class="form-control"/>
        <span asp-validation-for="Title" class="text-danger"></span>
      </div>
      <div class="form-group">
        <label asp-for="Date" class="control-label"></label>
        <input asp-for="Date" class="form-control"/>
        <span asp-validation-for="Date" class="text-danger"></span>
      </div>...

More examples here https://docs.microsoft.com/en-us/aspnet/core/mvc/razor-pages/?tabs=visual-studio.

Markdig

Want to use Markdown in your app, then this library is great. https://github.com/lunet-io/markdig.

Very simple to use;

var parsedHtml = Markdown.ToHtml(markDownText, new MarkdownPipelineBuilder().UseAdvancedExtensions().Build())

One thing to note is that the library does not do any security filtering of the produced markup, you'll need to use something else to take care of XSS, etc if you have untrusted users saving markdown on your site.

Visual Studio Team Services

I am have been using TFS (Team Foundation Server) for many years. As the primary administrator for our company I like to keep it up to date and were currently running the latest version of TFS 2017. But, even with that we are missing a heap load of functionality available in VSTS. I am hoping to migrate us to VSTS later this year if we get InfoSec sign off, etc, but in the meantime this blog is a great opportunity for me to check it our properly.

My main area of expertise is DevOps and the Continuous Integration and Continuous Delivery pipelines. We use Octopus Deploy, which is a fantastic tool and given the developmental stage of Release Management in TFS at the time (WCF based separate app), was definitely the right choice for us.

However Release Management has massively improved over the last couple of years and with the pending agent based deployment system, I believe it will be the equal of Octopus. I'm looking forward to trying it out having the option of using one or the other.

The Builds in TFS / VSTS have also come a very long way from the XAML based build system a few years back. I remember taering my hair out trying to get the simplest thing done and making massive customizations to the XAML work flow. Now it's easy, just add a step and run some PowerShell.

For the blog, I've used Builds and Releases in VSTS. I'm hosting the site on Azure App Service, which is PaaS for web apps. This makes the whole process so straight forward. The build is a few steps to restore packages, build, run tests and publish. The Release is literally one step that takes the artifact of the build and pushes it up to the Azure App Service. It's seamless and I'm really impressed at how quickly I got it up and running.

Azure App Service

As mentioned this is PaaS (platform as a service) in Azure for web apps. It makes application deployments a breeze, there is no VM to spin up, no IIS to configure, no routing, firewalls, etc.

I also configured it to use my personal url and applied an SSL cert. All was very straight forward with help from the docs.

Conclusion

I've had fun writing the code for this blog so far, I will continue to add to it.

Caveat: I don't work for Microsoft or sell their products. I run an engineering team in a law firm. I've worked with the Microsoft stack for many years and have always been impressed by how easy it is to get going and build enterprise grade apps. The latest developments with the DevOps and Web Stack are particularly impressive and have prompted me to stick with Microsoft as the first choice for new apps. It's also given me some motivation to write this blog, as there is a lot to learn and talk about at the moment.

Obviously there is a cost associated with using Microsoft tools, operating systems and Azure and there can be a hefty bill for Visual Studio subscriptions and the such. I think for enterprise development it's a good choice, as engineers are (more) readily available than for other stacks and the amount of documentation and support on the internet is great.

However Microsoft can;t cater for everything we need on premise and there are other technologies that we use or intend to use to enhance the Microsoft stack, such as Elastic Search, RabbitMQ and Redis, so you might see article on those in the future too.

Attachments

Blog Repository Code