Here's my five latest blog posts - or you can browse a complete archive of all my posts since 2008.

“How To Be a Rockstar Developer” at DDD North

I’m off to Hull this weekend for DDD North where I’ll be presenting How To Be A Rockstar Developer - the story of how a programming language I invented in a bar as a joke got way out of hand, and ended up as a real thing, complete with a web assembly runtime, test suite, documentation… and lots of stupid jokes about Bon Jovi.

I love DDD (which is short for Developer! Developer! Developer!, inspired by a thing Steve Ballmer did when he was CEO of Microsoft, and not to be confused with Domain-Driven Design which is a completely different thing). It’s a series of free, one-day developer events around the UK. And in Australia, but that’s a bit far to go for a one-day event. And apparently they had one in Seoul. DDD’s historical associations with Microsoft mean it attracts a lot of folks who work with .NET, but with an open CFP and sessions chosen via a public vote, there’s usually a pretty good balance of speakers and topics.

It’s free, it’s on a Saturday - this Saturday, in fact! - and it’s always a really friendly bunch of people. There’s still a few tickets left at dddnorth.co.uk, and if you’re going to be around, come and say hi.

"“How To Be a Rockstar Developer” at DDD North" was posted by Dylan Beattie on 17 February 2025 • permalink

Faking the HTTP Request URL in ASP.NET MVC

Because I always, always, forget how to do this: here’s how you fake, spoof, whatever you want to call it the HTTP request in ASP.NET Core. Useful if you’ve got controller actions that do things like generate absolute URL links to put into outgoing emails, and you want them to reflect the URL where the code was actually running (so code running on localhost sends mails with links to localhost, code running on test.example.com links to test.example.com, and so on), and you want to write tests for that code because why wouldn’t you write tests?

Looks like this:

protected ControllerContext SimulateControllerContext(string uriString) {
	var uri = new Uri(uriString);
	return new ControllerContext {
		HttpContext = new DefaultHttpContext {
			Request = { Scheme = uri.Scheme, Host = new HostString(uri.Host) }
		}
	};
}

var controller = new WhateverController() {
	ControllerContext = SimulateControllerContext("https://example.com")
}

I’ll normally mix this up with a little extension method, usually while wishing that the people who wrote the very excellent Path.Combine had elbowed their way into the room where they were building System.Uri and Got Involved:

public static class UriExtensions {
	public static Uri Append(this Uri uri, params string[] paths)
		=> new(paths.Aggregate(uri.AbsoluteUri, (current, path)
			=> $"{current.TrimEnd('/')}/{path.TrimStart('/')}"));

	public static Uri GetWebsiteBaseUri(this HttpRequest request)
		=> new($"{request.Scheme}://{request.Host}/");
}

(also, yay blogging with Sveltia means no more messing around with git. Write, publish. done.)

"Faking the HTTP Request URL in ASP.NET MVC" was posted by Dylan Beattie on 15 February 2025 • permalink

Posting with SveltiaCMS from my phone

And here’s the ultimate acid test for low-friction blogging… how quickly can I write and publish a post using my phone? Well, the layouts are a little janky:

Composing a blog post in Chrome on an iPhone using Sveltia CMS

…but it works. Nice. Expect more off-the-cuff blogging.

"Posting with SveltiaCMS from my phone" was posted by Dylan Beattie on 13 February 2025 • permalink

SveltiaCMS, Jekyll and GitHub Pages

I used to blog a lot. Back in the good old days of Windows Live Writer and Blogger, when I could click “New post”, bash out a few hundred words, paste an image or two, and… done.

In 2020 I moved all my stuff from Blogger to Jekyll and GitHub Pages, because I wanted more control over the content on my site. It worked, and I love Jekyll dearly and it’s a fantastic tool, but it kinda killed my blogging because even a two-paragraph post meant git pull, create a new Markdown file, make sure to get the filename right (and filenames are based on dates, so it if you don’t get around to posting it the day you started it you’ve gotta rename stuff), git add, git commit, build… yeah.

So I asked around for whatever’s the closest thing to Windows Live Writer - with the caveats that cntent stays in Markdown, and for now it stays on Github. I own my content. I want it under my control, in a portable format.

Chris Simon pointed me at Decap CMS, which looked really interesting: it’s a JS app that runs from a subfolder inside your static site, connects directly to GitHub, and edits Markdown files right in your repo. Except (a) I managed to crash their live demo editor within fifteen seconds by trying to paste an image into it (I know! Pasting an image! Into a blog post! Totally weirdo edge case that’ll never happen in real life!), and (b) once I’d figured out how to Not Paste Images, I couldn’t get the auth for it running reliably. It uses Netlify to authenticate with GitHub – GitHub can’t do pure JS authentication ‘cos it needs a server to handle the post-authentication callback – and seemed to have some problems using Netlify to authenticate when the site I was trying to edit wasn’t hosted on Netlify.

Then I found Sveltia CMS. It’s the same idea: CMS as a JS app, in a subfolder of a static website, that pushes stuff straight to a GitHub repo - along with a Cloudflare worker app that handles the authentication bit.

So if you’re reading this? It worked: this was posted from Sveltia, which is hooked into dylanbeattie.net/admin, and maybe means bashing out those quick 2-paragraph blog posts might just be as easy as it was in the days of Live Writer.

"SveltiaCMS, Jekyll and GitHub Pages" was posted by Dylan Beattie on 13 February 2025 • permalink

Windows Defender detects Trojan:Script/Wacatac.B!ml in a zipped .NET 9 AOT binary

Earlier today, somebody alerted me that Rockstar binary releases for Windows were being blocked by Windows Defender… and sure enough, since I switched the build system from .NET 8 to .NET 9, the Windows ZIP file releases on the releases page are being incorrectly identified as being infected with Trojan:Script/Wacatac.B!ml malware.

It’s not just Rockstar, though. It’s any .NET 9 binary compiled with AOT enabled and then compressed in a ZIP file. Try it. First, create a new .NET 9 console app:

dotnet new console -o HelloWorld

Then edit the .csproj file and add StripSymbols and PublishAot directives:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net9.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
    </PropertyGroup>
    <!-- ADD THIS PropertyGroup to create native binary EXE builds -->
    <PropertyGroup Condition="'$(Configuration)'=='Release'">
        <DebugSymbols>False</DebugSymbols>
        <DebugType>None</DebugType>
        <PublishAot>true</PublishAot>
        <StripSymbols>true</StripSymbols>
    </PropertyGroup>
</Project>

Now publish a binary release:

dotnet publish -c Release -o published

Look in /published and you’ll see a single binary HelloWorld.exe

Create a ZIP file containing that EXE - in Windows Explorer, right-click, Send to > Compressed (zipped) folder:

creating a ZIP file using Windows Explorer

Right-click the ZIP file, Scan with Microsoft Defender…

Microsoft Defender Trojan result

For a second opinion, upload the ZIP file to VirusTotal.com, and you’ll probably see that Microsoft Defender thinks it’s infected with a trojan. I’ve had multiple hits reporting Trojan:Script/Wacatac.B!ml and one reporting Trojan:Win32/AgentTesla!ml

"Windows Defender detects Trojan:Script/Wacatac.B!ml in a zipped .NET 9 AOT binary" was posted by Dylan Beattie on 09 December 2024 • permalink