2014-05-22 71 views
0

我有一個基於視圖模型顯示許多輸入的局部視圖。在某些情況下,其中一些輸入不是由局部視圖渲染的,但仍在視圖模型中使用[Required]屬性進行修飾。因此,當表單被髮回給我的控制器時,ModelState.IsValid返回false。有沒有辦法繞過這個?如何防止隱藏字段干擾MVC中的服務器端驗證?

+1

我要說的是,你應該改變你的視圖模型,但很難在不知道的情況說。您可以手動「從ModelState中刪除錯誤」,請參閱:http://stackoverflow.com/questions/14008561/is-there-a-strongly-named-way-to-remove-modelstate-errors-in-asp-net- mvc –

+0

當帖子內容綁定到視圖模型時,字段的源是輸入[type = hidden]還是input [type = text]並不重要。如果有一個值,它將被綁定,否則不會。之後將進行模型驗證。 – gustavodidomenico

+0

mvc不驗證該字段,它正在驗證該類。所以如果你的類有一個必需的屬性,並且你發佈了一個'x'類,它不會是有效的,你必須手動刪除它或創建另一個沒有所需文件的類 –

回答

1

我建議將您的驗證與您的基本模型分開。

public class MyModel 
{ 
    public string MyString { get; set; } 
    public string MyHiddenField { get; set; } 
} 

public interface IMyModel_ValidateMystringOnly 
{ 
    [Required] 
    string MyString { get; set; } 
} 

[MetadataType(TypeOf(IMyModel_ValidateMystringOnly))] 
public class MyModel_ValidateMystringOnly : MyModel 

這允許您創建任意數量的驗證類型,並且只在需要時驗證您想要的內容。

public ActionResult ShowMyModel() 
{ 
    var model = new MyModel(); // or Respository.GetMyModel() whatever.. 

    View(model); 
} 

public ActionResult ValidateModel(MyModel_ValidateMystringOnly model) 
{ 
    if (ModelState.IsValid) 
    { 
    // Hey Validation! 
    } 

    // MyModel_ValidateMyStringOnly is a MyModel 
    // so it can be passed to the same view! 
    return View("ShowMyModel", model); 
} 

這只是一個例子,但應該清楚如何在有或無驗證的情況下重複使用相同的模型。

1

您可以使用Foolproof有條件地驗證您的字段。這樣,只有在需要時才需要它們,正如鏈接示例中所示。

private class Person 
{ 
    [Required] 
    public string FirstName { get; set; } 

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

    public bool Married { get; set; } 

    [RequiredIfTrue("Married")] 
    public string MaidenName { get; set; } 
} 

在這個例子中,MaidenName只會改變你ModelState.IsValid爲假,如果Married == true

1

你應該總是您的視圖模型從你的域模型分開。這有一個很好的理由,它與安全性有關。當您使用域模型作爲視圖模型時,您很容易受到重發和/或底層攻擊的攻擊。你可以閱讀更多關於它在這些網頁:

  1. http://odetocode.com/blogs/scott/archive/2012/03/12/complete-guide-to-mass-assignment-in-asp-net-mvc.aspx
  2. http://blogs.msdn.com/b/rickandy/archive/2012/03/23/securing-your-asp-net-mvc-4-app-and-the-new-allowanonymous-attribute.aspx
  3. https://hendryluk.wordpress.com/tag/asp-net-mvc/

總之,如果你並不需要一個字段,則它不應該在你的視圖模型。您應該轉換 - 將您的視圖模型映射到域模型。雖然它可能很乏味,但它使您的應用程序更安全。您可以使用庫來幫助您進行Automapper等映射。

編輯:由於我原來的答案,我已經得出結論,處理這種類型的情況最簡單的方法是讓您的視圖模型實現IValidatableObject接口,然後在驗證方法內寫入您的驗證邏輯。它不會爲您提供客戶端驗證,但它是完成基於自定義/方案驗證的最有效和最乾淨的方式,無需編寫自己的自定義過濾器。

你可以閱讀更多關於它在這裏:有時http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3

+0

這是一個視圖模型而不是域模型。基本上這是一個局部視圖,有多種類型的輸入,用戶可以從中選擇。但是輸入的數量和類型是可配置的。但是需要顯示任何顯示的輸入。 – Mykroft

1

我已經使用方法,其中的形式略有變化基於特定的下拉或單選按鈕選擇。

內,您的操作方法,你檢查你ModelState.IsValid可以這樣做ModelState.Remove("Object.PropertyName")

前:屬性名應該是一樣的呈現給客戶端的ID。用一個 」。」對於任何下劃線。

If isSomeCondition Then 
     ModelState.Remove("Property1") 
     ModelState.Remove("Property2") 
    End If 

    If ModelState.IsValid() Then 
     ... 
    End If