我有一个视图模型:
public class SelectVendorViewModel : IValidatableObject
{
[Display(Name = "Document Date")]
[RequiredUnless("IsPidDv")]
public DateTime? DocumentDate { get; set; }
[Display(Name = "Document Number")]
[RequiredUnless("IsPidDv")]
public int? DocumentNumber { get; set; }
[Display(Name = "Vendor")]
[RequiredUnless("IsPidDv")]
public Guid? VendorId { get; set; }
public List<SelectListItem> Vendors { get; set; }
[Display(Name="PID/DV")]
public bool IsPidDv { get; set; }
public Guid? SalesReportId { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
return SelectVendorViewModelValidator.ValidateSalesReport(validationContext, this);
}
}
自定义模型装订器:
internal class SelectVendorViewModelBinder : DefaultModelBinder, IModelBinder<SelectVendorViewModel>
{
private readonly IVendorUnitOfWork _uow;
public SelectVendorViewModelBinder(IVendorUnitOfWork uow)
{
_uow = uow;
}
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var model = bindingContext.Model as SelectVendorViewModel;
if (model == null || !model.VendorId.HasValue || !model.DocumentDate.HasValue || !model.DocumentNumber.HasValue)
{
return;
}
var salesReport = _uow.SalesReportRepository.GetSalesReport(model.VendorId.Value, model.DocumentNumber.Value,
model.DocumentDate.Value);
if (salesReport != null)
{
model.SalesReportId = salesReport.Id;
}
}
}
验证员:
internal class SelectVendorViewModelValidator
{
internal static IEnumerable<ValidationResult> ValidateSalesReport(ValidationContext validationContext, SelectVendorViewModel viewModel)
{
if (viewModel.IsPidDv)
{
yield break;
}
if (!viewModel.SalesReportId.HasValue || viewModel.SalesReportId.Value == default(Guid))
{
yield return new ValidationResult("Sales report document does not exist.");
}
}
}
正在发布的控制器操作:
[HttpPost]
public virtual ActionResult SelectVendor(SelectVendorViewModel selectVendorVM)
{
selectVendorVM.Vendors = GetVendors();
if (!ModelState.IsValid)
{
return View(selectVendorVM);
}
return RedirectToAction(MVC.Licensing.Endorsements.Create(selectVendorVM.SalesReportId));
}
活页夹正常运行,我可以在调试器中单步执行。但是永远不会调用SelectVendorViewModel.Validate
方法。属性验证通过,如果我在控制器中设置断点,则动作ModelState.IsValid
为真。我认为它可能是自定义RequiredUnless
注释的东西,但即使我删除它们,验证也不起作用。我在这个应用程序的很多地方使用相同的模式,但这是唯一不起作用的模式。我能在这个和其他人之间找到的唯一区别是RequiredUnless
注释,我能够排除这一点。我错过了什么?
编辑:这是我如何注册模型粘合剂:
自定义IModelBinderProvider
:
public class GenericModelBinder : IModelBinderProvider
{
public IModelBinder GetBinder(Type modelType)
{
var genericBinder = typeof(IModelBinder<>).MakeGenericType(modelType);
var binder = DependencyResolver.Current.GetService(genericBinder) as IModelBinder;
return binder;
}
}
在Global.asax Application_Start方法中:
ModelBinderProviders.BinderProviders.Add(new GenericModelBinder());
在Ninject配置中:
kernel.Bind<IModelBinder<SelectVendorViewModel>>().To<SelectVendorViewModelBinder>();
答案 0 :(得分:1)
哦(畏缩)你没有调用ModelBinder
的基本方法,后者又调用模型上的Validate方法。 ;)
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var model = bindingContext.Model as SelectVendorViewModel;
if (model == null || !model.VendorId.HasValue || !model.DocumentDate.HasValue || !model.DocumentNumber.HasValue)
{
return;
}
var salesReport = _uow.SalesReportRepository.GetSalesReport(model.VendorId.Value, model.DocumentNumber.Value,
model.DocumentDate.Value);
if (salesReport != null)
{
model.SalesReportId = salesReport.Id;
}
// this is important as we overrode but still need base
// functionality to effect a validate
base.OnModelUpdated(controllerContext, bindingContext);
}