zrg*_*zrg 163 c# asp.net ivalidatableobject
据我所知,IValidatableObject它用于以一种方式验证对象,让人们相互比较属性.
我仍然希望有属性来验证单个属性,但我想在某些情况下忽略某些属性的失败.
我是否试图在下面的情况下错误地使用它?如果不是我如何实现这个?
public class ValidateMe : IValidatableObject
{
[Required]
public bool Enable { get; set; }
[Range(1, 5)]
public int Prop1 { get; set; }
[Range(1, 5)]
public int Prop2 { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!this.Enable)
{
/* Return valid result here.
* I don't care if Prop1 and Prop2 are out of range
* if the whole object is not "enabled"
*/
}
else
{
/* Check if Prop1 and Prop2 meet their range requirements here
* and return accordingly.
*/
}
}
}
Run Code Online (Sandbox Code Playgroud)
zrg*_*zrg 155
首先,感谢@ paper1337指出我正确的资源...我没有注册,所以我不能投票给他,如果有人读到这个,请这样做.
以下是如何完成我想要做的事情.
可验证类:
public class ValidateMe : IValidatableObject
{
[Required]
public bool Enable { get; set; }
[Range(1, 5)]
public int Prop1 { get; set; }
[Range(1, 5)]
public int Prop2 { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (this.Enable)
{
Validator.TryValidateProperty(this.Prop1,
new ValidationContext(this, null, null) { MemberName = "Prop1" },
results);
Validator.TryValidateProperty(this.Prop2,
new ValidationContext(this, null, null) { MemberName = "Prop2" },
results);
// some other random test
if (this.Prop1 > this.Prop2)
{
results.Add(new ValidationResult("Prop1 must be larger than Prop2"));
}
}
return results;
}
}
Run Code Online (Sandbox Code Playgroud)
Validator.TryValidateProperty()如果验证失败,则使用将添加到结果集合.如果没有验证失败,则不会向结果集合添加任何内容,这表示成功.
做验证:
public void DoValidation()
{
var toValidate = new ValidateMe()
{
Enable = true,
Prop1 = 1,
Prop2 = 2
};
bool validateAllProperties = false;
var results = new List<ValidationResult>();
bool isValid = Validator.TryValidateObject(
toValidate,
new ValidationContext(toValidate, null, null),
results,
validateAllProperties);
}
Run Code Online (Sandbox Code Playgroud)
validateAllProperties将此方法设置为false 非常重要.如果validateAllProperties为false,则仅[Required]检查具有属性的属性.这允许该IValidatableObject.Validate()方法处理条件验证.
Chr*_*uts 76
验证对象时,Validator.ValidateObject中应用以下过程:
- 验证属性级属性
- 如果任何验证器无效,则中止验证返回失败
- 验证对象级属性
- 如果任何验证器无效,则中止验证返回失败
- 如果在桌面框架上并且该对象实现了IValidatableObject,则调用其Validate方法并返回任何失败
这表明您尝试做的事情不会开箱即用,因为验证将在步骤#2中止.您可以尝试创建从内置属性继承的属性,并在执行正常验证之前专门检查是否存在已启用的属性(通过接口).或者,您可以将所有逻辑用于验证Validate方法中的实体.
Stu*_*tLC 33
只是添加几点:
因为Validate()方法签名返回IEnumerable<>,yield return可以用于懒惰地生成结果 - 如果某些验证检查是IO或CPU密集型,这将是有益的.
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (this.Enable)
{
// ...
if (this.Prop1 > this.Prop2)
{
yield return new ValidationResult("Prop1 must be larger than Prop2");
}
Run Code Online (Sandbox Code Playgroud)
此外,如果您正在使用MVC ModelState,您可以将验证结果失败转换ModelState为如下条目(如果您在自定义模型绑定器中进行验证,这可能很有用):
var resultsGroupedByMembers = validationResults
.SelectMany(vr => vr.MemberNames
.Select(mn => new { MemberName = mn ?? "",
Error = vr.ErrorMessage }))
.GroupBy(x => x.MemberName);
foreach (var member in resultsGroupedByMembers)
{
ModelState.AddModelError(
member.Key,
string.Join(". ", member.Select(m => m.Error)));
}
Run Code Online (Sandbox Code Playgroud)
我实现了一个用于验证的通用抽象类
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace App.Abstractions
{
[Serializable]
abstract public class AEntity
{
public int Id { get; set; }
public IEnumerable<ValidationResult> Validate()
{
var vResults = new List<ValidationResult>();
var vc = new ValidationContext(
instance: this,
serviceProvider: null,
items: null);
var isValid = Validator.TryValidateObject(
instance: vc.ObjectInstance,
validationContext: vc,
validationResults: vResults,
validateAllProperties: true);
/*
if (true)
{
yield return new ValidationResult("Custom Validation","A Property Name string (optional)");
}
*/
if (!isValid)
{
foreach (var validationResult in vResults)
{
yield return validationResult;
}
}
yield break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
106446 次 |
| 最近记录: |