代码之家  ›  专栏  ›  技术社区  ›  Johnny Oshika

ASP.NET MVC:数据注释验证是否足够?

  •  27
  • Johnny Oshika  · 技术社区  · 16 年前

    我正在ASP.NET MVC 2中广泛使用数据注释验证。这个新特性节省了大量的时间,因为我现在能够在一个地方定义客户端验证和服务器端验证。然而,当我进行一些详细的测试时,我意识到,如果我只依赖数据注释验证,那么很容易有人绕过服务器端验证。例如,如果我通过用[Required]属性注释属性来定义一个必需字段,并将该必需字段的文本框放置在表单中,那么用户可以简单地从DOM中删除该文本框(可以通过Firebug轻松完成),现在在模型绑定期间,不会对该属性触发数据注释验证。控制器内部。为了确保触发“必需的”验证,我可以在模型绑定发生后重复验证,但随后将重复验证逻辑。

    每个人对验证的建议是什么?数据注释验证是否足够?或者需要重复验证以确保在所有情况下触发验证?

    后续评论: 基于下面的答案,我似乎不能仅仅依靠模型绑定器和数据注释验证。由于我们得出的结论是需要额外的服务器端验证,那么我的服务层是否有一种简单的方法根据数据注释中定义的内容触发验证?似乎这将使我们得到这两个词中最好的一个……我们不需要重复验证代码,但我们仍然可以确保验证得到执行,即使模型绑定器没有触发它。

    我将把这个后续评论作为一个单独的问题发布,因为它提出了一个与原始问题不同的问题。

    5 回复  |  直到 13 年前
        1
  •  18
  •   Matt Kocaj    16 年前

        2
  •  7
  •   Robert Koritnik    16 年前

    • IObjectValidator Validate()
    • ValidateBusinessObjectAttribute

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        IEnumerable<KeyValuePair<string, object>> parameters = filterContext.ActionParameters.Where<KeyValuePair<string, object>>(p => p.Value.GetType().Equals(this.ObjectType ?? p.Value.GetType()) && p.Value is IObjectValidator);
        foreach (KeyValuePair<string, object> param in parameters)
        {
            object value;
            if ((value = param.Value) != null)
            {
                IEnumerable<ErrorInfo> errors = ((IObjectValidator)value).Validate();
                if (errors.Any())
                {
                    new RulesException(errors).AddModelStateErrors(filterContext.Controller.ViewData.ModelState, param.Key);
                }
            }
        }
    }
    

    [ValidateBusinessObject]
    public ActionResult Register(User user, Company company, RegistrationData registrationData)
    {
        if (!this.ModelState.IsValid)
        {
            return View();
        }
        ...
    }
    
        3
  •  2
  •   Martijn Laarman    16 年前

    // Only bind properties that are part of the request
    if (bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey)) {
    

    // Only bind properties that are part of the request
    bool contextHasKey = bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey);
    bool isRequired = GetValidationAttributes(propertyDescriptor).OfType<RequiredAttribute>().Count() > 0;
    if (contextHasKey || (!contextHasKey && isRequired)) {
    
        4
  •  2
  •   John Bledsoe    16 年前

    public interface IValidationService
    {
        void Validate(object instance);
    
        IEnumerable<ErrorInfo> GetErrors(object instance);
    }
    
    public abstract class BaseValidationService : IValidationService
    {
        public void Validate(object instance)
        {
            var errors = GetErrors(instance);
    
            if (errors.Any())
                throw new RulesException(errors);
        }
    
        public abstract IEnumerable<ErrorInfo> GetErrors(object instance);
    }
    

        5
  •  1
  •   Michael Freidgeim    13 年前

    Server-side Input Validation using Data Annotations

            // Use the ValidationContext to validate the Product model against the product data annotations
            // before saving it to the database
            var validationContext = new ValidationContext(productViewModel, serviceProvider: null, items:null);
            var validationResults = new List<ValidationResult>();
    
            var isValid = Validator.TryValidateObject(productViewModel, validationContext,validationResults, true);