using System.Web.Mvc.Html;

Es ist nur eine kleine Sache, aber es kann je nach dem dauern, bis man darauf kommt (wie bei mir heute…):

Wenn man eine neue Extension Method für HtmlHelper schreiben will, z.B. einen speziell „konfigurierte“ Variante von Html.ActionLink, sind Methoden wie eben ActionLink erst sichtbar, wenn man neben System.Web.Mvc auch System.Web.Mvc.Html importiert.

Man kommt deshalb so schlecht drauf, weil Visual Studio 2010 nicht genügend schlau ist, auf diese Tatsache hinzuweisen, wenn man im Code htmlHelper.ActionLink hinschreibt, bzw. der „using“-Assistent findet zwar heraus, dass man für einen HtmlHelper einen Import von System.Web.Mvc benötigt, versagt aber für ActionLink und ähnliche Methoden.

Veröffentlicht in Allgemein. Schlagwörter: . Leave a Comment »

Eigene Fehlerseiten in ASP.NET MVC2

Heute wollte ich in der ASP.NET-MVC2-Web-Applikation, an der ich gerade arbeite, eigene Fehlerseiten einrichten, vor allem natürlich für den HTTP-Fehler 404.

Auf den ersten Blick sieht alles ziemlich einfach aus, denn solche eigene Fehlerseiten sind ein häufig benötigtes Feature, und die Erbauer von MVC haben entsprechend etwas bereitgestellt: Die Stichworte sind da Einsatz des HandleErrorAttribute im Code und customErrors in web.config, bei Microsoft z.B. hier beschrieben.

Rein optisch sieht das Resultat im Browser perfekt aus, bei Fehler kommt die eigene Seite, die man nach Belieben selbst gestalten kann. Die Sache hat aber einen ziemlich grossen Schönheitsfehler: Der Webserver liefert die Fehlerseite nicht mit dem Fehler als Statuscode aus, sondern mit Code 200 „alles in Ordnung“. Das ist im besten Fall einfach Unsinn und führt im schlimmsten Fall dazu, dass Roboter von Suchmaschinen beim Abklappern der Website ein ziemlich schiefes Bild davon bekommen.

Bei meiner Suche im Internet nach einer Lösung für dieses Problem kam ich dann ganz schön ins Staunen: Ich glaube, ich habe noch nie einen solchen Wildwuchs von Lösungen und Lösungsversuchen betreffend MVC angetroffen wie bei dieser Sache! Eine Auswahl von dem, was ich gefunden habe:

Dieser Artikel beschreibt das Problem ausführlich und schlägt eine Lösung vor, die etwas kompliziert aussieht und zudem schon etwas älter zu sein scheint. Dieser Artikel zählt eine lange Liste diverser Eingriffe auf, bei denen wohl die Meinung sein soll, sie seien alle nötig, damit es sicher mit jeder Kombination von Framework und IIS klappt, was mir etwas unwahrscheinlich erschien.

Implementiert habe ich schliesslich die hier beschriebene Lösung, die up-to-date, einfach und übersichtlich ist und an der ich (bis jetzt zumindest) trotzdem keinen Haken finden konnte; kann ich also empfehlen.

Diese Lösung klappt übrigens nicht nur mit dem Wert On für den Parameter mode bei customErrors, sondern ebensogut mit RemoteOnly, was für das Debugging gewisse Vorteile haben kann.

Veröffentlicht in Allgemein. Schlagwörter: , . Leave a Comment »

Debugging von ASP.NET-MVC2-Applikationen

Irgendwie ging immer alles schief, wenn ich Fehler aufspüren wollte in der Applikation, die ich gerade mit ASP.NET MVC2 entwickle: Z.B. bei der Verwendung eines Objekts, das fehlerhafterweise null war, stoppte der Debugger nicht am Ort des Fehlers, sondern irgendwo im MVC2-Code, dort nämlich, wo ein „hoch oben“ angesiedelter Handler per catch die resultierende Exception abfing.

Um noch eins draufzusetzen, hatte Visual Studio zudem etwas am entsprechenden MVC2-Source-File mit dem catch drin zu meckern, das es vom Microsoft-Source-Code-Server heruntergeladen hatte, irgendetwas mit Some bytes have been replaced with the Unicode substitution character while loading file, so wie bei StackOverflow hier beschrieben, notabene ohne Tipps zur Abhilfe.

Es gibt in Visual Studio eine Einstellung, mit der der Debugger gleich stoppt, sobald irgendeine Exception auftritt, unabhängig davon, ob ein catch dafür zuständig ist oder nicht, so wie hier beschrieben, aber dieser Mechanismus hat auch so seine Probleme:

Mit Debugging-Option Enable Just My Code nicht gesetzt gibt’s viel zu viele Exceptions, weil in MVC2 vieles über Exceptions abgehandelt wird, die man dann alle erst „wegklicken“ muss, bis schliesslich die eigene Exception drankommt, um die es eigentlich geht. Und mit Option gesetzt klappt’s mit Exceptions innerhalb von MVC2 nicht, die auftreten, weil man z.B. einer Methode einen Parameter als null übergeben hat, der definiert sein muss.

Die Rettung war schliesslich folgendes Vorgehen:

Man kann dankenswerterweise den Source Code von ASP.NET MVC2 bei Microsoft CodePlex hier herunterladen, in einer Form, über die Visual Studio nichts zu meckern hat. Und es ist überraschend einfach, diesen Code quasi als „eigenen“ Code in sein Projekt einzubinden, so wie hier beschrieben. (Die Beschreibung ist zwar noch für MVC1, es klappt aber auch mit MVC2.)

Für die Zeit der Entwicklung meiner Applikation habe ich nun an zwei Orten in diesem MVC2-Source-Code catch-Anweisungen auskommentiert, so dass der Debugger die meisten auftretenden Exceptions als unhandled taxiert und gleich stoppt. (So komme ich jetzt ohne die erwähnte untaugliche Option aus, die den Debugger bei jeder Exception stoppen lässt.)

Auch sonst ist es natürlich ganz interessant, ein paar Blicke auf diesen Source-Code zu werfen, und man findet im Netz etliche Kommentare von Leuten, die schwierige Probleme in ihren Web-Applikationen nur dadurch lösen konnten, indem sie anhand dieser Sourcen im Debugger verfolgten, was innerhalb ASP.NET MVC2 genau passierte.

Veröffentlicht in Allgemein. Schlagwörter: , , . Leave a Comment »

ASP.NET, EF4 und Threads: Klappt das eigentlich?

Seit einiger Zeit arbeitete ich mich in die Welt der Programmierung von Web-Applikationen ein, mit Hilfe von ASP.NET MVC2, unter Verwendung von Entity Framework 4 (EF4) für den Datenbank-Zugriff.

Es ging eine ganze Weile, bis mir auffiel, dass in allem Demo-Code und in allen Demo-Projekten wie etwa dem Nerd Dinner nirgends die Rede war von Datenkonsistenz-Problemen, die es geben kann bei Verwendung von ASP.NET und EF4. ASP.NET arbeitet per se mit Multi-Threading, und deshalb können die Datenbankzugriffe ganz schön durcheinandergehen, wenn man auf einem Web-Server eine anständige Menge an Zugriffen hat. Zudem bringt die Verwendung von EF4 mit sich, dass in einem ObjectContext-Objekt eine Menge Daten zwischengespeichert werden können. Die Gefahr, dass sich mehrere Nutzer meiner Web-Applikation gegenseitig ihre Änderungen überschreiben, schien mir real zu sein.

Heute bin ich deshalb dieser Frage auf den Grund gegangen und dabei auf eine kleine Überraschung gestossen.

Multi-Threading in ASP.NET findet statt auf der Ebene der Requests: 1 Request wird jeweils in einem eigenen Thread ausgeführt. In ASP.NET MVC2 werden Controllers pro Request jeweils neu erzeugt; wenn man also wie in den Samples vorgegeben einen EF4-Objekt-Kontext als normale Property der Controller-Klasse implementiert, leben diese Objekte nur recht kurz, womit sich auch das Risiko von Konflikten deutlich reduziert.

Nebenbei bemerkt: Solange man nicht selbst Threads erzeugt in seiner MVC-Applikation, sondern nur dem „automatischen“ Threading von ASP.NET unterworfen ist, hat man also kein Problem damit, dass ObjectContext wie viele andere Framework-Klassen nicht thread-safe ist. Man darf nur nicht auf die Idee kommen, ein solches Objekt static zu deklarieren in seinem Controller!

Soweit, so gut, aber das Risiko von Konflikten sinkt damit natürlich nicht auf Null.

Die erwähnte Überraschung (zumindest für mich) fand sich schliesslich in diesem MSDN-Artikel: Per Default prüft EF4 bei Datenveränderungen nicht auf irgendwelche Optimismus-Verletzungen, sondern überschreibt einfach munter mit den aktuellen Daten in den Entities.

Mir persönlich scheint das ein etwas fragwürdiger Default zu sein, aber zum Glück kann man ihn relativ einfach überstimmen: Auf der Ebene einzelner Properties in einem EF4-Datenmodell ändert man einfach die Eigenschaft Concurrency Mode weg vom Default None auf Fixed. Die korrekte Behandlung einer OptimisticConcurrencyException, die es dann bei SaveChanges() geben kann, wird z.B. in diesem MSDN-Artikel erläutert. Wieso allerdings dieser Modus „fixed“ heisst, hat sich mir bisher nicht erschlossen…

Wenn’s etwas komplizierter wird und man z.B. einen eigenen Datenzugriffs-Layer in seiner Applikation implentieren will, findet man hier gute Erläuterungen zu Varianten, wie man die „Lebenszeit“ von ObjectContext-Objekten organisieren kann.

Veröffentlicht in Allgemein. Schlagwörter: , , . 1 Comment »