以下是针对《工业上位机接口规范设计:RESTful API + JSON契约》的更多代码示例补充,主要覆盖 .NET 8/9 时代最常见的几种实现方式,以及实际工业项目中最常遇到的几种场景。
我将按以下分类给出更详细、可直接复制粘贴的示例代码:
1. 统一响应模型(推荐做法)
// ResponseBase.cs
public abstract class ResponseBase
{
public int Code { get; set; } = 0;
public string Message { get; set; } = "success";
public string TraceId { get; set; } = Activity.Current?.Id ?? Guid.NewGuid().ToString("N");
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}
// 成功响应
public class ApiResponse<T> : ResponseBase
{
public T? Data { get; set; }
public static ApiResponse<T> Success(T data) => new() { Data = data };
public static ApiResponse<T> Success() => new();
}
// 失败响应
public class ApiErrorResponse : ResponseBase
{
public List<ErrorDetail>? Errors { get; set; }
public static ApiErrorResponse Fail(int code, string message, List<ErrorDetail>? errors = null)
{
return new ApiErrorResponse
{
Code = code,
Message = message,
Errors = errors
};
}
}
public class ErrorDetail
{
public string? Field { get; set; }
public string? Reason { get; set; }
public object? Value { get; set; }
}
2. 全局异常处理中间件(推荐放在 Program.cs)
// ExceptionMiddleware.cs
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionMiddleware> _logger;
public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (ValidationException ex) // FluentValidation
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
var errors = ex.Errors.Select(e => new ErrorDetail
{
Field = e.PropertyName,
Reason = e.ErrorMessage,
Value = e.AttemptedValue
}).ToList();
await context.Response.WriteAsJsonAsync(ApiErrorResponse.Fail(1001, "参数校验失败", errors));
}
catch (BusinessException ex) // 自定义业务异常
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
await context.Response.WriteAsJsonAsync(ApiErrorResponse.Fail(ex.Code, ex.Message));
}
catch (Exception ex)
{
_logger.LogError(ex, "未处理的异常发生。TraceId: {TraceId}", Activity.Current?.Id);
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
await context.Response.WriteAsJsonAsync(ApiErrorResponse.Fail(9999, "服务器内部错误,请联系管理员"));
}
}
}
// Program.cs 中使用
app.UseMiddleware<ExceptionMiddleware>();
3. 控制器常用写法示例
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class DevicesController : ControllerBase
{
private readonly IDeviceService _deviceService;
private readonly IIdempotencyService _idempotencyService;
public DevicesController(IDeviceService deviceService, IIdempotencyService idempotencyService)
{
_deviceService = deviceService;
_idempotencyService = idempotencyService;
}
/// <summary>
/// 获取单台设备实时状态
/// </summary>
[HttpGet("{deviceId}/status")]
[ProducesResponseType(typeof(ApiResponse<DeviceStatusDto>), 200)]
[ProducesResponseType(typeof(ApiErrorResponse), 400)]
public async Task<IActionResult> GetStatus(string deviceId)
{
var status = await _deviceService.GetDeviceStatusAsync(deviceId);
return Ok(ApiResponse<DeviceStatusDto>.Success(status));
}
/// <summary>
/// 局部更新设备参数(幂等)
/// </summary>
[HttpPatch("{deviceId}/parameters")]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(ApiErrorResponse), 400)]
public async Task<IActionResult> UpdateParameters(string deviceId, [FromBody] UpdateDeviceParametersRequest request)
{
await _deviceService.UpdateParametersAsync(deviceId, request);
return NoContent();
}
/// <summary>
/// 下发生产指令(带幂等键)
/// </summary>
[HttpPost("commands")]
[ProducesResponseType(typeof(ApiResponse<CommandResult>), 200)]
[ProducesResponseType(typeof(ApiErrorResponse), 400)]
public async Task<IActionResult> IssueCommand([FromBody] IssueCommandRequest request)
{
// 检查幂等键
if (await _idempotencyService.ExistsAsync(request.IdempotencyKey))
{
var previous = await _idempotencyService.GetResultAsync(request.IdempotencyKey);
return Ok(ApiResponse<CommandResult>.Success(previous));
}
var result = await _deviceService.IssueCommandAsync(request);
// 记录幂等结果(建议异步 + 缓存/数据库)
await _idempotencyService.SaveResultAsync(request.IdempotencyKey, result, TimeSpan.FromDays(7));
return Ok(ApiResponse<CommandResult>.Success(result));
}
}
4. DTO 示例(带 FluentValidation 校验)
public class UpdateDeviceParametersRequest
{
public int? TargetSpeed { get; set; }
public bool? AutoMode { get; set; }
public string? RecipeId { get; set; }
}
public class UpdateDeviceParametersRequestValidator : AbstractValidator<UpdateDeviceParametersRequest>
{
public UpdateDeviceParametersRequestValidator()
{
RuleFor(x => x.TargetSpeed)
.InclusiveBetween(800, 3000).When(x => x.TargetSpeed.HasValue)
.WithMessage("目标速度必须在800-3000之间");
RuleFor(x => x.RecipeId)
.MaximumLength(50).When(x => !string.IsNullOrEmpty(x.RecipeId));
}
}
5. Swagger / OpenAPI 配置增强(Program.cs)
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "工业上位机 REST API",
Version = "v1.0",
Description = "工业现场上位机标准接口(RESTful + JSON契约)"
});
// 支持 ApiVersion
c.OperationFilter<AddApiVersionHeader>();
// JWT 示例
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "请输入 Bearer Token",
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
},
Array.Empty<string>()
}
});
});
6. 简单幂等中间件(可选,适合轻量项目)
public class IdempotencyMiddleware
{
private readonly RequestDelegate _next;
private readonly IIdempotencyService _idempotencyService;
public IdempotencyMiddleware(RequestDelegate next, IIdempotencyService idempotencyService)
{
_next = next;
_idempotencyService = idempotencyService;
}
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Method == HttpMethods.Post &&
context.Request.Headers.TryGetValue("Idempotency-Key", out var idempotencyKeyValues))
{
var key = idempotencyKeyValues.FirstOrDefault();
if (!string.IsNullOrEmpty(key) && await _idempotencyService.ExistsAsync(key))
{
var result = await _idempotencyService.GetResultAsync(key);
context.Response.StatusCode = StatusCodes.Status200OK;
await context.Response.WriteAsJsonAsync(result);
return;
}
}
await _next(context);
}
}
7. 客户端调用示例(Refit 接口定义)
public interface IDeviceApiClient
{
[Get("/api/v1/devices/{deviceId}/status")]
Task<ApiResponse<DeviceStatusDto>> GetDeviceStatus(string deviceId);
[Patch("/api/v1/devices/{deviceId}/parameters")]
Task UpdateParameters(string deviceId, [Body] UpdateDeviceParametersRequest request);
[Post("/api/v1/production/commands")]
[Headers("Idempotency-Key: {idempotencyKey}")]
Task<ApiResponse<CommandResult>> IssueCommand(string idempotencyKey, [Body] IssueCommandRequest request);
}
这些代码示例覆盖了目前工业上位机项目中最常见的 80% 场景。如果你需要某个具体接口的完整 Controller + Service + DTO + Validator 组合,或者想看 Golang / Python / Java 的对应实现,也可以继续告诉我,我可以继续补充。
网硕互联帮助中心







评论前必须登录!
注册