![]() |
VOOZH | about |
dotnet add package SiLA2.Frontend.Razor --version 10.2.4
NuGet\Install-Package SiLA2.Frontend.Razor -Version 10.2.4
<PackageReference Include="SiLA2.Frontend.Razor" Version="10.2.4" />
<PackageVersion Include="SiLA2.Frontend.Razor" Version="10.2.4" />Directory.Packages.props
<PackageReference Include="SiLA2.Frontend.Razor" />Project file
paket add SiLA2.Frontend.Razor --version 10.2.4
#r "nuget: SiLA2.Frontend.Razor, 10.2.4"
#:package SiLA2.Frontend.Razor@10.2.4
#addin nuget:?package=SiLA2.Frontend.Razor&version=10.2.4Install as a Cake Addin
#tool nuget:?package=SiLA2.Frontend.Razor&version=10.2.4Install as a Cake Tool
| Package | SiLA2.Frontend.Razor |
| Version | 10.0.0 |
| Framework | .NET 10 |
| License | MIT |
| Repository | https://gitlab.com/SiLA2/sila_csharp |
| Wiki | https://gitlab.com/SiLA2/sila_csharp/-/wikis/home |
SiLA2.Frontend.Razor is an optional web frontend extension for SiLA2 servers that provides pre-built Blazor Server components for server introspection, monitoring, and management. This module enables developers to quickly add professional web UI capabilities to their SiLA2 laboratory automation servers.
Built on Blazor Server with SignalR, the frontend supports real-time server monitoring with automatic UI updates via server-push technology. The module includes ready-to-use components for displaying server information, feature definitions, user management, and security settings.
Key Benefits:
Pre-Built Razor Components
ServerInformationComponent - Display server metadata, UUID, version, and connection detailsServerFeaturesComponent - List all implemented features with interactive command/property executionUserManagementComponent - Manage users, roles, and permissions (requires SiLA2.Authentication)SecurityComponent - View security settings and certificate informationServer Data Services
IServerDataService - Query server metadata and feature definitions via gRPCIConnectionViewModelProvider - Manage connection view models for UI bindingICommandPayloadProvider - Dynamic command payload construction for generic executionReal-Time Capabilities
Modern UI
File Transfer Support
Install the NuGet package in your Blazor Server application:
# Package Manager Console
Install-Package SiLA2.Frontend.Razor
# .NET CLI
dotnet add package SiLA2.Frontend.Razor
Dependencies (automatically installed):
Important: This package is designed for Blazor Server applications, not Blazor WebAssembly.
using SiLA2.Frontend.Razor.Services;
using SiLA2.Utils.gRPC;
using SiLA2.Utils.Config;
var builder = WebApplication.CreateBuilder(args);
// Add Blazor Server services
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// Add Blazor Bootstrap
builder.Services.AddBlazorBootstrap();
// Add SiLA2 Frontend services
builder.Services.AddSingleton<IGrpcChannelProvider, GrpcChannelProvider>();
builder.Services.AddScoped<IServerDataService, ServerDataService>();
builder.Services.AddScoped<ICommandPayloadProvider, CommandPayloadProvider>();
// Configure server connection
var serverConfig = new ServerConfig(
name: "My SiLA2 Server",
uuid: Guid.Parse("12345678-1234-1234-1234-123456789abc"),
fqhn: "localhost",
port: 50051);
builder.Services.AddSingleton<IServerConfig>(serverConfig);
var app = builder.Build();
// Configure HTTP pipeline
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
// Map Blazor endpoints
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
Create Pages/_Host.cshtml:
@page "/"
@using Microsoft.AspNetCore.Components.Web
@namespace YourNamespace.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="~/" />
<title>SiLA2 Server Frontend</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css"
rel="stylesheet" />
<link href="_content/Blazor.Bootstrap/blazor.bootstrap.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="Server" />
</head>
<body>
<component type="typeof(App)" render-mode="Server" />
<div id="blazor-error-ui">
An error has occurred. This application may no longer respond until reloaded.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.server.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="_content/Blazor.Bootstrap/blazor.bootstrap.js"></script>
</body>
</html>
Create Pages/Index.razor:
@page "/"
<h1>SiLA2 Server Dashboard</h1>
<ServerInformationComponent></ServerInformationComponent>
Create Pages/Features.razor:
@page "/features"
<h1>Server Features</h1>
<ServerFeaturesComponent></ServerFeaturesComponent>
Create _Imports.razor to import necessary namespaces:
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Forms
@using BlazorBootstrap
@using SiLA2.Frontend.Razor
dotnet run
Navigate to https://localhost:5001 to see your SiLA2 server web frontend.
Displays server metadata retrieved from the SiLAService core feature.
Usage:
<ServerInformationComponent></ServerInformationComponent>
Displays:
Dependencies:
IServerDataService (injected)IServerConfig (injected)IGrpcChannelProvider (injected)Interactive component that lists all implemented features with the ability to execute commands and query properties.
Usage:
<ServerFeaturesComponent></ServerFeaturesComponent>
Features:
Dependencies:
IServerDataService (injected)IDynamicMessageService (injected)ICommandPayloadProvider (injected)Example Command Execution:
<ServerFeaturesComponent></ServerFeaturesComponent>
The component dynamically generates input fields based on command parameter types and executes commands via gRPC.
Comprehensive user administration interface (requires SiLA2.Authentication module).
Usage:
@using SiLA2.Frontend.Razor
<UserManagementComponent></UserManagementComponent>
Features:
Dependencies:
IUserManager (from SiLA2.Authentication)ILogger<UserManagementComponent>Prerequisites:
// In Program.cs
builder.Services.AddSiLA2Authentication(options =>
{
options.UseSqlite(configuration.GetConnectionString("DefaultConnection"));
});
// Initialize database
app.Services.EnsureAuthenticationDatabaseCreated();
Displays security settings and certificate information.
Usage:
<SecurityComponent></SecurityComponent>
Features:
Service for querying SiLA2 server metadata and feature definitions via gRPC.
Interface:
public interface IServerDataService
{
Task<ServerData> GetServerData(string host, int port, bool acceptAnyServerCertificated = true);
Task<IDictionary<string, Feature>> GetServerFeatures(string host, int port, bool acceptAnyServerCertificated = true);
}
Usage Example:
@inject IServerDataService ServerDataService
@inject IServerConfig ServerConfig
@code {
private ServerData _serverData;
private IDictionary<string, Feature> _features;
protected override async Task OnInitializedAsync()
{
// Get server metadata
_serverData = await ServerDataService.GetServerData(
ServerConfig.FQHN,
ServerConfig.Port,
acceptAnyServerCertificated: true);
// Get all feature definitions
_features = await ServerDataService.GetServerFeatures(
ServerConfig.FQHN,
ServerConfig.Port,
acceptAnyServerCertificated: true);
}
}
Methods:
GetServerData - Retrieves server configuration and information
ServerData object with ServerConfig and ServerInformationGetServerFeatures - Retrieves all feature definitions
Get_ImplementedFeatures to get feature listGetFeatureDefinition for each featureFeature objectsFeatureService for constructing dynamic command payloads from user input.
Usage:
@inject ICommandPayloadProvider CommandPayloadProvider
@code {
private IDictionary<Tuple<string, string, string>, string> _parameterMap;
private IDictionary<string, object> GetPayload(FeatureCommand command, Feature feature)
{
return CommandPayloadProvider.GetPayloadMap(_parameterMap, command, feature);
}
}
This service handles conversion of user input strings to appropriate protobuf message types based on parameter definitions.
Service for managing connection view models in the UI.
Usage:
@inject IConnectionViewModelProvider ConnectionViewModelProvider
@code {
private ConnectionViewModel _viewModel = ConnectionViewModelProvider.CreateViewModel(host, port);
}
Here's a complete example showing Program.cs configuration with all required services:
using SiLA2.Frontend.Razor.Services;
using SiLA2.Utils.gRPC;
using SiLA2.Utils.Config;
using SiLA2.Communication.Services;
using SiLA2.Authentication.Extensions;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Blazor Server configuration
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddBlazorBootstrap();
// SiLA2 Authentication (optional)
builder.Services.AddSiLA2Authentication(options =>
{
options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection"));
});
// SiLA2 Frontend services
builder.Services.AddSingleton<IGrpcChannelProvider, GrpcChannelProvider>();
builder.Services.AddScoped<IServerDataService, ServerDataService>();
builder.Services.AddScoped<ICommandPayloadProvider, CommandPayloadProvider>();
builder.Services.AddScoped<IDynamicMessageService, DynamicMessageService>();
builder.Services.AddScoped<IPayloadFactory, PayloadFactory>();
builder.Services.AddScoped<IDynamicAssemblyBuilder, DynamicAssemblyBuilder>();
// Server configuration
var serverConfig = new ServerConfig(
builder.Configuration["ServerConfig:Name"],
Guid.Parse(builder.Configuration["ServerConfig:UUID"]),
builder.Configuration["ServerConfig:FQHN"],
int.Parse(builder.Configuration["ServerConfig:Port"]));
builder.Services.AddSingleton<IServerConfig>(serverConfig);
var app = builder.Build();
// Configure pipeline
if (!app.Environment.IsDevelopment())
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
// Initialize authentication database (if using SiLA2.Authentication)
app.Services.EnsureAuthenticationDatabaseCreated();
// Map Blazor endpoints
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
appsettings.json:
{
"ServerConfig": {
"Name": "Temperature Controller Server",
"UUID": "a7c9e3d2-4f1a-4b5c-8e3d-1a2b3c4d5e6f",
"FQHN": "localhost",
"Port": 50051
},
"ConnectionStrings": {
"DefaultConnection": "Data Source=authentication.db"
}
}
Blazor Server uses SignalR for real-time communication between server and browser. The frontend components leverage this for live monitoring.
@inject IDynamicMessageService DynamicMessageService
@inject IGrpcChannelProvider GrpcChannelProvider
@code {
private async Task MonitorTemperature(Feature feature, FeatureProperty property)
{
var channel = await GrpcChannelProvider.GetChannel(ServerConfig.FQHN, ServerConfig.Port, true);
var asyncEnumerable = DynamicMessageService.SubcribeObservableProperty(
property.Identifier, channel, feature);
await InvokeAsync(async () =>
{
var enumerator = asyncEnumerable.GetAsyncEnumerator();
while (await enumerator.MoveNextAsync())
{
// Update UI automatically
_currentValue = enumerator.Current;
StateHasChanged(); // Trigger UI refresh
}
});
}
}
Key Pattern:
InvokeAsync() ensures UI updates happen on the correct threadStateHasChanged() triggers Blazor to re-render the component@code {
private async Task ExecuteObservableCommand(FeatureCommand command, Feature feature)
{
var channel = await GrpcChannelProvider.GetChannel(ServerConfig.FQHN, ServerConfig.Port, true);
var payloadMap = CommandPayloadProvider.GetPayloadMap(_parameterMap, command, feature);
var result = DynamicMessageService.ExecuteObservableCommand(
command.Identifier, channel, feature, payloadMap);
await InvokeAsync(async () =>
{
var enumerator = result.Item2.GetAsyncEnumerator();
while (await enumerator.MoveNextAsync())
{
// Show progress updates
_progressInfo.Add(JsonConvert.SerializeObject(enumerator.Current));
StateHasChanged();
if (enumerator.Current.CommandStatus == ExecutionInfo.Types.CommandStatus.FinishedSuccessfully)
{
break;
}
}
// Get final result
var finalResult = DynamicMessageService.GetObservableCommandResult(
result.Item1.CommandExecutionUUID, command.Identifier, channel, feature, result.Item4);
_finalResponse = JsonConvert.SerializeObject(finalResult);
StateHasChanged();
});
}
}
You can create custom pages that use the pre-built components or query server data directly.
Example: Custom Dashboard
@page "/dashboard"
@using SiLA2.Frontend.Razor.Services
@inject IServerDataService ServerDataService
@inject IServerConfig ServerConfig
<h1>Server Dashboard</h1>
<div class="row">
<div class="col-md-6">
<ServerInformationComponent></ServerInformationComponent>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">Custom Metrics</div>
<div class="card-body">
<p>Feature Count: @_featureCount</p>
<p>Server Status: @_serverStatus</p>
</div>
</div>
</div>
</div>
@code {
private int _featureCount;
private string _serverStatus = "Unknown";
protected override async Task OnInitializedAsync()
{
try
{
var features = await ServerDataService.GetServerFeatures(
ServerConfig.FQHN, ServerConfig.Port, true);
_featureCount = features.Count;
_serverStatus = "Online";
}
catch
{
_serverStatus = "Offline";
}
}
}
A complete working example is available in the repository:
Location: src/Examples/TemperatureController/SiLA2.Temperature.Server.App.Webfrontend
To Run:
dotnet run --project src/Examples/TemperatureController/SiLA2.Temperature.Server.App.Webfrontend/SiLA2.Temperature.Server.App.Webfrontend.csproj
URL: https://localhost:5011
Features Demonstrated:
Key Files:
Pages/Index.razor - Dashboard with ServerInformationComponentPages/Features.razor - Feature explorer with ServerFeaturesComponentPages/Temperature.razor - Custom temperature monitoring pagePages/UserManagement.razor - User administrationProgram.cs - Complete service configurationThe UserManagementComponent requires SiLA2.Authentication module.
Setup:
// In Program.cs
builder.Services.AddSiLA2Authentication(options =>
{
options.UseSqlite(configuration.GetConnectionString("DefaultConnection"));
// or
options.UseSqlServer(configuration.GetConnectionString("SqlServerConnection"));
});
var app = builder.Build();
// Initialize database
app.Services.EnsureAuthenticationDatabaseCreated();
Protect Pages with Authorization:
@page "/admin"
@attribute [Authorize(Roles = "Admin")]
<h1>Admin Dashboard</h1>
<UserManagementComponent></UserManagementComponent>
Authentication Configuration:
// Add authentication middleware
app.UseAuthentication();
app.UseAuthorization();
The frontend uses Blazor Bootstrap 3.5.0, which provides modern Bootstrap 5 components.
Custom CSS:
Create wwwroot/css/site.css:
/* Custom primary color for SiLA2 */
:root {
--sila-primary: #0F3052;
--sila-secondary: #6c757d;
}
.btn-custom-primary {
background-color: var(--sila-primary);
border-color: var(--sila-primary);
color: white;
}
.btn-custom-primary:hover {
background-color: #0a2340;
border-color: #0a2340;
}
.header {
color: var(--sila-primary);
}
Pre-built components can be styled via CSS without modifying component code:
<style>
.table-striped tbody tr:nth-of-type(odd) {
background-color: rgba(0,0,0,.02);
}
.featurerow {
background-color: #f8f9fa;
font-weight: bold;
}
</style>
<ServerFeaturesComponent></ServerFeaturesComponent>
Create a custom layout in Shared/MainLayout.razor:
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<h3>SiLA2 Server Management</h3>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
It's Open Source (License: MIT) - feel free to use or contribute!
MIT License - see LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.2.4 | 138 | 3/13/2026 |
| 10.2.3 | 118 | 3/7/2026 |
| 10.2.2 | 126 | 2/12/2026 |
| 10.2.1 | 145 | 1/25/2026 |
| 10.2.0 | 246 | 12/23/2025 |
| 10.1.0 | 212 | 11/29/2025 |
| 10.0.0 | 363 | 11/11/2025 |
| 9.0.4 | 261 | 6/25/2025 |
| 9.0.3 | 201 | 6/21/2025 |
| 9.0.2 | 223 | 1/6/2025 |
| 9.0.1 | 237 | 11/17/2024 |
| 9.0.0 | 233 | 11/13/2024 |
| 8.1.2 | 235 | 10/20/2024 |
| 8.1.1 | 309 | 8/31/2024 |
| 8.1.0 | 354 | 2/11/2024 |
| 8.0.0 | 652 | 11/15/2023 |
| 7.5.4 | 295 | 10/27/2023 |
| 7.5.3 | 452 | 7/19/2023 |
| 7.5.2 | 358 | 7/3/2023 |
| 7.5.1 | 360 | 6/2/2023 |