2011-01-18 22 views
6

DropDownListFor(ASP.NET MVC3リリース)で異常な動作が検出されました。ドロップダウンでModelプロパティ値の代わりにViewBagプロパティ値を選択します。Modelプロパティ値の代わりにDropDownListForのViewBagプロパティ値

モデル:

public class Country { 
    public string Name { get; set; } 
} 
public class User { 
    public Country Country { get; set; } 
} 

コントローラーインデックスアクション:

ViewBag.CountryList = new List<Country> { /* Dropdown collection */ 
    new Country() { Name = "Danmark" }, 
    new Country() { Name = "Russia" } }; 

var user = new User(); 
user.Country = new Country(){Name = "Russia"}; /* User value */ 
ViewBag.Country = new Country() { Name = "Danmark" }; /* It affects user */ 
return View(user); 

ビュー:それは "デンマーク" の値を持つ "ロシア" 値とドロップダウンで、テキストボックスを表示します

@Html.EditorFor(user => user.Country.Name)  
@Html.DropDownListFor(user => user.Country.Name, 
    new SelectList(ViewBag.CountryList, "Name", "Name", Model.Country), "...") 

「ロシア」の代わりに選択された。

この動作に関するドキュメントは見つかりませんでした。この動作は正常ですか?なぜそれは正常ですか?なぜならViewBagとModelのプロパティ名を制御することは非常に難しいからです。 HTMLヘルパーが生成されたコントロールの値を拾うために、いくつかの異なる場所に見えるためだ

ViewBag.Country = new Country() { Name = "Danmark" }; /* It affects user */ 

This sample MVC3 project sources

答えて

5

MVCフレームワークがパラメータ提供の値を使用する前にViewData提供の値を使用しようとしたため、なぜこの決定が行われたのか分かりません。そのため、ViewBag.Countryはパラメータ提供値Model.Countryをオーバーライドします。

メソッドSelectInternalのMVCフレームワークでは、それはwrittenでした。

object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string)); 

// If we haven't already used ViewData to get the entire list of items then we need to 
// use the ViewData-supplied value before using the parameter-supplied value. 
if (!usedViewData) { 
    if (defaultValue == null) { 
     defaultValue = htmlHelper.ViewData.Eval(fullName); 
    } 
} 

if (defaultValue != null) { 
    IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue }; 
    IEnumerable<string> values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture); 
    HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase); 
    List<SelectListItem> newSelectList = new List<SelectListItem>(); 

    foreach (SelectListItem item in selectList) { 
     item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text); 
     newSelectList.Add(item); 
    } 
    selectList = newSelectList; 
} 

このコードdefaultValue = htmlHelper.ViewData.Eval(fullName);ViewDataから値を取得しようとしましたが、それは価値を得ることができれば、それは新しいリストで指定されたパラメータselectListを上書きします。

希望すると助かります。ありがとう。

サイドノード:ViewBagは、ViewDataの動的ラッパークラスです。

4

あなたのアクションメソッドからの次の行には、コードを混乱されているものです。この場合、ViewData["Country"]ModelState["Country"]と衝突します。そのプロパティの名前を変更してください。

+0

名前の衝突を避けるため、常にViewBagプロパティ名にprefixを使用することをお勧めしますか? Ex。 ViewBag.ViewBag_Country –

+0

聖なるもの、そうです。これをありがとう...私の日を救った::) – dizzwave

関連する問題