mvc之Action方法,参数为集合时的数据绑定
mvc框架里面,Action方法的参数绑定是一个很重要的概念,而框架自带的默认绑定方式是不支持绑定集合类的参数的。
不过不用担心,我们可以基于IModelBinder接口进行自定义的参数绑定,下面是一个绑定List类型参数的小例子,废话不多说,上代码
public class ArrayBind<T> : IModelBinder where T : class,new() { private _T GetValue<_T>(ModelBindingContext bindingContext, string key) { ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(key); bindingContext.ModelState.SetModelValue(key, valueResult); return (_T)valueResult.ConvertTo(typeof(_T)); } #region IModelBinder 成员 public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { List<T> list = new List<T>(); string[] allKey = controllerContext.HttpContext.Request.Form.AllKeys; string newKey = ""; string oldKey = ""; T entity = new T(); T beginEntity = entity; PropertyInfo[] infos = typeof(T).GetProperties(); foreach (string key in allKey) { if (!key.StartsWith(bindingContext.ModelName, StringComparison.CurrentCultureIgnoreCase)) { continue; } int index = key.LastIndexOf('['); if (index < 0) continue; newKey = key.Substring(0, index); if (string.IsNullOrEmpty(oldKey)) oldKey = key.Substring(0, index); if (newKey != oldKey) { list.Add(entity); entity = new T(); oldKey = newKey; } string currentKey = key.Substring(index); currentKey = currentKey.Replace("]", "").Replace("[", ""); var obj = bindingContext.ValueProvider.GetValue(key); PropertyInfo info = infos.Where(p => p.Name == currentKey).FirstOrDefault(); if (info != null) { if (info.PropertyType.IsEnum)//不处理枚举 continue; object value = null; if (info.PropertyType.Name.Contains("Nullable")) { Type type = typeof(Nullable<>); var types = info.PropertyType.GetGenericArguments(); Type runningType = type.MakeGenericType(types); string a = ((string[])obj.RawValue)[0]; object argument = Convert.ChangeType(a, types[0]); if (string.IsNullOrEmpty(a)) value = null; else value = Activator.CreateInstance(runningType, new object[] { argument }, null); } else { string str = ((string[])obj.RawValue)[0]; if (info.PropertyType.IsValueType && string.IsNullOrEmpty(str)) value = 0; else { if (info.PropertyType == typeof(Guid)) { Guid gid = Guid.Empty; Guid.TryParse(str, out gid); value = gid; } else value = Convert.ChangeType(str, info.PropertyType); } } info.SetValue(entity, value, null); } } if (!beginEntity.Equals(entity)) list.Add(entity); return list; } #endregion }
action方法的写法是:
public ActionResult Record([ModelBinder(typeof(ArrayBind<PersonEntity>))]List<PersonEntity> persons) { object result = null; if (persons != null && persons.Count > 0) result = new { success = true }; else result = new { success = false }; return Json(result); }
其中的PersonEntity是一个自定义的Model实体,前端采用的是post方式提交,传递参数的方式是json,格式是:{persons:[{Name:"张三",Age:18},{Name:"王五",Age:20}]},代码如下:
var data = []; for (var i = 0; i < 5; i++) { var json = { Name: "张三" + i.toString(), Age: 18 + i, Sex: (i % 2 == 0 ? "男" : "女") }; if (i % 2 == 0) { json.Birthday = "1998-10-25"; } data.push(json); } $.ajax({ url: "/Home/Record", type: "post", data: { persons: data }, dataType:"json", success: function (result) { alert(result.success); } });
捕捉提交的请求,发现其提交的数据格式为: