2011-08-29 1 views
8

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

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

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

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

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

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

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

Думаю, я бы рассмотрел возможность создания пользовательского атрибута Data Annotation, если бы я был вами. Если это то, о чем вы вообще знакомы, возьмите его и бегите с ним. Если нет, прокомментируйте это, и я расскажу вам кое-что. –

+0

@Rick, мне было бы очень интересно увидеть вашу реализацию. –

+0

Я получу несколько ссылок и пример кода завтра в офисе и отправлю их здесь. –

ответ

14

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

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); 
     } 
    } 
} 

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

+0

Спасибо, это сработало очень хорошо, и это был именно тот тип решения, которое я искал. –

0

Bind to string с вашей модели. Затем, когда переход обратно к реальной модели.

+0

Да, я подумал об этом. (Я добавил, что в качестве решения я бы предпочел не рассматривать в моем вопросе.) Но тогда я должен сделать это с * каждым свойством процента *, плюс он в значительной степени нарушает парадигму MVC. –

1

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

+0

Да, это было первое потенциальное решение, о котором я упомянул в первоначальном вопросе. Я не против этого, но кажется довольно драконовским, чтобы создать еще один целый класс домена, чтобы обойти форматирование и привязку поведения структуры. –

+2

Ну, если вы посмотрите на это с точки зрения, что это представляет собой конкретное деловое требование, мне кажется гораздо более подходящим. –