RobotNet10.CustomConfiguration
Thư viện quản lý cấu hình động cho ứng dụng RobotNet10, cho phép import/export, chỉnh sửa và quản lý các file cấu hình dạng JSON với hỗ trợ nhiều kiểu dữ liệu.
📋 Mục lục
- Tính năng
- Cấu trúc Project
- Cài đặt và Cấu hình
- Hướng dẫn sử dụng Backend
- Hướng dẫn sử dụng Frontend
- Format JSON Config
- API Endpoints
- Ví dụ sử dụng
- Troubleshooting
✨ Tính năng
- ✅ Import/Export Config: Import và export các file cấu hình dạng JSON
- ✅ Quản lý Config Files: Tạo, đọc, cập nhật, xóa các file cấu hình
- ✅ Quản lý Variables: Thêm, sửa, xóa các biến trong config
- ✅ Hỗ trợ nhiều kiểu dữ liệu: String, Int, Double, Bool, Object, Array, Enum
- ✅ Validation: Kiểm tra tính hợp lệ của dữ liệu theo type và constraints
- ✅ Tìm kiếm: Tìm kiếm config theo tên, loại
- ✅ UI Component: Component Blazor sẵn có để quản lý config qua giao diện
- ✅ Storage Manager: Tích hợp với RobotNet10.StorageManager (Local hoặc MinIO)
📁 Cấu trúc Project
RobotNet10.CustomConfiguration/
├── Controllers/
│ └── ConfigController.cs # REST API Controller
├── DTOs/
│ ├── ConfigFileDto.cs
│ ├── ConfigFileMetadataDto.cs
│ ├── ConfigVariableDto.cs
│ └── Requests/
│ ├── CreateConfigRequest.cs
│ ├── UpdateConfigRequest.cs
│ └── UpdateVariableRequest.cs
├── Extensions/
│ └── ServiceCollectionExtensions.cs # DI Extension methods
├── Helpers/
│ ├── JsonConfigParser.cs # Parse/Serialize JSON
│ └── VariableTypeConverter.cs # Convert variable types
├── Models/
│ ├── ConfigFile.cs
│ ├── ConfigFileMetadata.cs
│ ├── ConfigVariable.cs
│ └── ConfigVariableType.cs
├── Services/
│ ├── IConfigService.cs
│ ├── ConfigService.cs
│ ├── ConfigService.Implementation.cs
│ └── ConfigService.Metadata.cs
└── Validators/
└── ConfigValidator.cs # Validation logic
🚀 Cài đặt và Cấu hình
1. Thêm Project Reference
Thêm reference vào project của bạn:
<ItemGroup>
<ProjectReference Include="..\Commons\RobotNet10.CustomConfiguration\RobotNet10.CustomConfiguration.csproj" />
</ItemGroup>
2. Cấu hình Backend (ASP.NET Core)
Bước 1: Thêm using trong Program.cs
using RobotNet10.CustomConfiguration.Extensions;
using RobotNet10.StorageManager;
Bước 2: Đăng ký Services
Cách 1: Từ appsettings.json (Khuyến nghị)
// Trong Program.cs
builder.Services.AddCustomConfiguration(builder.Configuration, "StorageConfig");
Thêm vào appsettings.json:
{
"StorageConfig": {
"UsingLocal": true,
"LocalFolder": "Configs",
"Bucket": "",
"RetryCount": 3,
"MinioConfig": {
"Endpoint": "localhost:9000",
"User": "minioadmin",
"Password": "minioadmin",
"EnableSSL": false
}
}
}
Cách 2: Trực tiếp trong code
var storageConfig = new StorageConfig
{
UsingLocal = true,
LocalFolder = "Configs",
Bucket = "",
RetryCount = 3
};
builder.Services.AddCustomConfiguration(storageConfig);
Bước 3: Đảm bảo đã map Controllers
var app = builder.Build();
// ... middleware ...
app.MapControllers(); // Đảm bảo có dòng này
app.Run();
3. Cấu hình Frontend (Blazor)
Bước 1: Thêm Project Reference
<ItemGroup>
<ProjectReference Include="..\Components\RobotNet10.CustomConfigurationEditor\RobotNet10.CustomConfigurationEditor.csproj" />
</ItemGroup>
Bước 2: Đăng ký Services trong Program.cs hoặc Client/Program.cs
using RobotNet10.CustomConfigurationEditor.Services.API;
using RobotNet10.CustomConfigurationEditor.Services.State;
// HttpClient (nếu chưa có)
builder.Services.AddScoped(sp => new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
// MudBlazor (nếu chưa có)
builder.Services.AddMudServices();
// CustomConfiguration Services
builder.Services.AddScoped<ConfigApiService>();
builder.Services.AddScoped<ConfigManagerState>();
Bước 3: Copy JavaScript file
Copy file downloadFile.js từ RobotNet10.CustomConfigurationEditor/wwwroot/js/downloadFile.js vào wwwroot/js/ của project frontend.
Thêm vào index.html hoặc App.razor:
<script src="js/downloadFile.js"></script>
Bước 4: Thêm using trong _Imports.razor
@using RobotNet10.CustomConfigurationEditor.Components.ConfigManager
📖 Hướng dẫn sử dụng Backend
Sử dụng IConfigService
Inject IConfigService vào service hoặc controller của bạn:
public class MyService
{
private readonly IConfigService _configService;
public MyService(IConfigService configService)
{
_configService = configService;
}
public async Task<ConfigFile> GetMqttConfigAsync()
{
return await _configService.GetConfigByTypeAsync("MQTTBrokerConfig");
}
}
Các phương thức chính
// Lấy tất cả configs (metadata)
var configs = await _configService.GetAllConfigsAsync();
// Lấy config theo ID
var config = await _configService.GetConfigByIdAsync(id);
// Lấy config theo ConfigType
var mqttConfig = await _configService.GetConfigByTypeAsync("MQTTBrokerConfig");
// Tạo config mới
var newConfig = await _configService.CreateConfigAsync(
configType: "MyConfig",
variables: variables,
description: "My configuration"
);
// Cập nhật config
await _configService.UpdateConfigAsync(id, variables, description);
// Xóa config
await _configService.DeleteConfigAsync(id);
// Import từ file
using var stream = File.OpenRead("config.json");
var imported = await _configService.ImportConfigAsync(stream, "config.json", "MyConfig");
// Export ra file
var exportStream = await _configService.ExportConfigAsync(id);
// Cập nhật variable
await _configService.UpdateVariableAsync(id, "port", 8080);
// Thêm variable
await _configService.AddVariableAsync(id, newVariable);
// Xóa variable
await _configService.RemoveVariableAsync(id, "variableName");
🎨 Hướng dẫn sử dụng Frontend
Sử dụng Component
Tạo page mới hoặc thêm vào page hiện có:
@page "/config-manager"
@using RobotNet10.CustomConfigurationEditor.Components.ConfigManager
<ConfigManagerComponent />
Sử dụng ConfigManagerState
Inject ConfigManagerState vào component của bạn:
@inject ConfigManagerState State
<MudButton OnClick="LoadConfigs">Load Configs</MudButton>
@code {
protected override async Task OnInitializedAsync()
{
await State.LoadConfigsAsync();
}
private async Task LoadConfigs()
{
await State.LoadConfigsAsync();
}
}
Các phương thức State
// Load tất cả configs
await State.LoadConfigsAsync();
// Load với search query
await State.LoadConfigsAsync("MQTT");
// Load config theo ID
await State.LoadConfigByIdAsync(id);
// Load config theo ConfigType
await State.LoadConfigByTypeAsync("MQTTBrokerConfig");
// Select config
await State.SelectConfigAsync(configMetadata);
// Tạo config mới
var config = await State.CreateConfigAsync(
configType: "MyConfig",
variables: variables,
description: "My config"
);
// Cập nhật config
await State.UpdateConfigAsync(variables, description);
// Xóa config
await State.DeleteConfigAsync(id);
// Import config
using var stream = file.OpenReadStream();
var imported = await State.ImportConfigAsync(stream, file.Name, "MyConfig");
// Export config
var stream = await State.ExportConfigAsync(id);
// Cập nhật variable
await State.UpdateVariableAsync("port", 8080);
// Thêm variable
await State.AddVariableAsync(newVariable);
// Xóa variable
await State.RemoveVariableAsync("variableName");
📄 Format JSON Config
Cấu trúc cơ bản
File config là một mảng JSON chứa các variable:
[
{
"name": "port",
"type": "int",
"value": 8080,
"Min": 0,
"Max": 65535,
"Roles": ""
},
{
"name": "host",
"type": "string",
"value": "localhost",
"Roles": ""
},
{
"name": "enableSSL",
"type": "bool",
"value": true,
"Roles": ""
}
]
Các kiểu dữ liệu hỗ trợ
1. String
{
"name": "host",
"type": "string",
"value": "localhost",
"Roles": ""
}
2. Int
{
"name": "port",
"type": "int",
"value": 8080,
"Min": 0,
"Max": 65535,
"Roles": ""
}
3. Double
{
"name": "timeout",
"type": "double",
"value": 30.5,
"Min": 0.0,
"Max": 100.0,
"Roles": ""
}
4. Bool
{
"name": "enableSSL",
"type": "bool",
"value": true,
"Roles": ""
}
5. Enum
{
"name": "logLevel",
"type": "enum",
"value": "Info",
"EnumValues": ["Debug", "Info", "Warning", "Error"],
"Roles": ""
}
6. Object
{
"name": "database",
"type": "object",
"value": {
"host": "localhost",
"port": 5432,
"name": "mydb"
},
"Roles": ""
}
7. Array
{
"name": "allowedIPs",
"type": "array",
"value": ["192.168.1.1", "192.168.1.2", "10.0.0.1"],
"Roles": ""
}
Các thuộc tính
| Thuộc tính | Bắt buộc | Mô tả |
|---|---|---|
name |
✅ | Tên của variable (duy nhất trong config) |
type |
✅ | Kiểu dữ liệu: string, int, double, bool, enum, object, array |
value |
✅ | Giá trị của variable |
Min |
❌ | Giá trị tối thiểu (cho int và double) |
Max |
❌ | Giá trị tối đa (cho int và double) |
EnumValues |
❌ | Danh sách giá trị cho phép (cho enum) |
Roles |
❌ | Roles string (có thể để trống) |
🔌 API Endpoints
Config File Management
GET /api/configs
Lấy tất cả configs (metadata only)
Query Parameters:
search(optional): Tìm kiếm theo tên hoặc ConfigType
Response: 200 OK
[
{
"id": "guid",
"configType": "MQTTBrokerConfig",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"description": "MQTT Broker Configuration"
}
]
GET /api/configs/{id}
Lấy config theo ID
Response: 200 OK
{
"id": "guid",
"configType": "MQTTBrokerConfig",
"variables": [...],
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"description": "MQTT Broker Configuration"
}
GET /api/configs/by-type/{configType}
Lấy config theo ConfigType
Response: 200 OK (same as GET by ID)
GET /api/configs/exists/{configType}
Kiểm tra ConfigType có tồn tại không
Response: 200 OK
true
POST /api/configs
Tạo config mới
Request Body:
{
"configType": "MyConfig",
"variables": [
{
"name": "port",
"type": "int",
"value": 8080
}
],
"description": "My configuration"
}
Response: 201 Created
PUT /api/configs/{id}
Cập nhật config
Request Body:
{
"variables": [...],
"description": "Updated description"
}
Response: 200 OK
DELETE /api/configs/{id}
Xóa config
Response: 204 No Content
Import/Export
POST /api/configs/import
Import config từ JSON file
Request: multipart/form-data
file: JSON fileconfigType: ConfigType name
Response: 200 OK
GET /api/configs/{id}/export
Export config ra JSON file
Response: 200 OK (application/json)
Variable Management
PUT /api/configs/{id}/variables/{variableName}
Cập nhật giá trị variable
Request Body:
{
"variableName": "port",
"value": 8080
}
Response: 200 OK
POST /api/configs/{id}/variables
Thêm variable mới
Request Body:
{
"name": "newVariable",
"type": "string",
"value": "value"
}
Response: 200 OK
DELETE /api/configs/{id}/variables/{variableName}
Xóa variable
Response: 200 OK
💡 Ví dụ sử dụng
Ví dụ 1: Tạo MQTT Broker Config
var variables = new List<ConfigVariable>
{
new ConfigVariable
{
Name = "host",
Type = ConfigVariableType.String,
Value = "localhost"
},
new ConfigVariable
{
Name = "port",
Type = ConfigVariableType.Int,
Value = 1883,
Min = 0,
Max = 65535
},
new ConfigVariable
{
Name = "enableSSL",
Type = ConfigVariableType.Bool,
Value = false
}
};
var config = await _configService.CreateConfigAsync(
configType: "MQTTBrokerConfig",
variables: variables,
description: "MQTT Broker Configuration"
);
Ví dụ 2: Import Config từ File
using var stream = File.OpenRead("mqtt-config.json");
var config = await _configService.ImportConfigAsync(
stream: stream,
fileName: "mqtt-config.json",
configType: "MQTTBrokerConfig"
);
Ví dụ 3: Sử dụng Config trong Service
public class MqttService
{
private readonly IConfigService _configService;
public MqttService(IConfigService configService)
{
_configService = configService;
}
public async Task ConnectAsync()
{
var config = await _configService.GetConfigByTypeAsync("MQTTBrokerConfig");
var host = config.Variables.First(v => v.Name == "host").Value?.ToString();
var port = (int)config.Variables.First(v => v.Name == "port").Value!;
// Connect to MQTT broker using host and port
}
}
Ví dụ 4: Cập nhật Variable qua API
// C# HttpClient
var client = new HttpClient();
var request = new
{
variableName = "port",
value = 8883
};
var response = await client.PutAsJsonAsync(
"https://api.example.com/api/configs/{id}/variables/port",
request
);
Ví dụ 5: Frontend - Sử dụng Component
@page "/settings/config"
@using RobotNet10.CustomConfigurationEditor.Components.ConfigManager
<PageTitle>Configuration Manager</PageTitle>
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="mt-4">
<ConfigManagerComponent />
</MudContainer>
🔧 Troubleshooting
Lỗi: "ConfigType already exists"
Nguyên nhân: ConfigType đã tồn tại trong hệ thống.
Giải pháp:
- Sử dụng ConfigType khác
- Xóa config cũ trước khi tạo mới
- Kiểm tra bằng
ConfigTypeExistsAsync()trước khi tạo
Lỗi: "Invalid variable type"
Nguyên nhân: Type của variable không hợp lệ.
Giải pháp:
- Kiểm tra type là một trong:
string,int,double,bool,enum,object,array - Đảm bảo value phù hợp với type
Lỗi: "Value out of range"
Nguyên nhân: Giá trị vượt quá Min/Max.
Giải pháp:
- Kiểm tra giá trị nằm trong khoảng Min và Max
- Cập nhật Min/Max nếu cần
Lỗi: "Invalid JSON format"
Nguyên nhân: File JSON không đúng format.
Giải pháp:
- Kiểm tra file là mảng JSON hợp lệ
- Đảm bảo mỗi variable có
name,type,value - Validate JSON trước khi import
Lỗi: "StorageManager not initialized"
Nguyên nhân: StorageConfig chưa được cấu hình.
Giải pháp:
- Đảm bảo đã gọi
AddCustomConfiguration()trongProgram.cs - Kiểm tra
StorageConfigtrongappsettings.json
Frontend: Component không hiển thị
Nguyên nhân: Services chưa được đăng ký.
Giải pháp:
- Kiểm tra đã đăng ký
ConfigApiServicevàConfigManagerState - Đảm bảo có
HttpClientvớiBaseAddress - Kiểm tra đã có
MudBlazorservices
Frontend: Export không hoạt động
Nguyên nhân: JavaScript file chưa được thêm.
Giải pháp:
- Copy
downloadFile.jsvàowwwroot/js/ - Thêm script tag vào
index.htmlhoặcApp.razor
📝 Lưu ý
- ConfigType là duy nhất: Mỗi ConfigType chỉ có thể tồn tại một lần trong hệ thống
- Validation: Tất cả dữ liệu đều được validate trước khi lưu
- Storage: Config files được lưu trong
configs/{ConfigType}.jsontrong StorageManager - Metadata: Metadata được lưu trong
configs/_metadata.json - Thread Safety: Services được đăng ký là
Scoped, phù hợp cho web applications
📚 Tài liệu tham khảo
🤝 Đóng góp
Nếu bạn phát hiện lỗi hoặc có đề xuất cải thiện, vui lòng tạo issue hoặc pull request.
📄 License
[Thêm thông tin license nếu có]