2013-07-31 71 views
15

我有一個模型,我用於記錄的編輯和插入頁面。其中一項業務要求是編輯時需要某個字段,而不是新的字段。原來之前這個特殊的功能被添加到案卷,我有模型,像這樣:MVC模型的條件驗證

[Required(ErrorMessage = "*")] 
[Range(0.0, (double)decimal.MaxValue)] 
[DisplayName("Cost")] 
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)] 
public decimal ProposedCost { get; set; } 

我想要麼刪除所需的屬性,如果它是一個插入的形式,或者,如果編輯的形式添加。什麼是更好的方法?我所有的其他驗證都按照上面的方式完成或者我可以改變模型狀態?思考?

編輯

東西我要澄清的是,他們仍然被允許插入新的成本,就不是必需的。

回答

32

如果您使用的是MVC3/.NET4,則可以使用IValidatableObject,它專門用於此目的。

引用ScottGu

...的IValidatableObject界面可以進行模型級 驗證,並允許您提供特定的整體模型的狀態驗證錯誤消息 ....

你的模型看起來像

public class MyViewModel : IValidatableObject 
{ 
    public long? Id { get; set; } 
    public decimal? ProposedCost { get; set; } 

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     if (Id != null && ProposedCost == 0) { 
      yield return new ValidationResult("ProposedCost must be provided."); 
     } 
    } 
} 

然後在控制器,

[HttpPost] 
public ActionResult Submit(MyViewModel model) 
{ 
    if (!ModelState.IsValid) { 
     //failed - report an error, redirect to action etc 
    } 
    //succeeded - save to database etc 
} 

否則,最乾淨的解決辦法是使用視圖模型 - UpdateViewModel在需要的財產,CreateViewModel它不是必需的。

+0

我試過這個,但仍然能夠保存編輯記錄沒有建議的成本。我放置了一個斷點,並打了Validationresult。思考? – Seth

+0

你確定你檢查過'ModelState.IsValid'嗎?我更新了答案以示例。另外請注意,如果我們不允許設置ProposedCost,則ProposedCost必須爲空。 – andreister

+0

是的,我錯過了,很好。添加的其他屬性在後臺自動進行客戶端檢查。無論如何,我可以挖掘到?這當然超出了我原來的問題範圍。 – Seth

3

您可以使用MVC Foolproof Validation項目中的RequiredIf驗證屬性。 我已經在項目中使用它來啓用您所需的功能。

另一種方法是使用RemoteAttribute並在方法中自己實現邏輯。

+3

我個人不喜歡'RequiredIf',因爲它不是類型安全的 - 你必須寫'[RequiredIf( 「SomeProperty」,值,...)]',它意味着編譯器不會警告你'SomeProperty'被重命名,但舊名稱被卡在屬性 – andreister

+0

@andreister中,你可以使用'[RequiredIf(nameof(SomeProperty),value,...)]''它可以編譯實時驗證並應對「SomeProperty」的重命名 –

+0

非常真實@JamesCulshaw--我最喜歡的C#6功能之一,因爲它有助於確切的場景。 – christophano

0

您可以嘗試與驗證:

ModelState.Remove("ProposedCost"); 

或延長你的模型是這樣的:

public class NewModeViewModel : EditModeViewModel 
{ 
    public new decimal ProposedCost { get; set; } 
} 

,並傳遞給編輯視圖。

4

還有就是MVC萬全庫:http://foolproof.codeplex.com/

例如,你需要有這樣的事情在你的模型:

[RequiredIfTrue("Required", ErrorMessage = "*")] 
[Range(0.0, (double)decimal.MaxValue)] 
[DisplayName("Cost")] 
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)] 
public decimal ProposedCost { get; set; } 

public bool Required { get; set; } 

然後,您就需要在此基礎上的形式設置Required屬性模型將會。

如果您希望執行客戶端驗證,您還需要在表單上隱藏一個輸入字段來表示Required屬性。

希望幫助...