Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在ASP.NET中干净地共享数据模型、视图模型和DTO的自定义验证器(ValidationAttribute)_C#_Asp.net_Asp.net Mvc_Model Binding_Validationattribute - Fatal编程技术网

C# 如何在ASP.NET中干净地共享数据模型、视图模型和DTO的自定义验证器(ValidationAttribute)

C# 如何在ASP.NET中干净地共享数据模型、视图模型和DTO的自定义验证器(ValidationAttribute),c#,asp.net,asp.net-mvc,model-binding,validationattribute,C#,Asp.net,Asp.net Mvc,Model Binding,Validationattribute,我正在学习ASP.NETMVC课程。我正在使用ASP.NETWebAPI 2构建RESTWebAPI。该应用程序还包含标准MVC5视图。我使用DTO(数据传输对象)将API与数据模型解耦。我已经创建了一个自定义ValidationAttribute,并将其应用于数据模型中的属性,我希望对DTO上的属性以及MVC视图中使用的属性ViewModel使用相同的验证属性 这需要将ValidationContext.ObjectInstance强制转换为正确的类型。我已经找到了一个简单的解决方案,但我觉得

我正在学习ASP.NETMVC课程。我正在使用ASP.NETWebAPI 2构建RESTWebAPI。该应用程序还包含标准MVC5视图。我使用DTO(数据传输对象)将API与数据模型解耦。我已经创建了一个自定义ValidationAttribute,并将其应用于数据模型中的属性,我希望对DTO上的属性以及MVC视图中使用的属性ViewModel使用相同的验证属性

这需要将
ValidationContext.ObjectInstance
强制转换为正确的类型。我已经找到了一个简单的解决方案,但我觉得它不是很优雅,我想知道是否有更好的方法来做到这一点

我所说的特定ValidationAttribute和属性:

[Min18YearsIfAMember]
public DateTime? DateOfBirth { get; set; }
在解决方案的上下文中(为了简洁起见删除了一些详细信息,包括CustomServiceWModel):

它是可读的,但我发现它很难看,必须检查每个可能的情况,比如像客户那样检查
ValidationContext.ObjectInstance


有更好的方法吗?

在数据注释属性中,可以在附加属性时指定从属属性,并使用该属性验证对象类型的属性:

public class Min18YearsIfAMemberAttribute : ValidationAttribute
{
    private string _dependentProperty { get; set; }

    public Min18YearsIfAMemberAttribute(string dependentProperty)
    {
        this._dependentProperty = dependentProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var field = validationContext.ObjectType.GetProperty(_dependentProperty);
        if (field != null)
        {
            var dependentValue = (byte)field.GetValue(validationContext.ObjectInstance, null);
            
            return DoValidation(dependentValue, (DateTime?)value);
        }
        else
        {
            return new ValidationResult("<Your message here>");
        }
    }

    private ValidationResult DoValidation( int membershipTypeId, DateTime? DateOfBirth)
    { 
        // Do the validation....
    }

太好了!我喜欢这个解决方案允许我们使用具有不同名称的依赖属性的方式。但是,我知道我没有说明性能是一项要求,如果我错了,请纠正我,但是我认为调用
validationContext.ObjectType.GetProperty
可能比使用
as
操作符尝试执行类型转换要慢。您可以根据
validationContext.ObjectType.GetProperty的类型在静态字典中捕获validationContext.ObjectInstance
的输出。但是,
field.GetValue
也用于通过无法缓存的反射检索值。。。您可以运行基准测试来确定它是否真的值得关注,我是否遗漏了什么?您有
var dependentValue=(byte).
然后检查
dependentValue
是否为空-但它不能为空,因为它是一种值类型。@Wailae您是对的。我已经提出了一些修改建议,但尚未获得批准。@WaiHaLee-是的,我错了,我已经更新了代码
public class Min18YearsIfAMemberAttribute : ValidationAttribute
{
    private string _dependentProperty { get; set; }

    public Min18YearsIfAMemberAttribute(string dependentProperty)
    {
        this._dependentProperty = dependentProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var field = validationContext.ObjectType.GetProperty(_dependentProperty);
        if (field != null)
        {
            var dependentValue = (byte)field.GetValue(validationContext.ObjectInstance, null);
            
            return DoValidation(dependentValue, (DateTime?)value);
        }
        else
        {
            return new ValidationResult("<Your message here>");
        }
    }

    private ValidationResult DoValidation( int membershipTypeId, DateTime? DateOfBirth)
    { 
        // Do the validation....
    }
public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public MembershipType MembershipType { get; set; }
    public byte MembershipTypeId { get; set; }

    [Min18YearsIfAMember(nameof(MembershipTypeId))]
    public DateTime? DateOfBirth { get; set; }
}