如何在Controller的Action执行前自动填充模型的OwnerId与CreatedBy属性?
自动填充输入模型属性的可行方案
针对你需要批量为输入模型的OwnerId和CreatedBy属性自动赋值的需求,推荐以下几种实用方案:
方案一:Action全局过滤器(推荐)
通过自定义Action过滤器,在Action执行前自动识别目标模型并填充属性,适合批量处理所有Action。
步骤1:定义标记接口(可选但更高效)
创建接口标识需要填充属性的模型,避免反射开销:
public interface IHasAuditProperties { int OwnerId { get; set; } DateTime CreatedBy { get; set; } }
让你的输入模型实现该接口:
public class PackingListProductFromSalePermitInput : IHasAuditProperties { // 其他业务属性 public int OwnerId { get; set; } public DateTime CreatedBy { get; set; } }
步骤2:实现Action过滤器
public class AuditPropertiesFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { // 遍历所有Action参数 foreach (var paramValue in context.ActionArguments.Values) { if (paramValue is IHasAuditProperties auditModel) { // 这里替换为实际获取OwnerId的逻辑(比如从当前用户Claims读取) auditModel.OwnerId = 10; // 填充创建时间(建议用UtcNow统一时区) auditModel.CreatedBy = DateTime.UtcNow; } } } public void OnActionExecuted(ActionExecutedContext context) { // 无需处理执行后逻辑 } }
步骤3:注册全局过滤器
在Program.cs中注册过滤器,让所有Action生效:
builder.Services.AddControllers(options => { options.Filters.Add<AuditPropertiesFilter>(); // 若只想给特定控制器/Action生效,可在对应位置加[ServiceFilter(typeof(AuditPropertiesFilter))] });
最终效果
Action中无需手动赋值,属性已自动填充:
[HttpPost] public async Task<bool> ExportPackingListProductBulkInsert(PackingListProductFromSalePermitInput input) { // input.OwnerId和CreatedBy已自动赋值 // 执行插入逻辑 return await Task.FromResult(true); }
方案二:自定义模型绑定器
如果需要在模型绑定阶段就完成属性填充(更早的生命周期),可以使用自定义模型绑定器:
实现绑定器及提供器
public class AuditModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { if (context.Metadata.ModelType.GetInterface(nameof(IHasAuditProperties)) != null) { return new AuditModelBinder(); } return null; } } public class AuditModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext.Model is IHasAuditProperties auditModel) { auditModel.OwnerId = 10; auditModel.CreatedBy = DateTime.UtcNow; } return Task.CompletedTask; } }
注册绑定器
builder.Services.AddControllers(options => { options.ModelBinderProviders.Insert(0, new AuditModelBinderProvider()); });
方案三:反射兼容方案(无需修改模型)
如果无法给现有模型添加接口,可以通过反射直接检查属性并赋值:
public class AuditPropertiesFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { foreach (var paramValue in context.ActionArguments.Values) { if (paramValue == null) continue; var ownerIdProp = paramValue.GetType().GetProperty("OwnerId"); var createdByProp = paramValue.GetType().GetProperty("CreatedBy"); if (ownerIdProp != null && ownerIdProp.PropertyType == typeof(int)) { ownerIdProp.SetValue(paramValue, 10); } if (createdByProp != null && createdByProp.PropertyType == typeof(DateTime)) { createdByProp.SetValue(paramValue, DateTime.UtcNow); } } } public void OnActionExecuted(ActionExecutedContext context) { } }
内容的提问来源于stack exchange,提问作者Sasan
相关产品推荐
相关产品推荐

