我有一个RouteValueDictionary
附加到传递给视图的对象。此对象包含一个名为SelectedItems的其他对象数组,用于使用用户可以选择的复选框填充网格。由于此对象随后会传递回控制器并根据用户与UI的交互方式进行不同的路由,因此它还包含一个名为ReturnValues的RouteValueDictionary
。该类的基本设置看起来或多或少是这样的:
[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
中返回“null”之外,这将完美地运行在阅读关于词典映射的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
的集合变为{{1}的集合。 (即,字符串成为数组)。因此,抽出来的词典条目看起来像这样:
String[1]
对此:
{ "key1", "routeValue1" }
我玩了好几个小时,但我似乎无法找出问题所在。由于我的控制器中的代码路由到关联值的{ "key1", { "routeValue1" } }
,因此我的完整路径最终看起来像ToString()
将/area/controller/System.String[]/
映射到隐藏字段时,是否存在我遗漏的内容?
更新:我最终为RouteValueDictionary
个对象制作了自定义模型绑定器。 (见下面的答案)
答案 0 :(得分: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;
}