Today's .NET is fully open-source and cross-platform. As a .NET developer, you're probably already used to developing Windows applications, Linux Web APIs, and even building mobile or cross-platform apps with MAUI or Avalonia using C#.
In addition, there's another project under the .NET Foundation—.NET nanoFramework, designed specifically to run C# on microcontrollers like ESP32 and STM32. It strips the full .NET runtime down to a few hundred KB, enabling MCUs to execute C# code. You can develop projects using Visual Studio and deploy them to your board with a single click.
PicoServer is a lightweight .NET web capability aggregate library—single DLL, zero dependencies, AOT-compatible, and only a few tens of KB. PicoServer.Nano is my humble attempt to bring that experience to nanoFramework—letting embedded devices build lightweight web services using C#. It stays true to PicoServer's philosophy of being "simple, straightforward, non-architecturally intrusive," while adapting to the constraints of MCUs by making deliberate trade-offs: prioritizing routing, static file hosting, token authentication, custom middleware, SSE, and other commonly used features.
Unlike the official WebServer library, PicoServer.Nano avoids reflection, resulting in lower memory and CPU usage, leaving more resources for your application logic.
Key Features at a Glance
- Routing, custom middleware, token authentication, static file hosting, SSE persistent connections, file upload/download
For detailed usage, see the official documentation
I. ESP32 and STM32 Use Cases
A quick overview of the two chip families: ESP32 integrates Wi-Fi/Bluetooth, offers fast development, and is cost-effective—making it a popular choice for smart home and IoT projects. STM32, on the other hand, is known for its rich peripherals, strong real-time responsiveness, and industrial-grade stability—dominating fields like industrial control and automotive electronics. While each has different strengths, both can quickly provide web capabilities using PicoServer.Nano.
II. Quick Start: Running a Web API on ESP32
1. Flash nanoFramework Firmware
nanoff --target ESP32_S3_ALL --serialport COM5 --update --masserase
2. Add NuGet Package
dotnet add package PicoServer.Nano
3. Write Code
using PicoServer.Nano;
using System.Net;
var server = new WebAPIServer();
server.AddRoute("/hello", (req, res) => res.Write("Hello from MCU!"), "GET");
server.StartServer();
Console.WriteLine($"Server started: http://{server.GetIPAddress()}/");
Build, deploy/run, and visit http://<device IP>/hello in your browser to see the response.
III. Static File Hosting
Host an entire folder with a single line of code:
server.AddStaticFiles("/web", "I:\\www", maxAge: 3600);
Visit http://device IP/web/index.html to see the webpage.
IV. Performance Benchmark
Test Platform: ESP32-S3 N16R8, LAN Wi-Fi
# 6 concurrent short-duration stress test command
hey -n 50 -c 6 http://192.168.2.67
| Configuration | Stable Concurrency | QPS | Avg Latency | Success Rate |
|---|---|---|---|---|
| Without PSRAM | 6 | ~8 | ~220ms | 100% |
| With PSRAM | 6 | ~26 | ~210ms | 100% |
Enabling PSRAM significantly improves QPS. STM32 with Ethernet or hardware protocol stacks is expected to achieve even higher performance. Concurrency should be kept within 6; exceeding this may cause packet loss at the underlying lwIP stack.
V. Consistent C# Development Experience
PicoServer on Windows/Linux/macOS/iOS/Android:
server.AddRoute("/hello", async (req, res) => await res.WriteAsync("Hello"));
PicoServer.Nano on ESP32/STM32:
server.AddRoute("/hello", (req, res) => res.Write("Hello"));
Virtually the same API, delivering a consistent web development experience across desktop, cloud, and embedded microcontrollers.
VI. Important Notes
-
Path Format: Use backslashes
\in nanoFramework, e.g.,"I:\\www" - Static File Hosting: Files must be deployed to the device (set Build Action to "Content"). Middlewares execute sequentially—add static file hosting first.
- Whitelist: Static file routes must be added to the whitelist to bypass authentication.
-
Persistent Connections: After pushing with
WriteChunk, you must callres.Close().
VII. Resources
- NuGet:
PicoServer.Nanohttps://www.nuget.org/packages/PicoServer.Nano - Documentation: https://docs.picoserver.cn/PicoServer-Nano.html
- Official Website: https://picoserver.cn
- nanoFramework Official Website: https://www.nanoframework.net

Top comments (0)