ASP.NET MVC控制器动作与自定义参数转换?

我想设置一个ASP.NET MVC路由,如下所示:

routes.MapRoute( "Default", // Route name "{controller}/{action}/{idl}", // URL with parameters new { controller = "Home", action = "Index", idl = UrlParameter.Optional } // Parameter defaults ); 

路由请求看起来像这样……

 Example/GetItems/1,2,3 

…到我的控制器动作:

 public class ExampleController : Controller { public ActionResult GetItems(List id_list) { return View(); } } 

问题是,我如何设置将idl url参数从string转换为List并调用适当的控制器操作?

我在这里看到一个相关的问题 ,使用OnActionExecuting预处理字符串,但没有改变类型。 我不认为这对我ActionExecutingContext ,因为当我在我的控制器中覆盖OnActionExecuting并检查ActionExecutingContext参数时,我看到ActionParameters字典已经有一个空值的idl键 – 可能是从字符串到List …这是我想要控制的路由的一部分。

这可能吗?

一个不错的版本是实现自己的Model Binder。 你可以在这里找到一个样本

我试着给你一个想法:

 public class MyListBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { string integers = controllerContext.RouteData.Values["idl"] as string; string [] stringArray = integers.Split(','); var list = new List(); foreach (string s in stringArray) { list.Add(int.Parse(s)); } return list; } } public ActionResult GetItems([ModelBinder(typeof(MyListBinder))]List id_list) { return View(); } 

就像slfan所说的那样,自定义模型绑定器是可行的方法。 这是我博客的另一种方法,它是通用的,支持多种数据类型。 它还优雅地回退到模型绑定实现的默认值:

 public class CommaSeparatedValuesModelBinder : DefaultModelBinder { private static readonly MethodInfo ToArrayMethod = typeof(Enumerable).GetMethod("ToArray"); protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder) { if (propertyDescriptor.PropertyType.GetInterface(typeof(IEnumerable).Name) != null) { var actualValue = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name); if (actualValue != null && !String.IsNullOrWhiteSpace(actualValue.AttemptedValue) && actualValue.AttemptedValue.Contains(",")) { var valueType = propertyDescriptor.PropertyType.GetElementType() ?? propertyDescriptor.PropertyType.GetGenericArguments().FirstOrDefault(); if (valueType != null && valueType.GetInterface(typeof(IConvertible).Name) != null) { var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(valueType)); foreach (var splitValue in actualValue.AttemptedValue.Split(new[] { ',' })) { list.Add(Convert.ChangeType(splitValue, valueType)); } if (propertyDescriptor.PropertyType.IsArray) { return ToArrayMethod.MakeGenericMethod(valueType).Invoke(this, new[] { list }); } else { return list; } } } } return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder); } }