EmbedIO: Building Desktop Applications with .NET and a Browser UI

EmbedIO: Building Desktop Applications with .NET and a Browser UI

What if you could build a desktop application using only .NET and a browser UI — bundled inside your executable, with no installer dependencies? EmbedIO is a lightweight, cross-platform .NET library that embeds a full web server inside your application, letting you use HTML, CSS, and JavaScript as your UI layer while keeping all business logic in C#.

What Is EmbedIO?

EmbedIO is a NuGet library maintained by the Unosquare team. It provides a complete embedded HTTP server for .NET 6+, supporting REST API routing with attribute-based controllers, static file serving from embedded resources or the filesystem, WebSocket bi-directional communication, CORS, compression, and custom middleware — all with no IIS, Kestrel, or external server required.

The Architecture: Desktop App with Browser UI

How It Works

1. .NET Backend
EmbedIO server hosts your REST API, serves static files, handles WebSocket messages. All C# business logic.
2. Browser Window
WebView2 (Windows), CefSharp, or system browser displays your HTML/CSS/JS frontend connecting to localhost.
3. Final Result
A native-looking desktop application with modern web UI, packaged as a single .exe or cross-platform binary.

Getting Started

1. Install EmbedIO

dotnet add package EmbedIO

2. Create the Web Server

using EmbedIO;
using EmbedIO.WebApi;

public class Program
{
    public static async Task Main(string[] args)
    {
        var url = "http://localhost:8080";

        var server = new WebServer(o => o
            .WithUrlPrefix(url)
            .WithMode(HttpListenerMode.EmbedIO))
            .WithLocalSessionManager()
            .WithWebApi("/api", m => m.WithController<ApiController>())
            .WithStaticFolder("/", "wwwroot", true);

        // Open in system browser
        System.Diagnostics.Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });

        await server.RunAsync();
    }
}

3. Define API Controller

using EmbedIO.Routing;
using EmbedIO.WebApi;

public class ApiController : WebApiController
{
    [Route(HttpVerbs.Get, "/greeting")]
    public async Task<string> GetGreeting()
    {
        return "Hello from EmbedIO!";
    }

    [Route(HttpVerbs.Post, "/data")]
    public async Task<object> PostData()
    {
        var data = await HttpContext.GetRequestDataAsync<MyDto>();
        return new { success = true, received = data };
    }
}

4. Frontend (wwwroot/index.html)

<!DOCTYPE html>
<html>
<body>
  <h1>My Desktop App</h1>
  <button onclick="callApi()">Fetch Greeting</button>
  <div id="result"></div>
  <script>
    async function callApi() {
      const resp = await fetch('/api/greeting');
      document.getElementById('result').textContent = await resp.text();
    }
  </script>
</body>
</html>

WebSockets for Real-Time Communication

using EmbedIO.WebSockets;

public class ChatModule : WebSocketModule
{
    public ChatModule(string urlPath) : base(urlPath, true) { }

    protected override Task OnMessageReceivedAsync(
        IWebSocketContext context,
        byte[] buffer,
        IWebSocketReceiveResult result)
    {
        var message = Encoding.UTF8.GetString(buffer);
        return BroadcastAsync($"Echo: {message}");
    }
}

// Register in server setup:
server.WithModule(new ChatModule("/chat"));

EmbedIO vs. Traditional Desktop Frameworks

Aspect WinForms / WPF Electron EmbedIO + Browser
PlatformWindows onlyCross-platformCross-platform
UI LanguageXAML / WinFormsHTML/CSS/JSHTML/CSS/JS
Runtime Size~50–200 MB~150–300 MB~10–30 MB
Backend LanguageC# / VB.NETNode.js / JSC# / .NET
Startup SpeedFastSlowFast
Modern UIDifficultEasyEasy
.NET IntegrationNativeVia IPCNative

Self-Contained Single-File Deployment

To create a truly self-contained single-file executable, embed your HTML/CSS/JS files as resources and serve them from memory:

<!-- In .csproj -->
<EmbeddedResource Include="wwwroot**" />
server.WithEmbeddedResources("/", typeof(Program).Assembly, "MyApp.wwwroot");

Conclusion

EmbedIO is an excellent choice for developers who want to build cross-platform desktop applications with a modern web UI while keeping all logic in .NET/C#. It is far lighter than Electron, more flexible than WinForms, and doesn't require learning a new framework. For internal tools, admin panels, dashboards, and utilities, EmbedIO is a highly practical and underutilized solution in the .NET ecosystem.

Post a Comment

Previous Post Next Post