[C#]Model or List To RouteValueDictionary

 有時候我們在使用Url.Action()的時候會想要new{}一些 參數帶回Controller HttpGet的Action,如果需要帶回的參數越多,我們要手動bind就越麻煩,這時候我就在想可不可以直接寫一個擴充方法,把事先組好的model 轉為 RouteValueDictionary 直接帶入Url.Action()裡。

範例:

*測試用模型(盡可能測試各種TYPE)

 public class UrlTestModel
        {
            public string Str { get; set; }
            public bool Bol { get; set; }
            public DateTime Date { get; set; }
            public List<UrlSubModel> List { get; set; }
            public UrlSubModel[] Array { get; set; }
            public int[] IntArray { get; set; }
        }
        public class UrlSubModel
        {
            public string Name { get; set; }
        }

1.建立一個UrlHelper

ps:「paramName」只有在如果controller需要接的參數是個List或Array的時候,才需要帶入參數名稱給這個「paramName」。

  public static class UrlHelper
    {
        /// <summary>
        /// 轉換  Model To RouteValueDictionary
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="paramName">參數名稱(若 類型為List 須給 binding的名稱)</param>
        /// <returns></returns>
        public static RouteValueDictionary ModelToRouteValueDictionary<T>(T obj,string paramName=default)
        {
            var rvDic = new RouteValueDictionary();
            if (obj == null)
            {
                return rvDic;
            }
            var type = obj.GetType();
            if ((type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                       || typeof(ICollection).IsAssignableFrom(type)
                       || typeof(Object[]).IsAssignableFrom(type))
            {
                var list= obj as IEnumerable;
                var index = 0;
                foreach (var item in list)
                {
                    var value = GetObjectRouteValueDictionary(item);
                    foreach (var subItem in value)
                    {
                        rvDic.Add($"{paramName}[{index}].{subItem.Key}", subItem.Value);
                    }
                    index++;
                }
                return rvDic;
            }
            rvDic = GetObjectRouteValueDictionary(obj);
            return rvDic;
        }
        /// <summary>
        /// 取得物件 RouteValueDictionary
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static RouteValueDictionary GetObjectRouteValueDictionary<T>(T obj)
        {
            var rvDic = new RouteValueDictionary();
            var type = obj.GetType();
            var properties = type.GetProperties();
            for (var i = 0; i < properties.Length; i++)
            {
                var property = properties[i];
                var propertyType = property.PropertyType;
                if ((propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                       || typeof(ICollection).IsAssignableFrom(propertyType)
                       || typeof(Object[]).IsAssignableFrom(propertyType))
                {
                    IEnumerable list = (IEnumerable)property.GetValue(obj);
                    if (list == null)
                    {
                        continue;
                    }
                    var index = 0;
                    foreach (var item in list)
                    {
                        var subpropertyName = string.Concat(property.Name, "[", index, "]");
                        var subproperties = item.GetType().GetProperties();
                        if (subproperties != null && subproperties.Any())
                        {
                            var subValue = GetObjectRouteValueDictionary(item);
                            foreach (var subItem in subValue)
                            {
                                rvDic.Add($"{subpropertyName}.{subItem.Key}", subItem.Value);
                            }
                            index++;
                            continue;
                        }
                        rvDic.Add(subpropertyName, item);
                        index++;
                    }
                    continue;
                }
                var propertyValue = property.GetGetMethod().Invoke(obj, null);
                if (propertyValue == null)
                {
                    continue;
                }
                rvDic.Add(property.Name, propertyValue);
            }
            return rvDic;
        }
    }

2.測試 html code

<button onclick="TestFunc();">測試物件轉換成RouteValueDictionary</button>
<button onclick="TestListFunc();">測試物件轉換成List RouteValueDictionary</button>


@{
    //單一模型
    var data = ViewData["TestData"] as MVCTest.Helpers.UrlHelper.UrlTestModel;
    //List
    var list = ViewData["TestList"] as List<MVCTest.Helpers.UrlHelper.UrlTestModel>;
}
@*Action 單一模型URL*@
@Html.Hidden("TESTUrl", Url.Action("TestUrl", "Home", UrlHelper.ModelToRouteValueDictionary(data)))
@*Action List*@
@Html.Hidden("TESTListUrl", Url.Action("TestListUrl", "Home", UrlHelper.ModelToRouteValueDictionary(list, "data")))
*ViewData Set Value
  var sublist = new List<UrlSubModel>()
            {
                new UrlSubModel()
                {
                    Name="A"
                },
                new UrlSubModel()
                {
                    Name="B"
                }
            };
            var model = new UrlTestModel()
            {
                Str = "Test",
                Date = DateTime.Now,
                List = sublist,
                Array = sublist.ToArray(),
                IntArray = new int[] { 1, 2 }
            };
            ViewData["TestData"] = model;
            var list = new List<UrlTestModel>();
            list.Add(model);
            list.Add(model);
            ViewData["TestList"] = list;

3.JavaScript Code

 <script>
        //單一模型
        function TestFunc() {
            window.location.href = $('#TESTUrl').val();
        }
        //List
        function TestListFunc() {
            window.location.href = $('#TESTListUrl').val();
        }
    </script>

4.結果

    (1) Action 單一模型 結果


    (2)Action List 結果



留言

這個網誌中的熱門文章

[Visual Studio]位於網際網路或是限制區域上 或是檔案上標有 web 字樣 所以無法處理該檔案。若希望處理這些檔案 請移除 web 字樣。

[IIS] IIS執行時,發生拒絕存取路徑 問題

[SourceTree]修改使用者帳號密碼