2011-09-22 46 views
1

我有一個動作,基本上做到這一點:ID獲取寫入眼簾

public ViewResult Save(Foo postedFoo)   
{ 
    Foo foo; 
    if (postedFoo.Id == 0) //New foo; need to save for first time 
    { 
    foo = new Foo(); 
    } 
    else //Already exists, need to load and update 
    { 
    foo = FooRepository.LoadFoo(postedFoo.Id); 
    } 
    UpdateModel(foo); 
    FooRepository.Save(foo); 
    return View(foo); 
} 

正如你所看到的,動作可以同時處理創造新Foo實例和更新現有的。

的Foo的ID屬性寫入隱藏字段中的觀點是這樣的:

@Html.HiddenFor(m => m.Id) 

的問題是,在用戶保存一個新FooFooId財產的情況下(這正被設置在行FooRepository.Save(foo))在頁面重新顯示給用戶之前不被寫入隱藏字段。

這意味着,如果用戶保存一個新Foo,然後立即改變的東西,節省再次,控制器認爲這是另一個新的Foo並在數據庫中創建一個新的Foo而不僅僅是更新它。

任何人都可以提出爲什麼隱藏字段沒有被填充?

+2

您應該使用POST/REDIRECT/GET。是的,還有其他方法可以解決這個問題,但是P/R/G是*正確*方式。 –

+0

怎麼這樣?.......... – David

+0

你的兩個單詞問題給我提供了不足的上下文來給出任何有用的答案。 –

回答

2

ModelState.Remove("Id") 

之前返回View();

此行爲是由一個事實,即ModelState是價值的主要供應商渲染時引起的(是的,不是Model本身)。所以從ModelState去除標識,使得編輯人員使用Model的價值(在你的情況,更新Id

+1

太棒了。在我真正的代碼中,Id值是前綴,所以我需要調用'ModelState.Remove(「myPrefix.Id」)''。你對MVC的瞭解是非常棒的。 – David

+0

我不得不說,ModelState是主要供應商是最不直觀的。 – David

+2

如果你濫用它,這只是違反直覺的,這是問題中的代碼所做的。如果考慮到'ModelState'的預期目的,在保存失敗並且用戶再次呈現其表單以便他們可以修復其不良輸入的情況下,重新向最終用戶顯示不良用戶輸入是完全合理的。 –

0

不應該else線讀取

foo = FooRepository.LoadFoo(postedFoo.Id); 

此外,new Foo();沒有設置的值除非您已將其硬編碼到您的模型中,否則無法在任何地方使用。 但是,如果FooRepository.Save(foo)是爲了做到這一點,事實並非如此。您需要將ID字段返回給您的控制器。

foo = FooRepository.Save(foo); 
+0

第一個問題,是的:謝謝,我會更新這個問題。 – David

+0

'new Foo()'將有一個0的ID,這很好。調試確認'FooRepository.Save(foo)'給'foo'一個新的(正)'Id'值。在動作的最後一行('return View(foo);'),調試確認foo.Id已被設置並且大於零。 – David