Martin Costello's Blog

The blog of a software developer and tester.

Using the .NET JSON Source Generator with ASP.NET Core Minimal APIs

28 November 2021 by Martin Costello |
28 November 2021 by Martin Costello

I've recently completed upgrading a bunch of personal and work applications to ASP.NET Core 6, and now that the dust has finally settled on those efforts, I thought I'd look into a new feature of .NET 6 that I hadn't tried out yet - JSON source generators.

If you haven't come across them before, C# source generators are a way to write some code that can generate more code during compilation. It's a form of metaprogramming.

One of the benefits of the new JSON source generator for the System.Text.Json serializer is that it is more performant that the APIs introduced as part of .NET 5. This is because the serializer is able to leverage code that is compiled ahead-of-time (the source generator part) to serialize and deserialize objects to and from JSON without using reflection (which is relatively slow).

It sounds like that could give applications a performance boost at runtime, but how can we use the new JSON source generator with ASP.NET Core Minimal APIs?

Read more...

GitHub Codespaces Gotchas with ASP.NET Core OAuth

15 August 2021 by Martin Costello |
15 August 2021 by Martin Costello

This week GitHub Codespaces was made generally available for Teams and Enterprise, and coupled with the release of the ability to open any repository in Visual Studio Code in a web browser just by pressing ., I thought I'd give it a try with some existing projects. In the process I hit a few gotchas that took me a few hours to get to the bottom of. This post goes through some of those and how to resolve them.

Read more...

Integration Testing ASP.NET Core Resources Protected with Antiforgery Using Application Parts

16 June 2020 by Martin Costello |
16 June 2020 by Martin Costello

To protect your POST resources in an ASP.NET Core application from Cross-Site Request Forgery (CSRF) an application developer would typically use the antiforgery features to require an antiforgery token and cookie are included in HTTP POST form requests.

A necessary downside of these protections is that they make it harder to integration test such resources, particularly in a headless manner. This is because the tests need to acquire the antiforgery token and cookie to be able to successfully pass the antiforgery protections on a resource that needs to be tested.

A typical approach for this is to scrape the HTML response from the application for the hidden form field token (often named __RequestVerificationToken) using Regular Expressions and then using that, along with the cookie, in the request(s) the test(s) make. This can however make tests brittle to change, particularly if the UI is refactored.

In this blog post I'll discuss an alternate approach using ASP.NET Core Application Parts that can make such tests easier to author and maintain, allowing you to concentrate on the core logic of your tests, rather than boilerplate setup.

Read more...

Integration testing AWS Lambda C# Functions with Lambda Test Server

11 November 2019 by Martin Costello |
11 November 2019 by Martin Costello

Lambda Test Server is a .NET Core 3.0 library available from NuGet which builds on top of the TestServer class in the Microsoft.AspNetCore.TestHost NuGet package to provide infrastructure to use with end-to-end/integration tests for .NET Core AWS Lambda Functions using a custom runtime.

The example below shows how Lambda Test Server can be used to write an xunit integration test for a simple C# Lambda function that reverses an array of integers:

[Fact]
public static async Task Function_Reverses_Numbers()
{
    // Arrange
    using var server = new LambdaTestServer();
    using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1));

    await server.StartAsync(cancellationTokenSource.Token);

    int[] value = new[] { 1, 2, 3 };
    string json = JsonConvert.SerializeObject(value);

    LambdaTestContext context = await server.EnqueueAsync(json);

    using var httpClient = server.CreateClient();

    // Act
    await ReverseFunction.RunAsync(httpClient, cancellationTokenSource.Token);

    // Assert
    Assert.True(context.Response.TryRead(out LambdaTestResponse response));
    Assert.True(response.IsSuccessful);

    json = await response.ReadAsStringAsync();
    int[] actual = JsonConvert.DeserializeObject<int[]>(json);

    Assert.Equal(new[] { 3, 2, 1 }, actual);
}

The source is available in GitHub - pull requests are welcome!

Further samples for using the library with xunit are available in GitHub here: https://github.com/martincostello/lambda-test-server/tree/main/samples

Read more...

Using Refit with the new System.Text.Json APIs

16 June 2019 by Martin Costello |
16 June 2019 by Martin Costello

I'm a big fan of the Refit library for calling HTTP APIs from my .NET applications.

It uses code generation to let you do simple HTTP calls using interfaces and uses JSON.NET under-the-hood to handle serializing and deserializing JSON.

For example, to get a repository from the GitHub API you could define these types:

public class Organization
{
    [JsonProperty("login")]
    public string Login { get; set; }

    [JsonProperty("id")]
    public long Id { get; set; }

    // ... other properties
}

[Headers("Accept: application/vnd.github.v3+json", "User-Agent: My-App/1.0.0")]
public interface IGitHub
{
    [Get("/orgs/{organization}")]
    Task<Organization> GetOrganizationAsync(string organization);
}

Then you could call the API like this:

var client = RestService.For<IGitHub>("https://api.github.com");
var org = await client.GetOrganizationAsync("dotnet");

This week .NET Core 3.0 preview 6 was released, and with that the new System.Text.Json APIs. These new APIs are designed to be more performant and do less allocations that JSON.NET, so should bring performance benefits to applications that use them.

So what should you do if you want to use the new System.Text.Json APIs with Refit?

Read more...

Prototyping Sign In with Apple for ASP.NET Core

10 June 2019 by Martin Costello |
10 June 2019 by Martin Costello

Last week at Apple's WWDC 2019 conference, Apple announced a forthcoming service for enabling users to log into apps and services using their Apple ID, Sign In with Apple.

The main points of note about the new service are:

  • Users can sign in without having to give their email address to a third-party;
  • It will be required as an option in the future for apps that support third-party sign-in.

Just one day after the announcement at WWDC19, @leastprivilege of Identity Server fame, opened a GitHub issue over at the AspNet.Security.OAuth.Providers repository requesting a provider to support Sign In with Apple.

While the issue was opened slightly tongue-in-cheek, it's a valid start to the conversation about investigating support for this new technology (or not).

I've recently become a maintainer of the aspnet-contrib organisation in GitHub.com, which provides a suite of community-written providers for various OAuth 2.0 and Open ID 2.0 third-party authentication providers. Over the last few years I've made a number of contributions; for an Amazon Login provider, and most recently starting the work to add support for ASP.NET Core 3.0.

Given the community discussion and appetite, some previous experience implementing Apple Pay JS for ASP.NET Core, and some shiny new technology to play with, last I decided to try my hand at adding support for Sign In with Apple for ASP.NET Core myself via AspNet.Security.OAuth.Providers.

Read more...

Pseudo-localization with ASP.NET Core

17 December 2018 by Martin Costello |
17 December 2018 by Martin Costello

Earlier this year I read a blog post by Tim Brandall at Netflix about how they use pseudo-localization to test the User Interfaces of their various native applications for layout issues. For example, text in languages such as German and Finnish can be up to 40% longer than their English equivalents, causing text overflow in UI elements that don't account for such differences.

A simple example of pseudo-localisation would be changing the text of the sentence below.

The quick brown fox jumped over the lazy dog

With transformations to lengthen the text, apply accents and surround it in brackets applied, it becomes:

[Ţĥéẋ ǫûîçķẋẋ ƀŕöŵñẋẋ ƒöẋẋ ĵûɱþéðẋẋ öṽéŕẋẋ ţĥéẋ ļåžýẋẋ ðöĝẋẋ]

I found the approach particularly interesting, so wondered how I could look at using it in my own day-to-day work.

Read more...

SQL LocalDB Wrapper v2 - The Next Generation

2 October 2018 by Martin Costello |
2 October 2018 by Martin Costello

After over 2 years and 100,000 package downloads since the last release of SQL LocalDB Wrapper, I've released version 2 to NuGet.

Version 2.0.0 of SQL LocalDB Wrapper is a major rewrite of version 1.x.x, and is now fully .NET Core compatible. You can read more about the changes in the release notes.

Read more...

Writing Logs to xunit Test Output

30 September 2018 by Martin Costello |
30 September 2018 by Martin Costello

Today I've published a NuGet package that simplifies the mechanics of writing logs to the test output for xunit tests, MartinCostello.Logging.XUnit v0.1.0. It's open-source with an Apache 2.0 licence and available on GitHub.

Pull Requests and questions are welcome over on GitHub - I hope you find it useful!

Read more...

Deploying a static website to Azure Storage from AppVeyor

30 June 2018 by Martin Costello |
30 June 2018 by Martin Costello

This week the Azure storage team finally announced that Azure Storage now support hosting static websites. This has been a long-standing request from users of Azure (for nearly 4 years), so it's great to see something now available for use, even if at the time of writing it's currently only in public preview.

I've been hosting this blog in AWS for almost a year now, so I thought I'd give the public preview a try and automate deployment with AppVeyor as well at the same time.

Read more...