Microsoft’s opening up of .NET allowed the metaphorical thousand flowers to bloom, with its governance under the auspices of the .NET Foundation. The model has encouraged a wide variety of new frameworks and technologies that build on its cross-platform nature and its mix of development tools.

What was a monoculture dominated by Microsoft projects is now a wider ecosystem with different projects offering different ways of solving common problems. Web servers are one area where there’s a lot of development, despite a dominant Microsoft-sponsored project in ASP.NET Core. Although ASP.NET Core offers a one-stop shop for a wide variety of different web development scenarios, it’s a heavyweight tool.

There are many use cases where you need something lighter, when you want a project that can be built quickly but will still give you the scope to deliver complex projects without sacrificing maintainability. That’s where tools like Sisk come in, building on familiar web platform concepts such as Ruby on Rails or Node.js Express.

Introducing Sisk

Like many modern .NET tools, Sisk is an open source project focused on building front ends for cloud applications. It’s agnostic, adapting to your choice of design pattern. That’s unusual. We’re used to opinionated tools that push particular patterns and practices, but it makes sense to start small and then build out. We can start with the bare minimum code and quickly get a minimum viable product up and running, adding features as we get closer to a shipping site or service.

Sisk has been in development for a while and recently launched its first stable 1.0 release. It’s always possible to build prototypes on development code, but having a stable release makes it possible to recommend Sisk as an alternative to other .NET web application frameworks.

You can look at a tool like this and see a way of building user interfaces, but it’s perhaps better suited to delivering RESTful APIs for your applications and services, as it builds on the familiar .NET HttpListener and on the .NET 6 release. This is a key base class, as it supports everything from REST to gRPC, GraphQL, and more.

Keeping things lightweight makes sense for supporting edge devices. Instead of requiring a server with plenty of memory and compute, Sisk runs on less than 1GB of RAM while still delivering more than 20,000 requests a second. That makes it more than suitable for running on single-board Arm systems, offering a way of quickly adding a web API to an IoT device.

Importantly, Sisk is designed to support multiple requests asynchronously, keeping resource requirements to a minimum and allowing you to quickly roll out an application without adding the complexities that come with Kubernetes or another orchestration platform.

Building your first Sisk application

Getting started with Sisk is like working with any other .NET development framework. You need to have .NET and the core SDKs installed before using the .NET CLI to create a project for your web application. That will create a directory with a skeleton .NET application. Use the CLI to add the Sisk package to your application.

You’re now ready to start adding code to your Sisk application. Sisk behaves very similarly to frameworks like Express. You begin by creating a port for your application to listen on. This acts as a host for any number of routers that are each tied to a specific path under that port, which can take an HTTP request (a GET or a POST) and return a response.

At the heart of a Sisk application is the idea of a request life cycle that guides you through all the operations of a service from the receipt of a request to the delivery of a response. This model allows your code to manage request routing, collect any events, process the data attached to a request, then hand it to a service. Once that data has been processed and your service has generated its response, that data is handed back to Sisk to construct a response, which is then delivered via HTTP to the calling client.

As you can see, Sisk makes it very easy to construct a web API for an application. You only need a handful of lines of code to implement a port and its associated routes. However, it’s important to plan your APIs before writing any code to ensure you’ve got the best combination of routes to deliver an efficient set of APIs.

Although planning helps with initial application design, Sisk’s architecture does simplify extending APIs, simply adding new routes as necessary. Starting with a well-structured application, new routes can be added with minimal disruption while ensuring code remains understandable. This is an important feature, as it ensures your applications and APIs are able to respond to new demands from users.

Routes, requests, and responses

Routes don’t need to be static. They can be dynamic and based on parameters set by other parts of an application or other user inputs. So, for example, if you’re using Sisk to provide access to an online catalog, you can have one route that starts at the root of the catalog, dynamically adding routes to pages inside the catalog.

Two key elements are associated with a route: requests and responses. Requests are received by Sisk and their URLs are matched to the router. At the same time, payloads are attached to a request object, ready for processing by the code associated with the route. Query strings aren’t matched, as they’re part of the request payload.

You can use a request handler to process requests within the flow of a route, which allows them to force a response and end a flow. For example, a request handler could manage a payment workflow. If payment is refused, you can jump straight to ending the transaction.

A flow can have multiple request handlers running before and after the router callback. There are many different ways to attach a request handler to a flow; some can only work with a router or even a specific router, while others are attached to attributes. Usefully there’s the option to have global handlers that apply to all the routes in your application—and can be ignored as required.

Although it’s most likely you’ll use Sisk to build a lightweight API framework, you still need to send responses, even if they’re only “200 OK” when using a request to trigger a remote action. Sisk’s response objects are HTTP responses to requests, so you can use them to deliver JSON messages from a host application or even use streams to deliver files to a client.

More than APIs

You’re not limited to APIs, as a Sisk application can deliver templated HTML content. This allows you to use it in parallel to a more traditional web server to add interactive content to a web application.

Usefully Sisk’s support for Native Ahead of Time (AOT) compilation allows you to deliver binaries to servers without the overhead of the complete .NET runtime. It’s been designed to compile and support dynamic routes. You still need to ensure that your code is compatible with AOT, including support for AOT Trimming. However, if you follow Microsoft’s best practices, there should be little or no problem.

Having an open source tool like Sisk should help developers simplify the process of building HTTP APIs in .NET applications. Sisk offers a logical way to manage requests and deliver responses, all in a few lines of code. There’s no need for hefty libraries; everything you need beyond Sisk is in the base .NET SDK.

It’s important that the .NET ecosystem have as wide a selection of tools as possible, avoiding the perils that come with a monoculture. ASP.NET Core may be the first to come to mind, but it’s well worth looking at what else is out there. You may be surprised at what you find.