Model binding form posts to immutable objects

I’ve been working on porting over my blog to a static site generator and fired up an Azure Function to handle the form-comment to PR process to enable user comments to still be part of the site without using a 3rd party commenting system - more on that in a future post - and found the ASP.NET model binding for form posts distinctly lacking.

It’s been great getting back into .NET and brushing up some skills making the code clear, short and reusable. What I wanted was a super-clear action on my controller that tried to collect, validate and sanitize the data then if all was well create the pull request or report errors.

Ideally it would look like this;

public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestMessage request) {
    var form = await request.Content.ReadAsFormDataAsync();
    if (TryCreateComment(form, out Comment comment, out var errors))
        await CreateCommentAsPullRequest(comment);
    return request.CreateResponse(errors.Any()
      ? HttpStatusCode.BadRequest : HttpStatusCode.OK, String.Join("\n", errors));

To do that however we need a function capable of creating the Comment class from the form post. Sure you can manually do it field by field but that’s not very reusable, repetitive and of course no fun. The Comment class is also - like all good little objects - immutable.

Creating a function to do this is simple with a little bit of reflection;

private static object ConvertParameter(string parameter, Type targetType) {
    return String.IsNullOrWhiteSpace(parameter)
           ? null : TypeDescriptor.GetConverter(targetType).ConvertFrom(parameter);

private static bool TryCreateCommentFromForm(NameValueCollection form, out Comment comment, out List<string> errors) {
    var constructor = typeof(Comment).GetConstructors()[0];
    var values = constructor.GetParameters()
                            .ToDictionary(p => p.Name, p => ConvertParameter(form[p.Name], p.ParameterType)
                                      ?? (p.HasDefaultValue ? p.DefaultValue : new MissingRequiredValue()));
    errors = values.Where(p => p.Value is MissingRequiredValue)
                   .Select(p => $"Form value missing for '{p.Key}'").ToList();
    comment = errors.Any() ? null : (Comment)constructor.Invoke(values.Values.ToArray());
    return !errors.Any();

What this does is grab the constructor for the Comment and try to find keys in the form that match the parameter name. Any that are missing are reported as errors unless they have a default value in which case that is used. MissingRequiredValue is just an empty object to act as a sentinel. The use of TypeDescriptor.GetConverter means it should be quite happy handling ints, decimals, urls etc.

The constructor for Comment specifies which fields are required and the parameter names must match the form field names by convention. Any value that is optional has a default value that the constructor will happily fill in a sensible default for.

public Comment(string post_id, string message, string author, string email,
    DateTime? date = null, Uri url = null, int? id = null, string gravatar = null) {
    this.post_id = pathValidChars.Replace(post_id, "-");
    this.message = message; = author; = email; = date ?? DateTime.UtcNow;
    this.url = url; = id ?? new { this.post_id,, this.message, }.GetHashCode();
    this.gravatar = gravatar ?? EncodeGravatar(email);

I’ll post more of the form commenting system source soon once it’s a bit better tested and I look into anti-spam integration. Ideally I’ll also provide an AWS Lambda variant of the code so you can choose (or load balance) comment posting and almost certainly get what you need on the free tier. For now the Jekyll rendering templates and WordPress exporter are available.


Differences between Azure Functions v1 and v2 in C#

I’ve been messing around in the .NET ecosystem again and have jumped back in with Azure Functions (similar to AWS Lambda) to get my blog onto 99% static hosting. I immediately ran into the API changes between v1 and v2 (currently in beta).

These changes are because v1 was based around .NET 4.6 using WebAPI 2 while the v2 is based on ASP.NET Core which uses MVC 6. There are some guides around to converting but none in the pure context of Azure Functions.

I’ll illustrate with a PageViewCount sample that uses Table Storage to retrieve and update a simple page count.

v1 (.NET 4.61 / WebAPI 2)

public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get")]HttpRequestMessage req, TraceWriter log) {
    var page = req.MessageUri.ParseQueryString()["page"];
    if (String.IsNullOrEmpty(page))
        return req.CreateErrorResponse(HttpStatusCode.BadRequest, "'page' parameter missing.");

    var table = Helpers.GetTableReference("PageViewCounts");
    var pageView = await table.RetrieveAsync<PageViewCount>("", page)
        ?? new PageViewCount(page) { ViewCount = 0 };
    var operation = pageView.ViewCount == 0
        ? TableOperation.Insert(pageView)
        : TableOperation.Replace(pageView);
    await table.ExecuteAsync(operation);

    return req.CreateResponse(HttpStatusCode.OK, new { viewCount = pageView.ViewCount });

v2 (ASP.NET Core / MVC 6)

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get")]HttpRequest req, TraceWriter log) {
    var page = req.Query["page"];
    if (String.IsNullOrEmpty(page))
       return new BadRequestObjectResult("'page' parameter missing.");

    var table = Helpers.GetTableReference("PageViewCounts");
    var pageView = await table.RetrieveAsync<PageViewCount>("", page)
        ?? new PageViewCount(page) { ViewCount = 0 };
    var operation = pageView.ViewCount == 0
        ? TableOperation.Insert(pageView)
        : TableOperation.Replace(pageView);
    await table.ExecuteAsync(operation);

    return new OkObjectResult(new { viewCount = pageView.ViewCount });


The main differences are that:

  1. Return types are IActionResult/ObjectResult objects rather than extension methods against HttpRequestMessage (easier to mock/create custom ones)
  2. Input is the HttpRequest object rather than HttpResponseMessage (easier to get query parameters)

If you get the error ‘Can not create abstract class’ when executing your function then you are trying to use the wrong tech for that environment.


Both classes above use a small helper class to take care of Table Storage which doesn’t have the nicest to use API. A wrapper much like a data context that ensures the right types go to the right table names might be an even better options.

static class Helpers {
    public static CloudStorageAccount GetCloudStorageAccount() {
        var connection = ConfigurationManager.AppSettings["DamienGTableStorage"];
        return connection == null ? CloudStorageAccount.DevelopmentStorageAccount : CloudStorageAccount.Parse(connection);

    public static CloudTable GetTableReference(string name) {
        return GetCloudStorageAccount().CreateCloudTableClient().GetTableReference(name);

    public static async Task<T> RetrieveAsync<T>(this CloudTable cloudTable, string partitionKey, string rowKey)
        where T:TableEntity {
        var tableResult = await cloudTable.ExecuteAsync(TableOperation.Retrieve<T>(partitionKey, rowKey));
        return (T)tableResult.Result;

To compile

If you want to compile this or maybe you were just looking for code to do a simple page counter here’s the missing TableEntity class;

public class PageViewCount : TableEntity
    public PageViewCount(string pageName)
        PartitionKey = "";
        RowKey = pageName;

    public PageViewCount() { }
    public int ViewCount { get; set; }


Download files with progress in Electron via window.fetch

Working on Atom lately I need to be able to download files to disk. We have a couple of ways to do this today but they do not show download progress which leads to confusion and sometimes frustration on larger downloads such as updates or big packages.

There are many npm libraries out there but they either don’t expose a progress indicator or they bypass Chrome (thus not using proxy settings, caching and network inspector) by using node directly.

I’m also not a fan of sprawling dependencies to achieve what can be done simply in a function or two.

Hello window.fetch

window.fetch is a replacement for XMLHttpRequest currently shipping in Chrome (and therefore Electron) as well as a whatWG living standard. While there is some documentation around most of it relies on grabbing the entire content as JSON, a blob or text. This is not advised for streaming where the files might be large and you want to not only minimize memory impact but also display a progress indicator to your users.

Thankfully window.fetch has a getReader() function that will give you a ReadableStreamReader although this reads in chunks (32KB on my machine) and isn’t compatible with Node’s streams, pipes and data events.

Download function

With a little work though we can wire these two things up to get us a file downloader that has no extra dependencies outside of Electron, honors the Chrome cache, proxy and network inspector and best of all is incredibly easy to use;

import fs from 'fs';

export default async function download(sourceUrl, targetFile, progressCallback, length) {
  const request = new Request(sourceUrl, {
    headers: new Headers({'Content-Type': 'application/octet-stream'})

  const response = await fetch(request);
  if (!response.ok) {
    throw Error(`Unable to download, server returned ${response.status} ${response.statusText}`);

  const body = response.body;
  if (body == null) {
    throw Error('No response body');

  const finalLength = length || parseInt(response.headers.get('Content-Length' || '0'), 10);
  const reader = body.getReader();
  const writer = fs.createWriteStream(targetFile);

  await streamWithProgress(finalLength, reader, writer, progressCallback);

async function streamWithProgress(length, reader, writer, progressCallback) {
  let bytesDone = 0;

  while (true) {
    const result = await;
    if (result.done) {
      if (progressCallback != null) {
        progressCallback(length, 100);
    const chunk = result.value;
    if (chunk == null) {
      throw Error('Empty chunk received during download');
    } else {
      if (progressCallback != null) {
        bytesDone += chunk.byteLength;
        const percent = length === 0 ? null : Math.floor(bytesDone / length * 100);
        progressCallback(bytesDone, percent);

A FlowType annotated version is also available.

Using it

Using it is simplicity - call it with a URL to download and a local file name to save it as along with an optional callback that will receive download progress.'', '', (bytes, percent) => console.log(`Downloaded ${bytes} (${percent})`));


Some servers do not send the Content-Length header. You have two options if this applies to you;

  1. Don’t display a percentage just the KB downloaded count (percentage will be null in the callback)
  2. Bake-in the file size if it’s a static URL - just pass in as final parameter to the download function



Typography in bits: For a few pixels more

It’s been a while since I visited the bitmap fonts of old computers (see the bottom of the post for links) there are still some to look at!

There are a lot of subtle variations here as machines often used an off-the-shelf video chip and then made a few tweaks or had them slightly customized.

TRS-80 Color Computer & Dragon – custom MC6847 (1982)

TRS-80 system font

The initial model of the TRS 80 Color Computer – affectionately known as CoCo – as well as the UK’s Dragon 32 & 64 computers used the Motorola MC6847 character generator and so used the same embedded font.

Unusual characteristics

  • No lowercase
  • Serifs on B&D
  • Over-extended ‘7’
  • Asterisk is a diamond!
  • Square ‘O’
  • Cute ‘@’
  • Thin ‘0?’
  • Tight counter on ‘4’
  • Unjoined strokes on ‘#’


The font has some rough edges although the softer fuzzier look of a CRT TV almost certainly fuzzed those out like many home computer fonts at the time. The awful dark-green on light-green color scheme wasn’t helping though.


Has similar proportions and characters to much of the Apple ][ font but feels like they tried to make the characters more distinguished on low-quality TV’s hence the serifs on B & D and the differentiation between 0 and O.

Technical notes

Motorola actually offered custom versions of this ROM so it would have been entirely possible to have an alternative character set.

TRS-80 Color Computer v2+ (1985)

TRS-80 v2+ system font

The follow-up v2 model of the TRS 80 Color Computer – also known as the Tandy Color Computer used an enhanced Motorola MC6847T1 variant.

Unusual characteristics

  • Serifs on B&D, over-extended 7 as per v1
  • Ugly ‘@’
  • Very soft center bar on ‘3’
  • Tight counter on ‘4’
  • Tight top of ‘f’


In general a much improved font over the v1 fixing the oddities with the asterisk, O, 0, 3, 4, S, ? and # as well as making the slashes straighter and reducing the boldness of comma, colon, semi-colon and apostrophe although the @ and 3 are worse than the previous version.


Based on the previous model however lower-case does have some resemblance to Apple and MSX. This may in fact be a custom version as the spec sheet for the T1 variant has bold versions of ,;:.’ glyphs, shorter descenders on y and g, more curvature on p and q, stronger curves on 369, tighter t, semi-broken #

Technical notes

You can identify CoCo2 models that have the lower-case as they say Tandy on the screen not TRS-80.

Tatung Einstein (1984)

Tatung Einstein system font

The Tatung Einstein TC-01 was a British Z80 based machine launched in the UK that never really took off with the public but had some success in the game development word being a compiler and debugger for other more popular Z80 systems thanks to its CP/M compatible OS and disk system (it came with the same oddball 3″ disks used on the Sinclair ZX Spectrum +3 and Amstrad CPC/PCW range)</a>.

Unusual characteristics

  • Odd missing pixels on ‘9S’
  • Little flourishes on ‘aq’
  • Massively tall ‘*’
  • Chunky joins on ‘Kv’
  • High counters and bowls on ‘gpqy’


Given the 40 column mode the generous spacing in 32 column mode makes sense and the font isn’t too bad. Many of the negative unusual characteristics would be lost on a CRT.


It feels like the Sinclair Spectrum font with some horizontal width sacrifices.

Commodore 128 (1985)

Commodore 128 80-column font

While the follow-up to the Commodore 64 used the exact same font at boot – it had the same VIC-II video chip – switching it into 80-column mode reveals a new font with double-height pixels powered by the MOS 8563 VDC.

Unusual characteristics

  • ‘£’ aligned left not right, thin strokes
  • ‘Q’ fails to take advantage of descender
  • Cluttered redundant stroke on ‘7’
  • Rounded ‘<>’


Quite a nice font with very little weirdness that probably looked good on any monitor at the time although TV’s probably struggled to display detail with such fine verticals on some letters.



Switching to 80 column mode could be achieved by using the keyboard or the GRAPHIC 5 command.

Texas Instruments TI-99/4A (TMS9918) (1985)

TI-99/4A system font

The follow-up v2 model of the TRS 80 Color Computer – also known as the Tandy Color Computer used an enhanced Motorola MC6847T1 variant.

Unusual characteristics

  • Lower case is small caps
  • Serifs on ‘BD’
  • Square ‘O’
  • Poor slope on ‘N’
  • Bar very tight on ‘G’


The lower-case small caps feels quite awful and appears to be an attempt to avoid having to deal with descenders. Other fonts brought the bowl up a line and descenders look a little off instead although some machines like the Sinclair QL just left space for them.


Based on the previous model however lower-case does have some resemblance to Apple and MSX.

Oric Atmos (1983)

Oric Atmos system font

The follow-up v2 model of the TRS 80 Color Computer – also known as the Tandy Color Computer used an enhanced Motorola MC6847T1 variant.

Unusual characteristics

  • Bold ‘{}’
  • Vertical line on ‘^’
  • Awkward horizontal stroke on ‘k’
  • Square ‘mw’


Not a bad choice although I suspect cheaper TV’s would struggle with the non-bold and tight spacing which is probably why they went with high-contrast black-and-white.


A complete copy of the Apple ][ system font with only a few tweaks to remove over-extension of 6 and 9 and un-bolding [ and ] but they forgot { and } weirdly. Additions of ^ and £ don’t quite fit right.