2

複雑な型の配列を RouteValueDictionary または互換性のある型に追加するエレガントな方法があるかどうか疑問に思っていましたか?

たとえば、クラスとアクションがある場合:

public class TestObject
{
    public string Name { get; set; }
    public int Count { get; set; }

    public TestObject()
    {
    }

    public TestObject(string name, int count)
    {
        this.Name = name;
        this.Count = count;
    }
}

public ActionResult Test(ICollection<TestObjects> t)
{
    return View();
}

次に、このアクションを URL "/Test?t[0].Name=One&t[0].Count=1&t[1].Name=Two&t[1].Count=2" で呼び出すと、MVC がマップすることがわかります。これらのクエリ文字列パラメーターは、自動的に ICollection 型に戻されます。ただし、Url.Action() を使用して手動でどこかにリンクを作成していて、RouteValueDictionary に ICollection を追加すると、パラメーターの RouteValueDictionary を渡したい場合、Url.Action は &t= のようにそれを型としてレンダリングします。 System.Collections.Generic.List。

例えば:

RouteValueDictionary routeValDict = new RouteValueDictionary();
List<TestObject> testObjects = new List<TestObject>();

testObjects.Add(new TestObject("One", 1));
testObjects.Add(new TestObject("Two", 2));
routeValDict.Add("t", testObjects);

// Does not properly create the parameters for the List<TestObject> collection.
string url = Url.Action("Test", "Test", routeValDict);    

そのコレクションを、MVC がマッピング方法も理解できる形式に自動的にレンダリングする方法はありますか、それとも手動で行う必要がありますか?

この美しいマッピングがアクションに存在するようにするのに、URL を作成するために逆方向に手動で作業する方法を提供しないのはなぜですか?

4

2 に答える 2

5

まあ、私は他の(よりエレガントな)ソリューションを受け入れていますが、このq/aにある拡張メソッドを使用して機能させました:https://stackoverflow.com/a/5208050/1228414、リフレクションを使用するように適応させますプリミティブ型の配列を想定する代わりに、複雑な型のプロパティの場合。

私のコード:

public static RouteValueDictionary ToRouteValueDictionaryWithCollection(this RouteValueDictionary routeValues)
{
    RouteValueDictionary newRouteValues = new RouteValueDictionary();

    foreach (var key in routeValues.Keys)
    {
        object value = routeValues[key];

        if (value is IEnumerable && !(value is string))
        {
            int index = 0;
            foreach (object val in (IEnumerable)value)
            {
                PropertyInfo[] properties = val.GetType().GetProperties();
                foreach (PropertyInfo propInfo in properties)
                {
                    newRouteValues.Add(
                        String.Format("{0}[{1}].{2}", key, index, propInfo.Name),
                        propInfo.GetValue(val));
                }
                index++;
            }
        }
        else
        {
            newRouteValues.Add(key, value);
        }
    }

    return newRouteValues;
}
于 2013-11-13T20:11:10.443 に答える
5

私もこの問題に遭遇し、Zack のコードを使用しましたが、バグが見つかりました。IEnumerable が文字列の配列 (string[]) である場合、問題があります。だから私は私の拡張バージョンを共有したいと思った.

    public static RouteValueDictionary ToRouteValueDictionaryWithCollection(this RouteValueDictionary routeValues)
    {
        var newRouteValues = new RouteValueDictionary();

        foreach(var key in routeValues.Keys)
        {
            object value = routeValues[key];

            if(value is IEnumerable && !(value is string))
            {
                int index = 0;
                foreach(object val in (IEnumerable)value)
                {
                    if(val is string || val.GetType().IsPrimitive)
                    {
                        newRouteValues.Add(String.Format("{0}[{1}]", key, index), val);
                    }
                    else
                    {
                        var properties = val.GetType().GetProperties();
                        foreach(var propInfo in properties)
                        {
                            newRouteValues.Add(
                                String.Format("{0}[{1}].{2}", key, index, propInfo.Name),
                                propInfo.GetValue(val));
                        }
                    }
                    index++;
                }
            }
            else
            {
                newRouteValues.Add(key, value);
            }
        }

        return newRouteValues;
    }
于 2014-04-24T13:45:27.993 に答える