自定义验证器中忽略 MetadataType 属性

发布于 2024-11-12 06:11:20 字数 5295 浏览 4 评论 0原文

(.NET 4.0/WebForms/EF 4.1 POCO)

嗨,

我正在使用自定义验证器将 DataAnnotations 与 WebForms 结合使用(源代码如下)。

当我直接在生成的类中使用 DataAnnotations 时,一切都很顺利。但是,当我在具有部分类的元数据类中使用 DataAnnotations 时,DataAnnotations 属性似乎在验证中被绕过。我知道元数据已被正确识别,因为当我将数据保存在 DbContext 中时,它正在被验证,并且 EntityValidationErrors 返回已验证的错误。

我做了一些搜索,发现了这个:(http://stackoverflow.com/questions/2657358/net-4-rtm-metadatatype-attribute-ignored-when-using-validator/2657644#2657644)。不幸的是我的实施没有成功。可能是我不知道在哪里称呼它。我尝试在元数据类的构造函数中调用它,但它不起作用。

public static class MetadataTypesRegister
{
    static bool installed = false;
    static object installedLock = new object();

    public static void Install()
    {
        if (installed)
        {
            return;
        }

        lock (installedLock)
        {
            if (installed)
            {
                return;
            }

            // TODO: for debug purposes only (please remove in production)
            Assembly assembly = Assembly.GetExecutingAssembly();
            Type[] types = assembly.GetTypes();
            //------

            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
            {
                foreach (MetadataTypeAttribute attrib in type.GetCustomAttributes(typeof(MetadataTypeAttribute), true))
                {
                    TypeDescriptor.AddProviderTransparent(
                        new AssociatedMetadataTypeTypeDescriptionProvider(type, attrib.MetadataClassType), type);
                }
            }

            installed = true;
        }
    }
}

要验证的模型位于 DataLayer.dll 中,DataAnnotationsValidator 类位于 Common.dll 中。

这是我的 DataAnnotationsValidator 类:

[ToolboxData("<{0}:DataAnnotationsValidator runat=server></{0}:DataAnnotationsValidator>")]
public class DataAnnotationsValidator : BaseValidator
{

    private string _propertyName = string.Empty;
    public string PropertyName
    {
        get { return _propertyName; }
        set { _propertyName = value; }
    }

    public string _sourceType = string.Empty;
    public string SourceType
    {
        get { return _sourceType; }
        set { _sourceType = value; }
    }

    public ValidationDataType _type = ValidationDataType.String;
    public ValidationDataType Type
    {
        get { return _type; }
        set { _type = value; }
    }

    public string _cssError = string.Empty;
    public string CssError
    {
        get { return _cssError; }
        set { _cssError = value; }
    }

    protected override bool EvaluateIsValid()
    {   
        // get specified type for reflection
        Type objectType = System.Type.GetType(_sourceType, true, true);

        // get a property to validate
        PropertyInfo prop = objectType.GetProperty(_propertyName);

        // get the control to validate
        TextBox control = this.FindControl(this.ControlToValidate) as TextBox;

        object valueToValidate = null;
        if (control.Text != String.Empty)
        {
            if (Type == ValidationDataType.Double)
                valueToValidate = double.Parse(control.Text);
            else if (Type == ValidationDataType.Integer)
                valueToValidate = int.Parse(control.Text);
            else if (Type == ValidationDataType.Date)
                valueToValidate = DateTime.Parse(control.Text);
            else if (Type == ValidationDataType.Currency)
                valueToValidate = decimal.Parse(control.Text);
            else
                valueToValidate = control.Text;
        }

        CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
        bool result = true;
        try
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            // The custom validator can return only one error message. Because the field model being validated can have more than 
            // one DataAnnotation validation (Required, Range, RegularExpression, etc.) the DataAnnotationsValidator will return only the first 
            // error message that it evaluates.
            foreach (ValidationAttribute attr in prop.GetCustomAttributes(typeof(ValidationAttribute), true).OfType<ValidationAttribute>())
            {
                Thread.CurrentThread.CurrentCulture = currentCulture;

                if (!attr.IsValid(valueToValidate))
                {
                    result = false;
                    var displayNameAttr = prop.GetCustomAttributes(typeof(DisplayNameAttribute), true).OfType<DisplayNameAttribute>().FirstOrDefault();
                    string displayName = displayNameAttr == null ? prop.Name : displayNameAttr.DisplayName;

                    ErrorMessage = attr.FormatErrorMessage(displayName);
                    break;
                }
            }
        }
        finally
        {
            Thread.CurrentThread.CurrentCulture = currentCulture;

            if (result)
            {
                if (!string.IsNullOrEmpty(CssError))
                    control.RemoveCssClass(CssError);
            }
            else
            {
                if (!string.IsNullOrEmpty(CssError))
                    control.AddCssClass(CssError);
            }
        }
        return result;
    }
}

谢谢!!

(.NET 4.0/WebForms/EF 4.1 POCO)

Hi,

I´m using a Custom Validator to use DataAnnotations with WebForms (source code is bellow).

Everything goes fine when I use DataAnnotations directly in the generated classes. But when I use the DataAnnotations in a Metadata class with a partial class, the DataAnnotations attributes seems to be bypassed in the validation. I know that the metadata was properly recognized, because when I save the data in the DbContext it is being validated and EntityValidationErrors returns the validated errors.

I did some searches and found this: (http://stackoverflow.com/questions/2657358/net-4-rtm-metadatatype-attribute-ignored-when-using-validator/2657644#2657644). Unfortunately my implementation did not worked. May be I don´t know where to call it. I´ve tried to call it in the constructor of the Metadata class but it didn´t work.

public static class MetadataTypesRegister
{
    static bool installed = false;
    static object installedLock = new object();

    public static void Install()
    {
        if (installed)
        {
            return;
        }

        lock (installedLock)
        {
            if (installed)
            {
                return;
            }

            // TODO: for debug purposes only (please remove in production)
            Assembly assembly = Assembly.GetExecutingAssembly();
            Type[] types = assembly.GetTypes();
            //------

            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
            {
                foreach (MetadataTypeAttribute attrib in type.GetCustomAttributes(typeof(MetadataTypeAttribute), true))
                {
                    TypeDescriptor.AddProviderTransparent(
                        new AssociatedMetadataTypeTypeDescriptionProvider(type, attrib.MetadataClassType), type);
                }
            }

            installed = true;
        }
    }
}

The model to be validated is located in DataLayer.dll and the DataAnnotationsValidator class is in Common.dll.

This is my DataAnnotationsValidator class:

[ToolboxData("<{0}:DataAnnotationsValidator runat=server></{0}:DataAnnotationsValidator>")]
public class DataAnnotationsValidator : BaseValidator
{

    private string _propertyName = string.Empty;
    public string PropertyName
    {
        get { return _propertyName; }
        set { _propertyName = value; }
    }

    public string _sourceType = string.Empty;
    public string SourceType
    {
        get { return _sourceType; }
        set { _sourceType = value; }
    }

    public ValidationDataType _type = ValidationDataType.String;
    public ValidationDataType Type
    {
        get { return _type; }
        set { _type = value; }
    }

    public string _cssError = string.Empty;
    public string CssError
    {
        get { return _cssError; }
        set { _cssError = value; }
    }

    protected override bool EvaluateIsValid()
    {   
        // get specified type for reflection
        Type objectType = System.Type.GetType(_sourceType, true, true);

        // get a property to validate
        PropertyInfo prop = objectType.GetProperty(_propertyName);

        // get the control to validate
        TextBox control = this.FindControl(this.ControlToValidate) as TextBox;

        object valueToValidate = null;
        if (control.Text != String.Empty)
        {
            if (Type == ValidationDataType.Double)
                valueToValidate = double.Parse(control.Text);
            else if (Type == ValidationDataType.Integer)
                valueToValidate = int.Parse(control.Text);
            else if (Type == ValidationDataType.Date)
                valueToValidate = DateTime.Parse(control.Text);
            else if (Type == ValidationDataType.Currency)
                valueToValidate = decimal.Parse(control.Text);
            else
                valueToValidate = control.Text;
        }

        CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
        bool result = true;
        try
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            // The custom validator can return only one error message. Because the field model being validated can have more than 
            // one DataAnnotation validation (Required, Range, RegularExpression, etc.) the DataAnnotationsValidator will return only the first 
            // error message that it evaluates.
            foreach (ValidationAttribute attr in prop.GetCustomAttributes(typeof(ValidationAttribute), true).OfType<ValidationAttribute>())
            {
                Thread.CurrentThread.CurrentCulture = currentCulture;

                if (!attr.IsValid(valueToValidate))
                {
                    result = false;
                    var displayNameAttr = prop.GetCustomAttributes(typeof(DisplayNameAttribute), true).OfType<DisplayNameAttribute>().FirstOrDefault();
                    string displayName = displayNameAttr == null ? prop.Name : displayNameAttr.DisplayName;

                    ErrorMessage = attr.FormatErrorMessage(displayName);
                    break;
                }
            }
        }
        finally
        {
            Thread.CurrentThread.CurrentCulture = currentCulture;

            if (result)
            {
                if (!string.IsNullOrEmpty(CssError))
                    control.RemoveCssClass(CssError);
            }
            else
            {
                if (!string.IsNullOrEmpty(CssError))
                    control.AddCssClass(CssError);
            }
        }
        return result;
    }
}

Thanks!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

埋葬我深情 2024-11-19 06:11:20

我在这里找到了一个解决方案(http://stackoverflow.com/questions/5600707/how-do-you-do-web-forms-model-validation)。

我修改 EvaluateIsValid 方法的代码以包含以下代码以查找元数据属性:

    // get specified type for reflection
    Type objectType = System.Type.GetType(_sourceType, true, true);

    // check for the types that have MetadataType attribute because 
    // it is they who have the DataAnnotations attributes
    IEnumerable<MetadataTypeAttribute> mt = objectType.GetCustomAttributes(typeof(MetadataTypeAttribute), false).OfType<MetadataTypeAttribute>();
    if (mt.Count() > 0)
    {
        objectType = mt.First().MetadataClassType;
    }

一切顺利!

I´ve found a solution here (http://stackoverflow.com/questions/5600707/how-do-you-do-web-forms-model-validation).

I modify the code of EvaluateIsValid method to include the code bellow to looking for Metadata Attributes:

    // get specified type for reflection
    Type objectType = System.Type.GetType(_sourceType, true, true);

    // check for the types that have MetadataType attribute because 
    // it is they who have the DataAnnotations attributes
    IEnumerable<MetadataTypeAttribute> mt = objectType.GetCustomAttributes(typeof(MetadataTypeAttribute), false).OfType<MetadataTypeAttribute>();
    if (mt.Count() > 0)
    {
        objectType = mt.First().MetadataClassType;
    }

And everything goes fine!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文