我目前正在创建一个类似于现有"Remote"属性的属性。客户端验证是通过javascipt调用一个操作来检查(针对我们的数据库)输入是否有效来进行的。问题是,当涉及到服务器端验证时,我无法确定如何调用该操作。"远程"属性没有帮助,因为"不进行服务器端验证"
没有显示客户端代码,因为它运行良好。
属性
[AttributeUsage(AttributeTargets.Property)]
public class AjaxValidation : Attribute, IModelValidator {
private readonly string _action;
private readonly string _area;
private readonly string _controller;
public AjaxValidation(string action, string controller = null, string area = null) {
_action = action;
_area = area;
_controller = controller;
}
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context) {
List<ModelValidationResult> result = new List<ModelValidationResult>();
//Need to call the action and check the result here
//Create the controller with reflection?
//Call the method with reflection?
if(false was returned) {
result.Add(new ModelValidationResult("", "{0} is invalid"));
}
return result;
}
}
显示其使用的模型
[AjaxValidation ("Validate", "Home", "Examples")]
public string Value{ get; set; }
以及模型将调用的动作(客户端也使用)
public ActionResult Validate(string id) {
if (id.Length == 3) {
return Json(new { Success = true });
} else {
return Json(new { Success = false });
}
}
您在这里混合了各种概念,这让您自己很难理解。
相反,您应该将验证逻辑提取到一个单独的服务中,而不是在控制器中捕获验证逻辑,您可以在控制器和属性中轻松使用该服务。有很多方法可以使用各种内置的DataAnnotations
等来实现这一点,但至少可以将代码拉到不同的服务中。
首先,创建您的验证服务
public class Validator
{
public bool Validate(string id)
{
if (id.Length == 3) {
return true;
} else {
return false;
}
}
}
将此注入到现有的控制器中,以根据需要返回结果:
public class ValidationController
{
private readonly ValidationService _validator;
public ActionResult Validate(string id) {
var result = _validator.Validate(id);
return Json(new { Success = result });
}
}
然后,您需要配置您的操作过滤器,以便类似地注入验证器。我建议你阅读ASP。NET核心操作筛选器,以及如何在运行时使用ServiceFilter
属性注入服务。这个答案描述了如何实现我认为你正在寻找的目标。