Web Server Guide
InfiniLore.InfiniFrame.WebServer runs a standard ASP.NET Core web application in a background thread while opening a native window pointed at it
This approach gives you the full ASP.NET Core pipeline — middleware, controllers, SignalR, minimal APIs, Blazor Server — without any browser overhead
Contents
- How It Works
- Installation
- Minimal Setup
- Builder API
- Start URL
- Accessing the Window from ASP.NET Core
- Graceful Shutdown
- Example: Blazor Server
- Static Web Assets
- Thread Model
How It Works
- The ASP.NET Core server starts on a background thread
- A native window opens and navigates to the server's URL
- Both shut down together when the window is closed (with
UseAutoServerClose())
Installation
dotnet add package InfiniLore.InfiniFrame.WebServer
Minimal Setup
using InfiniFrame.WebServer;
var app = InfiniFrameWebApplication.CreateBuilder(args)
.Build()
.UseAutoServerClose();
app.WebApp.MapGet("/", () => "Hello from InfiniFrame");
app.Run();
app.Run() starts the web server in the background, opens the window, and blocks until the window is closed
Builder API
InfiniFrameWebApplication.CreateBuilder(args) returns an InfiniFrameWebApplicationBuilder with two properties:
| Property | Type | Description |
|---|---|---|
WebApp |
WebApplicationBuilder |
Standard ASP.NET Core builder — add services, configure Kestrel, etc. |
Window |
InfiniFrameWindowBuilder |
Fluent window configuration |
Configuring the window
var builder = InfiniFrameWebApplication.CreateBuilder(args);
builder.Window
.SetTitle("My Desktop App")
.SetSize(1280, 720)
.Center()
.SetDevToolsEnabled(true);
builder.WebApp.Services.AddControllers();
builder.WebApp.Services.AddSignalR();
var app = builder.Build().UseAutoServerClose();
app.WebApp.MapControllers();
app.WebApp.MapHub<MyHub>("/hub");
app.Run();
Start URL
The window's start URL is automatically resolved from configuration in this priority order:
ASPNETCORE_URLSenvironment variableurlsconfiguration key (e.g. inappsettings.json)- Manual override via
builder.Window.SetStartUrl(...)
// appsettings.json
{
"urls": "http://localhost:5200"
}
If multiple URLs are configured (e.g. "http://localhost:5200;https://localhost:7200"), the first one is used as the window's start URL
Accessing the Window from ASP.NET Core
IInfiniFrameWindow and IInfiniFrameWindowBuilder are registered in the web app's DI container:
app.WebApp.MapGet("/close", (IInfiniFrameWindow window) => {
window.Close();
return Results.Ok();
});
public class MyController(IInfiniFrameWindow window) : ControllerBase {
[HttpGet("minimize")]
public IActionResult Minimize() {
window.Invoke(() => { /* minimize logic */ });
return Ok();
}
}
Note: Window operations that affect the native UI must be marshalled to the window thread using
window.Invoke(...)
Graceful Shutdown
UseAutoServerClose
Automatically stops the web server when the window is closed or a close is requested:
var app = builder.Build().UseAutoServerClose();
Internally this registers handlers on both WindowClosing and WindowClosingRequested that call WebApp.StopAsync() in a background task, so the UI thread is never blocked
Manual shutdown
app.Stop(); // Stops the web server and closes the window
await app.WebApp.StopAsync(); // Stop server only
app.Window.Close(); // Then close window
Example: Blazor Server
using InfiniFrame.WebServer;
var builder = InfiniFrameWebApplication.CreateBuilder(args);
builder.Window
.SetTitle("Blazor Server App")
.SetSize(1280, 720)
.Center();
builder.WebApp.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build().UseAutoServerClose();
app.WebApp.UseStaticFiles();
app.WebApp.UseAntiforgery();
app.WebApp.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
Static Web Assets
UseStaticWebAssets() is called automatically during builder initialization, so static files from Razor class libraries are served correctly without additional configuration
UseDefaultFiles() is also applied during Build(), which causes requests to / to serve wwwroot/index.html if it exists
Thread Model
| Thread | Runs |
|---|---|
| Main thread | Native window (UI thread) |
| Background thread | ASP.NET Core / Kestrel |
All window API calls from ASP.NET Core handlers must use window.Invoke(...) to marshal to the window thread
Web server calls from window event handlers can be made directly since ASP.NET Core is thread-safe
Windows: The main thread must be STA. Add
[STAThread]to yourMainmethod and use an explicitstatic void Main()— top-level statements andasync Task Maindo not support STA correctly
Examples
InfiniFrameExample.WebApp.Blazor(examples/InfiniFrameExample.WebApp.Blazor) - Blazor Server with InteractiveServerComponents, HttpClient factory, and InfiniFrameJsInfiniFrameExample.WebApp.React(examples/InfiniFrameExample.WebApp.React) - React frontend with custom scheme handler and two-way messagingInfiniFrameExample.WebApp.Vue(examples/InfiniFrameExample.WebApp.Vue) - Vue.js frontend with all built-in JS message handlers