疯狂的想法...当传递给模型中的布尔值时,Asp.Net MVC 应该只接受选中的复选框为“真”...。
我认为下面的——ModelBinder 接受 HTML 标准“on”表示真——应该一直是 Asp.Net MVC 中的默认实现。此解决方案适用于 Classic/Non-Core,但应该很容易适应 Core。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Brass9.Web.Mvc.ModelBinders
{
public class FixedCheckboxFormModelBinder : System.Web.Mvc.IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (
// Form POST
!controllerContext.HttpContext.Request.ContentType.StartsWith
("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)
/*
// Note: This is implied - by the way we add this ModelBinder to the global app list (typeof(bool))
||
bindingContext.ModelMetadata.ModelType != typeof(bool)
*/
)
{
return null;
}
string name = bindingContext.ModelName;
var valueProviderResult = bindingContext.ValueProvider.GetValue(name);
if (valueProviderResult.AttemptedValue == "on")
{
var replacementResult = new ValueProviderResult(true, "on", System.Globalization.CultureInfo.CurrentCulture);
bindingContext.ModelState.SetModelValue(name, replacementResult);
return true;
}
return null;
}
}
}
然后在 Global.asax.cs 中启用它Application_Start()
:
ModelBinders.Binders.Add(typeof(bool), new Brass9.Web.Mvc.ModelBinders.FixedCheckboxFormModelBinder());
所以,我们只是构建了一个自定义的 ModelBinder,只过滤模型值,期望从 POST 表单中传入一个布尔值,然后将 HTML 标准“打开”传递给我们——安全地将其干预限制为复选框。
尝试应用此修复程序实际上有点奇怪,因为大多数关于 ModelBinders 的文档都是赞扬的,几乎没有明确的操作方法。
为什么我们以这种方式解决它:
我们正在迁移旧应用程序以完全使用原始 Asp.Net MVC(非核心)。不仅将所有复选框移动到@Html.Checkbox...
(很多不是这样写的)需要很长时间,而且还会产生很多不良结果,因为额外的、不必要的隐藏输入以及迁移页面的困难。例如,我们知道有些页面有 Javascript 以特定顺序遍历 DOM 预期元素,隐藏的输入会中断,并且不想梳理每个页面以查找这些错误。