2

我们有一个使用 ServiceStack 作为后端的工作网站,相当于一个复杂的数据输入表单。

我的用户已请求表单的“离线编辑器”。要使用离线程序,用户必须连接到 ServiceStack 服务,创建表单的空实例,然后我将使用 ServiceStack 的 JSON 序列化程序将服务中的 POCO 保存到磁盘。用户可以从那里注销服务并编辑 POCO。完成后,他们重新连接到服务,并发布/放置编辑后的 ​​POCO 对象。

这一切都很好。我的问题涉及验证。验证逻辑内置在我的 Service.Interface 库中,该库不能离线使用。winforms 程序仅引用 POCO 库和 ServiceStack“通用”库,它们看起来并不包含 ServiceStack.Validation 命名空间。

有没有办法可以重新安排我的项目,以便服务和 Winforms 客户端都可以针对 POCO 运行验证,以便他们可以在离线时进行数据验证?

更新:越来越近了,我想——我把所有的验证类都移到了他们自己的项目中。在我的 Winforms 项目中,我现在可以为 POCO 类手动设置验证器,如下所示:

 ServiceStack.FluentValidation.IValidator<SomePOCO> IValidator;
 IValidator = new Tonto.Svc.Validation.SomePOCOValidator();

 ServiceStack.FluentValidation.Results.ValidationResult vr = 
    IValidator.Validate(_rpt);

我可以看到正在设置验证器构造函数并正在初始化规则,但是 .Validate 方法似乎没有做任何事情。(对象返回有效,并且自定义验证器代码中的断点永远不会到达那里)。

更新#2

我发现我的验证器代码没有从 Winforms 运行,因为我的验证器都只指定了一个 servicestack ApplyTo Put/Post(请参见下面的示例代码)。但是,当我删除整个规则集子句时,验证会在我的 GET 服务中发生——这是我永远不想要的。

任何人都可以想出一种方法来配置验证器规则,使其仅在从 ServiceStack 调用时运行 POST/PUT,但在不在 servicestack 中时也始终运行?很近!

public class SomePOCOValidator : AbstractValidator<SomePOCO>    
    {
        public SomePOCO()
        {
            RuleSet(ApplyTo.Put | ApplyTo.Post, () =>
            {
               (rules)
            });
        }
    }
4

3 回答 3

1

ServiceStack 使用的验证框架名为FluentValidation。它没有 WinForms 支持。FluentValidation 的创建者 Jeremy Skinner 早在 2010 年就在他的论坛上回答了一个关于此的问题

就我个人而言,我不将 FV 与 WinForms 一起使用——我的绝大多数项目都是基于 Web 的,偶尔也会有 WPF 项目。

但是,如果我要这样做,那么我可能不会直接验证控件,而是使用绑定到控件的 ViewModel。我会使用一个相当严格的约定,其中控件的名称将与它们绑定的属性的名称相匹配。然后,在验证完成后,我将遍历控件层次结构以查找名称与验证失败的属性匹配的控件(我不确定您如何在 WinForms 中执行此操作,但在 WPF 中我会使用 LogicalTreeHelper. FindLogicalNode),然后使用 ErrorProvider 设置相应的错误。

杰里米

于 2013-05-02T20:30:52.767 回答
1

我能够制定出一个解决方案,允许我在 ServiceStack 客户端和离线客户端上使用 ServiceStack 验证库。这是详细信息。

  1. 将所有 AbstractValidator 移到它们自己的项目:Proj.Svc.Validation。

  2. 摆脱 AbstractValidators 中的所有规则集。

  3. 从 Proj.Svc.Interface 和 Proj.OfflineWinformsClient 项目中引用 Proj.Svc.Validation。

  4. 关闭服务中的 ValidationFeature() 插件。所有验证都必须手动完成。这意味着在您的服务类中没有 iOC 注入验证器。

  5. 当需要从您的服务或离线客户端进行验证时,手动声明验证器并像这样使用它。

    IValidator 验证器 = new Tonto.Svc.Validation.SomePOCOValidator(); ServiceStack.FluentValidation.Results.ValidationResult vr = validator.Validate(poco);

    if (!vr.IsValid) (抛出异常或以某种方式通知用户);

于 2013-05-05T16:17:23.100 回答
1

如果您的验证正在做任何有趣的事情,那么它可能必须“在线”完成。

也许只是允许您的客户将 POCO 保存在本地,直到它们重新上线,此时您将它们发送到您的服务器。任何正常、正常处理以及失败的交易都会返回给用户进行编辑(因此您的客户需要一些聪明才智才能拥有一组工作的 POCO 进行编辑)......

如果您不希望客户端上有任何额外的东西,只需将无法验证的事务填充到服务器上的“needs_corrections”表中,然后编写一个主管类型的屏幕来管理该表。

于 2013-05-01T16:23:41.640 回答