17

我在 ASP.NET MVC 2 中使用自定义模型绑定器,如下所示:

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }
        if (bindingContext == null)
        {
            throw new ArgumentNullException("bindingContext");
        }

        BaseContentObject obj = (BaseContentObject)base.BindModel(controllerContext, bindingContext);
        if(string.IsNullOrWhiteSpace(obj.Slug))
        {
            // creating new object
            obj.Created = obj.Modified = DateTime.Now;
            obj.ModifiedBy = obj.CreatedBy = controllerContext.HttpContext.User.Identity.Name;
            // slug is not provided thru UI, derivate it from Title; property setter removes chars that are not allowed
            obj.Slug = obj.Title;
            ModelStateDictionary modelStateDictionary = bindingContext.ModelState;
            modelStateDictionary.SetModelValue("Slug", new ValueProviderResult(obj.Slug, obj.Slug, null));
...

当我从这个活页夹返回到控制器动作时,作为动作参数提供的我的业务对象被正确更改(obj.Created = .... 行工作)。

但是,ModelState 没有更新。我知道这一点是因为我在我的业务对象的 Slug 属性上有Required,虽然我在我的自定义模型绑定器中更改了 ModelStateDictionary,为它提供了一个 Slug(如您在上面看到的),但 ModelState.IsValid 仍然是错误的。

如果我将 ModelState["Slug"] 放在调试会话的 Watch 窗口中,它会说它有错误 (1),所以显然它是空的,因此失败了。

如何正确更改自定义模型绑定器代码中的 ModelState?

4

1 回答 1

22

显然,一旦您更改了某个键的值,就无法重新验证 ModelState。IsValid 保持为假,因为为某个键设置新值不会触发重新验证。

解决方案是首先删除触发 IsValid 为 false 的键,然后重新创建它并将值分配给它。当您这样做时,ModelState 会自动重新验证,如果一切正常,IsValid 返回 true。

像这样:

bindingContext.ModelState.Remove("Slug");
bindingContext.ModelState.Add("Slug", new ModelState());
bindingContext.ModelState.SetModelValue("Slug", new ValueProviderResult(obj.Slug, obj.Slug, null));
于 2010-04-07T12:37:51.103 回答