Привязывание к модели списка значений, разделенных запятыми (asp.net-mvc)

В прошлой заметке я описывал как передавать списки значений в контроллер. Теперь опишу как создать пользовательский привязчик к модели, который будет привязывать параметр  со значениями, разделенными запятыми, к списку значений в контроллере.

Допустим есть такой контроллер

public void GetFilters(List<int> filterIds)
{
}

И мы хотим передать список значений таким образом

/GetFilters?filterIds=1,2,3

Для этого создадим класс — привязчик к модели

public class CommaSeparatedModelBinder : DefaultModelBinder
{
    private static readonly MethodInfo ToArrayMethod = typeof(Enumerable).GetMethod("ToArray");

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        return BindCsv(bindingContext.ModelType, bindingContext.ModelName, bindingContext)
            ?? base.BindModel(controllerContext, bindingContext);
    }

    protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
    {
        return BindCsv(propertyDescriptor.PropertyType, propertyDescriptor.Name, bindingContext)
            ?? base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
    }
    private object BindCsv(Type type, string name, ModelBindingContext bindingContext)
    {
        if (type.GetInterface(typeof(IEnumerable).Name) == null)
            return null;

        var actualValue = bindingContext.ValueProvider.GetValue(name);
        if (actualValue == null)
            return null;

        var valueType = type.GetElementType() ?? type.GetGenericArguments().FirstOrDefault();
        if (valueType == null || valueType.GetInterface(typeof(IConvertible).Name) == null)
            return null;

        var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(valueType));

        foreach (var splitValue in actualValue.AttemptedValue.Split(new[] { ',' }))
        {
            if (!String.IsNullOrWhiteSpace(splitValue))
                list.Add(Convert.ChangeType(splitValue, valueType));
        }

        if (type.IsArray)
            return ToArrayMethod.MakeGenericMethod(valueType).Invoke(this, new[] { list });
        else
            return list;
    }
}

И в классе Global.asax пропишем такие строчки

ModelBinders.Binders.Add(typeof(List<string>), new CommaSeparatedModelBinder());
ModelBinders.Binders.Add(typeof(List<long>), new CommaSeparatedModelBinder());
ModelBinders.Binders.Add(typeof(List<int>), new CommaSeparatedModelBinder());

На этом наш пользовательский привязчик к модели готов.

Ссылки:

По теме:
Выполняем get запрос по расписанию c#

Напишем простенькую программу, которая будет выполнять get запрос по истечению определенного интервала времени. class Program { private static Timer _timer; Read more

Выполняем действие по расписанию (asp.net, c#)

Раньше я писал программку, которая выполняла get запрос по расписанию, но так же можно написать обычный HttpModule, который будет делать Read more

Выбираем технологии и инструменты для разработки веб приложений

1 Выбор и настройка инструментов для разработки фронтенда (только самые важные): 1.1 Twitter bootstrap — фреймворк позволяет писать качественную верстку Read more

Делаем водяной знак на картинке (c#, .net)

Нанесем несколько раз картинку watermark на другую картинку. public void DrawWatermark(string watermarkImagePath, System.Drawing.Image image) { using (System.Drawing.Image watermarkImage = System.Drawing.Image.FromFile(watermarkImagePath)) Read more

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *