2012-10-29 84 views
6

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

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

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

有没有完全熄灭模型验证简单的方法(在的.config也许键)?

+3

个人而言,我想我会使用不同的视图模型为每个向导一步。这将允许您在需要的地方使用验证(即从当前向导步骤的值!)。 –

回答

8

我不知道这会工作,但你试试这个(引导代码或Global.asax中)

ModelValidatorProviders.Providers.Clear(); 
+0

我检查过它。此代码有效。在我的项目中,我无法使用它,因为通过'DataAnnotationsModelValidatorProvider'从已清除的集合中创建的验证器可用于为客户端验证程序(而不是默认的“*”)获取ErrorMessages。 但这是对我的问题最简单的答案。 – user1782982

+0

这对我不起作用,我不明白为什么 –

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;

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

我首选的方案,而不是周围试图乱用你的持久模型的验证,会从你的一个视图模型模型实现对每个向导步骤的分离你的视图实现,例如: -

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.DateOfBirthRequired,但你需要能够在它被填充的步骤之前坚持它,那么实际上User.DateOfBirth不是必需的(例如,EF CodeFirst不能使列NOT NULL,因为我们需要在此期间能够保留空值)。您需要执行一些有条件验证(例如,IValidatableObject,MvcFoolproof,Fluent Validation),以便稍后验证您的完整模型。

+0

+1 iain - 很好的总结:) –

0
@{ 
HtmlHelper.ClientValidationEnabled = false; 
}