API-Minimalismus

Ich verfolge schon seit geraumer Zeit, was auf dem Gebiet der Smartphone-Betriebssysteme passiert.

Eines der bemerkenswertesten Ereignisse auf diesem Gebiet in letzter Zeit ist für mich die Art, wie Microsoft Windows Phone 7 zum Laufen gekriegt hat: Während Nokia viele Jahre damit verbracht hat, einen Versuch der Symbian-Modernisierung nach dem anderen an die Wand zu fahren, hat Microsoft in der unglaublich kurzen Zeit von etwa anderthalb Jahren ein einigermassen brauchbares Smartphone-OS mit modernem und sogar stellenweise innovativem User Interface aus dem Boden gestampft.

Natürlich ist WP7 bei näherem Hinsehen nicht „neu“: Im Inneren werkelt der immer noch gleiche uralte Windows-CE-Kernel, und die Benutzeroberfläche besteht im wesentlichen aus Silverlight und XNA, beides Systeme, die bereits bestanden und zu Beginn der Arbeiten an WP7 bereits eine ordentliche Reife erlangt hatten. Es ist aber meiner Meinung nach trotzdem eine tolle Leistung, all diese Teile brauchbar zu kombinieren und in kurzer Zeit zur Marktreife zu bringen.

So weit, so gut. Seit einigen Tagen allerdings hat mein Bild von WP7 ein paar Kratzer abbekommen. Ich habe WP7 gewählt, um mich in die WPF/Silverlight/XAML-basierte Welt der .NET-Benutzeroberflächen-Programmierung für „konventionelle“ Applikationen (im Gegensatz zu Web-Applikationen) einzuarbeiten und komme doch ziemlich ernüchtert von ersten Detail-Abklärungen zurück.

Auch Microsoft konnte nicht zaubern, und um WP7 in so kurzer Zeit zu stemmen, musste wohl jemand mit eiserner Hand die Aufgabe auf ein handhabbares Mass reduzieren. Herausgekommen ist ein Smartphone-OS mit einer API, die arg schwach auf der Brust ist.

Am konkreten Beispiel: Was kann ein Programmierer, der eine WP7-App baut, punkto SMS auf dem Gerät alles anstellen?

Kann er sich in den Empfang von SMS einklinken, um z.B. eine SMS-Auto-Responder-App zu bauen? Nein, es gibt keine API hierfür. Kann er eine App bauen, die – Erlaubnis des Smartphone-Besitzers natürlich vorausgesetzt – automatisch SMS versendet, die z.B. Kollegen an nahende Termine erinnern? Nein. Kann er eine App bauen, die es möglich macht, eine früher gesendete SMS abzuändern und jemand anderem ebenfalls zu senden? Oder eine App für den Backup aller SMS? Nein, kann er nicht, die API gewährt keinen Zugriff auf den SMS-Speicher.

Ja, gibt es denn überhaupt irgendwelche Unterstützung im API betreffend SMS? Nun ja, eine WP7-App kann betreffend SMS genau eine Funktion ausführen, eine einzige: Sie kann einen SMS-Text und eine Liste von Empfängern vorbereiten und an den SMS-Erfassungs-View senden, wo dann der Benutzer bei Bedarf noch ändern und die fertige SMS schliesslich senden kann.

Kann die App dann wenigstens in Erfahrung bringen, ob der Benutzer die solchermassen vorbereitete SMS tatsächlich abgeschickt hat? Sie ahnen es wohl schon: Natürlich nicht.

Wer sich nun sagt, halb so wild, SMS ist sowieso auf dem absteigenden Ast: Ganz ähnliche Einschränkungen scheinen auch für E-Mails zu gelten.

Ich komme für mich zum Schluss: Mit einer derart limitierten API ist es extrem schwierig, wirklich interessante und innovative Apps für WP7 zu programmieren. Hier muss sich meiner Meinung nach in kurzer Zeit sehr viel tun, wenn WP7 je zu iOS und Android aufschliessen will.

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

Keine Indices für nvarchar(MAX)

Heute habe ich an einer SQL-Datenbank, die ich via Entity Framework 4 von einer C#-Anwendung aus anspreche, „von Hand“ Kolonnen hinzugefügt, um Änderungen an meinen Entities nachzuvollziehen, ohne die Daten in den Tabellen zu verlieren. Dabei ist mir zum ersten mal richtig aufgefallen, dass alle meine textuellen Kolonnen vom Typ nvarchar(MAX) sind, bzw. dass EF4 die Kolonnen so für mich definiert hat.

MAX schien mir Overkill, aber richtig, ich hatte ja bei den Properties im EF-Designer keine Maximal-Längen-Angaben gemacht. Irgendwie verständlich, weil man schliesslich beim O/R-Mapping vom C#-Datentyp String her kommt, wo man sich keine Gedanken über Maximallängen machen muss.

Zur Sicherheit klärte ich ab, ob ich mir mit der Verwendung von nvarchar(MAX) irgendwelche Nachteile einhandle. Ich dachte da an eine mögliche Speicherverschwendung, die so zustandekommt. Eine Frage auf Stack Overflow brachte Klärung: Nein, Speicherverschwendung ist kein Problem, aber SQL Server mag keine normalen Indices bauen mit MAX-Kolonnen drin.

Es ist tatsächlich ein bisschen schwierig, einen B-Baum zu führen mit potentiell beliebig langen Schlüsseln in Seiten fixer Länge!

Neugierig geworden, forschte ich noch etwas weiter. Maximallängen setzen bei den Properties im EF4-Designer löst zwar das erwähnte Indizier-Problem, hat aber eine Schwäche: EF4 selbst überwacht die Maximallängen nicht, sondern gibt einfach alles an den SQL Server weiter, wo es dann zwar schon einen Fehler gibt, aber offenbar einen, bei dem man unter Umständen nicht versteht, wo das Problem liegt. Diese Geschichte ist hier näher beschrieben.

Weiterhin scheint es überraschend schwierig zu sein, die Maximallängen-Angaben, die man im Designer macht, zur Programmlaufzeit abzufragen, z.B. um irgendwelche Eingabe-Controls dynamisch und „generisch“ auf die betreffenden Längen einzuschränken. Nachlesen kann man das z.B. hier.

Schliesslich scheint es mit Code First in EF4.1 und/oder bei Einsatz von SQL Server Compact eine Reihe neuer Fragen rund um die Maximallänge von Text-Kolonnnen zu geben, wie man hier beschrieben findet.

Es ist schon interessant, wie sich beim Programmieren mit .NET immer mal wieder Dinge als vielschichtiger herausstellen, als man auf den ersten Blick annimmt.

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

Informationspolitik

Wenn es um Windows 8 geht in offiziellen Verlautbarungen von Microsoft, glänzen C#, .NET, WPF und Silverlight meistens durch Abwesenheit. Stattdessen wird jede Menge über HTML 5 und JavaScript für eine schöne neue Welt von modernen Windows-Applikationen erzählt.

Als das vor ein paar Monaten losging, waren verständlicherweise viele Programmierer ziemlich beunruhigt und haben auf verschiedenen Wegen Microsoft um Klärung gebeten. Die Auskunft damals war: Liebe Leute, wir verstehen Eure Sorgen, aber es tut uns leid, wir können im Moment nichts sagen. Wartet bis zur BUILD Conference in den USA im September.

Es versteht sich, das dieses Schweigen Microsofts nicht zur Beruhigung beigetragen hat, wie man ziemlich deutlich z.B. an isdotnetdead.com und Open Plea by Silverlight / WPF Devs ersehen kann.

Nun kam für mich als Schweizer gestern folgende Meldung: Für die TechDays 11 in Bern am 20. und 21. Oktober, also zeitlich eine ganze Weile nach der BUILD, wird bezüglich Windows 8 umdisponiert. An den TechDays gibt es neu keine Informationen über Windows 8; wer sich als Schweizer Programmierer dafür interessiert, wartet auf einen eigenen Informationsanlass am 9. Februar 2012. Zu lesen ist das z.B. auf der TechDays-Website oder der Website des SWISS DPE Teams.

Das monatelange Schweigen von Microsoft über die zukünftigen Stossrichtungen betreffend Programmieren für Windows 8 und jetzt die Verschiebung der Orientierung der Schweizer auf den Februar 2012 finde ich persönlich nicht gut, sehe das aber noch knapp innerhalb eines „normalen“ Rahmens.

Was ich allerdings jetzt definitiv nicht mehr verstehe und was mich über die Klippe gestossen und zu diesem Blog-Eintrag veranlasst hat: Microsoft liefert, so viel ich weiss, keine brauchbare Begründungen für all diese Wartereien und Verschiebungen, die man uns zumutet.

Wenn man schon die Leute monatelang hängenlässt, was in der heutigen Zeit eine kleine Ewigkeit bedeutet, gehört doch einfach dazu, den Leuten zu erklären, warum man das tut. Ohne Erklärung werden die Ängste nur um so grösser, und die Spekulationen umso wilder.

Ich bin Realist und weiss, wie klein die Chancen sind, dass nun genau dieser Blog-Eintrag etwas bewirkt, aber es musste mal gesagt sein.

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

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 »

EF4: Zu meckern gibt es immer etwas

Im Rahmen meiner bisherigen Arbeit mit dem EF4 bin ich auf ein paar Dinge gestossen, welche dieses Framework nicht kann, die aber wünschenswert und sinnvoll wären. Ich führe diese hier auf, weil es eine nützliche Information sein kann zu wissen, dass etwas nicht geht – man kann dann nämlich aufhören nach einer direkten Lösung zu suchen und sein Ansinnen entweder fallenlassen oder damit beginnen, eine Umgehungslösung zu suchen.

Weil sich solche Dinge heutzutage schnell ändern können: Die folgenden Aussagen beziehen sich auf das Entity Framework 4, so wie in Visual Studio 2010 (original d.h. ohne Service Pack 1) enthalten.

  • Es gibt im Datenbank-Designer für das EF4 keine Möglichkeit, die Reihenfolge von Properties zu ändern, weder mit der Maus interaktiv (etwa via „Drag & Drop“) noch durch Änderungen im Eigenschaften-Fenster. Umgehungslösung: Direkt im XML hinter dem Designer herumpfuschen, so wie z.B. hier erläutert.
  • Arbeitet man Design First d.h. generiert die Datenbank ab Design, gibt es keine Möglichkeit, sich im Designer zu Indices zu äussern: Indices kennt dieser schlicht nicht, abgesehen von denjenigen für Primary Keys natürlich.
  • Ebensowenig kennt der Designer Unique Constraints.
  • EF4 unterstützt Enumerations nicht. Leute lassen sich hier alle möglichen Umgehungslösungen einfallen, wie z.B. diese hier, aber das grundsätzliche Problem schleckt keine Geiss weg, wie man hier in der Schweiz zu sagen pflegt. Etwas pikant ist an dieser Geschichte noch, dass LINQ to SQL offenbar Enumerations unterstützt.

Bei allen 4 aufgeführten Dingen erstaunt es mich etwas, dass man mit dem Entity Framework Release 4 erreicht, ohne eine Lösung anzubieten. Wenn man die Signale von Microsoft richtig deutet, ist ja das EF zumindest im Moment die favorisierte Datenbank-Zugriffs-Technologie für .NET-Programme und hätte darum Detail-Pflege sicher verdient.

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 »

Visual Studio Refactoring und Code in .aspx

Als ich vor ein paar Jahren die Refactoring-Befehle in Visual Studio kennenlernte, insbesondere das Rename-Kommando, hatte ich irgendwie das Gefühl, nach einem langem Aufenthalt in der Tool-Steinzeit endlich in der Moderne angekommen zu sein: Nie wieder der Horror von rein textuellem Search & Replace, wenn 2 ganz verschiedene Dinge gleich heissen und man nur eines davon umbenennen will.

Mit der Zeit denkt man gar nicht mehr so darüber nach: Ist doch selbstverständlich, den Texteditor mit dem Compiler zusammenzuschalten, der schliesslich ganz genau weiss, welche Referenz auf welches Objekt zeigt, ganz egal, wie viele Dinge rein textuell gesehen gleich heissen.

Als vor kurzem ein ASP.NET-MVC2-Projekt nach einem Refactoring mit Fehlern in .aspx-Files nicht mehr kompilieren wollte, dachte ich zuerst an eine Fehlbedienung meinerseits oder an einen nur sporadisch auftretenden Bug in Visual Studio 2010, aber eine Recherche heute brachte schliesslich Klarheit: Es herrscht wieder Steinzeit. Das Refactoring in VS2010 ist nicht schlau genug, bei Rename auch Code-Stücke in .aspx-Files zu erfassen.

Man findet dieses Problem im Internet, z.B. in dieser Frage auf Stack Overflow, aber eine eigentliche Empörung über dieses klaffende Loch im System scheint es interessanterweise nicht zu geben. (Intellisense funktioniert auch in .aspx-Files, irgendwie, aber mit einem Fehlen jenes Features wäre Microsoft wahrscheinlich nicht durchgekommen bei der Entwickler-Gemeinde.)

Zum Glück gibt es Leute, welche sich solcher Probleme annehmen, und Tools wie ReSharper programmieren, welche die Welt sozusagen wieder geraderücken.

Allerdings droht bereits neues Ungemach: Leute scheinen sich immer wieder neue Spielarten von Syntax auszudenken, wie man am besten und elegantesten C#-Code mit HTML mischt, nicht zuletzt Microsoft selbst mit der neuen Razor View Engine für ASP.NET MVC3. Und diese neuen Spielarten überfordern dann Tools wie den erwähnten ReSharper zunächst wieder, wie man etwa im Blog der Hersteller-Firma nachlesen kann.

Das ist wohl ein nicht zu vermeidendes Problem im Zuge der rasanten Weiterentwicklung, welche die ganze .NET-Welt mitmacht…

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

Wie funktioniert ASP.NET-Inline-Code?

Seit den Anfangszeiten von ASP.NET vor vielen Jahren gibt es die Möglichkeit von Inline-Code, also die Möglichkeit, Code-Schnippsel in HTML einzustreuen. Hier ist ein kleines aktuelles Beispiel mit ASP.NET MVC 2, Teil einer Seite mit einer HTML-Tabelle, bei der die Zeilen mit Hilfe einer Schleife gebildet werden, die in C# programmiert ist:

<table>
    <% foreach (var item in Model) { %>
        <tr>
            <td>
                <%: Html.ActionLink("Edit", "Edit", new { id=item.Id }) %> |
                <%: Html.ActionLink("Delete", "Delete", new { id=item.Id })%>
            </td>
            <td>
                <%: item.Id %>
            </td>
            <td>
                <%: item.Title %>
            </td>
            <td>
                <%: String.Format("{0:g}", item.DateReleased) %>
            </td>
        </tr>
    <% } %>
</table>

Ich habe mich in der Vergangenheit schon öfters gefragt, wie genau ein solches buntes Gemisch von HTML und Code zur Ausführung kommt. Es wird ja wohl nicht so sein, dass irgendein Prozess den Text durchgeht und dabei jeweils fliegend zwischen einer Art „HTML-Modus“ und einer Art „Code-Modus“ wechselt, also quasi die Mischung nachvollzieht. Aber wie es geht es dann?

Am einfachsten sieht man, was läuft, wenn man auf irgendwelchen Code auf so einer Seite einen Breakpoint setzt und sich dann nach einem Break im Debugger genauer ansieht, wo man denn gelandet ist. Die Seiten einer Website mit Code werden durch dynamische Compilation in eine temporäre .NET-Assembly verwandelt, die typischerweise unter kryptischem Namen in einer kryptischen Directory abgelegt ist, bei mir z.B.

C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\d0bb04eb\40bc3df1\App_Web_sm1qknju.dll

Pro Seite gibt es 1 Klasse, und in jeder Klasse ist eine Methode namens __RenderContent2() zuständig dafür, den Inhalt der Seite d.h. das reine HTML zu generieren. Dank dem IL-Disassembler ILDASM kann man sich auf einfache Weise die Details einer solchen Methode ansehen.

Die Lösung, wie genau die Mischung von Code und HTML realisiert wird, ist denkbar einfach und eigentlich wenig überraschend: Es wird alles zu Code. Was schon Code ist, bleibt natürlich Code, und alle verbleibenden Sequenzen von Zeichen vor, zwischen und nach Code-Stücken, die HTML darstellen, werden mit Hilfe von Aufrufen von System.Web.UI.HtmlTextWriter.Write ausgegeben.

Das sieht disassembliert dann z.B. so aus:

IL_0031: ldarg.1
IL_0032: ldstr „\r\n </td>\r\n“
IL_0037: callvirt instance void [mscorlib]System.IO.TextWriter::Write(string)

Nun zu wissen, „wie es geht“, bringt mir nicht unbedingt viel, aber immerhin habe ich jetzt kein schlechtes Gefühl mehr, wenn mir das ständige Abwechseln von kleinen HTML-Stücken und Code-Stücken zu dumm wird und ich dann Dinge schreibe wie:

<% Response.Write("<td>"+item.Id+"</td><td>"+item.Title+"</td><td>"+String.Format("{0:g}", item.DateReleased)+"</td>") %>

Schliesslich entspricht das mehr oder weniger dem, was technisch gesehen zur Ausführung kommt, wenn ich es als „Mischung“ hinschreibe. (Acht geben muss ich dabei allerdings darauf, dass ich den bei <%: automatisch inbegriffenen Aufruf von Server.HtmlEncode bei Bedarf selbst mache; siehe hierzu z.B. diesen Artikel.)

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