2011-08-29 19 views
8

Moja aplikacja ma wiele modeli, z których wiele zawiera dane procentowe. Są one reprezentowane w modelu jako konstrukcje decimal lub decimal?. Jednak nie wszystkie właściwości o strukturach decimal są procentami. Niektóre powinny być traktowane jak zwykłe znaki dziesiętne.Wartości procentowe w MVC 3

Procenty wymagają szczególnej uwagi:

  • Na wyświetlaczu powinny używać formatu {0:P2}. (Mam tę część działa.)
  • Do edycji, powinny one pozwolić na taki sam format jak wyświetlacz, tj. "95" lub "95%" lub "95,00%" wszystkie wiążą się z wartością 0,95.

zacząłem dół drogi tworzenia PercentModelBinder który implementuje IModelBinder, ale potem zrozumiałem, że można zastosować tylko ModelBinderAttribute się do klasę, a nie materialnych.

Jaki jest najlepszy sposób na obsłużenie tego przypadku, w którym niektóre zastosowania typu wymagają specjalnej obsługi zarówno do wyświetlania, jak i wiązania?

Każde rozwiązanie, o którym myślę, że źle pachnie przesadą, walczy z ramami MVC. Z pewnością nie jest to lepszy sposób niż:

  • Tworzenie niestandardowego Percentage struct i używając go jako podstawa do IModelBinder i EditorTemplates lub
  • reimplementing zachowanie decimal i decimal? wiązania domyślne i zmieniającym logikę parsowania opartej na intymnej znajomości mojego modelu lub
  • Realizacja spinacza modelu niestandardowych dla każdej klasy, która zawiera właściwość procentowe lub
  • Korzystanie fałszywe właściwości proxy w modelu (tj zerwania MVC)
+0

Myślę, że rozważyłbym napisanie niestandardowego atrybutu adnotacji danych, gdybym był tobą. Jeśli to jest coś, co w ogóle znasz, weź to i biegnij z tym. Jeśli nie, komentarz z powrotem, a ja wstawię dla ciebie kilka informacji. –

+0

@ Rick, byłbym bardzo zainteresowany widząc twoją implementację. –

+0

Zdobędę kilka linków i przykładowy kod razem jutro w biurze i zamieszczę je tutaj. –

Odpowiedz

14

Jedną z możliwości jest napisać niestandardowy metadanych świadomy atrybut:

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

następnie ozdobić swoje Widok Model właściwości, które reprezentują procenty z nim:

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

i środka wiążącego testu modelu klienta na obecność tej wartości:

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

Teraz możesz zarejestrować ten model spoiwa dla wszystkich miejsc dziesiętnych.

+0

Dziękuję, działało to bardzo dobrze i było dokładnie takim rozwiązaniem, jakiego szukałem. –

0

Powiąż z string w swoim modelu widoku. Następnie kiedy konwersja z powrotem do prawdziwego modelu.

+0

Tak, myślałem o tym. (Dodałem, że jako rozwiązanie wolałbym nie brać pod uwagę w moim pytaniu.) Ale wtedy muszę to zrobić z * każdą pojedynczą procentową własnością *, plus to zepsuje paradygmat MVC. –

1

Zamiast reprezentować swoje procentowe właściwości za pomocą prymitywów dziesiętnych (patrz Primitive Obsession), dlaczego nie utworzyć typu procentowego, aby zawinąć pożądaną funkcjonalność? Trzeba mieć dużo większą elastyczność, robi to w ten sposób ...

+0

Tak, to było pierwsze potencjalne rozwiązanie, o którym wspomniałem w pierwotnym pytaniu. Nie jestem przeciwny temu, ale wydaje się dość drakońskim, że trzeba stworzyć kolejną całą klasę domen, aby obejść formatowanie i zachowanie wiążące ramy. –

+2

Cóż, jeśli spojrzeć na to z perspektywy, że reprezentuje konkretny wymóg biznesowy, wydaje mi się to o wiele bardziej odpowiednie. –