2011-12-06 15 views
3

私はのように見えるASP.NET MVCのルートを設定したい:私のコントローラのアクションに... ...ASP.NET MVCコントローラのカスタムパラメータ変換アクション

Example/GetItems/1,2,3 

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

次のようになりルート要求していることを:

私は List<int>stringから idl URLパラメータを変換し、Aを呼び出すように設定するのです何の問題がある
public class ExampleController : Controller 
{ 
    public ActionResult GetItems(List<int> id_list) 
    { 
     return View(); 
    } 
} 

、適切なコントローラのアクション?

related question here私は文字列を前処理するためにOnActionExecutingを使用しましたが、タイプを変更していないことがわかりました。私はコントローラでOnActionExecutingを無効にしてActionExecutingContextのパラメータを調べると、idlのキーにnull値のキーが既に存在することがわかります。おそらく、文字列からList<int> ...これは私が制御したいルーティングの一部です。

これは可能ですか?

答えて

8

いいバージョンは、独自のモデルバインダーを実装することです。あなたは、私はあなたのアイデアを与えることを試みるサンプルhere

を見つけることができます。slfanのよう

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

は、カスタムモデルバインダーを移動するための方法である、と言います。ここに別のアプローチ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); 
    } 
} 
関連する問題