2014-11-24 59 views
1

因爲今天我接受一個對象到我的一個動作中,我發現如果我的對象有一個屬性是一個可空結構,並且我填充了它,我得到了一個ArgumentNullException。動作參數對象屬性導致ArgumentNullException可空時結構

這就是它看起來像(在極端簡化,使用GET來創建一個簡單的例子):

//Action 
[HttpGet] 
public JsonResult Test(SuperClass model) 
{ 
    return Json("The will not work...", JsonRequestBehavior.AllowGet); 
} 

//... 

public class SuperClass 
{ 
    public string ArbitraryProperty { get; set; } 

    public SpecialDate SpecialDateA { get; set; } 

    //This seems to be the problem 
    public SpecialDate? SpecialDateB { get; set; } 
} 

public struct SpecialDate 
{ 
    public int? Year { get; set; } 
    public int Month { get; set; } 
    public int Day { get; set; } 
} 

現在,如果我叫下面的網址: http://EXAMPLE.COM/Home/Test/?ArbitraryProperty=Foo&SpecialDateA.Year=2014&SpecialDateA.Month=8&SpecialDateA.Day=12&SpecialDateB.Year=2015&SpecialDateB.Month=9&SpecialDateB.Day=10 後來我設置了所有數據我真的需要但是我在System.ComponentModel.DataAnnotations.ValidationContext構造中得到一個ArgumentNullException。

以下網址將然而工作:http://EXAMPLE.COM/Home/Test/?ArbitraryProperty=Foo&SpecialDateA.Year=2014&SpecialDateA.Month=8&SpecialDateA.Day=12

所以設置在MVC5動作參數不起作用爲空的結構特性。在這種情況下,我只需要切換一個類的結構,但是爲了以後的使用,知道爲什麼這不起作用會很有趣。

編輯:

爲了澄清,所述ArgumentNullException由MVC框架在我請求反序列化對象時拋出(參見實施例URLS)。 在這個例子中,上面代碼中的測試操作被放置在我的HomeController中,並且執行永遠不會進入方法,在調用示例URL之前拋出錯誤。

編輯2: 在由@Shoe評論的方面,我還測試了以下網址: http://EXAMPLE.COM/Home/Test/?ArbitraryProperty=Foo&SpecialDateA.Year=2014&SpecialDateA.Month=8&SpecialDateA.Day=12&SpecialDateB.Value.Year=2015&SpecialDateB.Value.Month=9&SpecialDateB.Value.Day=10

我所做的是試圖通過其價值財產分配SpecialDateB但它沒有似乎也有效。

編輯3:

爲了澄清進一步這裏是問題的一個更簡單例子:

這工作:

[HttpGet] 
public JsonResult Fest(int? foo) 
{ 
    return Json("This will work", JsonRequestBehavior.AllowGet); 
} 

這不工作:

[HttpGet] 
public JsonResult Fest(Fee fee) 
{ 
    return Json("This won't work...", JsonRequestBehavior.AllowGet); 
} 
... 
public class Fee 
{ 
    public int? Foo { get; set; } 
} 
+0

那麼問題是什麼?此外,您可能想要顯示一些初始化此代碼的代碼,或者至少顯示引發異常和異常消息的方法。 – IllidanS4 2014-11-24 15:55:40

+0

問題是爲什麼引發異常並且執行是URL(儘管URL是假的,它的結構是正確的,它調用了測試操作)。 – Maffelu 2014-11-25 04:55:32

+0

你可以顯示行,你反序列化? – Zeeshan 2014-11-25 05:20:10

回答

1

ASP.NET MVC的默認模型聯編程序使用Activator.CreateInstance(System.Type)來創建您的模型及其屬性,並且它沒有用於處理Nullable<>類型的特殊魔法。

由於您對「SpecialDateB」使用Nullable<SpecialDate>,因此在調用Activator.CreateInstance(System.Type)時,MVC會獲得空引用,因爲它沒有初始值。 MVC然後更新觸發模型驗證的模型狀態。

這是碰撞進入的地方。

System.ComponentModel.DataAnnotations.ValidationContextMSDN reference here)爲其驗證使用MVC要求「實例」參數(在這種情況下,「SpecialDateB」屬性的值)不爲空,並引發ArgumentNullException否則。

簡而言之,MVC不支持Nullable<>類型的參數(或參數的屬性,如您的情況)。

我建議使用類而不是結構,直到MVC團隊已修復支持Nullable<>

編輯:

爲了澄清我的回答:我的意思,聲稱「MVC不支持Nullable<>類型參數」是隻呈現的情況。像intDateTime等簡單類型可以正常工作爲可空參數。但是,只要將複雜類型創建爲結構並嘗試將其用作可爲空的參數,MVC就無法處理它。無論您是爲其指定值還是爲可選項。對不起,我的上述答案不清楚。

+1

儘管MVC確實支持可空類型。你可以使用'int?'或'Datetime?'作爲參數。 – Shoe 2014-11-25 14:31:17

+0

你可以使用int嗎?作爲一個參數,它的效果很好。這不是我的問題或問題。我的問題是當你使用一個對象作爲參數,並且**這個**對象使用可爲空的屬性時,它會中斷。那真是太奇怪了。 – Maffelu 2014-11-26 06:56:31