05 Dec
2010

Vereinfachte Lokalisierung eines ViewModels in ASP.NET MVC

 

Ich arbeite gerade an einer Anwendung die ich auch mehrsprachig anbieten möchte. Dabei sind mir ein paar Sachen aufgefallen die unhandlich sind. Hier dazu meine Lösungen

Display-Name von Properties in ViewModels

In ASP.NET MVC 3 kann ich mit der leichten Syntax

  [Display(ResourceType=typeof(SpeakertNetStrings), Name="Speaker_Session")] 
  public string Fullname { get; set; } 

  [Display(ResourceType=typeof(SpeakertNetStrings), Name="Speaker_Session")] 
  public int SessionCount { get; set; } 

die passenden Resource-Strings angeben, dieser wird dann mit dem Label- bzw. LabelFor-HtmlHelper dargestellt. Da dies jedoch ein .NET 4 Attribute ist, funktioniert es unter .NET 3.5 nicht. Auch ist es unpraktisch in der Anwendung. Das unter ASP.NET MVC 2 verwendetet DisplayNameAttribute funktioniert zwar auch unter MVC 3, jedoch kann ich da nur einen String direkt angegeben, von Lokalisierung keine Spur.

Also habe ich mir folgendes Attribute gebastelt, was nur noch entsprechend der Anwendung angepasst werden muss.

public class LabelAttribute : DisplayNameAttribute 
  { 
  public LabelAttribute(string resourceName) 
      : base(GetDisplayName(resourceName)) 
  { 
  } 

  private static string GetDisplayName(string resourceName) 
  { 
     var displayName = SpeakertNetStrings.ResourceManager.GetString(resourceName, SpeakertNetStrings.Culture); 
     return displayName ?? "Missing: " + resourceName; 
  } 
} 

Hiermit ist die Auszeichnung der Properties mit ResourceS-trings viel einfacher. Man muss nur noch den Resource-String angeben.

  [Label("Speaker_Session")] 
  public string Fullname { get; set; } 

  [Label("Speaker_Session")]
  public int SessionCount { get; set; } 

  

Dies funktioniert unter ASP.NET MVC 2 und 3, dass DisplayAttribute ist sealed und davon ist eine Ableitung nicht möglich. Die notwendige Anpassung besteht darin auf die eigenen Resourcen zu verweisen.

Darstellung des Display-Namens

Um den übersetzten Namen der Property anzuzeigen gibt es die Label- und LabeFor-HtmlHelper. Jedoch funktionieren die nicht an allen Stellen in einem View und manchmal muss man sich die Resource-Strings dann manuell holen. Desweiteren will man auch nicht überall ein Label-Tag drum herum haben und einfach mal nur den Namen anzeigen.

Dies geht, aber ist etwas unpraktisch sobald man z.B. den Resource-Namen umbenennt.  Dann muss ich dies in allen Views auch anpassen und nicht nur an einer Stelle am ViewModel.

Jedoch liegen die notwendige Information in den Meta-Daten vor, also müssten Sie nur noch rausgepult werden. Dazu habe ich mir mal zwei Extensionmethoden gebaut.

public static class MetadataExtensions 
  { 
  public static string GetDisplayName(this Type type, string propertyName) 
  {
    return ModelMetadataProviders.Current
	       .GetMetadataForProperty(() => null, type, propertyName).GetDisplayName(); 
  } 

  public static string GetDisplayName(this T instance, string propertyName) 
  {
    return ModelMetadataProviders.Current
	       .GetMetadataForProperty(() => instance, typeof(T), propertyName).GetDisplayName(); 
  } 
}

Diese Variante ist hier bewusst einfach gehalten, sie kann den Anwendungsanforderungen entsprechend einfach ergänzt werden um z.B. typisierten Zugriff auf die PropertyNamen zu erhalten.

Die Anwendung ist sehr einfach gezeigt, ein Bespiel in der Razor-Syntax

<th>@Model.GetDisplayName("Fullname")</th> 
<th>@typeof(SpeakerSessionListModel).GetDisplayName("SessionCount")</th>

Ich hoffe dies hilft weiter


Der Eintrag ist mir etwas Wert
 
Comments have been closed on this topic.