如何在MVC视图模型的自定义验证器中获取当前Action名称?
获取共享视图模型对应的当前Action名称(自定义验证器场景)
当然可以!不管你用的是ASP.NET Core还是传统ASP.NET MVC,都能在自定义验证器里拿到当前触发的Action名称,下面分场景给你具体实现方案:
ASP.NET Core 场景
方法1:通过 ActionContextAccessor 自动获取
首先得在项目的服务容器里注册这个访问器(.NET 6+ 在 Program.cs,老版本在 Startup.cs):
// .NET 6+ Program.cs builder.Services.AddHttpContextAccessor(); builder.Services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
然后在你的自定义验证器里,直接从验证上下文里获取这个服务,就能拿到Action名称了:
public class MyCustomValidator : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 从验证上下文获取ActionContextAccessor var actionContextAccessor = validationContext.GetService<IActionContextAccessor>(); if (actionContextAccessor?.ActionContext == null) { return ValidationResult.Success; } // 精准获取Action名称(从路由值里拿) var currentAction = actionContextAccessor.ActionContext.ActionDescriptor.RouteValues["action"]; // 这里根据Action名称写你的验证逻辑 if (currentAction == "Create" && value == null) { return new ValidationResult("创建操作时该字段不能为空"); } return ValidationResult.Success; } }
方法2:手动传递Action名称到视图模型
如果不想依赖框架上下文,也可以在Controller的Action里手动把当前Action名称赋值给视图模型的一个属性:
// 先给视图模型加个属性 public class SharedViewModel { public string CurrentAction { get; set; } // 其他共享属性... } // 在Controller的Action里赋值 public IActionResult Create(SharedViewModel model) { model.CurrentAction = "Create"; if (ModelState.IsValid) { // 业务逻辑... } return View(model); } // 自定义验证器里直接用这个属性 public class MyCustomValidator : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var model = validationContext.ObjectInstance as SharedViewModel; if (model?.CurrentAction == "Create" && value == null) { return new ValidationResult("创建操作时该字段不能为空"); } return ValidationResult.Success; } }
传统ASP.NET MVC 场景
在老版本MVC里,可以通过HttpContextBase获取路由数据里的Action名称:
public class MyCustomValidator : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 获取HttpContext var httpContext = validationContext.GetService(typeof(HttpContextBase)) as HttpContextBase; if (httpContext == null) { return ValidationResult.Success; } // 从路由数据里拿Action名称 var currentAction = httpContext.Request.RequestContext.RouteData.Values["action"].ToString(); // 验证逻辑 if (currentAction == "Edit" && value == null) { return new ValidationResult("编辑操作时该字段不能为空"); } return ValidationResult.Success; } }
额外:FluentValidation 场景
如果你用的是FluentValidation做验证,同样可以注入ActionContextAccessor来获取Action名称:
public class SharedViewModelValidator : AbstractValidator<SharedViewModel> { private readonly IActionContextAccessor _actionContextAccessor; public SharedViewModelValidator(IActionContextAccessor actionContextAccessor) { _actionContextAccessor = actionContextAccessor; RuleFor(x => x.MyProperty) .NotEmpty() .When(_ => { var currentAction = _actionContextAccessor.ActionContext?.ActionDescriptor.RouteValues["action"]; return currentAction == "Create"; }); } }
简单总结下:自动获取的方式更省心,适合大多数场景;手动传递的方式更可控,避免依赖框架上下文。你可以根据自己的项目情况选最合适的方案~
内容的提问来源于stack exchange,提问作者Thorkil Værge
相关产品推荐
相关产品推荐

