PicoServer
Source Code URL:
https://github.com/densen2014/MauiPicoAdmin
I. From API Server to Complete Application
In the previous articles, we have gradually built the core capabilities of PicoServer in MAUI:
Article 1
Embed PicoServer local web service in MAUI.
Article 2
Implement PicoServer routing mechanism and API design.
Article 3
Build a scalable REST API architecture including:
- Controller
- Service
- Model
Article 4
Implement static file hosting to enable PicoServer to run web pages.
At this point, our system already has the following components:
- Local Web Server
- Local REST API
- Local Web Frontend
In other words:
The infrastructure of a complete web application is already in place.
Next, we need to do something more important:
Build a truly usable Web Admin management backend
For example:
- Product management
- Device management
- System configuration
- Log viewing
The final effect will be similar to this flow:
localhost:8090
↓
Admin Dashboard
↓
API
↓
MAUI Local Logic
II. Web Admin Architecture
Under the PicoServer + MAUI architecture, the structure of a complete backend system is as follows:
┌─────────────────────┐
│ Web Admin │
│ Vue / React / UI │
└──────────▲──────────┘
│ fetch
│
┌──────────┴──────────┐
│ PicoServer │
│ Static + REST │
└──────────▲──────────┘
│
┌──────┴──────┐
│ Controller │
└──────▲──────┘
│
┌──────┴──────┐
│ Service │
└──────▲──────┘
│
┌──────┴──────┐
│ MAUI Logic │
└─────────────┘
Core Ideas:
- Use web technologies for UI
- Use PicoServer for API
- Use C# for business logic
This pattern is very common in many systems, such as:
- Industrial equipment systems
- IoT management platforms
- Local control systems
- Embedded device backends
III. Choosing an Admin UI Framework
Developing backend interfaces usually does not require starting from scratch. You can directly use mature Admin UI frameworks.
Here are several commonly recommended solutions:
Bootstrap Admin
The simplest solution with the tech stack:
- Bootstrap
- Chart.js
- jQuery
Suitable for:
- Lightweight backends
- Rapid development
Vue Admin
A common solution with the tech stack:
- Vue
- Element Plus
- Vite
Advantages:
- Rich component library
- High development efficiency
- Mature ecosystem
React Admin
Tech stack:
- React
- Ant Design
Suitable for:
- Complex systems
- Large-scale backends
In this series, for simplicity, we will first use:
Native HTML + Bootstrap
It can be upgraded to Vue later.
IV. Creating Admin Pages
Create the following files and directories under the wwwroot folder:
wwwroot
├─ index.html
├─ product.html
├─ css
└─ js
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PicoServer Admin</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="container">
<h1 class="mt-4">PicoServer Admin</h1>
<div class="mt-4">
<a href="product.html" class="btn btn-primary">
Product Management
</a>
</div>
</body>
</html>
Visit the address:
http://localhost:8090
And you can see the backend homepage.
V. Product Management Page
Create the product.html page with the following structure:
<h2>Product Management</h2>
<button onclick="loadProducts()">
Load Products
</button>
<table id="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody></tbody>
</table>
VI. Calling API to Load Data
Add the following JavaScript code:
async function loadProducts()
{
let res = await fetch("/api/product/list");
let json = await res.json();
let list = json.data;
let tbody = document.querySelector("#table tbody");
tbody.innerHTML = "";
for(let p of list)
{
let row = `
<tr>
<td>${p.id}</td>
<td>${p.name}</td>
<td>${p.price}</td>
</tr>
`;
tbody.innerHTML += row;
}
}
At this point, the data flow is as follows:
Page
↓
fetch API
↓
PicoServer
↓
Return JSON
↓
Render Table
VII. API Implementation
Controller
public async Task List(HttpListenerRequest req, HttpListenerResponse res)
{
var data = service.GetProducts();
var result = ApiResult.Success(data);
string json = JsonSerializer.Serialize(result);
res.ContentType = "application/json";
await res.WriteAsync(json);
}
Service
public List<object> GetProducts()
{
return new List<object>
{
new { id = 1, name = "Apple", price = 10 },
new { id = 2, name = "Orange", price = 8 }
};
}
Complete Page Code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PicoServer Admin</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
<h4 class="mb-0">Product Management</h4>
<button onclick="loadProducts()" class="btn btn-light btn-sm">
<span class="bi bi-arrow-repeat"></span> Load Products
</button>
</div>
<div class="card-body">
<div id="spinner" class="text-center my-3" style="display:none;">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div class="table-responsive">
<table id="table" class="table table-striped table-hover align-middle">
<thead class="table-primary">
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
async function loadProducts() {
document.getElementById("spinner").style.display = "block";
let res = await fetch("/api/product/list");
let json = await res.json();
let list = json.data;
let tbody = document.querySelector("#table tbody");
tbody.innerHTML = "";
for (let p of list) {
let row = `
<tr>
<td>${p.id}</td>
<td>${p.name}</td>
<td>${p.price}</td>
</tr>
`;
tbody.innerHTML += row;
}
document.getElementById("spinner").style.display = "none";
}
</script>
</body>
</html>
VIII. Adding CRUD Functions
Backend systems usually require complete CRUD capabilities, such as:
- Add product
- Edit product
- Delete product
- Query product
API Examples
- GET /api/product/list
- GET /api/product/detail?id=1
- POST /api/product/add
- POST /api/product/delete
Frontend Calls
fetch("/api/product/add")
fetch("/api/product/delete")
IX. Final Effect of the Admin Backend
After completion, the system structure is as follows:
localhost:8090
Backend Pages:
- Homepage
- Product Management
- System Configuration
Call Flow:
Web UI
↓
fetch API
↓
PicoServer
↓
Controller
↓
Service
↓
MAUI Logic
At this point, your MAUI application has essentially become:
A complete web application container
X. Why This Architecture Is Powerful
This architecture has significant advantages in many scenarios, such as:
1. Industrial Equipment Systems
- Equipment control
- Parameter configuration
- Log viewing
2. IoT Systems
- Device management
- Data display
- Remote control
3. Local Management Backends
- Inventory systems
- POS systems
- Offline business systems
4. Cross-Platform UI
The same set of Web UI can run on:
- Windows
- Android
- iOS
- Mac
- Linux
XI. WebView App Shell
In MAUI, you can directly embed the following code:
<WebView Source="http://127.0.0.1:8090" />
Application Structure:
MAUI App
↓
WebView
↓
PicoServer
↓
Web Admin
This is the Local Web Shell architecture.
Many desktop applications actually use a similar architecture, such as:
- VS Code
- Slack
- Notion
XII. Summary of This Article
In this article, we have achieved an important milestone of the entire series:
Building a complete Web Admin management backend
The implemented contents include:
- Admin Dashboard page
- Product management CRUD example
- API and frontend interaction
- Complete Web Admin architecture
At this point, our MAUI application has the following capabilities:
- Local Web Server
- Local API
- Local Web UI
- Complete Admin system
Next Article Preview
Next, we will continue to upgrade the system with:
Practical Combat of MAUI Embedded Web Architecture (6)
Web Admin Permission System and Login Authentication
We will implement:
- User login
- Token authentication
- Permission control
- Login interception
- API authentication
Ultimately, we will build a truly usable Admin management system.

Top comments (0)