为什么不能在我的IValidatableObject上调用?

时间:2015-03-02 23:30:15

标签: c# asp.net-mvc

我有一个视图模型:

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>();

1 个答案:

答案 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);
    }