Archiv für die Kategorie „C#“

Seltsamer Fehler beim Start einer Silverlight-Anwendung.

Mittwoch, 9. September 2009

Nach “F5” kommt erst dieses Fenster:

image

Und dann dieses:

ArgumentException occured: Der Kulturname "uploads" wird nicht unterstützt. Parametername: name

Es handelt sich um eine Silverlight-Anwendung mit den .Net RIA Services. Bilder sind auch involviert. Der Fehler kommt, egal ob die Anwendung im Internet Explorer oder im Firefox startet, allerdings nur einmal nach einem Rebuild. Folgende Starts haben den Fehler nicht und klicke ich auf “Continue” funktioniert meine Anwendung auch ganz normal.

Ich habe schon im ganzen Projekt nach “uploads” gesucht ohne Erfolg sowie das komplette Projekt vor und nach dem ersten Start gedifft, aber auch hier keine Auffälligkeiten.

Ungewöhnlich ist auch, dass die Nachricht der Exception auf Deutsch ist, obwohl Visual Studio, Silverlight SDK und die .Net RIA Services auf Englisch installiert sind.

Ich konnte das Problem bisher nicht lösen, daher die Bitte, wer was weiß, sich bei mir zu melden. Habe ich eine Lösung, werde ich ein Update schreiben.

(weiterlesen…)

.Net RIA Services – kurz erklärt

Montag, 27. Juli 2009

image

Ich hab mich etwas mit den .Net RIA Services beschäftigt und möchte nun einen groben Überblick geben. Wir stellen uns also eine 3-Schichten Architektur vor, bestehend aus Silverlight 3, ASP.net und einem quasi beliebigem Data Access Layer.

Der Data Access Layer erzeugt aus einer Datenbank Objekte, welche nun in der mittleren Schicht sind (im Bild “Order”) und bietet auch die Standard CRUD-Funktionalität. In der Regel kann man diese Objekte nicht ohne weiteres an den Client übergeben.

Hier kommen nun die .Net RIA Services ins Spiel und generieren in der Silverlight-Applikation eine identische Klasse und ein asynchrones Kontextobjekt, um mit der Serviceschicht zu interagieren.

Alles was man noch tun muss, ist in der Mittelschicht eine Serviceklasse zu schreiben, die alle Funktionen zur Verfügung stellt, die der Client nutzen können soll. Dies können die normalen CRUD-Operationen sein, spezielle Servicemethoden, die mit den Objekten interagieren oder ganz allgemein beliebige Funktionen.

Reichert man die Klassen durch Metadaten an, bekommt man die Validierung der Daten auf beiden Schichten “fast geschenkt”:

[Range(0, 120, ErrorMessage = "Sprechende Fehlermeldung!")]
public int? Age { get; set; }

Hat man dies z.B. so bei einer Person definiert, wird der Nutzer bereits beim Eingeben der Daten auf dem Client mit einer sprechenden Fehlermeldung auf seinen Fehler hingewiesen. Zusätzlich wird aber auch auf der Mittelschicht eine erneute Validierung der Daten vorgenommen. Dies ist eine sehr schöne Ausprägung des DRY-Prinzips.

Außerdem werden alle Dateien mit dem Dateinamen *.shared.cs oder *.shared.vb in den Client kopiert, was Shared Code ermöglicht. Dies kann man nutzen, um generierte Properties anzulegen.

Das Ganze erleichtert den Entwicklungsprozess von viel langweiliger Arbeit und gibt einem mehr Zeit, für die wesentlichen Aspekte!

Weiterführende Links:

Präsentation auf der Mix09

Download von Setup und Dokumentation

Fluent Interfaces: Sinnvoll?

Donnerstag, 4. Juni 2009

Ich hatte Fluent Interfaces mal in einem Blog gelesen und hatte es seit dem auf meinem Zettel stehen, das mal genauer anzusehen.

Was ist das eigentlich? Wikipedia weiß es natürlich.

Sucht man bei Google danach findet man Blogs mit Einträgen von 2006/2007…sind Fluent Interfaces schon tot? Vielleicht!

Einige Beispiele:

IConfigurationFluent config =
      new ConfigurationFluent().SetColor("blue")
                               .SetHeight(1)
                               .SetLength(2)
                               .SetDepth(3);

Das schreit einfach nach dem Object Initializer von C#! In etwa so:

IConfiguration config =
      new Configuration {Color = “blue”, Height=1, Length=2, Depth=3};

Dann spart mach sich das zusätzliche “return this” in der Implementierung.

Ok, dann hat Troy Demonbreun folgendes Beispiel:

order
    .AddFreeShipping()
    .IncludeItem(15)
    .SuppressTax();

Das sieht an sich ja ganz nett aus, allerdings hat seine Implementierung den “Fehler”, dass IncludeItem() den Kontext von Order auf OrderItem ändert. Nach meinem Verständnis von Fluent Interfaces müsste aber folgendes möglich sein (geht bei ihm nicht):

order
    .AddFreeShipping()
    .IncludeItem(15).SuppressTax()
    .IncludeItem(4)
    .IncludeItem(77)
    .PrepareAsGift();

Und als drittes Beispiel hab ich folgendes, leicht komplexes Konstrukt gefunden:

EventComponent planningMeeting =
   Plan.Event("Project planning meeting").
      RelatedTo(planningTask).
      WithPriority(1).
      At("Head office").
      OrganizedBy("jane@megacorp.com", "Jane Doe").
      StartingAt("12:00").Lasting(45).Minutes.
      Attendants(
         "peter@megacorp.com",
         "paul@megacorp.com",
         "mary@contractor.com").AreRequired.
      Attendant("john@megacorp.com").IsOptional.
      Resource("Projector").IsRequired.
      ClassifyAs("Public").
      CategorizeAs("Businees", "Development").
      Recurring.Until(2008).EverySingle.Week.On(Day.Thursday).
      Except.Each.Year.In(Month.July | Month.August);
planningMeeting.SendInvitations();

…hier kann ich schon etwas verstehen, warum Fluent Interfaces (=FIs) sexy sein könnten. Aber zuerst muss ich hier auch sofort wieder an Object Initializer und Collection Initializer denken (Nein, ich bau das jetzt nicht um :-P ) und dann hab ich da noch einen letzten Punkt zu: Man kann FIs nur einsetzen, wenn man zu einem Zeitpunkt bereits alles weiß zu dem Objekt, was man erstellen will. Das ist an sich ja nicht schlecht, aber wie kommt denn die Liste der Attendants da rein? Doch meistens mit foreach und das geht nicht in dieser Kette von Aufrufen.

Ach und noch ein allerletzter Punkt: In diesem Ansatz muss ich viel Schmalz darauf verbraten, wann eine Methode Sinn macht:

…Attendants( … ).Except.Minutes.WithPriority(1); //?!

Fazit:
[x] Ich hab mir Fluent Interfaces angesehen
[x] Ich weiß keinen guten Fall, wann das Ganze wirklich Sinn macht