Skip to main content

Posts

Building a Query DSL in C#

I recently built a REST API prototype where one of the endpoints accepted a string representing a filter to apply to a set of results. For instance, for entities with named properties "Foo" and "Bar", a string like "(Foo = 'some string') or (Bar > 99)" would filter out the results where either Bar is less than or equal to 99, or Foo is not "some string". This would translate pretty straightforwardly into a SQL query, but as a masochist I was set on using Google Datastore as the backend, which unfortunately has a limited filtering API : It does not support disjunctions, ie. "OR" clauses. It does not support filtering using inequalities on more than one property. It does not support a not-equal operation. So in this post, I will describe the design which achieves the following goals: A backend-agnostic querying API supporting arbitrary clauses, conjunctions ("AND"), and disjunctions ("OR"). Implemen...

Sasa v1.0.0-RC1

I've finally updated Sasa to target .NET standard 1.3, removed a lot of superfluous abstractions, and rewrote some of the existing API to target third-party packages that are better supported. This may be the last stable release of Sasa, since I'm shifting. Fortunately, the remaining Sasa features are very stable so there's not much need to evolve them further. You can find the full API documentation for v1.0.0 here , and obviously you can find Sasa itself via nuget . Here's the current breakdown of features: Sasa Assembly The core Sasa assembly contains extensions on standard .NET types, and a few new and useful abstractions that are typical for most programs: Sasa.FilePath: structured file system path handling, including jail, ensuring combined paths don't escape a root path. Sasa.Func: extensions to create delegates on methods and for operators with no restrictions, unlike the standard .NET delegate APIs. For instance, open instance delegates to virtual m...

RazorInterfaces: interfaces for the standard HTTP methods

In playing around with Razor Pages, I was irritated again that Microsoft couldn't just standardize a set of interfaces for their methods so that they wouldn't need so much magic. So I just quickly hacked up RazorInterfaces , available also on nuget.org . It's probably most useful to people just learning Razor Pages, since it requires you to correctly implement the common HTTP methods you'll need to get things running: public class CustomerPage : PageModel , IPageGet , IPagePostAsync<Customer> { public IActionResult OnGet() { return Page(); } public async Task<IActionResult> OnPostAsync(Customer customer) { await DataLayer.Update(customer); return Page(); } } There are interfaces for all of the standard HTTP methods: GET, POST, PUT, DELETE, HEAD, OPTIONS. The interface names conform to the following format: IPage[HTTP method] and IPage[HTTP method]Async for the async variant, and there a...

Minimal ASP.NET Core Dependencies for Google Cloud

After a long hiatus, I'm slowly starting back on blogging and some personal projects. To get me back in the swing of things, here's a short post on running ASP.NET core on Google Cloud, since this seems poorly documented online. The default project created by the Google Cloud tools includes Microsoft.AspNetCore.All which is a huge dependency. If you want something more minimal: uninstall-package Microsoft.AspNetCore.All install-package Microsoft.AspNetCore install-package Microsoft.AspNetCore.Mvc.Core install-package Microsoft.AspNetCore.Mvc This creates a runnable project using the standard Google Cloud Web API project template, although it still isn't ideal as it includes the Razor pages dependencies.

Investigative Capabilities in a Digital World - My Responses

A thread on reddit pointed to Canada's consultation on what sort of legislative framework they should create to facilitate investigations in the digital world. Many of the questions are leading and borderline deceptive in their phrasing, but if we're being charitable, this is a good opportunity to inform policy makers. To that end, these are my responses: How can the Government address challenges to law enforcement and national security investigations posed by the evolving technological landscape in a manner that is consistent with Canadian values, including respect for privacy, provision of security and the protection of economic interests? Evidence-based policy suggest you first demonstrate the actual need for such respective legislative changes, and further, that the proposed changes actually solve the problems they are intended to solve. Impartial third-party studies should be required for any proposed measures. As a computer scientist with some expertise in computer...

Semantic Tab Panels via HTML Tables

There are plenty of tutorials online for creating tabbed panels in HTML documents, some using JavaScript, some using pure CSS tricks. Most of the approaches seem to assume that a list of some type is the appropriate element to use for a tabbed interface, but I'd argue that lists are not semantically descriptive of tabbed interfaces. They either include the main tab content along with the tab name, like so: <ul class="tabs"> <li class="tab-active"><a href="">Active</a> Active tab content goes here</li> <li><a href="">Second</a> Inactive second tab content goes here</li> <li><a href="">Third</a></li> </ul> Or the tab content has no semantic relationship with the tabs that control their display, like: <ul class="tabs"> <li class="tab-active"><a href="#first">Active</a></li> ...

Versioning Domain Entities with Ordinary SQL

In any system with mutable entities saved in an object store, it's inevitable that you'll want to audit the changes made to a particular entity. Explicitly versioning your entities solves this problem, and it's often pretty useful to end users of a sophisticated application, say for undo purposes. However, it's not always so clear how to transform a mutable entity into an versioned entity. There are also a number of complications to versioning mutable objects: Handling parent-child relations such that a child change does not propagate to every parent Supporting efficient queries on history Supporting efficient queries for the newest version Space complexity of data representation Concurrent changes Some of the above properties also have a natural tension, ie. supporting efficient queries often require storing more data so their space complexity is worse. I'm going to provide an overview here of a very simple schema for versioned entities with the following...