2012-10-29 127 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; 
}