Tindakan pengontrol ASP.NET MVC dengan konversi parameter khusus?

Saya ingin menyiapkan rute ASP.NET MVC yang terlihat seperti:

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

Itu merutekan permintaan yang terlihat seperti ini...

Example/GetItems/1,2,3

...untuk tindakan pengontrol saya:

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

Pertanyaannya adalah, apa yang harus saya atur untuk mengubah parameter url idl dari string menjadi List<int> dan memanggil tindakan pengontrol yang sesuai?

Saya telah melihat pertanyaan terkait di sini yang menggunakan OnActionExecuting untuk memproses string terlebih dahulu, tetapi tidak mengubah jenisnya. Saya rasa itu tidak akan berhasil untuk saya di sini, karena ketika saya mengganti OnActionExecuting di pengontrol saya dan memeriksa parameter ActionExecutingContext, saya melihat bahwa kamus ActionParameters sudah memiliki kunci idl dengan nilai nol- mungkin, percobaan cast dari string ke List<int>... ini adalah bagian dari perutean yang ingin saya kendalikan.

Apakah ini mungkin?


person Factor Mystic    schedule 06.12.2011    source sumber


Jawaban (2)


Versi yang bagus adalah mengimplementasikan Model Binder Anda sendiri. Anda dapat menemukan contohnya di sini

Saya mencoba memberi Anda gambaran:

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(); 
} 
person slfan    schedule 06.12.2011

Seperti yang dikatakan slfan, pengikat model khusus adalah cara yang tepat. Inilah pendekatan lain dari blog saya yang bersifat generik dan mendukung banyak tipe data. Ini juga secara elegan kembali ke implementasi pengikatan model default:

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);
    }
}
person Nathan Taylor    schedule 07.12.2011