繁体   English   中英

Silverlight应用程序的服务器端验证

[英]Server-side Validation for Silverlight Application

当我看到INotifyDataErrorInfo用于异步验证时,我正要实现IDataErrorInfo。 当进一步深入研究时,我注意到使用这些接口的示例全部在ViewModel上。 我需要对模型进行验证,并且需要将与模型一起存储的错误用于持久性。 我有很多实体的大图。 该图需要传递回服务器以进行复杂的验证。 我不确定现在应该使用哪种方法。

我是否只需将接口实现移至模型?

我看到的另一个示例具有单独的验证服务。 就我而言,我的验证规则很复杂,并且我正在考虑使用Windows Workflow及其规则引擎来提高验证规则的可维护性。

我需要单独的验证服务吗?

验证完成后,必须将图形传递回客户端。 然后需要显示任何错误/警告。

我应该在模型中实现INotifyDataErrors并在验证返回到客户端以将错误发布到View(通过ViewModel)时引发事件吗?

事实证明,在引用类库中包含INotifyDataErrors的程序集时遇到麻烦。 它会在共享这些类的程序集中产生冲突。

当您有大型项目时,RIA可能不是一个好主意,例如具有不同层(服务,应用程序,域,基础结构)的应用程序。

前一段时间,我不得不在具有复杂规则的Silverlight应用程序中实现Validation。 我正在使用通过实体框架生成的自我跟踪实体。 我的需要之一是重新使用所有验证代码。

首先,我尝试使用EntLib验证模块,并在客户端和服务器上使用相同的代码。 由于SL和.NET4.0使用不同版本的DataAnnotations程序集,因此遇到一些问题时,此方法不起作用。

最后,我最终在服务器上编写了某种验证服务,该服务将返回实体的错误(如果有)。 像这样:

interface IValidate
{
    IEnumerable<string> Validate(Entity entity); 
}

然后在客户端上使ViewModels实现INotifyDataErrorInfo(此接口支持异步验证),因此您可以使用Service验证实体并将错误保存在ViewModel上。

class SomeViewModel : INotifyDataErrorInfo
{
    public Entity Entity { get; set; }

    public void Validate()
    {
        this.ClearErrors();
        // this method make the service calls
        var service = -- service instance --;
        var errors = -- get errors from service --;
        foreach (string error in errors)
            this.AddTopLevelError(error);
    }

    {...}
}

这样,所有验证逻辑都位于服务器上,并且可以在不影响客户端的情况下随时更改,因为所有实体都是通过此服务传递的,然后再添加到数据库中(如果使用的是实体)。

该服务还可以返回错误以及与错误关联的属性,这样您就可以与Silverlight进行更丰富的交互。 因此服务可能是:

interface IValidate
{
    IEnumerable<PropertyError> Validate(Entity entity); 
}

class PropertyError
{
    public string PropertyName { get; }
    public IEnumerable<string> Errors { get; }
}

在这里,您会注意到验证规则可能会在服务器上更改,并且该逻辑的实现方式无关紧要。 所有这些都可以正常工作并满足您的要求,问题是Silverlight要求被验证的对象包含所有带有错误的属性。

例如,在使用数据库时,这不是常见的情况(这是一个简单的模型)

简单模型

该模型是使用Entity Framework 4.1完成的

因为如果您有用户实例并想要访问Email属性,则必须输入:user_instance.Person.Email。 因此,电子邮件属性不在用户类型中, 这是此解决方案的问题,因为您可能也想验证电子邮件。

难道不是这样吗?当您有一个带有实体(如上)的ViewModel(实现INotifyDataErrorInfo)并希望对该实体(在这种情况下为User)进行验证时,只需向属性Entity添加一个错误。 Person.Email

但是这个世界并不完美,所以我找到的解决方案是复制要在ViewModel上验证的每个属性,如下所示:

class SomeViewModel : INotifyDataErrorInfo
{
    public User Entity { get; set; }

    public string Name { get { return Entity.UserName; } set {...} }        
    public string Email { get { return Entity.Person.Email; } set {...} }

    {...}
}

这样,您可以将控件绑定到ViewModels属性而不是实体属性,但是使用更改通知会有些困难。

您可能还需要检查: 工具箱。 它解决了为实体定义包装纸的问题,并使用DynamicObject模拟了具有包装对象中所有属性的对象。 当处理大量数据时,这有点慢,但是却大大简化了工作。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM