Пользовательский редактор связей модели DateTime в Asp.net MVC

Я хотел бы записать свой собственный образцовый редактор связей для DateTime ввести. В первую очередь, я хотел бы записать новый атрибут, как который я могу присоединить к своему свойству модели:

[DateTimeFormat("d.M.yyyy")]
public DateTime Birth { get; set,}

Это - легкая часть. Но часть редактора связей является немного более трудной. Я хотел бы добавить новый образцовый редактор связей для типа DateTime. Я могу также

  • реализация IModelBinder соедините интерфейсом и запишите мое собственное BindModel() метод
  • наследуйтесь DefaultModelBinder и переопределение BindModel() метод

Моя модель имеет свойство, как замечено выше (Birth). Таким образом, когда модель пытается связать, запрашивают данные к этому свойству, мой образцовый редактор связей BindModel(controllerContext, bindingContext) вызывается. Все хорошо, но. Как я получаю атрибуты свойства от controller/bindingContext, для парсинга моей даты правильно? Как я могу добраться до PropertyDesciptor из свойства Birth?

Править

Из-за разделения проблем мой образцовый класс определяется в блоке, который не делает (и не был должен), ссылочная Система. Сеть. Блок MVC. Установка пользовательской привязки (подобный примеру Scott Hanselman) атрибуты является остановкой здесь.

23
задан Robert Koritnik 1 March 2010 в 15:26
поделиться

2 ответа

Я не думаю, что вам следует помещать в модель атрибуты, специфичные для конкретной местности.

Два других возможных решения этой проблемы:

  • Пусть ваши страницы транслитерируют даты из локально-специфического формата в общий формат, такой как yyyy-mm-dd, на JavaScript. (Работает, но требует JavaScript.)
  • Напишите связующую модель, которая учитывает текущую культуру пользовательского интерфейса при разборе дат.

Чтобы ответить на ваш вопрос, способ получить пользовательские атрибуты (для MVC 2) - написать AssociatedMetadataProvider.

3
ответ дан 29 November 2019 в 00:39
поделиться

У меня самого была эта очень большая проблема, и после нескольких часов попыток и неудач я получил рабочее решение, как вы и просили.

Прежде всего, поскольку привязка только к свойству невозможна, вы должны реализовать полноценный ModelBinder. Поскольку вы не хотите связывать все свойства, а только то, которое вам важно, вы можете наследовать от DefaultModelBinder и затем связать одно свойство:

public class DateFiexedCultureModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.PropertyType == typeof(DateTime?))
        {
            try
            {
                var model = bindingContext.Model;
                PropertyInfo property = model.GetType().GetProperty(propertyDescriptor.Name);

                var value = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);

                if (value != null)
                {
                    System.Globalization.CultureInfo cultureinfo = new System.Globalization.CultureInfo("it-CH");
                    var date = DateTime.Parse(value.AttemptedValue, cultureinfo);
                    property.SetValue(model, date, null);
                }
            }
            catch
            {
                //If something wrong, validation should take care
            }
        }
        else
        {
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        }
    }
}

В моем примере я разбираю дату с фиксированной культурой, но то, что вы хотите сделать, возможно. Вы должны создать CustomAttribute (например, DateTimeFormatAttribute) и поместить его над вашим свойством:

[DateTimeFormat("d.M.yyyy")]
public DateTime Birth { get; set,}

Теперь в методе BindProperty вместо того, чтобы искать свойство DateTime, вы можете искать свойство с вашим DateTimeFormatAttribute, взять формат, который вы указали в конструкторе, а затем разобрать дату с помощью DateTime.ParseExact

Надеюсь, это поможет, у меня ушло очень много времени, чтобы прийти к этому решению. На самом деле это решение было простым, как только я понял, как его искать :(

14
ответ дан 29 November 2019 в 00:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: