【问题标题】:How to disable MVC 4 model validation?如何禁用 MVC 4 模型验证?
【发布时间】:2012-10-18 19:38:01
【问题描述】:

我正在开发一个在 mvc 4 上编写的项目,该项目有几个类似向导的行为实例 - 通过相同的半填充模型的少数视图链。从第二个视图开始,控件最初显示为无效(这是逻辑模型,传递给控制器​​方法的相应属性为空)。现在 ModelState.Clear(); 使用了解决方案,但将其放入每个方法中,模型作为参数看起来很难看。与此处找到的方法相同Disable Model Validation in Asp.Net MVC

ModelBinders.Binders[typeof(MyModelType)] = new NonValidatingModelBinder();

项目有太多(超过 100 个)模型类,无法手动注册每个。

是否有更简单的方法(可能在 .config 中键入)完全关闭模型验证?

【问题讨论】:

  • 就个人而言,我认为我会为每个向导步骤使用不同的 ViewModel。这将允许您在需要的地方使用验证(即在当前向导步骤中的值上!)。

标签: c# asp.net-mvc model-validation


【解决方案1】:

我不知道这是否可行,但您尝试过吗(引导代码或 global.asax)

ModelValidatorProviders.Providers.Clear();

【讨论】:

  • 我查过了。此代码有效。在我的项目中,我无法使用它,因为 DataAnnotationsModelValidatorProvider 从已清除集合中创建的验证器用于获取客户端验证器的错误消息(而不是默认的“*”)。但这是对我的问题最简单的回答。
【解决方案2】:

我知道它并没有真正回答你的问题,只是为了扩展我的评论:-

听起来你有类似的东西:-

public class MyModel
{
  [Required]
  public string Foo { get; set; } // Populated in step 1
  [Required]
  public string Bar { get; set; } // Populated in step 2
}

您在发布第 1 步时遇到问题,因为用户尚未输入 Bar 的值,所以有一个 ModelStateError

我更喜欢的解决方案是在每个向导步骤中使用 ViewModel 将您的视图实现与模型实现分离,而不是试图搞乱您的持久性模型的验证,例如:-

public class MyModel
{
  [Required]
  public string Foo { get; set; }
  [Required]
  public string Bar { get; set; }
}

public class StepOneModel
{
  [Required]
  public string Foo { get; set; }
}

public class StepTwoModel
{
  // This really depends on the behaviour you want.
  // In this example, the model isn't persisted until
  // the last step, but you could equally well persist
  // the partial model server-side and just include a
  // key in subsequent wizard steps.
  [Required]
  public StepOneModel StepOne { get; set; }

  [Required]
  public string Bar { get; set; }
}

您的控制器操作类似于:-

public ActionResult StepOne()
{
  return View(new StepOneViewModel());
}
[HttpPost]
public ActionResult StepOne(StepOneViewModel model)
{
  if(ModelState.IsValid)
  {
    var stepTwoModel = new StepTwoViewModel ()
    {
      StepOne = model
    };

    // Again, there's a bunch of different ways
    // you can handle flow between steps, just
    // doing it simply here to give an example
    return View("StepTwo", model);
  }

  return View(model);
}
[HttpPost]
public ActionResult StepTwo(StepTwoViewModel model)
{
  if (ModelState.IsValid)
  {
    // You could also add a method to the final ViewModel
    // to do this mapping, or use something like AutoMapper
    MyModel model = new MyModel()
    {
      Foo = model.StepOne.Foo
      Bar = model.Bar
    };

    this.Context.MyModels.Add(model);
    this.Context.SaveChanges();
  }

  return View(model);
}

您的 StepOne 视图类似于:-

@model StepOneModel
@using (html.BeginForm()) {
   @html.EditorFor(x => x.Foo);
}

您的 StepTwo 视图类似于:-

@model StepTwoModel
@using (html.BeginForm("StepTwo")) {
  @html.HiddenFor(x => x.StepOne);
  @html.EditorFor(x => x.Bar);
}

与仅关闭模型验证相比,主要优势在于您可以将当前步骤的验证要求放在 ViewModel 上 - 您可以确保第一步中的所有值都有效,然后再进行第二步。

  • 如果您想要一种更 RESTful 的方法(控制器不关心数据来自向导样式视图),另一种流行的解决方案是将每个步骤包装在

    客户端中随着用户的进展,使用 javascript 隐藏/显示它们。
  • 如果您的模型需要在步骤之间保持不变,那么您需要考虑模型上的 ValidationAttributes 以及它们的含义。如果您已经用Required 注释了User.DateOfBirth,但您需要能够在填充它的步骤之前将其持久化,那么实际上User.DateOfBirth 不是 必需的(例如EF CodeFirst不能使列 NOT NULL 因为我们需要能够同时保留空值)。您需要进行一些条件验证(例如IValidatableObjectMvcFoolproofFluent Validation)以便稍后验证您的完整模型。

【讨论】:

    【解决方案3】:

    我不知道 web.config 中的所有选项或类似的东西。但你可以使用这个:

    Assembly.GetExecutingAssembly()
       .GetTypes()
       .Where(t => t.IsClass && t.Namespace == "Your.Name.Space")
       .ToList()
       .ForEach(t => ModelBinders.Binders[t] = new NonValidatingModelBinder());
    

    或者

    typeof(MyModelType)
       .Assembly
       .GetTypes()
       .Where(t => t.IsClass && t.Namespace == "Your.Name.Space")
       .ToList()
       .ForEach(t => ModelBinders.Binders[t] = new NonValidatingModelBinder());
    

    或删除&& t.Namespace == "Your.Name.Space" 部分,以便将您的程序集中的所有类添加到 NonValidatingModelBinder。

    别忘了加using System.Linq;

    【讨论】:

      【解决方案4】:
      @{
      HtmlHelper.ClientValidationEnabled = false;
      }
      

      【讨论】:

        猜你喜欢
        相关资源
        最近更新 更多
        热门标签