Asp.net mvc 使用视图模型时的MVC.net EF验证
我正在开发一个MVC应用程序,并试图实现一些验证。我已经构建了一个使用EF存储的站点和一组带有automapper的视图模型 我想添加一些验证,如果我将其添加到视图模型中,我相信这些验证会起作用,但是我假设最好将验证与EF模型一起添加,因此如果将来我创建另一个接口,同样的验证也会应用 首先,这是正确的方法,其次,我如何让MVC在保存对象之前实际测试验证。目前它只是跳过我的EF验证 地址模型是自动生成的,因此我创建了这个分部类来添加验证:Asp.net mvc 使用视图模型时的MVC.net EF验证,asp.net-mvc,validation,Asp.net Mvc,Validation,我正在开发一个MVC应用程序,并试图实现一些验证。我已经构建了一个使用EF存储的站点和一组带有automapper的视图模型 我想添加一些验证,如果我将其添加到视图模型中,我相信这些验证会起作用,但是我假设最好将验证与EF模型一起添加,因此如果将来我创建另一个接口,同样的验证也会应用 首先,这是正确的方法,其次,我如何让MVC在保存对象之前实际测试验证。目前它只是跳过我的EF验证 地址模型是自动生成的,因此我创建了这个分部类来添加验证: public partial class Address
public partial class Address : IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!string.IsNullOrWhiteSpace(this.AddressLine1) &&
!string.IsNullOrWhiteSpace(this.AddressLine2) &&
!string.IsNullOrWhiteSpace(this.AddressLine3) &&
!string.IsNullOrWhiteSpace(this.Town) &&
!string.IsNullOrWhiteSpace(this.City) &&
!string.IsNullOrWhiteSpace(this.County) &&
!string.IsNullOrWhiteSpace(this.Postcode))
yield return new ValidationResult("Address cannot be blank.");
}
}
这是我的控制器
public ActionResult AddAddress(AddressVM vm)
{
IncidentAddress theAddress = Mapper.Map<AddressVM, Address>(vm);
if (ModelState.IsValid)
{
UOW.Addresses.Add(theAddress);
UOW.Save();
}
return PartialView("AddressVM-edit", vm);
}
public ActionResult AddAddress(AddressVM)
{
附带地址theAddress=Mapper.Map(vm);
if(ModelState.IsValid)
{
地址添加(地址);
UOW.Save();
}
返回PartialView(“AddressVM编辑”,vm);
}
对于您的对象来说,这始终是正确的,因为它将查找您的模型的有效性,即AddressVM(您从视图中收到它,所以这是您的模型),并且没有任何验证器。ModelState不知道您已将此对象映射到实现验证的其他对象。您需要手动对其他对象运行验证,并将验证错误添加到ModelState
如果希望将其分离,可以在AddressVM上实现IValidatableObject,并通过创建Address实例、将其从AddressVM映射(this)并返回其Validate方法的结果来在内部执行验证。您还可以将构造的相同地址对象公开为属性,并使用它执行实体操作
AddressVM的示例:
public class AddressVM : IValidatableObject
{
public int? ID { get; set; }
[Display(Name = "Address line 1")]
public string AddressLine1 { get; set; }
[Display(Name = "Address line 2")]
public string AddressLine2 { get; set; }
[Display(Name = "Address line 3")]
public string AddressLine3 { get; set; }
[Display(Name = "Town")]
public string Town { get; set; }
[Display(Name = "City")]
public string City { get; set; }
[Display(Name = "County")]
public string County { get; set; }
[Display(Name = "Postcode")]
public string PostCode { get; set; }
//// I added this and interface in class definition:
public IncidentAddress GetIncidentAddress()
{
return Mapper.Map<AddressVM, Address>(this);
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return this.GetIncidentAddress().Validate(validationContext);
}
}
公共类地址vm:IValidatableObject
{
公共int?ID{get;set;}
[显示(Name=“地址行1”)]
公共字符串AddressLine1{get;set;}
[显示(Name=“地址行2”)]
公共字符串AddressLine2{get;set;}
[显示(Name=“地址行3”)]
公共字符串AddressLine3{get;set;}
[显示(Name=“Town”)]
公共字符串{get;set;}
[显示(Name=“City”)]
公共字符串City{get;set;}
[显示(Name=“County”)]
公共字符串country{get;set;}
[显示(Name=“Postcode”)]
公共字符串邮政编码{get;set;}
////我在类定义中添加了这个和接口:
公共IncidentAddress GetIncidentAddress()
{
返回Mapper.Map(this);
}
公共IEnumerable验证(ValidationContext ValidationContext)
{
返回此.GetIncidentAddress().Validate(validationContext);
}
}
这样,您的逻辑保留在您的业务对象中,并且您的viewmodel使用它时没有它的副本或其他依赖项。在您的情况下,
Address
类和AddressVm
没有相互绑定-AutoMapper不进行验证,它只是复制值。因此,不会填充ModelState
并执行验证
我在考虑两个变通办法
AddressVm
上定义验证。如果ModelState.IsValid
,则将AddressVm
映射到Address
并保存AddressVm
。将操作签名更改为预期地址
参数。这样,ModelState.IsValid
将由验证系统自动填充(不是最佳解决方案)AddAddressModel
,仅用于添加地址,并仅定义创建地址所需的属性。然后,在AddAddressModel
上定义验证,并使用mapper将ViewModel映射到Address
实例(因此,我更喜欢第一个解决方案,再加上定义特定模型)
如果您需要可重用的验证器类,您可以签出。它对asp.net-mvc也有很好的支持 MVC:Controller=MVVM:ViewModel
if (ModelState.IsValid)
public class AddressVM : IValidatableObject
{
public int? ID { get; set; }
[Display(Name = "Address line 1")]
public string AddressLine1 { get; set; }
[Display(Name = "Address line 2")]
public string AddressLine2 { get; set; }
[Display(Name = "Address line 3")]
public string AddressLine3 { get; set; }
[Display(Name = "Town")]
public string Town { get; set; }
[Display(Name = "City")]
public string City { get; set; }
[Display(Name = "County")]
public string County { get; set; }
[Display(Name = "Postcode")]
public string PostCode { get; set; }
//// I added this and interface in class definition:
public IncidentAddress GetIncidentAddress()
{
return Mapper.Map<AddressVM, Address>(this);
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return this.GetIncidentAddress().Validate(validationContext);
}
}