ASP.NET MVC-ViewModel-mapping mit benutzerdefinierten Formatierung

Dem Projekt an dem ich arbeite hat eine große Anzahl von Währung Eigenschaften in der Domäne Modell, und ich bin benötigen für format diese als $#,###.## für die übertragung zu und von der Ansicht. Ich hatte einen Gedanken auf die verschiedenen Ansätze, die genutzt werden könnten. Ein Ansatz könnte sein, formatieren Sie die Werte explizit innerhalb der Ansicht, wie in "Muster 1" von Steve Michelotti :

...aber diese startet gegen DRY-Prinzip sehr schnell.

Der bevorzugte Ansatz zu sein scheint, zu tun, die Formatierung während der Zuordnung zwischen DomainModel und ein ViewModel (als pro ASP.NET MVC in Aktion Abschnitt 4.4.1 und "Muster 3"). Mit AutoMapper, wird dies dazu führen, dass code wie der folgende:

[TestFixture]
public class ViewModelTests
{
 [Test]
 public void DomainModelMapsToViewModel()
 {
  var domainModel = new DomainModel {CurrencyProperty = 19.95m};

  var viewModel = new ViewModel(domainModel);

  Assert.That(viewModel.CurrencyProperty, Is.EqualTo("$19.95"));
 }
}

public class DomainModel
{
 public decimal CurrencyProperty { get; set; }
}

public class ViewModel
{
 ///<summary>Currency Property - formatted as $#,###.##</summary>
 public string CurrencyProperty { get; set; }

 ///<summary>Setup mapping between domain and view model</summary>
 static ViewModel()
 {
  //map dm to vm
  Mapper.CreateMap<DomainModel, ViewModel>()
   .ForMember(vm => vm.CurrencyProperty, mc => mc.AddFormatter<CurrencyFormatter>());
 }

 ///<summary> Creates the view model from the domain model.</summary>
 public ViewModel(DomainModel domainModel)
 {
  Mapper.Map(domainModel, this);
 }

 public ViewModel() { }
}

public class CurrencyFormatter : IValueFormatter
{
 ///<summary>Formats source value as currency</summary>
 public string FormatValue(ResolutionContext context)
 {
  return string.Format(CultureInfo.CurrentCulture, "{0:c}", context.SourceValue);
 }
}

Mit IValueFormatter diese Weise Super funktioniert. Nun, wie man eine Karte wieder aus dem DomainModel zu ViewModel? Ich habe versucht, mit einer benutzerdefinierten class CurrencyResolver : ValueResolver<string,decimal>

public class CurrencyResolver : ValueResolver<string, decimal>
{
 ///<summary>Parses source value as currency</summary>
 protected override decimal ResolveCore(string source)
 {
  return decimal.Parse(source, NumberStyles.Currency, CultureInfo.CurrentCulture);
 }
}

Dann abgebildet mit:

  //from vm to dm
  Mapper.CreateMap<ViewModel, DomainModel>()
   .ForMember(dm => dm.CurrencyProperty, 
    mc => mc
     .ResolveUsing<CurrencyResolver>()
     .FromMember(vm => vm.CurrencyProperty));

Befriedigen können diesen test:

 ///<summary>DomainModel maps to ViewModel</summary>
 [Test]
 public void ViewModelMapsToDomainModel()
 {
  var viewModel = new ViewModel {CurrencyProperty = "$19.95"};

  var domainModel = new DomainModel();

  Mapper.Map(viewModel, domainModel);

  Assert.That(domainModel.CurrencyProperty, Is.EqualTo(19.95m));
 }

... Aber ich habe das Gefühl, dass ich sollte nicht müssen, explizit zu definieren, welche Eigenschaft es ist, die zugeordnet wird, die aus mit FromMember nach ResolveUsing da die Eigenschaften die den gleichen Namen haben - gibt es eine bessere Art und Weise zu definieren diese Zuordnung? Wie ich bereits erwähnte, gibt es eine gute Anzahl von Eigenschaften, die mit Währung Werte, die abgebildet werden müssen in diesem Mode.

Dass gesagt wird - gibt es eine Möglichkeit, ich könnte diese Zuordnungen automatisch gelöst werden, durch die Definition einige Regel weltweit? Die ViewModel-Eigenschaften sind bereits dekoriert mit DataAnnotation Attribute [DataType(DataType.Currency)] für die Validierung, also ich hatte gehofft, dass ich definieren könnte, eine Regel, die funktioniert:

if (destinationProperty.PropertyInfo.Attributes.Has(DataType(DataType.Currency)) 
  then Mapper.Use<CurrencyFormatter>()
if (sourceProperty.PropertyInfo.Attributes.Has(DataType(DataType.Currency)) 
  then Mapper.Use<CurrencyResolver>()

... so dass ich können Sie minimieren die Menge an boilerplate-setup für die einzelnen Objekttypen.

Ich bin auch daran interessiert zu hören von anderen Strategien für die Erfüllung benutzerdefinierte Formatierung an-und-aus der Sicht.


Vom ASP.NET MVC in Aktion:

Zuerst könnten wir versucht sein, Sie zu passieren
dieses einfache Objekt direkt an der
Ansicht, aber die DateTime? Eigenschaften
[im Modell] wird zu Problemen führen.
Zum Beispiel, wir müssen wählen
die Formatierung für Sie wie
ToShortDateString() oder ToString(). Die
Ansicht gezwungen sein würde zu tun, null
überprüfen, um zu halten Sie den Bildschirm aus
Sprengung, wenn die Eigenschaften sind
null. Ansichten sind schwer zu Einheit
testen, so dass wir wollen, um Sie so Dünn
wie möglich. Da die Ausgabe ein
view ist ein string, der an die
Antwort stream, wir benutzen nur
Objekte, die stringfriendly; dass
Objekte, die nie Versagen, wenn
ToString() aufgerufen wird. Die
ConferenceForm view-model-Objekt ist ein
Beispiel. Beachten Sie in listing
4.14, dass alle Eigenschaften sind strings. Wir haben die Termine richtig
formatiert, bevor das view-Modell
Objekte, die sich in den Daten anzeigen. Diese
Möglichkeit, die anzeigen müssen nicht der Auffassung der
Objekt, und es kann das format der
Informationen richtig.

  • <%= string.Format("{0:c}", Modell.CurrencyProperty) %> sieht ziemlich zu mir. Vielleicht bin ich nur benutzt, um es...
Schreibe einen Kommentar