17

ASP.NETMVC2で次のようなカスタムモデルバインダーを使用しています。

    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 = .... work)。

ただし、ModelStateは更新されません。これを知っているのは、ビジネスオブジェクトのSlugプロパティにRequiredがあり、カスタムモデルバインダーでModelStateDictionaryを変更して、Slugを提供しているにもかかわらず(上記のように)、ModelState.IsValidはまだfalseです。

デバッグセッションのウォッチウィンドウにModelState["Slug"]を配置すると、エラー(1)があると表示されるため、空であるため失敗します。

カスタムモデルバインダーコード内のModelStateを正しく変更するにはどうすればよいですか?

4

1 に答える 1

22

Apparently there is no way to revalidate the ModelState once you change a value of some key. The IsValid remains false because setting a new value to some key does not trigger revalidation.

The solution is to first remove the key that triggered IsValid to be false and recreate it and assign the value to it. When you do that the ModelState automatically revalidates and if everything is fine, IsValid returns true.

Like this:

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 に答える