我有一个使用带有2个实体的View Model的mvc3创建页面 喜欢
class ViewModel1{
public User user{get;set;}
public Company company{get;set;}
}
其中User和Company是EF4实体(表)。我需要使用单个页面来创建两个(相关的)表。现在公司实体在某些条件下是可选的,我使用jQuery来隐藏视图中的相应部分。
但是,由于公司需要字段,因此回发创建函数的ModelState.Valid
为false。
我想要做的是如果隐藏了公司部分,我想跳过在服务器的ViewModel中验证公司实体(我避免验证客户端中的隐藏元素)。
也许有更好更合适的做法?
答案 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; }
}
现在,根据您对视图模型验证的具体要求,我们会为您专门设计UserViewModel
和CompanyViewModel
类。
答案 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));
前两个是最佳批准方法,第三个是实现功能的另一种方式