2011-12-06 34 views
3

我想建立一個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<int> id_list) 
    { 
     return View(); 
    } 
} 

的問題是,我該怎麼設置從stringidl URL參數轉化爲List<int>,並調用一個適當的管制員行動?

我看到related question here使用OnActionExecuting預處理字符串,但沒有改變類型。我不認爲這適用於我,因爲當我在我的控制器中覆蓋OnActionExecuting並檢查ActionExecutingContext參數時,我看到ActionParameters字典已經有一個空值的idl鍵 - 可能是從字符串到List<int> ...這是我想要控制的路由的一部分。

這可能嗎?

回答

8

一個很好的版本是實現你自己的模型活頁夾。你可以找到一個樣本here

我試着給你一個想法:

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<int>(); 
     foreach (string s in stringArray) 
     { 
      list.Add(int.Parse(s)); 
     } 
     return list; 
    } 
} 


public ActionResult GetItems([ModelBinder(typeof(MyListBinder))]List<int> id_list) 
{ 
    return View(); 
} 
3

像slfan的說,自定義模型粘合劑是要走的路。這是另一種方法from my blog,它是通用的並且支持多種數據類型。它也優雅地回落到默認的模型綁定實施:

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); 
    } 
} 
相關問題