Процентная недвижимость в MVC 3 - PullRequest
9 голосов
/ 29 августа 2011

В моем приложении много моделей, многие из которых содержат процентные данные. Они представлены как decimal или decimal? структуры в модели. Однако не все свойства с decimal структурами являются процентами. Некоторые должны рассматриваться как обычные десятичные дроби.

Проценты требуют особого внимания:

  • Для отображения они должны использовать формат {0:P2}. (У меня эта часть работает.)
  • Для редактирования они должны иметь тот же формат, что и дисплей, то есть «95», «95%» или «95,00%» все привязываются к значению 0,95.

Я начал создавать PercentModelBinder, который реализует IModelBinder, но затем понял, что вы можете применить ModelBinderAttribute только к классу , а не к свойству.

Как лучше всего справиться с этим случаем, когда некоторым (но не всем) типам использования требуется специальная обработка как для отображения, так и для привязки?

Каждое решение, которое мне кажется, плохо пахнет излишним, борясь с MVC. Конечно, есть лучший способ, чем:

  • Создание пользовательской структуры Percentage и использование ее в качестве основы для IModelBinder и EditorTemplates или
  • Переопределение поведения привязки по умолчанию decimal и decimal? и изменение логики синтаксического анализа на основе глубоких знаний моей модели, или
  • Реализация пользовательского связывателя модели для каждого класса, который содержит процентное свойство, или
  • Использование поддельных свойств прокси в модели (то есть взлом MVC)

Ответы [ 3 ]

15 голосов
/ 30 августа 2011

Одна возможность - написать атрибут с поддержкой пользовательских метаданных:

public class PercentageAttribute : Attribute, IMetadataAware
{
    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["percentage"] = metadata.EditFormatString;
    }
}

затем украсьте свойства вашей модели представления, которые представляют проценты с ним:

public class MyViewModel
{
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:P2}")]
    [Percentage]
    public decimal? Percentage { get; set; }
}

и внутри пользовательского теста на связывание модели на наличие этого значения:

public class PercentageModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelMetadata.AdditionalValues.ContainsKey("percentage"))
        {
            var format = (string)bindingContext.ModelMetadata.AdditionalValues["percentage"];
            // TODO: do the custom parsing here
            throw new NotImplementedException();
        }
        else
        {
            // Let the default parsing occur
            return base.BindModel(controllerContext, bindingContext);
        }
    }
}

Теперь вы можете зарегистрировать эту модель связывания со всеми десятичными знаками.

1 голос
/ 30 августа 2011

Вместо того, чтобы представлять ваши процентные свойства с помощью десятичных примитивов (см. Primitive Obsession ), почему бы вам не создать тип Percentage для упаковки желаемой функциональности?Вы должны иметь гораздо больше гибкости, делая это таким образом ...

0 голосов
/ 29 августа 2011

Привязать к string в вашей модели представления.Затем, когда сделать преобразование обратно в реальную модель.

...