asp.net-mvc - 如何从自定义验证代码返回额外的(即不仅仅是字段=>错误消息)验证信息到 Controller 或 View ?

标签 asp.net-mvc modelstate asp.net-mvc-validation

我正在寻找一种方法来从我的自定义验证代码中返回以下信息:

public enum ValidationErrorTypeFlags
{
    Error_Input = 1 << 0,               // a "field specific" error which is checked both clientside and serverside 
    Error_Input_ServerSide = 1 << 1,    // a "field specific" error which can only be checked serverside
    Error_General = 1 << 2              // serverside general error
}

在验证代码(IValidatableObject 或 ValidationAttribute)中,当我检测到错误时,我希望能够将上述错误类型之一与 ValidationResult 相关联。

然后我希望能够遍历 Controller 或 View 中的验证错误并区分这些错误类型。

我目前正在使用 MVC 3(很高兴升级到 4)。

注意:

  • ModelState 不保留 ValidationResults AFAIK - 您只能访问 ViewData.ModelState.Values.Items[x].Errors 中的错误 - 这些已转换为 System.Web.Mvc.ModelError
  • 似乎 MVC 验证只允许您在验证完成后访问 [key, 'error message'] 类型的验证结果。

我目前使用的hack是在自定义验证码中修饰错误信息:

var field = new[] { validationContext.DisplayName };
return new ValidationResult("+Invalid format - use yyyy-mm-dd", field);

然后在 Controller 中查找以+、-、*开头的错误信息。

最佳答案

从自定义验证代码(不知道如何从内置代码完成),您可以通过创建自定义 ValidationResult 来实现通过继承基类并从您的自定义验证属性返回。

public class CustomValidationResult: ValidationResult
{
   // additional properties
}

然后您可以从 Controller 中转换并检查验证结果是否为您的自定义类型并采取相应行动。

更新:

上面的想法行不通,因为 ValidationResult类在 DataAnnotations 程序集中,它们被转换为 ModelValidationResult这就是我们在 MVC 中可以访问的所有内容。

似乎将额外的信息从数据注释验证传递到 MVC 看起来不太容易!

我正在查看源代码,发现它是 ValidatableObjectAdapter转换 IEnumerable<ValidationResult>进入IEnumerable<ModelValidationResult> .我看不出扩展这个类有什么好处,但我们可以很容易地创建一个自定义的 ValidatableObjectAdapter通过实现 ModelValidator并复制 Validate代码。

我们必须创建一个自定义 ModelValidationResult和定制ValidationResult (正是这个自定义 ValidationResult 我们将从验证中返回)并且在 ConvertResults 中方法,我们可以放置处理附加信息的转换代码。

public class CustomValidatableObjectAdapter : ModelValidator
{
    public CustomValidatableObjectAdapter(ModelMetadata metadata, ControllerContext context)
      : base(metadata, context)
    {
    }

    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
      object model = Metadata.Model;
      if (model == null)
      {
        return Enumerable.Empty<ModelValidationResult>();
      }

      IValidatableObject validatable = model as IValidatableObject;
      if (validatable == null)
      {
        throw new Exception("model is of not type validatable");
      }

      ValidationContext validationContext = new ValidationContext(validatable, null, null);

      return ConvertResults(validatable.Validate(validationContext));
    }

    private IEnumerable<ModelValidationResult> ConvertResults(IEnumerable<ValidationResult> results)
    {
      foreach (ValidationResult result in results)
      {
        // iterate the ValidationResult enumeration and cast each into CustomValidationResult
        // and conver them into enumeration of CustomModelValidationResult.
      }
    }
}

最后我们要告诉DataAnnotationsModelValidatorProvider使用我们的 CustomValidatableObjectAdapterApplication_Start Global.asax.cs 的事件。

DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapterFactory((metadata, context) => new CustomValidatableObjectAdapter(metadata, context));

所以你必须创建一个自定义的ValidationResult , 定制 ModelValidationResult和自定义 ValidatableObjectAdapter .

我还没有测试过这个,但我希望它能起作用。我可能会建议一个比这更好、更简单的解决方案。

关于asp.net-mvc - 如何从自定义验证代码返回额外的(即不仅仅是字段=>错误消息)验证信息到 Controller 或 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11059030/

相关文章:

asp.net-mvc - 如何将 Web API 添加到现有的 ASP.NET MVC 4 Web 应用程序项目?

c# - 具有必需类和多个可选类的 View 模型

c# - JSIL与Script#与SharpKit

asp.net-mvc-3 - MVC3 删除 ModelState 错误

asp.net-mvc - jQuery.Validation.Unobtrusive 客户端验证仅在脚本位于 View 页面上时有效

c# - 传递列表以在 asp.net mvc 中查看

asp.net-mvc - ModelState 中需要 DateTime,但从未设置为

javascript - 如何组织多个 View 使用的 Backbone 模型?

asp.net-mvc-3 - 在 MVC3 中使用远程验证时的空值

c# - 在 ASP.NET MVC 中以编程方式验证模型列表