我正在研究一个在mvc 4上编写的项目,该项目有几个类似向导的行为实例 - 几个视图链通过相同的半填充模型。从第二个视图控件开始最初显示为无效(这是逻辑 - 模型,传递给控制器方法具有相应的属性为空)。目前
ModelState.Clear();
使用了解决方案,但是将模型作为参数放入每个方法看起来很难看。与Disable Model Validation in Asp.Net MVC
ModelBinders.Binders[typeof(MyModelType)] = new NonValidatingModelBinder();
项目有太多(超过100个)模型类来手动注册每个模型类。
是否有更简单的方法(可能是.config键)完全关闭模型验证?
答案 0 :(得分:8)
我不知道这可行,但你试试这个(bootstrap代码或global.asax)
ModelValidatorProviders.Providers.Clear();
答案 1 :(得分:4)
我知道它并没有真正回答你的问题,只是为了扩展我的评论: -
听起来你有类似的东西: -
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
。
我首选的解决方案,不是试图弄乱你的持久性模型的验证,而是将View实现与Model实现分离,每个Wizard步骤都有一个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的方法(你的控制器不关心数据是来自向导式的视图),另一个流行的解决方案是将每个步骤包装在< div>中。客户端并使用javascript在用户进展时隐藏/显示它们。
如果您的模型需要在步骤之间保持不变,那么您需要考虑模型上的ValidationAttributes及其含义。如果您使用User.DateOfBirth
对Required
进行了注释,但是您需要能够在填充它的步骤之前保留它,那么事实上User.DateOfBirth
不是 required(例如,EF CodeFirst不能使列NOT NULL,因为我们需要能够在此期间保持空值)。您需要进行一些条件验证(例如IValidatableObject,MvcFoolproof,Fluent Validation),以便稍后验证您的完整模型。
答案 2 :(得分:2)
我不知道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;
答案 3 :(得分:0)
@{
HtmlHelper.ClientValidationEnabled = false;
}