2014-02-12 12 views
1

我在MVC4中發現了一些使我困惑的功能。我有以下的模型和控制器動作:忽略int屬性時未收到ModelState錯誤

public class MyModel 
{ 
    public int Foo { get; set; } 
} 

public ActionResult MyAction(MyModel model) 
{ 
    // check ModelState.IsValid and do stuff 
} 

我遇到的問題是,如果我做一個GET請求MyAction並沒有任何參數傳遞,然後ModelState.IsValid是真實的。如果我將Foo作爲參數傳入一個空字符串作爲值,那麼ModelState.IsValid如預期的那樣爲false(帶有需要Foo的錯誤消息)。

所以我想我的問題是,當富被省略爲什麼ModelState.IsValid真的嗎?這是MVC中的錯誤還是我錯過了什麼?如果需要屬性,那麼當該屬性被省略時,似乎應該有一個ModelState錯誤。

只是踢我試圖改變美孚爲字符串,並添加[必需]屬性給它。當我這樣做時,上述兩個測試都返回了假的ModelState.IsValid,這也是我期望它爲非空的int屬性所做的。在這個測試之後,我將Foo改回到了一個int,並且留下了[Required]屬性,看看它是否有效。當它是一個沒有[Required]屬性的int時,仍然得到相同的結果。

+0

你確定'Foo'在你忽略它的時候是空的,還是默認爲0?我猜'Foo'會是0,如果沒有'[Required]'屬性,它會通過驗證。 – Brandon

+0

@布蘭登我從來沒有說過,當省略時,Foo是空的。在這兩種情況下都是0,但只有其中一種情況會引發ModelState錯誤。當省略時,它通過帶或不帶[Required]屬性的驗證(當Foo是一個int時)。 – bbak

+2

我想不同的是,一個不可爲空的'int'在模型中會有一個值,當它通過時沒有標記中的字段..即零。然而,一個'字符串',如果它在標記中沒有通過,它將是'null'。對我有意義(不是bug)。 –

回答

1

如果我不得不採取刺傷在黑暗中,我會說,這是在DefaultModelBinder類代碼導致此情況的點發生:

protected virtual void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) 
    { 
     // need to skip properties that aren't part of the request, else we might hit a StackOverflowException 
     string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name); 
     if (!bindingContext.ValueProvider.ContainsPrefix(fullPropertyKey)) 
     { 
      return; 
     } 

如果ValueProvider不提供屬性名稱(這只是最簡單的情況下,請求參數),那麼它跳過它...顯然是爲了防止無限遞歸在某些情況下。我想這是明智的嵌套模式的情況下,例如:

class Foo 
{ 
    public Foo InnerFoo { get; set; } 
} 

這似乎有點短視(或者也許我的診斷是有點短視...)做這種方式,即因爲像這個確切的帖子的情況。

我稱它是錯誤的,除非有人能聰明指正。

適當的解決辦法是爲@布蘭登的answer提示:

[Required] 
public int? Foo { get; set; } 

,然後用生活繼續......我們都寫更噁心的東西比我敢肯定:)

2

什麼西蒙在評論說是正確的。

如果您未將int傳遞給模型,它只是默認爲0,而字符串將傳入爲空,並且不會通過Required檢查。

如果要執行一個整數,你應該使用可空類型。這樣就保證了它默認爲null,不爲0

[Required] 
public int? Foo { get; set; } 
+0

偉大的思想...... :) –

+0

這確實在技術上是有效的,但它感覺就像是一個黑客來繞過一個錯誤。似乎有點後退使某些東西可以爲空,但然後說這是必需的。 – bbak