2

WebGrid分页链接在所有情况下都能正常工作,除了一个(我注意到)。

CheckBoxFor在 MVC 中使用时,它会为同一个字段创建一个input[type=hidden]和一个input[type=check-box],以便它可以处理状态。因此,如果您有一个名为的字段X并在方法中提交您的表单GET,您最终会得到一个如下所示的 URL:

http://foo.com?X=false&X=true

默认模型绑定器可以理解这些多个实例操作系统X并找出它的价值。

当您尝试对WebGrid. 它的行为是尝试捕获当前请求参数并在分页链接中重新传递它们。但是,由于不止一个X,它将通过X=false,true而不是预期的X=falseX=false&X=true

这是一个问题,因为X=false,true无法正确绑定。它将在动作开始之前触发模型绑定器中的异常。

有什么办法可以解决吗?

编辑:

这似乎是一个非常具体的问题,但事实并非如此。几乎每个带有复选框的搜索表单都会破坏 WebGrid 分页。(如果您使用的是 GET)

编辑2:

我认为我唯一的两个选择是:

  • 构建我自己的 WebGrid 分页器,它在为分页链接传递参数时更聪明
  • 构建我自己的理解false,true为有效的布尔模型绑定器
4

3 回答 3

5

如果其他人遇到所描述的问题,您可以使用自定义模型绑定器解决此问题,如下所示:

public class WebgridCheckboxWorkaroundModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.PropertyType == typeof (Boolean))
        {
            var value = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);
            if (value.AttemptedValue == "true,false")
            {
                PropertyInfo prop = bindingContext.Model.GetType().GetProperty(propertyDescriptor.Name, BindingFlags.Public | BindingFlags.Instance);
                if (null != prop && prop.CanWrite)
                {
                    prop.SetValue(bindingContext.Model, true, null);
                }
                return;
            }
        }

        base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
    }
}
于 2012-12-05T16:06:32.317 回答
1

从 DefaultModelBinder 继承的另一种方法是专门为可为空的布尔值实现 IModelBinder 接口。

internal class BooleanModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Get the raw attempted value from the value provider using the ModelName
        var param = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (param != null)
        {
            var value = param.AttemptedValue;
            return value == "true,false";
        }
        return false;
    }
}

然后,您可以将模型绑定添加到 Global.asax 或将其添加到参数中,如下所示:

public ActionResult GridRequests([ModelBinder(typeof(BooleanModelBinder))]bool? IsShowDenied, GridSortOptions sort, int? page)
{
    ...
}
于 2013-12-05T17:31:20.233 回答
1

对于那些想在 Dan 的解决方案中实现自定义模型绑定器但不确定如何实现的人。

您必须在 Global.asax 文件中注册模型绑定器:

protected void Application_Start()
    {
        ModelBinders.Binders.Add(typeof(HomeViewModel), new WebgridCheckboxWorkaroundModelBinder());
    }

并在您的操作中指定其用途:

public ActionResult Index([ModelBinder(typeof(WebgridCheckboxWorkaroundModelBinder))] HomeViewModel viewModel)
    {
        //code here
        return View(viewModel);
    }
于 2014-08-15T13:29:56.270 回答