MVC3仅验证ViewModel中的一个实体

时间:2012-01-15 14:44:37

标签: asp.net-mvc-3 validation viewmodel

我有一个使用带有2个实体的View Model的mvc3创建页面 喜欢

class ViewModel1{
    public User user{get;set;}
     public Company company{get;set;}
}

其中User和Company是EF4实体(表)。我需要使用单个页面来创建两个(相关的)表。现在公司实体在某些条件下是可选的,我使用jQuery来隐藏视图中的相应部分。 但是,由于公司需要字段,因此回发创建函数的ModelState.Valid为false。

我想要做的是如果隐藏了公司部分,我想跳过在服务器的ViewModel中验证公司实体(我避免验证客户端中的隐藏元素)。

也许有更好更合适的做法?

3 个答案:

答案 0 :(得分:3)

您展示的不是视图模型。您将其称为视图模型,但这不是因为它引用了您的EF域实体。

更逼真的视图模型如下所示:

class ViewModel1
{
    public UserViewModel User { get;set; }
    public CompanyViewModel Company { get; set; }
}

或甚至展平并仅包含您的视图所需的属性:

class ViewModel1
{
    public int UserId { get;set; }
    [Required]
    public string FullUserName { get;set; }
    [Required]
    public string CompanyName { get; set; }
}

现在,根据您对视图模型验证的具体要求,我们会为您专门设计UserViewModelCompanyViewModel类。

答案 1 :(得分:1)

不是将实体直接放在视图模型中,而是将实体的属性放在视图模型中,并在视图模型和服务器上的实际实体对象之间进行映射。这样,您就可以控制视图所需的属性。创建一些自定义验证规则,以在需要某些公司信息时验证所需的公司属性是否存在。要在服务器上执行此操作,您可以让视图模型实现IValidatableObject并在Validate方法中实现逻辑。在客户端上,您可以为jQuery validate插件添加规则以获取“required if”属性。

public class UserCreationViewModel : IValidatableObject
{
     [Required]
     public string Username { get; set; }

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

     ...

     public string CompanyName { get; set; }

     public string CompanyEmail { get; set; }

     public IEnumerable<ValidationResult> Validate( ValidationContext context )
     {
         if (!string.IsNullOrEmpty(CompanyName) && string.IsNullOrEmpty(CompanyEmail))
         {
             return yield new ValidationResult("Company Email is required if you specify a company", new [] { "CompanyEmail" });
         }
     }
}

我不确定我会在客户端做什么。您可以选择直接向validate插件添加特定规则,但可能很难使其看起来与使用MVC添加的不显眼的验证完全相同。或者,您可以使用jQuery从“required if”元素添加/删除不显眼的属性,具体取决于触发其要求的元素的状态。我建议尝试两种方式 - 查看验证插件的文档,了解如何添加自定义规则并检查MVC框架发出的代码,以便进行不显眼的验证,以查看为了使其工作所需添加的内容。 p>

另一种可能性是根据是否需要公司信息,在from中删除/删除公司属性的部分视图。也就是说,键入公司名称并使用AJAX获取公司所需的输入并将其添加到表单中。如果删除公司名称,请删除元素。保留服务器端验证的方式,但在部分视图中模仿框架将添加的HTML以进行不显眼的验证。这是两个世界中最好的,因为jQuery代码更简单,并且您也可以获得一致的验证。

答案 2 :(得分:1)

有很多方法可以实现,

1)更常见的是,不要在Company对象上使用[Required]属性,但要对Company对象内的参数进行适当的验证。

在这种情况下,如果Company对象为null,则仍会通过验证,但如果Company对象不为null,则它将验证每个属性。

2)如果验证涉及一些复杂的业务逻辑,那么请选择自我验证模型。 (继承自IValiddatableObject,并覆盖Validate(...)。

3)通过代码,在控制器中。

if(model.company == null)
this.ModelState.Keys.Where(k => k.Contains("company")).ToList().ForEach(k => this.ModelState.Remove(k));

前两个是最佳批准方法,第三个是实现功能的另一种方式

相关问题