自定义模型 - 粘合剂,从cookie问题?

Jef*_*eff 2 asp.net-mvc model-binding data-annotations

我正在尝试执行以下操作.

使用默认模型绑定器从查询字符串值绑定对象.
如果失败,我会尝试从cookie值绑定对象.

但是我在这个对象上使用dataannotations,我遇到了以下问题.

  1. 如果没有查询字符串参数,则默认模型绑定程序甚至不会在必填字段上注册任何验证错误.如果属性本身不在查询字符串集合中,它显然甚至不会触发这些验证器.我该如何改变这种行为?如果它们不在查询字符串中,我希望必填字段是错误的.
  2. 如果我确实有模型验证错误,我想从cookie加载模型然后重新验证对象.我不知道如何让模型绑定器验证我自己填充的对象.

这是我到目前为止所拥有的.

    public class MyCarBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var myCar = base.BindModel(controllerContext, bindingContext);

        if (!bindingContext.ModelState.IsValid)
        {
            myCar = MyCar.LoadFromCookie();
            // Not sure what to do to revalidate
        }

        return myCar;
    }
}
Run Code Online (Sandbox Code Playgroud)

任何有关如何正确执行此操作的帮助将不胜感激.

Jef*_*eff 5

好吧,我自己解决了.在此处发布解决方案,以防任何人有评论或想要使用它.

 public class MyCarBinder : DefaultModelBinder
 {
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var queryStringBindingContext = new ModelBindingContext()
        {
            FallbackToEmptyPrefix = bindingContext.FallbackToEmptyPrefix,
            ModelMetadata = bindingContext.ModelMetadata,
            ModelName = bindingContext.ModelName,
            PropertyFilter = bindingContext.PropertyFilter,
            ValueProvider = new QueryStringValueProvider(controllerContext),
            ModelState = new ModelStateDictionary()
        };

        var myCar = base.BindModel(controllerContext, queryStringBindingContext);

        if (queryStringBindingContext.ModelState.IsValid)
            return myCar;

        // try to bind from cookie if query string is invalid
        var cookieHelper = new Helpers.ControllerContextCookieHelper(controllerContext);
        NameValueCollection nvc = cookieHelper.GetCookies(Helpers.CookieName.MyCar);

        if (nvc == null)
        {
            bindingContext.ModelState.Merge(queryStringBindingContext.ModelState);
            return myCar;
        }

        var cookieBindingContext = new ModelBindingContext()
        {
            FallbackToEmptyPrefix = bindingContext.FallbackToEmptyPrefix,
            ModelMetadata = bindingContext.ModelMetadata,
            ModelName = bindingContext.ModelName,
            PropertyFilter = bindingContext.PropertyFilter,
            ValueProvider = new NameValueCollectionValueProvider(nvc, CultureInfo.InvariantCulture),
            ModelState = new ModelStateDictionary()
        };

        var myCarFromCookie = base.BindModel(controllerContext, cookieBindingContext);

        if (cookieBindingContext.ModelState.IsValid)
        {
            MyCar temp = myCarFromCookie as MyCar;
            if (temp != null)
                temp.FromCookie = true;

            return myCarFromCookie;
        }
        else
        {
            bindingContext.ModelState.Merge(queryStringBindingContext.ModelState);
            return myCar;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)