2013-03-13 12 views
2

我有一個RouteValueDictionary附加到傳遞給視圖的對象。該對象包含一個名爲SelectedItems的其他對象數組,用於使用用戶可以選擇的複選框填充網格。由於此對象隨後會傳回控制器並根據用戶與UI的交互方式進行不同的路由,因此它還包含一個名爲ReturnValues的返回值(RouteValueDictionary)。類的基本設置看起來或多或少是這樣的:RouteValueDictionary值在POST上從字符串變爲陣列

[Serializable] 
public class ItemSelection 
{ 
    public object[] SelectedItems { get; set; } 
    public RouteValueDictionary ReturnValues { get; set; } 

    public ItemSelection() 
    { 
     ReturnValues = new RouteValueDictionary() 
     { 
      { "key1", "routeValue1" }, 
      { "key2", "routeValue2" }, 
      { "key3", "routeValue3" } 
     } 
    } 
} 

這會完美地工作,除了ReturnValues財產在POST

回來了「空」讀this post關於映射之後字典,我想出了在視圖以下解決方案:

<% 
    foreach(var key in Model.Keys) 
    { 
     Html.Render(Html.HiddenFor(m => m[key])); 
    } 
%> 

這使得一堆隱藏投入的HTML看起來像這樣爲每個項目:

<input id="ReturnValues__key1_" name="ReturnValues.[key1]" type="hidden" value="routeValue1"> 

我也曾嘗試類似的東西this post

<% 
    for (var i = 0; i < Model.Count; i++) 
    { 
     Html.Hidden("ReturnValues[" + i + "].Key", Model.ElementAt(i).Key); 
     Html.Hidden("ReturnValues[" + i + "].Value", Model.ElementAt(i).Value); 
    } 
%> 

這使得這樣的:

<input id="ReturnValues_ReturnValues_0__Key" name="ReturnValues.ReturnValues[0].Key" type="hidden" value="key1"> 
<input id="ReturnValues_ReturnValues_0__Value" name="ReturnValues.ReturnValues[0].Value" type="hidden" value="routeValue1"> 

這兩項工作的一些,當RouteValueDictionary被調回控制器除外,該Values屬性從Strings的集合變爲String[1]的集合(即字符串變爲數組)。

{ "key1", "routeValue1" } 

要這樣:那麼,抽出,字典條目從看起來像這樣去

{ "key1", { "routeValue1" } } 

我與它周圍的玩弄了幾個小時,但我似乎無法找出什麼問題是。因爲在我的控制器代碼被路由到相應值的ToString(),我的全部路線最終看起來像/area/controller/System.String[]/

是不是有什麼我映射到RouteValueDictionary隱藏字段,當我失蹤?

更新:我最終爲RouteValueDictionary對象製作了自定義模型活頁夾。 (見下面的答案)

回答

1

我最終爲RouteValueDictionary對象製作了一個自定義模型聯編程序。以下是相關方法:

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{ 
    if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) 
    { 
     RouteValueDictionary baseModel = (bindingContext.Model as RouteValueDictionary) ?? (base.BindModel(controllerContext, bindingContext) as RouteValueDictionary); 

     if (baseModel != null) 
     { // start off with a direct copy of the bound model    
      var returnModel = new RouteValueDictionary(); 
      baseModel.ForEach(x => returnModel[x.Key] = item.Value); 

      // Sometimes the DefaultModelBinder turns the RouteValueDictionary.Values property into a collection of single-item arrays. This resets them to the correct values. 
      foreach (var key in baseModel.Keys) 
      { 
       returnModel[key] = GetValue(bindingContext, key); // GetValue method body below       
      } 

      return returnModel; 
     } 
    } 

    return null; 
} 

private object GetValue(ModelBindingContext context, string key) 
{ 
    var name = String.Format("{0}[{1}]", String.IsNullOrEmpty(context.ModelName) ? String.Empty : context.ModelName, key); 
    var attemptedResult = context.ValueProvider.GetValue(name); 

    if (attemptedResult != null && attemptedResult.AttemptedValue != null) 
    { 
     return attemptedResult.AttemptedValue;   
    } 

    return null; 
}