我有一个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的集合变为String[1]的集合(即,字符串变为数组)。因此,得出的字典条目看起来像这样:

{ "key1", "routeValue1" }


对此:

{ "key1", { "routeValue1" } }


我已经玩了几个小时,但似乎无法找出问题所在。由于控制器中的代码正在路由至关联值的ToString(),因此我的完整路由最终看起来像/area/controller/System.String[]/

RouteValueDictionary映射到隐藏字段时,我缺少什么吗?

更新:我最终为RouteValueDictionary对象制作了一个自定义模型绑定程序。 (请参见下面的答案)

最佳答案

我最终为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;
}

关于c# - RouteValueDictionary值在POST上从字符串更改为数组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15387132/

10-11 19:59