实体框架复杂类型自定义验证,停止验证递归

发布于 2024-10-31 22:29:57 字数 957 浏览 6 评论 0原文

我们使用复杂类型来管理可翻译字段,如下所示:

[ComplexType]
public class Translated
{
    [Required]
    public string NL { get; set; }

    [Required]
    public string EN { get; set; }

    [ScaffoldColumn(false)]
    public string TranslatedText
    {
        get
        {
           return Util.Translate(NL, EN); 
        }
    }
}

我们要求字段存在。但在某些情况下,整个 Translated 字段是可选的,如下所示:

public class Question
{
    ...

    [Optional(ErrorMessage="Foo")]
    public Translated Description { get; set; }

    ...
}

然而,Optional 属性似乎会被计算,并且当它返回 false 时,不会对结果进行任何处理。

class OptionalAttribute : ValidationAttribute 
{
    public override bool IsValid(object value)
    {
        return false;
    }
}

当我将可选属性放在非复杂类型上时,它会按预期工作,错误消息将始终是 Foo。

最终目标是在两种情况下都允许描述为空,但是当其中一个字段被填充时,错误当然应该传播。

停止验证递归会导致该字段成为可选字段,但如果字段被填写,它也会阻止对字段进行验证。

关于如何实现此目的有什么想法吗?

We are using complex types to manage our translatable fields like this:

[ComplexType]
public class Translated
{
    [Required]
    public string NL { get; set; }

    [Required]
    public string EN { get; set; }

    [ScaffoldColumn(false)]
    public string TranslatedText
    {
        get
        {
           return Util.Translate(NL, EN); 
        }
    }
}

We require the fields to be present. But in some cases the whole Translated field is optional as in:

public class Question
{
    ...

    [Optional(ErrorMessage="Foo")]
    public Translated Description { get; set; }

    ...
}

However, it seems that the Optional attribute gets calculated, and when it returns false nothing is done with the result.

class OptionalAttribute : ValidationAttribute 
{
    public override bool IsValid(object value)
    {
        return false;
    }
}

When I put the optional attribute on a non-complex type it works as expected, the error message will always be Foo.

The ultimate goal is to allow the Description to be empty in both cases, but when one of the fields is filled the errors should of course propagate.

Stopping the validation recursion would cause the field to be optional, but it would also prevent the validation of the fields in case they are filled in.

Any ideas on how to accomplish this?

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

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

发布评论

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

评论(2

浅忆 2024-11-07 22:29:57

在字符串属性上使用数据注释 [Required] 将在数据库中创建不可为 null 的字段。从您的描述来看,有时您似乎希望这两个值都为空。

我建议您实现自己的验证,定义使这些字段成为可选字段的原因。

[ComplexType]
public class Translated : IValidatableObject
{
    public string NL { get; set; }

    public string EN { get; set; }

    [NotMapped]
    public string TranslatedText
    {
        get
        {
            return Util.Translate(NL, EN);
        }
    }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!string.IsNullOrEmpty(NL) && string.IsNullOrEmpty(EN))
            yield return new ValidationResult("EN is required if NL is entered.");

        if (!string.IsNullOrEmpty(EN) && string.IsNullOrEmpty(NL))
            yield return new ValidationResult("NL is required if EN is entered.");
    }
}

Using the data annotation [Required] on your string properties will create non nullable fields in the database. From your description it seems that sometimes you'll want both of those values to be null.

I would suggest implementing your own validation defining what makes those fields optional.

[ComplexType]
public class Translated : IValidatableObject
{
    public string NL { get; set; }

    public string EN { get; set; }

    [NotMapped]
    public string TranslatedText
    {
        get
        {
            return Util.Translate(NL, EN);
        }
    }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!string.IsNullOrEmpty(NL) && string.IsNullOrEmpty(EN))
            yield return new ValidationResult("EN is required if NL is entered.");

        if (!string.IsNullOrEmpty(EN) && string.IsNullOrEmpty(NL))
            yield return new ValidationResult("NL is required if EN is entered.");
    }
}
神爱温柔 2024-11-07 22:29:57

这就是我现在正在做的事情。它的缺点是,对于每种 Translated(Translated、TranslatedOptional、TranslatedMultiline 和 TranslatedMultilineOptional),您都有单独的类。

另一个缺点是我不知道如何将验证结果添加到 NL en EN 字段本身而不是添加到 Translated。

[ComplexType]
public class TranslatedMultiline : IValidatableObject
{   
    [DataType(DataType.MultilineText)]
    [Display(Name = "dutch", ResourceType = typeof(Caracal.Resources.GUI))]
    public string NL { get; set; }

    [DataType(DataType.MultilineText)]
    [Display(Name = "english", ResourceType = typeof(Caracal.Resources.GUI))]
    public string EN { get; set; }

    [ScaffoldColumn(false)]
    public string TranslatedText
    {
        get
        {
            return Util.Translate(NL, EN);
        }
    }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (this is IOptional)
        {
            if (!string.IsNullOrEmpty(NL) && string.IsNullOrEmpty(EN))
                yield return new ValidationResult("EN is required if NL is entered.");
                // TODO: Translate

            if (!string.IsNullOrEmpty(EN) && string.IsNullOrEmpty(NL))
                yield return new ValidationResult("NL is required if EN is entered.");
                // TODO: Translate
        }
        else
        {
            if (string.IsNullOrEmpty(NL))
                yield return new ValidationResult("NL is required");

            if (string.IsNullOrEmpty(EN))
                yield return new ValidationResult("EN is required");

        }
    }
}

[ComplexType]
public class TranslatedMultilineOptional : TranslatedMultiline, IOptional { }

public interface IOptional {}

This is what I'm doing now. It has the disadvantage that for each kind of Translated (Translated, TranslatedOptional, TranslatedMultiline and TranslatedMultilineOptional) you have seperate classes.

Another disadvantage is that I don't know how to add the validation results to the NL en EN fields themselves instead of to the Translated.

[ComplexType]
public class TranslatedMultiline : IValidatableObject
{   
    [DataType(DataType.MultilineText)]
    [Display(Name = "dutch", ResourceType = typeof(Caracal.Resources.GUI))]
    public string NL { get; set; }

    [DataType(DataType.MultilineText)]
    [Display(Name = "english", ResourceType = typeof(Caracal.Resources.GUI))]
    public string EN { get; set; }

    [ScaffoldColumn(false)]
    public string TranslatedText
    {
        get
        {
            return Util.Translate(NL, EN);
        }
    }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (this is IOptional)
        {
            if (!string.IsNullOrEmpty(NL) && string.IsNullOrEmpty(EN))
                yield return new ValidationResult("EN is required if NL is entered.");
                // TODO: Translate

            if (!string.IsNullOrEmpty(EN) && string.IsNullOrEmpty(NL))
                yield return new ValidationResult("NL is required if EN is entered.");
                // TODO: Translate
        }
        else
        {
            if (string.IsNullOrEmpty(NL))
                yield return new ValidationResult("NL is required");

            if (string.IsNullOrEmpty(EN))
                yield return new ValidationResult("EN is required");

        }
    }
}

[ComplexType]
public class TranslatedMultilineOptional : TranslatedMultiline, IOptional { }

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