[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 結果
留言
張貼留言