A:调整部分日志;增加Client对于依赖注入的支持
This commit is contained in:
1 parent
2739a71134
commit
e1d059ed29
12 files changed
+143
-39
No files matched your search
@@ -10,3 +10,7 @@
|
|||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</Application.Resources>
|
</Application.Resources>
|
||||||
</Application>
|
</Application>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -2,7 +2,9 @@ using System;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using Client.Services;
|
using Client.Services;
|
||||||
using Client.ViewModels;
|
using Client.ViewModels;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Common;
|
using Common;
|
||||||
using Config;
|
using Config;
|
||||||
@@ -10,6 +12,7 @@ using NetClient.DependencyInjection;
|
|||||||
using Sharp.Infrastructure.Configuration;
|
using Sharp.Infrastructure.Configuration;
|
||||||
using Sharp.Log.Extensions;
|
using Sharp.Log.Extensions;
|
||||||
using Sharp.NetServer.DependencyInjection;
|
using Sharp.NetServer.DependencyInjection;
|
||||||
|
using Sharp.Wpf.Exceptions;
|
||||||
using Sharp.Wpf.Services;
|
using Sharp.Wpf.Services;
|
||||||
|
|
||||||
namespace Client
|
namespace Client
|
||||||
@@ -24,7 +27,7 @@ namespace Client
|
|||||||
protected override void OnStartup(StartupEventArgs e)
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnStartup(e);
|
base.OnStartup(e);
|
||||||
|
|
||||||
// 1) Build configuration manager from appsettings.json (+ reload on change + env vars)
|
// 1) Build configuration manager from appsettings.json (+ reload on change + env vars)
|
||||||
var cm = ConfigBuilder.BuildFromFiles(new[] { "appsettings.json" }, reloadOnChange: true, includeEnvironment: true, basePath: AppContext.BaseDirectory);
|
var cm = ConfigBuilder.BuildFromFiles(new[] { "appsettings.json" }, reloadOnChange: true, includeEnvironment: true, basePath: AppContext.BaseDirectory);
|
||||||
|
|
||||||
@@ -33,6 +36,7 @@ namespace Client
|
|||||||
|
|
||||||
// ConfigManager and typed SystemConfig accessor
|
// ConfigManager and typed SystemConfig accessor
|
||||||
services.AddSingleton(cm);
|
services.AddSingleton(cm);
|
||||||
|
services.TryAddSingleton<IConfiguration>(cm.Configuration); // Register IConfiguration for BindConfiguration
|
||||||
services.AddSystemConfig(cm);
|
services.AddSystemConfig(cm);
|
||||||
|
|
||||||
// Logging (binds from section "SharpLog")
|
// Logging (binds from section "SharpLog")
|
||||||
@@ -42,6 +46,9 @@ namespace Client
|
|||||||
services.AddNetClient(cm);
|
services.AddNetClient(cm);
|
||||||
services.AddNetServer(cm);
|
services.AddNetServer(cm);
|
||||||
|
|
||||||
|
// WPF exception handler
|
||||||
|
services.AddSingleton<IUiExceptionHandler, UiExceptionHandler>();
|
||||||
|
|
||||||
// WPF app services
|
// WPF app services
|
||||||
services.AddSingleton<IDialogService, DialogService>();
|
services.AddSingleton<IDialogService, DialogService>();
|
||||||
services.AddSingleton<IAuthenticationService, DemoAuthenticationService>();
|
services.AddSingleton<IAuthenticationService, DemoAuthenticationService>();
|
||||||
@@ -54,22 +61,32 @@ namespace Client
|
|||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
_serviceProvider = services.BuildServiceProvider();
|
||||||
|
|
||||||
// 3) Register global facades for convenience
|
// 3) Activate global WPF exception handler
|
||||||
|
var exceptionHandler = _serviceProvider.GetRequiredService<IUiExceptionHandler>();
|
||||||
|
exceptionHandler.Register();
|
||||||
|
|
||||||
|
// 4) Register global facades for convenience
|
||||||
Global.RegisterSingleton(_serviceProvider);
|
Global.RegisterSingleton(_serviceProvider);
|
||||||
Global.RegisterSingleton(cm);
|
Global.RegisterSingleton(cm);
|
||||||
Global.RegisterSingleton(_serviceProvider.GetRequiredService<ISystemConfigAccessor>());
|
Global.RegisterSingleton(_serviceProvider.GetRequiredService<ISystemConfigAccessor>());
|
||||||
|
|
||||||
// 4) Show login window first, then main shell if authenticated
|
// 5) Show login window first, then main shell if authenticated
|
||||||
|
var logger = _serviceProvider.GetRequiredService<ILogger<App>>();
|
||||||
|
logger.LogInformation("Showing login window");
|
||||||
var loginWindow = _serviceProvider.GetRequiredService<LoginWindow>();
|
var loginWindow = _serviceProvider.GetRequiredService<LoginWindow>();
|
||||||
var loginResult = loginWindow.ShowDialog();
|
var loginResult = loginWindow.ShowDialog();
|
||||||
|
|
||||||
|
logger.LogInformation("Login window closed with result: {LoginResult}", loginResult);
|
||||||
|
|
||||||
if (loginResult == true)
|
if (loginResult == true)
|
||||||
{
|
{
|
||||||
|
logger.LogInformation("Login successful, showing main window");
|
||||||
var main = _serviceProvider.GetRequiredService<MainWindow>();
|
var main = _serviceProvider.GetRequiredService<MainWindow>();
|
||||||
main.Show();
|
main.Show();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
logger.LogInformation("Login cancelled or failed, shutting down application");
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,4 +97,4 @@ namespace Client
|
|||||||
base.OnExit(e);
|
base.OnExit(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,27 @@
|
|||||||
using System;
|
using System;
|
||||||
using HandyControl.Controls;
|
using HandyControl.Controls;
|
||||||
using Client.ViewModels;
|
using Client.ViewModels;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Client;
|
namespace Client;
|
||||||
|
|
||||||
public partial class LoginWindow : GlowWindow
|
public partial class LoginWindow : GlowWindow
|
||||||
{
|
{
|
||||||
private readonly LoginViewModel _viewModel;
|
private readonly LoginViewModel _viewModel;
|
||||||
|
private readonly ILogger<LoginWindow>? _logger;
|
||||||
|
|
||||||
public LoginWindow(LoginViewModel viewModel)
|
public LoginWindow(LoginViewModel viewModel, ILogger<LoginWindow>? logger = null)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_viewModel = viewModel;
|
_viewModel = viewModel;
|
||||||
|
_logger = logger;
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
_viewModel.LoginSucceeded += HandleLoginSucceeded;
|
_viewModel.LoginSucceeded += HandleLoginSucceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleLoginSucceeded(object? sender, EventArgs e)
|
private void HandleLoginSucceeded(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
_logger?.LogInformation("HandleLoginSucceeded called, setting DialogResult = true");
|
||||||
DialogResult = true;
|
DialogResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Client.Services;
|
using Client.Services;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Sharp.Wpf.Commands;
|
using Sharp.Wpf.Commands;
|
||||||
using Sharp.Wpf.Mvvm;
|
using Sharp.Wpf.Mvvm;
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ public sealed class LoginViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
private readonly IAuthenticationService _authenticationService;
|
private readonly IAuthenticationService _authenticationService;
|
||||||
private readonly IUserSession _userSession;
|
private readonly IUserSession _userSession;
|
||||||
|
private readonly ILogger<LoginViewModel> _logger;
|
||||||
private readonly IAsyncCommand _loginCommand;
|
private readonly IAsyncCommand _loginCommand;
|
||||||
|
|
||||||
private string _userName = "admin";
|
private string _userName = "admin";
|
||||||
@@ -18,10 +20,11 @@ public sealed class LoginViewModel : ViewModelBase
|
|||||||
|
|
||||||
public event EventHandler? LoginSucceeded;
|
public event EventHandler? LoginSucceeded;
|
||||||
|
|
||||||
public LoginViewModel(IAuthenticationService authenticationService, IUserSession userSession)
|
public LoginViewModel(IAuthenticationService authenticationService, IUserSession userSession, ILogger<LoginViewModel> logger)
|
||||||
{
|
{
|
||||||
_authenticationService = authenticationService;
|
_authenticationService = authenticationService;
|
||||||
_userSession = userSession;
|
_userSession = userSession;
|
||||||
|
_logger = logger;
|
||||||
_loginCommand = new AsyncCommand(LoginAsync);
|
_loginCommand = new AsyncCommand(LoginAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,20 +70,29 @@ public sealed class LoginViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation("Login attempt for user: {UserName}", UserName);
|
||||||
IsBusy = true;
|
IsBusy = true;
|
||||||
ErrorMessage = null;
|
ErrorMessage = null;
|
||||||
|
|
||||||
var result = await _authenticationService.LoginAsync(UserName, Password).ConfigureAwait(false);
|
var result = await _authenticationService.LoginAsync(UserName, Password);
|
||||||
|
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning("Login failed for user: {UserName}, Error: {Error}", UserName, result.Error);
|
||||||
ErrorMessage = result.Error;
|
ErrorMessage = result.Error;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Login succeeded for user: {UserName}", UserName);
|
||||||
_userSession.SignIn(UserName, result.DisplayName);
|
_userSession.SignIn(UserName, result.DisplayName);
|
||||||
|
_logger.LogInformation("Invoking LoginSucceeded event");
|
||||||
LoginSucceeded?.Invoke(this, EventArgs.Empty);
|
LoginSucceeded?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Login failed for user: {UserName}", UserName);
|
||||||
|
ErrorMessage = "An unexpected error occurred.";
|
||||||
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
IsBusy = false;
|
IsBusy = false;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Data.OleDb;
|
using System.Data.OleDb;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Sharp.Data.Access.Connections;
|
using Sharp.Data.Access.Connections;
|
||||||
@@ -223,7 +224,11 @@ public class AccessDataService : IAccessDataService
|
|||||||
|
|
||||||
using var command = new OleDbCommand(sql, connection);
|
using var command = new OleDbCommand(sql, connection);
|
||||||
if (parameters.Length > 0)
|
if (parameters.Length > 0)
|
||||||
command.Parameters.AddRange(parameters);
|
{
|
||||||
|
// 克隆参数以避免重试时的"已包含在另一个集合中"错误
|
||||||
|
var clonedParams = parameters.Select(p => CloneParameter(p)).ToArray();
|
||||||
|
command.Parameters.AddRange(clonedParams);
|
||||||
|
}
|
||||||
|
|
||||||
var results = new List<T>();
|
var results = new List<T>();
|
||||||
using var reader = command.ExecuteReader();
|
using var reader = command.ExecuteReader();
|
||||||
@@ -250,7 +255,11 @@ public class AccessDataService : IAccessDataService
|
|||||||
|
|
||||||
using var command = new OleDbCommand(sql, connection);
|
using var command = new OleDbCommand(sql, connection);
|
||||||
if (parameters.Length > 0)
|
if (parameters.Length > 0)
|
||||||
command.Parameters.AddRange(parameters);
|
{
|
||||||
|
// 克隆参数以避免重试时的"已包含在另一个集合中"错误
|
||||||
|
var clonedParams = parameters.Select(p => CloneParameter(p)).ToArray();
|
||||||
|
command.Parameters.AddRange(clonedParams);
|
||||||
|
}
|
||||||
|
|
||||||
using var reader = command.ExecuteReader();
|
using var reader = command.ExecuteReader();
|
||||||
|
|
||||||
@@ -274,7 +283,11 @@ public class AccessDataService : IAccessDataService
|
|||||||
|
|
||||||
using var command = new OleDbCommand(sql, connection);
|
using var command = new OleDbCommand(sql, connection);
|
||||||
if (parameters.Length > 0)
|
if (parameters.Length > 0)
|
||||||
command.Parameters.AddRange(parameters);
|
{
|
||||||
|
// 克隆参数以避免重试时的"已包含在另一个集合中"错误
|
||||||
|
var clonedParams = parameters.Select(p => CloneParameter(p)).ToArray();
|
||||||
|
command.Parameters.AddRange(clonedParams);
|
||||||
|
}
|
||||||
|
|
||||||
var result = command.ExecuteScalar();
|
var result = command.ExecuteScalar();
|
||||||
_logger?.LogDebug("标量查询返回: {Result}", result);
|
_logger?.LogDebug("标量查询返回: {Result}", result);
|
||||||
@@ -293,7 +306,11 @@ public class AccessDataService : IAccessDataService
|
|||||||
|
|
||||||
using var command = new OleDbCommand(sql, connection);
|
using var command = new OleDbCommand(sql, connection);
|
||||||
if (parameters.Length > 0)
|
if (parameters.Length > 0)
|
||||||
command.Parameters.AddRange(parameters);
|
{
|
||||||
|
// 克隆参数以避免重试时的"已包含在另一个集合中"错误
|
||||||
|
var clonedParams = parameters.Select(p => CloneParameter(p)).ToArray();
|
||||||
|
command.Parameters.AddRange(clonedParams);
|
||||||
|
}
|
||||||
|
|
||||||
var rowsAffected = command.ExecuteNonQuery();
|
var rowsAffected = command.ExecuteNonQuery();
|
||||||
_logger?.LogDebug("命令影响了 {RowsAffected} 行", rowsAffected);
|
_logger?.LogDebug("命令影响了 {RowsAffected} 行", rowsAffected);
|
||||||
@@ -403,6 +420,27 @@ public class AccessDataService : IAccessDataService
|
|||||||
return ex.ErrorCode == -2147467259 || ex.ErrorCode == -2147217865;
|
return ex.ErrorCode == -2147467259 || ex.ErrorCode == -2147217865;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 克隆 OleDbParameter 以避免重试时参数被重复添加的问题
|
||||||
|
/// </summary>
|
||||||
|
private static OleDbParameter CloneParameter(OleDbParameter original)
|
||||||
|
{
|
||||||
|
var clone = new OleDbParameter
|
||||||
|
{
|
||||||
|
ParameterName = original.ParameterName,
|
||||||
|
Value = original.Value,
|
||||||
|
OleDbType = original.OleDbType,
|
||||||
|
Size = original.Size,
|
||||||
|
Direction = original.Direction,
|
||||||
|
IsNullable = original.IsNullable,
|
||||||
|
Precision = original.Precision,
|
||||||
|
Scale = original.Scale,
|
||||||
|
SourceColumn = original.SourceColumn,
|
||||||
|
SourceVersion = original.SourceVersion
|
||||||
|
};
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
private static T MapReaderToObject<T>(IDataReader reader) where T : new()
|
private static T MapReaderToObject<T>(IDataReader reader) where T : new()
|
||||||
{
|
{
|
||||||
var obj = new T();
|
var obj = new T();
|
||||||
|
|||||||
@@ -294,9 +294,20 @@ public class HttpServer
|
|||||||
var controller = _serviceProvider.GetService(controllerType);
|
var controller = _serviceProvider.GetService(controllerType);
|
||||||
if (controller != null)
|
if (controller != null)
|
||||||
return controller;
|
return controller;
|
||||||
|
|
||||||
|
// 使用 ActivatorUtilities 创建实例(可以解析构造函数参数)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ActivatorUtilities.CreateInstance(_serviceProvider, controllerType);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger?.LogError(ex, "Failed to create controller {ControllerType} with DI", controllerType.Name);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用激活器创建
|
// 没有 DI 容器时,使用默认激活器创建(需要无参构造)
|
||||||
return Activator.CreateInstance(controllerType)!;
|
return Activator.CreateInstance(controllerType)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ namespace Server.Controllers
|
|||||||
public async Task GetAll(HttpContext context)
|
public async Task GetAll(HttpContext context)
|
||||||
{
|
{
|
||||||
var items = _dataStore.Values.ToList();
|
var items = _dataStore.Values.ToList();
|
||||||
var result = ResultExtensions.HttpSuccess(new
|
var data = new
|
||||||
{
|
{
|
||||||
Count = items.Count,
|
Count = items.Count,
|
||||||
Items = items
|
Items = items
|
||||||
});
|
};
|
||||||
|
|
||||||
await WriteSuccessResponseAsync(context, result);
|
await WriteSuccessResponseAsync(context, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -49,8 +49,7 @@ namespace Server.Controllers
|
|||||||
|
|
||||||
if (_dataStore.TryGetValue(id, out var item))
|
if (_dataStore.TryGetValue(id, out var item))
|
||||||
{
|
{
|
||||||
var result = ResultExtensions.HttpSuccess(item);
|
await WriteSuccessResponseAsync(context, item);
|
||||||
await WriteSuccessResponseAsync(context, result);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -87,8 +86,7 @@ namespace Server.Controllers
|
|||||||
|
|
||||||
_dataStore[id] = item;
|
_dataStore[id] = item;
|
||||||
|
|
||||||
var result = ResultExtensions.HttpSuccess(item, "Data created successfully");
|
await WriteSuccessResponseAsync(context, item, "Data created successfully");
|
||||||
await WriteSuccessResponseAsync(context, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -129,8 +127,7 @@ namespace Server.Controllers
|
|||||||
item.UpdatedAt = DateTime.UtcNow;
|
item.UpdatedAt = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = ResultExtensions.HttpSuccess(item, "Data updated successfully");
|
await WriteSuccessResponseAsync(context, item, "Data updated successfully");
|
||||||
await WriteSuccessResponseAsync(context, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -150,8 +147,7 @@ namespace Server.Controllers
|
|||||||
|
|
||||||
if (_dataStore.TryRemove(id, out var item))
|
if (_dataStore.TryRemove(id, out var item))
|
||||||
{
|
{
|
||||||
var result = ResultExtensions.HttpSuccess(item, "Data deleted successfully");
|
await WriteSuccessResponseAsync(context, item, "Data deleted successfully");
|
||||||
await WriteSuccessResponseAsync(context, result);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -169,8 +165,8 @@ namespace Server.Controllers
|
|||||||
var count = _dataStore.Count;
|
var count = _dataStore.Count;
|
||||||
_dataStore.Clear();
|
_dataStore.Clear();
|
||||||
|
|
||||||
var result = ResultExtensions.HttpSuccess(new { DeletedCount = count }, "All data cleared");
|
var data = new { DeletedCount = count };
|
||||||
await WriteSuccessResponseAsync(context, result);
|
await WriteSuccessResponseAsync(context, data, "All data cleared");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,14 +19,14 @@ namespace Server.Controllers
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task Check(HttpContext context)
|
public async Task Check(HttpContext context)
|
||||||
{
|
{
|
||||||
var result = ResultExtensions.HttpSuccess(new
|
var data = new
|
||||||
{
|
{
|
||||||
Status = "Healthy",
|
Status = "Healthy",
|
||||||
Timestamp = DateTime.UtcNow,
|
Timestamp = DateTime.UtcNow,
|
||||||
Uptime = DateTime.UtcNow - Process.GetCurrentProcess().StartTime
|
Uptime = DateTime.UtcNow - Process.GetCurrentProcess().StartTime
|
||||||
});
|
};
|
||||||
|
|
||||||
await WriteSuccessResponseAsync(context, result);
|
await WriteSuccessResponseAsync(context, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -37,7 +37,7 @@ namespace Server.Controllers
|
|||||||
public async Task DetailedCheck(HttpContext context)
|
public async Task DetailedCheck(HttpContext context)
|
||||||
{
|
{
|
||||||
var process = Process.GetCurrentProcess();
|
var process = Process.GetCurrentProcess();
|
||||||
var result = ResultExtensions.HttpSuccess(new
|
var data = new
|
||||||
{
|
{
|
||||||
Status = "Healthy",
|
Status = "Healthy",
|
||||||
Timestamp = DateTime.UtcNow,
|
Timestamp = DateTime.UtcNow,
|
||||||
@@ -60,9 +60,9 @@ namespace Server.Controllers
|
|||||||
},
|
},
|
||||||
Threads = process.Threads.Count
|
Threads = process.Threads.Count
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
await WriteSuccessResponseAsync(context, result);
|
await WriteSuccessResponseAsync(context, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Server.Controllers
|
|||||||
[HttpGet("/info")]
|
[HttpGet("/info")]
|
||||||
public async Task GetSystemInfo(HttpContext context)
|
public async Task GetSystemInfo(HttpContext context)
|
||||||
{
|
{
|
||||||
var result = ResultExtensions.HttpSuccess(new
|
var data = new
|
||||||
{
|
{
|
||||||
MachineName = Environment.MachineName,
|
MachineName = Environment.MachineName,
|
||||||
UserName = Environment.UserName,
|
UserName = Environment.UserName,
|
||||||
@@ -30,9 +30,9 @@ namespace Server.Controllers
|
|||||||
CurrentDirectory = Environment.CurrentDirectory,
|
CurrentDirectory = Environment.CurrentDirectory,
|
||||||
TickCount = Environment.TickCount64,
|
TickCount = Environment.TickCount64,
|
||||||
Version = Environment.Version.ToString()
|
Version = Environment.Version.ToString()
|
||||||
});
|
};
|
||||||
|
|
||||||
await WriteSuccessResponseAsync(context, result);
|
await WriteSuccessResponseAsync(context, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -59,7 +59,7 @@ namespace Server.Controllers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var successResult = ResultExtensions.HttpSuccess(new { Name = name, Value = value });
|
var successResult = new { Name = name, Value = value };
|
||||||
await WriteSuccessResponseAsync(context, successResult);
|
await WriteSuccessResponseAsync(context, successResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ namespace Server.Controllers
|
|||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var utcNow = DateTime.UtcNow;
|
var utcNow = DateTime.UtcNow;
|
||||||
|
|
||||||
var result = ResultExtensions.HttpSuccess(new
|
var data = new
|
||||||
{
|
{
|
||||||
Local = new
|
Local = new
|
||||||
{
|
{
|
||||||
@@ -89,9 +89,9 @@ namespace Server.Controllers
|
|||||||
Time = utcNow.TimeOfDay,
|
Time = utcNow.TimeOfDay,
|
||||||
UnixTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
UnixTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
await WriteSuccessResponseAsync(context, result);
|
await WriteSuccessResponseAsync(context, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public sealed class ExceptionHandlingOptions
|
|||||||
public bool RethrowAfterHandle { get; set; } = false;
|
public bool RethrowAfterHandle { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Custom logger hook.
|
/// 日志钩子.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<Exception>? Log { get; set; }
|
public Action<Exception>? Log { get; set; }
|
||||||
= ex => System.Diagnostics.Debug.WriteLine(ex.ToString());
|
= ex => System.Diagnostics.Debug.WriteLine(ex.ToString());
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace Sharp.Wpf.Exceptions;
|
namespace Sharp.Wpf.Exceptions;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using WpfMessageBox = System.Windows.MessageBox;
|
using WpfMessageBox = System.Windows.MessageBox;
|
||||||
|
|
||||||
@@ -35,6 +36,10 @@ public sealed class UiExceptionHandler : IUiExceptionHandler
|
|||||||
private void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
private void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
Handle(e.Exception);
|
Handle(e.Exception);
|
||||||
|
if (CanRecover(e.Exception))
|
||||||
|
{
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,4 +91,20 @@ public sealed class UiExceptionHandler : IUiExceptionHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected bool CanRecover(Exception exception)
|
||||||
|
{
|
||||||
|
return exception switch
|
||||||
|
{
|
||||||
|
ArgumentException => true,
|
||||||
|
InvalidOperationException => true,
|
||||||
|
HttpRequestException => true,
|
||||||
|
TimeoutException => true,
|
||||||
|
OutOfMemoryException => false,
|
||||||
|
StackOverflowException => false,
|
||||||
|
AccessViolationException => false,
|
||||||
|
_ => true
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user