2012-12-13 167 views
5

纵观微风,我对它的许多功能印象深刻。Breeze服务器端验证

我无法弄清楚如何将服务器端DbContext验证错误返回给客户端。我知道Breeze拥有默认的验证器,可以对诸如“必需”之类的一些属性做出反应,但是其他所有属性又如何?我可以为Breeze编写一个自定义的JavaScript验证器来检查客户端,但我还需要检查以确保该实体在服务器端是有效的。

例如:该应用程序需要一个“人”来有一个有效的电子邮件地址。恶意用户会出现并获取通过客户端的电子邮件地址并发送到服务器,但日期不会通过“EmailAddress”验证器。到目前为止,我对Breeze的经验是,电子邮件地址将保存并不会冒泡任何DbContext/Entity Framework错误。

假设下面的模型,什么是获得任何实体验证错误的最佳方法?

public class PeopleContext : DbContext 
{ 
    public PeopleContext() 
     : base("name=ConnectionString"){ } 

    public DbSet<Person> People { get; set; } 
} 

public class Person 
{ 
    public int PersonId { get; set; } 
    public string FirstName { get; set; } 
    [Required] 
    public string LastName { get; set; } 
    [EmailAddress] 
    [Required] 
    public string Email { get; set; } 
} 

更新1:

这里有一些说明来重新创建,我遇到的问题。

  1. 按照说明来创建“待办事项”样品(http://www.breezejs.com/documentation/start-nuget
  2. 添加一个新的自定义验证到BreezeSampleTodoItem.cs文件

    [AttributeUsage(AttributeTargets.Property)] 
    public class CustomValidator : ValidationAttribute 
    { 
        public override Boolean IsValid(Object value) 
        { 
         string val = (string)value; 
         if (!string.IsNullOrEmpty(val) && val == "Error") 
         { 
          ErrorMessage = "{0} equal the word 'Error'"; 
          return false; 
         } 
         return true; 
        } 
    } 
    
  3. 装饰描述字段与新的自定义验证者:

    [CustomValidator] 
    public string Description { get; set; } 
    
  4. 添加正确使用的当然(“System”和“System.ComponentModel.DataAnnotations”)。

  5. 运行该项目。
  6. 在其中一个描述字段中输入“Error”并保存。

这是我期望通过微风看到错误,甚至从实体框架中抛出“DbEntityValidationException”的地方。我已经在2台独立的电脑上尝试了相同的结果。实体保存到数据库,就好像没有错误一样。事实上,如果你在自定义验证器的IsValid方法内的任何位置放置一个断点,你将会看到它甚至没有被调用。

回答

3

从Breeze v 0.78.1开始,所有注册的DbContext服务器端验证将在EntityManager SaveChanges调用期间执行。遇到的任何异常都会导致保存回滚,并将任何验证错误序列化回Breeze客户端。

请注意,此功能尚未支持较早的ObjectContext(而不是基于DbContext)的EF模型。

And ...感谢adamlj发现此问题并提出解决方案。

1

我不知道你所说的

获取服务器端的DbContext验证错误返回给客户端的意思

你可能意味着你要验证错误消息是发送给客户。但是您的其余问题表明您想知道(a)如何在服务器上运行自定义验证,以及(b)如何获取并在客户端上运行相应的JavaScript验证版本。我会解释你对这个问题的解释。

服务器

实体框架(你用你的例子)自动运行数据标注为你验证规则...除非你已停用了手动功能。如果以正确的方式创建定制验证规则,EF也会运行这些验证规则。 This post by Daniel Wertheim描述了如何编写这样的规则。我无法在每一个细节上担保这篇文章,但对我来说似乎是正确的。它甚至定义了一个自定义的电子邮件验证属性!

如果编写自定义的数据注释验证规则似乎太巴洛克你(因为它经常做给我),你可以写,并呼吁自己的验证逻辑的“Server-side Interception”讨论的BeforeSave...方法之一。

我认为这些是您最好的服务器选项。到客户端...

客户

微风注册客户端JavaScript验证,以匹配特定的服务器端数据注释(例如,RequiredMaxLength)是碰到的在元数据中连线。正如我写的,定制数据注释不会被识别,也不会包含在元数据中,并且它们没有客户端上的开箱即用类比。如果您希望客户端使用这些规则预先筛选实体,则必须编写您自己的相应JavaScript验证程序,并将其注册为相关实体类型,如Validation文档页面中所述。

如果您有建议或更好的选择,我们很乐意听到他们。

+0

嗨病房,感谢您的答复,和真棒项目!我编辑了我的问题,以提供如何复制我遇到的问题的示例。我遇到的问题是,在使用EFContextProvider.SaveChanges(saveBundle)方法时,没有任何数据注释正在被评估。我确实拉下了Breeze的源代码,如果我更改EFContextProvider.SaveChangesCore方法的代码,请使用((DbContext)(object)Context).SaveChanges()而不是ObjectContext.SaveChanges(),然后正确评估注释。但我宁愿不修改源文件。 – adamlj

+0

还有一点需要注意,我检查过BeforeSave方法。我担心的是我只能返回一个布尔值。对于验证错误,应该有一些方法可以将错误消息发回给用户。 – adamlj

+0

你应该抛出一个异常,包括失败的解释,例如抛出新的InvalidOperationException(“不能保存未知类型的实体”);'返回false仅仅告诉ContextProvider在保存期间跳过该实体;它不会终止保存!请参阅“[服务器端拦截](http://www.breezejs。com/documentation/server-side-interception)“页面 – Ward