【问题标题】:Propagate child errors to parent in FluentValidation在 FluentValidation 中将子错误传播给父级
【发布时间】:2013-01-07 13:53:50
【问题描述】:

环境:
我正在使用 MVC4、Razor 2 和 FluentValidation.MVC4 (3.4.6.0)。

场景:
我有一个特定页面的复杂视图模型,它上面还有一个子视图模型,如下所示:

public class ProfileViewModel
{
    public string FirstName {get; set;}
    public PhoneNumberViewModel Primary {get; set;}
    // ... other stuff ... //
}

public class PhoneNumberViewModel
{
    public string AreaCode { get; set; }
    public string Exchange { get; set; }
    public string Suffix { get; set; }
    public string Extension { get; set; }
}

可以编辑此配置文件并发布回来以进行更新。我为这两者创建了 Fluent Validators,如下所示:

public class ProfileViewModelValidator : AbstractValidator<ProfileViewModel>
{
    public ProfileViewModelValidator()
    {
        RuleFor(m => m.FirstName).NotEmpty().WithMessage("Please enter a First Name,");
        RuleFor(m => m.Primary).SetValidator(new PhoneNumberViewModelValidator()).WithMessage("Hello StackOverflow!");
        // ... other validation ... //
    }
}

public class PhoneNumberViewModelValidator : AbstractValidator<PhoneNumberViewModel>
{
    public PhoneNumberViewModelValidator()
    {
        RuleFor(m => m.AreaCode).NotEmpty();
    }     
}

然后,当然,我有视图来显示所有内容。

个人资料视图片段:

...
@Html.TextBoxFor(m => m.FirstName)
@Html.EditorFor(m => m.PrimaryPhoneNumber)
...

电话号码编辑器模板片段:

...
@Html.ValidationLabelFor(m => m, "Primary Phone:")
@Html.TextBoxFor(m => m.AreaCode)
@Html.TextBoxFor(m => m.Exchange)
@Html.TextBoxFor(m => m.Suffix)
@Html.TextBoxFor(m => m.Extension) 
@Html.ValidationMessageFor(m => m)
...

如果它是相关的,我会设置一些东西,以便它自动将验证器与各种对象连接起来。实际上,我什至不需要上面的 .SetValidator() 行...由于连线,一切都得到了验证。

目标:
如果我不输入名字,我会在 ValidationMessageFor 创建的区域中收到上面提供的错误消息。但是,如果子 PhoneNumberViewModel 的任何元素验证失败,我什么也得不到。文本框突出显示红色,这很棒,但我没有收到我在 .WithMessage() 中提供的消息,表明我的子属性无效。

目前我正在通过我的控制器中的额外工作来实现它......它在子对象上查找错误,然后将错误添加到父对象。这种方法闻起来非常非常糟糕。它将验证相关的问题放在控制器中,我只是不希望它们在那里。更不用说它最终还有大量的字符串索引来挖掘 ModelState,而且它只是......恶心。

是否有一种简单的方法可以为 ProfileViewModelValidator 定义一个验证规则,如果子验证失败,它将为 ProfileViewModel 添加错误?和/或它应该工作,但我做错了什么?我已经搜索和搜索,但我找不到令人满意的解决方案。

感谢您的宝贵时间!

【问题讨论】:

    标签: asp.net-mvc-4 fluentvalidation razor-2


    【解决方案1】:

    我发现了一种与我的问题中包含的臭名昭著的解决方案不同的解决方案。它也不太理想,但我认为我更喜欢上面提供的解决方案。也许其他人会同意,所以在出现更清晰的答案之前它可能很有用。

    我向PhoneNumberViewModel 添加了一个属性,它以格式化字符串的形式返回整个电话号码:

    public string FullNumber
    {
       get { return string.Format("{0}{1}{2}{3}", AreaCode, Exchange, Suffix, Extension); }
    }
    

    除了每个组件属性的规则之外,您还可以将验证规则应用于此属性。如果您仅将 .WithMessage() 应用于 FullNumber 属性,您最终将获得您期望的验证消息(并且只有一次)以及在失败时为每个单独的框突出显示的文本框。

    这种方法的主要缺点是您最终会重复验证规则。您单独验证每个组件,然后还必须验证组合属性,这基本上是您已经完成的验证的组合。您将代码加倍,处理量加倍。您还会将可能出错的地方增加一倍。

    在我的例子中,我使用的是正则表达式,所以还不错……我更喜欢它而不是在控制器中嵌入错误传播代码。然而,它仍然不理想 - 希望会有更好的解决方案出现。

    【讨论】:

    • 我已经等了一周才接受自己的不太理想的解决方案。最终,我怀疑最好的解决方案是删除自动验证接线,并始终手动设置验证。遗憾的是,在这种情况下,这不是我的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多