<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>ASP.extra von Karsten Samaschke</title>
	
	<link>http://www.aspextra.de</link>
	<description>Karsten Samaschkes Blog rund um .NET, Java und Webtechnologien</description>
	<lastBuildDate>Mon, 03 May 2010 09:31:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/aspextra" /><feedburner:info uri="aspextra" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>#Handwerk: Clean vs. pragmatisch?</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/EJ8B6mMBbRY/</link>
		<comments>http://www.aspextra.de/2010/05/03/handwerk-clean-vs-pragmatisch/#comments</comments>
		<pubDate>Mon, 03 May 2010 09:31:59 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[Handwerk]]></category>
		<category><![CDATA[Meinung]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2010/05/03/handwerk-clean-vs-pragmatisch/</guid>
		<description><![CDATA[Am Beispiel von Thomas’ Blogbeitrag “Null Verständnis” kann man wunderschön zwei Dinge erkennen: Erstens, wie schnell man aus einem praktischen Problem in eine Grundsatzdiskussion abgleiten kann und zweitens, dass es offensichtlich einen Unterschied zwischen möglichst sauberen Vorgehensweisen und pragmatischen Ansätzen geben kann. Oder ist dem nicht so? Zunächst zum Thema “Grundsatzdiskussion”: Ich persönlich bin kein [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Am Beispiel von Thomas’ Blogbeitrag “</strong><a href="http://blog.thomasbandt.de/39/2333/de/blog/null-verstaendnis.html"><strong>Null Verständnis</strong></a><strong>” kann man wunderschön zwei Dinge erkennen: Erstens, wie schnell man aus einem praktischen Problem in eine Grundsatzdiskussion abgleiten kann und zweitens, dass es offensichtlich einen Unterschied zwischen möglichst sauberen Vorgehensweisen und pragmatischen Ansätzen geben kann. Oder ist dem nicht so?</strong></p>
<p>Zunächst zum Thema “Grundsatzdiskussion”: Ich persönlich bin kein großer Freund dieser Form von Diskussionen, werden sie doch gerne anhand von vereinfachten Beispielen geführt und nähern sich schnell einem recht grundlegendem Level an, da ab einem gewissen Punkt das Selbstverständnis eines Teils der Diskussionspartner berührt werden könnte. Das beiseite gelassen, eignen sie sich jedoch wundervoll, um unterschiedliche Grundideen auszuarbeiten, wie es in diesem Fall geschehen ist: Auf der einen Seite die Fraktion, die gerne auf null als Rückgabewert von GetXXX-Funktionalitäten verzichten möchte, wenn diese als Parameter einen ID-Wert übergeben bekommen und der Datensatz nicht existiert (Begründung: ID kennzeichnet nun mal einen eindeutig identifizierten Datensatz, gibt es diesen nicht, ist irgendwas faul im Staate Dänemark – das Ganze kann dann wahlweise über ein Null-Objekt oder eine Exception abgebildet werden), auf der anderen Seite die Fraktion, die in diesem Fall eben null zurück gibt und das im Code abfragen und abfangen möchte.</p>
<p>Unabhängig davon, dass ich die Meinungen beider Fraktionen nachvollziehen kann (und dennoch gerne Null-Objekte einsetze, da sie die weitere Verarbeitung stark erleichtern können und oftmals der Wartbarkeit zuträglich sind), haben wir es hier mit einem eher grundsätzlicheren Problem zu tun: Clean Code vs. pragmatische Entwicklung, um es mal zugespitzt zu umschreiben. Dieser Widerspruch ist jedoch bei näherer Betrachtung keiner, jedenfalls soweit es mich betrifft, denn in Wahrheit haben wir es an dieser Stelle eher mit zwei verschiedenen Anforderungsmodellen zu tun:</p>
<p><font color="#656565">Beiden Fraktionen geht es um einen möglichst sauberen, wiederverwendbaren und auch für andere Entwickler leicht verständlichen Code. Da sind sich beide einig, der Unterschied liegt darin, ob und wie mit Annahmen außerhalb des DataLayers umgegangen wird:</font></p>
<ul>
<li><font color="#656565">Die “Clean Coder” wollen, dass der Code vertrauenswürdig ist, d.h. er soll sich in jedem Fall eindeutig verhalten und außerhalb des Kontextes etwa eines DataLayers keinerlei Annahmen über dessen Struktur und Funktionsweise erfordern. </font><font color="#656565">Ich folge diesem Ansatz in der Regel. Das bedeutet für: Null-Objekte, da wo es sinnvoll ist (Benutzer gehören für mich in aller Regel dazu), null bei nicht relevanten Geschichten oder Dingen, die schon ganz eindeutig aussagen, dass es eventuell auch KEIN Ergebnis geben kann (FindXXX-Methoden wäre klassische Kandidaten dafür).</font> </li>
<li><font color="#656565">Die “Pragmatiker” haben einen anderen Schwerpunkt: Sie legen weniger Wert auf die oben angesprochene Vertrauenswürdigkeit von Code, denn die erarbeiteten Lösungen werden entweder meist allein verwendet, oder stellen Lösungen dar, die von einem Endkunden in aller Regel nicht selbstständig weiterentwickelt werden. Hier heißt es: Null statt eines Null-Objekts, denn hier ist außen bekannt, wie das Repository sich verhält und die Anwendungsfälle für etwa Null-Objekte halten sich meist in Grenzen. </font></li>
</ul>
<p>Beide Fraktionen haben somit unterschiedliche Anforderungen an Code, der scheinbare Widerspruch zwischen pragmatischem und sauberen Programmieren ist also keiner – wir haben es schlicht mit unterschiedlichen Verwendungsszenarien zu tun. </p>
<p>Ob, und in welchem Umfang man nun die Meinung der einen oder der anderen Fraktion teilen mag, ist eine andere Frage. Ich persönlich tendiere zur Clean Code-Ansicht, denn ich habe für mich die Sinnhaftigkeit von Null-Objekten schon seit geraumer Zeit erkannt. Dementsprechend definiere ich meine Entitäten und meine Schichten auch und kann mich so darauf verlassen, stets eine funktionsfähige Objektinstanz zu besitzen und entsprechend meinen Code einfacher strukturieren. Das Ergebnis: Wartbarkeit und Sicherheit steigen, meine Applikation verhält sich vorhersagbarer, ich kann mindestens ebenso gut testen, wie beim eher “pragmatischen” Ansatz. </p>
<p>Insofern erscheint mir hier der Clean Code-Ansatz im Endeffekt sogar pragmatischer zu sein.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/EJ8B6mMBbRY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2010/05/03/handwerk-clean-vs-pragmatisch/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2010/05/03/handwerk-clean-vs-pragmatisch/</feedburner:origLink></item>
		<item>
		<title>#WP7S: Fakten-Roundup (III) von der #MIX10</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/MenBevYEp8M/</link>
		<comments>http://www.aspextra.de/2010/03/18/wp7s-fakten-roundup-iii-von-der-mix10/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 02:05:29 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[WP7S]]></category>
		<category><![CDATA[Windows Phone 7 Series]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2010/03/18/wp7s-fakten-roundup-iii-von-der-mix10/</guid>
		<description><![CDATA[Inzwischen ist die MIX-Konferenz bereits wieder Geschichte, aus meiner Sicht jedoch sehr interessante Geschichte. Ich habe enorm viel gelernt und den einen oder anderen sehr interessanten Menschen kennen gelernt. Hier nun die letzten Fakten zu Windows Phone 7 Series, die ich – wie die letzten Male auch – direkt wieder aus meiner Twitter-Timeline klaue: Performance [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Inzwischen ist die MIX-Konferenz bereits wieder Geschichte, aus meiner Sicht jedoch sehr interessante Geschichte. Ich habe enorm viel gelernt und den einen oder anderen sehr interessanten Menschen kennen gelernt.</strong></p>
<p>Hier nun die letzten Fakten zu Windows Phone 7 Series, die ich – wie die letzten Male auch – direkt wieder aus <a href="http://twitter.com/samaschke">meiner Twitter-Timeline</a> klaue:</p>
<ul>
<li>Performance beginnt schon beim Designer. Nicht erst beim Entwickler.</li>
<li>Fixed Width / Fixed Height bei Listen ist derzeit optimal. Data Virtualization (lade nur das, was Du brauchst).</li>
<li>30 Frames / Sekunde für Animationen / Video / etc.</li>
<li>Application.Current.Host.Settings.EnableFrameRateCounter &#8211; kann genutzt werden, um Performance zu messen.</li>
<li>Application.Current.Host.Settings.EnableRedrawRegions &#8211; Feststellen, was wann wie wo neu gezeichnet werden muss.</li>
<li>BitmapCache einschalten steigert Performance.</li>
<li>Gerade die Animationen können extrem performancehungrig werden. Sollte man sich tatsächlich mal in Ruhe irgendwo anschauen.</li>
<li>CacheModes sollten nicht gemischt werden &#8211; CacheMode=&quot;None&quot; innerhalb von CacheMode=&quot;BitmapCache&quot;-Elementen ist extrem unperformant.</li>
<li>Media mit geringstmöglicher Framerate codieren &#8211; sehr aufwändig zu rendern.</li>
<li>Auch bei MediaElement: CacheMode=&quot;BitmapCache&quot; setzen.</li>
<li>Media-Decoding + PNG-Handling stets hardwarebasiert, JPG-Handling KANN hardwarebasiert stattfinden.</li>
<li>Hardware-Beschleunigung nur für Elemente bis max 2.048&#215;2.048 Pixeln. Alles, was größer ist, muss per Software &quot;beschleunigt&quot; werden.</li>
<li>Wichtig: Applikationen laufen nur mit gültiger License</li>
<li>Code ist signiert</li>
<li>Applikationen können nur Ressourcen ansprechen, für die sie freigegeben sind, wird zur Laufzeit überprüft.</li>
<li>Klare Aussage: &quot;Echte Programme&quot; (C++) wird es nicht auf der Plattform geben.</li>
<li>Push-Notification-Tokens bleiben auch beim Pausieren gültig. App muss sich also noch dem Pausieren nicht neu registrieren.</li>
<li>Keine DLLs übers Netz nachladbar. Nur signierter Code wird ausgeführt. Signierter Code kommt nur über den Marketplace.</li>
<li>Find &amp; Wipe-Remote-Service existiert.</li>
<li>MyPhone-Service setzt Find &amp; Wipe-Remote-Service um</li>
<li>Updates für das Gerät werden von MS bereitgestellt, es wird aber keine Patch-Tuesdays geben. Also eher analog zu #iPhone.</li>
<li>Marketplace kann mehr, als bisher bekannt &#8211; es wird wohl Szenarios rund um geschlossene Benutzergruppen o.ä. geben.</li>
<li>Featured-App kontrolliert den Hintergrund des Marketplaces. <img src='http://www.aspextra.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li>Suche funktioniert natürlich auch im Marketplace.</li>
<li>Apps in der Regel innerhalb von 5 Tagen verfügbar, klare Aussagen über Timelines, Dokus ab Mai für Windows Phone aktualisiert.</li>
<li>Applikation wird von Microsoft auf benötigte Schnittstellen geprüft und mit einem Manifest versehen.</li>
<li>Applikationen / Käufe sind an die Live-ID gebunden, bis zu fünf Geräte parallel mit einer ID einsetzbar.</li>
<li>Kein Nexus von Microsoft geplant. MS verkauft weiterhin keine Entwickler-Phones. <img src='http://www.aspextra.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li>Kein Buy once &#8211; Play everywhere (XBox-Spiel kaufen und auf WP7S spielen) derzeit, vielleicht zukünftig.</li>
<li>XNA ist C#-only, Managed Code only.</li>
<li>Silverlight: Wenn Vektorgrafiken, XNA: Wenn 3D-Grafiken. Mal ganz pauschal gesagt. <img src='http://www.aspextra.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li>Konfigurierbare Standardeffekte, keine Custom Shaders. #XNA</li>
<li>Zugriff auf Audio, Video und Photos via #XNA-Framework. Nicht nur Chooser notwendig, wenn ich das richtig verstanden habe.</li>
<li>Zwei Profile bei #XNA: Reach (möglichst kompatibel für alle Plattformen) oder HiDef (spezifisch nur für eine Plattform).</li>
<li>Derzeit nur Entwicklung mit C#. VB kommt (vielleicht) später nach. #MIX10</li>
<li>Allgemein: class statt struct, struct nur für Dinge, die kleiner 16 Bytes sind</li>
<li>GC ist teuer. Zwei Strategien: Seltener laufen lassen (Objekte &lt; 1MB). Oder: Schnell fertig werden lassen (ValueTypes verwenden).</li>
<li>GC: Weniger Referenzen. Nur Objekte, wo notwendig. Weniger Listen, mehr Arrays.</li>
<li>GC manuell aufrufen: GC.Collect() &#8211; bitte nicht so oft. Teuer. Idealerweise nur nach dem Load oder in Pausen.</li>
<li>Boxing vermeiden. StringBuilder statt String. GC per WeakReference-Klasse überprüfen. CLR-Profiler verwenden (#XNA). .NET Reflektor.</li>
<li>foreach-Statement ist okay, darauf achten, dass der Enumerator ein primitiver Typ ist.</li>
<li>yield-Statement verwenden &#8211; wird zu einem Zustandsautomaten kompiliert.</li>
<li>Best practices für mobiles Web: Weniger Farben und Schriften, weniger JS, keine Backgrounds, Content an Screengröße anpassen. Kleine Bilder.</li>
<li>Best practices für mobiles Web (II): So wenig als möglich Input, sinnvolle Vorgaben, Cookies für Eingaben verwenden.</li>
<li>Entwicklung für mobiles Web: Standards verwenden (XHTML, HTML 4.01, XHTML-MP), CSS 2.1, DOM 1, ECMAScript3. DOCTYPE setzen.</li>
<li>Entwicklung für mobiles Web: Standard-Medientypen (JPEG, GIF, PNG, 3GP, AVI, WMV, MP4) verwenden. Keine Frames!</li>
<li>Entwicklung für mobiles Web: Keine Table-Layouts, keine nested Tables, keine Image-Maps, kein Flash.</li>
<li>Entwicklung für mobiles Web: Mobile-META-Tags verwenden: HandheldFriendly, MobileOptimized, Viewport.</li>
<li>Standard-Viewport für #WP7S: 1024px.</li>
<li>Entwicklung für mobiles Web: JS im Client für Fähigkeiten verwenden, UserAgent auf dem Server nutzen</li>
<li>Entwicklung für mobiles Web: Bei Codeplex mal nach #MBDF schauen &#8211; UserAgents und deren Fähigkeiten auswerten. BrowsCap 2.0?</li>
<li>IE7 + Features: getElementsByClassName, .querySelector, .querySelectorAll, Viewport, XHTML-Handling.</li>
<li>Viewport-Settings: width, height, user-scalable implementiert, minimum-scale, maximum-scale und initial-scale nicht implementiert.</li>
<li>CSS-Props: -ms-text-size-adjust, -webkit-text-size-adjust implementiert. Fixed positioning: Hängt am Dok., nicht am Window.</li>
</ul>
<p>So, das waren dann alle Informationen, die ich auf der MIX gesammelt und für bloggenswert befunden habe.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/MenBevYEp8M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2010/03/18/wp7s-fakten-roundup-iii-von-der-mix10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2010/03/18/wp7s-fakten-roundup-iii-von-der-mix10/</feedburner:origLink></item>
		<item>
		<title>#WP7S: Das Mißverständnis – oder: Windows Phone ist nicht Windows Mobile</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/dtLJgz9N49A/</link>
		<comments>http://www.aspextra.de/2010/03/17/wp7s-das-miverstndnis-oder-windows-phone-ist-nicht-windows-mobile/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 17:58:07 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[WP7S]]></category>
		<category><![CDATA[Windows Phone 7 Series]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2010/03/17/wp7s-das-miverstndnis-oder-windows-phone-ist-nicht-windows-mobile/</guid>
		<description><![CDATA[Auf der #MIX10 hat Microsoft virtuell die Hosen runtergelassen und viele, viele Details zu Windows Phone 7 Series veröffentlicht. Dabei waren Dinge, die für viele Entwickler, die bisher für Windows Mobile entwickelt haben, unverständlich sind und echte Showstopper darstellen, etwa der Verzicht auf C++, das Nicht-Vorhandensein einer Datenbank, die Einschränkungen hinsichtlich Ressourcen-Zugriff. Allgemein gibt es [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Auf der #MIX10 hat Microsoft virtuell die Hosen runtergelassen und viele, viele Details zu Windows Phone 7 Series veröffentlicht. Dabei waren Dinge, die für viele Entwickler, die bisher für Windows Mobile entwickelt haben, unverständlich sind und echte Showstopper darstellen, etwa der Verzicht auf C++, das Nicht-Vorhandensein einer Datenbank, die Einschränkungen hinsichtlich Ressourcen-Zugriff.</strong> </p>
<p>Allgemein gibt es im Moment ein gewaltiges Aufheulen in der Community, erste Petitionen werden gestartet, das große Jammern setzt ein. Dabei wird gerne übersehen, dass es zwei ganz gewaltige Unterschiede zwischen Windows Phone und Windows Mobile gibt:</p>
<ol>
<li>Windows Phone ist ein kompletter Neustart. Neu, neu, neu – alte Zöpfe wurden abgeschnitten, neue Ansätze ausgelotet. Das System ist darüber hinaus ein klassisches 1er Release, d.h. derzeit fehlende APIs und Funktionalitäten werden ziemlich sicher zukünftig nachgereicht.</li>
<li>Die Zielgruppe ist eine komplett andere: Bisher waren es Geschäftskunden in verschiedenen Ausprägungen (klingt irgendwie… krank), jetzt sind es Privatleute. Menschen, die ganz andere Dinge, als beim bisherigen System erwarten. Und damit ändern sich auch die zur Verfügung gestellten Funktionalitäten und die Schwerpunkte der Plattform.</li>
</ol>
<p>Beide Dinge sollte man verstehen, bevor man anfängt, sich über die Plattform aufzuregen.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/dtLJgz9N49A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2010/03/17/wp7s-das-miverstndnis-oder-windows-phone-ist-nicht-windows-mobile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2010/03/17/wp7s-das-miverstndnis-oder-windows-phone-ist-nicht-windows-mobile/</feedburner:origLink></item>
		<item>
		<title>#WP7S: Fakten-Roundup (II) von der #MIX10</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/9MtWuuN_Ou0/</link>
		<comments>http://www.aspextra.de/2010/03/17/wp7s-fakten-roundup-ii-von-der-mix10/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 23:23:58 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[WP7S]]></category>
		<category><![CDATA[Windows Phone 7 Series]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2010/03/17/wp7s-fakten-roundup-ii-von-der-mix10.html</guid>
		<description><![CDATA[Nächste Session zum Thema “Development für WindowsPhone 7 Series” ist vorbei. Hier wieder die wichtigsten Informationen: Applikationen sind Page-basiert. #WP7S Struktur: Application -&#62; Frame -&#62; Page(s). Navigation zwischen Pages: HyperlinkButtons Daten übertragen: QueryString-Parameter im HyperlinkButton Zugriff auf die QueryString-Parameter: NavigationContext.QueryString.TryGetValue(&#60;Schlüssel&#62;, out &#60;Variable&#62;); In aufgerufener Page: OnNavigatedTo()-Methode überschreiben, um entsprechende Initialisierung vorzunehmen. Navigation zurück: NavigationService.GoBack(); Orientation: [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Nächste Session zum Thema “Development für WindowsPhone 7 Series” ist vorbei. Hier wieder die wichtigsten Informationen:</strong></p>
<ul>
<li>Applikationen sind Page-basiert. #WP7S Struktur: Application -&gt; Frame -&gt; Page(s).</li>
<li>Navigation zwischen Pages: HyperlinkButtons</li>
<li>Daten übertragen: QueryString-Parameter im HyperlinkButton</li>
<li>Zugriff auf die QueryString-Parameter: NavigationContext.QueryString.TryGetValue(&lt;Schlüssel&gt;, out &lt;Variable&gt;);</li>
<li>In aufgerufener Page: OnNavigatedTo()-Methode überschreiben, um entsprechende Initialisierung vorzunehmen.</li>
<li>Navigation zurück: NavigationService.GoBack();</li>
<li>Orientation: SupportedOrientation-Property: Landscape, Portrait, PortraitOrLandscape.</li>
<li>OnOrientationChanged-Methode für entsprechendes Event überschreibbar.</li>
<li>App-Bar: Buttons und MenuItems. #WP7S Wichtig: Bilder für Buttons müsen als &#8220;Content&#8221; kompiliert werden.</li>
<li>Buttons werden in App-Bar direkt angezeigt, MenuItems sind halt das untergeordnete Menü</li>
<li>SplashScreen: SplashScreenImage.jpg, muss als &#8220;Content&#8221; kompiliert werden, wird automatisch angezeigt.</li>
<li>Standard-Controls beherrschen automatisch Theming und Skinning.</li>
<li>Push notifications: Vom Server initiiert. Großer Vorteil: Applikation muss nicht wirklich multitasken, wird per Push aktiviert.</li>
<li>Push Notifications: 3 Typen: Tile-Update, Toast-Notification (kleine Notification-Bar), App-Notification für laufende Applikationen.</li>
<li>Push-Notification: App sendet URI an eigenen Server, Server pushed an gegebene Applikation, Service benachrichtigt Device.</li>
<li>Push: Keine spezielle Software nötig, alles HTTP-Requests (POST).</li>
<li>Channel-URI wird von MS bereitgestellt..</li>
<li>HttpNotificationChannel-Klasse: HttpNotificationChannel channel = new HttpNotificationChannel(&#8220;&lt;APP-Name&gt;&#8221;);</li>
<li>EventHandler für ChannelUriUpdated -&gt; In EventHandler wird die URI entgegen genommen.</li>
<li>Das Push-Zeug sieht wirklich einfach und angenehm benutzbar aus.</li>
<li>Location-Services derzeit im Emulator nicht aktiviert.</li>
<li>Location-APIs sind die gleichen, wie bei Windows 7.</li>
<li>Location auf drei Wegen: Satellit, WIFI und Triangulation per Basis-Stationen.</li>
<li>Es gibt einen Location-Service (frei) von Microsoft, so dass man oft auf GPS verzichten könnte.</li>
<li>Location-Service kann Adresse auflösen.</li>
<li>Klasse für Geo-Koordinaten: GeoCoordinateWatcher.</li>
<li>Auflösen von Adressen: CivicAddressResolver-Klasse.</li>
<li>Location-Handling sieht sehr cool aus.</li>
<li>BackKey-Abfangen: OnBackKeyPress-Methode überschreiben.</li>
<li>Obscured / Unobscured-Events für Störungen bzw.. das Weggehen der Störungen. Noch nicht in den MIX-Bits.</li>
<li>Paused / Unpaused &#8211; Applikation wird suspended. Wenn der Benutzer wiederkommt: Resume.</li>
<li>Wenn Pause, dann alles wegspeichern, App könnte (wird) gekillt werden.</li>
<li>Resume kann genutzt werden, um den Status wieder herzustellen.</li>
</ul>
<p>So. Die nächste Session handelt von Performance-Optimierungen / –Überlegungen für Windows Phone 7 Series.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/9MtWuuN_Ou0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2010/03/17/wp7s-fakten-roundup-ii-von-der-mix10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2010/03/17/wp7s-fakten-roundup-ii-von-der-mix10/</feedburner:origLink></item>
		<item>
		<title>#WP7S: Fakten-Roundup (#MIX10)</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/nai9HTiDddQ/</link>
		<comments>http://www.aspextra.de/2010/03/16/wp7s-fakten-roundup-mix10/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 21:48:09 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[WP7S]]></category>
		<category><![CDATA[Windows Phone 7 Series]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2010/03/16/wp7s-fakten-roundup-mix10.html</guid>
		<description><![CDATA[So, eine weitere interessante Session ist rum, hier wieder ein paar neue Fakten zu Windows Phone 7 Series aus Entwicklersicht: Kein Zugriff auf die gesamte Kontaktliste, Einzel-Auswahl nur über Chooser Keine Bluetooth-API derzeit SD-Karten werden für den Programmierer nicht direkt unterstützt &#8211; Isolated Storage wird aber entsprechend dynamisch erweitert. Kein(!) Cut, Copy &#38; Paste-Support derzeit [...]]]></description>
			<content:encoded><![CDATA[<p><strong>So, eine weitere interessante Session ist rum, hier wieder ein paar neue Fakten zu Windows Phone 7 Series aus Entwicklersicht:</strong></p>
<ul>
<li>Kein Zugriff auf die gesamte Kontaktliste, Einzel-Auswahl nur über Chooser</li>
<li>Keine Bluetooth-API derzeit</li>
<li>SD-Karten werden für den Programmierer nicht direkt unterstützt &#8211; Isolated Storage wird aber entsprechend dynamisch erweitert. </li>
<li>Kein(!) Cut, Copy &amp; Paste-Support derzeit</li>
<li>Webbrowser-Control kann konfiguriert werden, so dass es JS ausführt: &lt;Instanz&gt;.EnableScript = true; </li>
<li>Webbrowser kann zu String navigieren (das, was bei #WM6 nicht funktionierte): &lt;Instanz&gt;.NavigateToString(&lt;HTML&gt;);</li>
<li>Kommunikation App &lt;-&gt; Webbrowser analog zu Windows: &lt;Browser&gt;.invokeScript(); Von Seite zu App: window.external.&lt;Methode&gt;(). </li>
<li>Eingebautes Webbrowser-Control ist stets die selbe Version, wie der Browser</li>
<li>Derzeit nur ein MediaElement pro Page. </li>
<li>Vibrationen auslösen: VibrateController vc = VibrateController.Default; vs.Start(TimeSpan.FromSeconds(60)); <img src='http://www.aspextra.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li>MIC-Input: RAW-WAF-Daten abgreifen. Latenz etwa 10ms</li>
<li>Accelerometer ansprechen: AccelerometerSensor acc = AccelerometerSensor.Default; Reaktion per ReadingChanged-Event.</li>
<li>Devicespezifische Assemblies im System.Devices-Namensraum (und entsprechenden Assemblies). </li>
<li>Accelerometer: X, Y, Z-Richtungen (X ist horizontal, Y ist vertikal, Z ist Entfernung). </li>
<li>InputScopes in #WP7S geben an, welche Art von Eingabe (Nummern, Email-Adressen, etc.) eingegeben werden kölnnen.</li>
<li>Basis ist Silverlight 3, zusätzliche Assemblies</li>
</ul>
<p>Mehr nach der nächsten Session.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/nai9HTiDddQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2010/03/16/wp7s-fakten-roundup-mix10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2010/03/16/wp7s-fakten-roundup-mix10/</feedburner:origLink></item>
		<item>
		<title>#MIX10: MIX-PIX</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/9O5ls-t4Fug/</link>
		<comments>http://www.aspextra.de/2010/03/16/mix10-mix-pix/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 15:59:47 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[Allgemeines]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2010/03/16/mix10-mix-pix.html</guid>
		<description><![CDATA[Hier einige Bilder von der MIX-Konferenz, relativ unmotiviert geschossen und nicht sortiert: Vollständiges Album anzeigen Inhaltlich ist die Konferenz definitiv spannender als die Bilder.]]></description>
			<content:encoded><![CDATA[<p>Hier einige Bilder von der MIX-Konferenz, relativ unmotiviert geschossen und nicht sortiert:</p>
<div id="scid:66721397-FF69-4ca6-AEC4-17E6B3208830:7c11a85d-ec8e-4d51-bd66-bdbeb9f18953" class="wlWriterEditableSmartContent" style="margin: 0px; display: inline; float: none; padding: 0px;"><a style="border: 0px;" href="http://cid-021ebae992868fcc.skydrive.live.com/redir.aspx?page=browse&amp;resid=21EBAE992868FCC!148&amp;ct=photos"><img style="border: 0px;" src="$InlineRepresentation98b2554b-5a1b-48d8-a796-2f21f460ea42[2].jpg" alt="MIX PIX anzeigen" /></a></p>
<div style="width: 626px; text-align: right;"><a href="http://cid-021ebae992868fcc.skydrive.live.com/redir.aspx?page=browse&amp;resid=21EBAE992868FCC!148&amp;ct=photos">Vollständiges Album anzeigen</a></div>
</div>
<p>Inhaltlich ist die Konferenz definitiv spannender als die Bilder. <img src='http://www.aspextra.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/9O5ls-t4Fug" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2010/03/16/mix10-mix-pix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2010/03/16/mix10-mix-pix/</feedburner:origLink></item>
		<item>
		<title>#WP7S: Die neuen Fakten</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/3vc-4IzTUZk/</link>
		<comments>http://www.aspextra.de/2010/03/16/wp7s-die-neuen-fakten/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 22:30:19 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[WP7S]]></category>
		<category><![CDATA[Windows Phone 7 Series]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2010/03/16/wp7s-die-neuen-fakten.html</guid>
		<description><![CDATA[Auf der #MIX10 hat Microsoft den Vorhang von der Entwicklung für Windows Phone 7 Series gezogen. Wichtigste Nachricht vorweg: Die Entwicklertools werden kostenfrei zur Verfügung stehen. Weitere sehr wichtige Informationen: Keine Datenbank derzeit auf dem Phone und kein Multitasking für eigene Applikationen, dafür ein Push-Mechanismus. Das sind die Fakten, die ich gerade einmal aus meiner [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Auf der #MIX10 hat Microsoft den Vorhang von der Entwicklung für Windows Phone 7 Series gezogen. Wichtigste Nachricht vorweg: Die Entwicklertools werden kostenfrei zur Verfügung stehen. Weitere sehr wichtige Informationen: Keine Datenbank derzeit auf dem Phone und kein Multitasking für eigene Applikationen, dafür ein Push-Mechanismus.</strong></p>
<p>Das sind die Fakten, die ich gerade einmal aus meiner Twitter-Timeline ziehe:</p>
<ul>
<li>VS2010 als primäres Tool für Entwickler</li>
<li>Der Emulator ist x86-kompiliert, dürfte also um Klassen schneller als der 6.5er-Emulator laufen</li>
<li>Unterstützung für Push-Notifications, keine Background-Tasks</li>
<li>LINQ to Objects, LINQ to XML sind verfügbar</li>
<li>Oberfläche mit Silverlight 3+</li>
<li>Ganz klar: Kein Migrationspfad von 6.5 nach 7</li>
<li>Einfachste API, um die Trial-Funktionalität im Marketplace umzusetzen</li>
<li>Marketplace unterstützt Kreditkarten und Abrechnung durch Netzbetreiber</li>
<li>Phone als Developer-Phone freischalten funktioniert über Webseite bei MS, Phone wird remote unlocked</li>
<li>Dateiformat ist XAP</li>
<li>Ausschließlich .NET-Code, vom System gemanagete Sandbox</li>
<li>Silverlight für Applikationen, XNA für Spiele, Plattformen sollen zusammenwachsen</li>
<li>Silverlight soll zukünftig auch auf dei XBox kommen.</li>
</ul>
<p>Das waren erst einmal die schnellen Fakten. More to come.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/3vc-4IzTUZk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2010/03/16/wp7s-die-neuen-fakten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2010/03/16/wp7s-die-neuen-fakten/</feedburner:origLink></item>
		<item>
		<title>Webbrowser-Control: ObjectForScripting</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/PNV8FBENsGg/</link>
		<comments>http://www.aspextra.de/2010/02/20/webbrowser-control-objectforscripting/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 21:48:39 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2010/02/20/webbrowser-control-objectforscripting.html</guid>
		<description><![CDATA[Man wird alt, wie ein Sack, man baut gefühlte siebenhundert Applikationen, die das Webbrowser-Control verwenden – und dann stellt man fest, das man bisher viel zu viel Arbeit in dämliche Workarounds gesteckt hatte, nur weil man die Doku nie komplett gelesen hat. So ging es mir heute, als ich über die ObjectForScripting-Eigenschaft des .NET-Webbrowser-Controls gestolpert [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Man wird alt, wie ein Sack, man baut gefühlte siebenhundert Applikationen, die das Webbrowser-Control verwenden – und dann stellt man fest, das man bisher viel zu viel Arbeit in dämliche Workarounds gesteckt hatte, nur weil man die Doku nie komplett gelesen hat.</strong></p>
<p>So ging es mir heute, als ich über die <em>ObjectForScripting</em>-Eigenschaft des .NET-Webbrowser-Controls gestolpert bin, die es erlaubt, eine Klasse zu definieren, deren Methoden vom Webbrowser-Control bzw. darin enthaltenem JavaScript-Code per <em>window.external.&lt;Methodenname&gt;</em> angesprochen werden kann. Einzige Bedingung: Die Klasse muss COM-sichtbar sein, also das <em>ComVisible</em>-Attribut muss mit dem Wert <em>true</em> gesetzt sein.</p>
<p>Tja, hätte man mal vorher in der Doku nachgeschaut…</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/PNV8FBENsGg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2010/02/20/webbrowser-control-objectforscripting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2010/02/20/webbrowser-control-objectforscripting/</feedburner:origLink></item>
		<item>
		<title>#SQLCLR: Rückgabenlänge von Userdefined Functions</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/GpebJkLfTJo/</link>
		<comments>http://www.aspextra.de/2009/12/19/sqlclr-rckgabenlnge-von-userdefined-functions/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 08:17:51 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Tipp]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[SQL CLR]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/12/19/sqlclr-rckgabenlnge-von-userdefined-functions.html</guid>
		<description><![CDATA[Wer mit der im SQL Server 2005 / 2008 integrierten .NET-Unterstützung arbeitet, will diese Funktionalitäten recht schnell nicht mehr missen – wird aber über kurz oder lang auch darüber stolpern, dass etwa die Rückgabelänge von Zeichenketten auf 8 KByte beschränkt ist. Das mag zwar nach viel klingen, aber wenn man ein XML-Fragment zurückgeben möchte, stößt [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Wer mit der im SQL Server 2005 / 2008 integrierten .NET-Unterstützung arbeitet, will diese Funktionalitäten recht schnell nicht mehr missen – wird aber über kurz oder lang auch darüber stolpern, dass etwa die Rückgabelänge von Zeichenketten auf 8 KByte beschränkt ist. Das mag zwar nach viel klingen, aber wenn man ein XML-Fragment zurückgeben möchte, stößt man recht zuverlässig an diese Grenze und fängt sich eine TruncationException ein.</strong></p>
<p>Eine gewöhnliche Userdefined Function in C# sieht etwa so aus:</p>
<p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:16fefbcb-fa12-469b-89ce-ac2e9f5c6f13" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">[SqlFunction]
public static SqlString Foo(String input) { ... }</pre>
</div>
<p>Sowohl Rückgabe, als auch der Übergabeparameter input sind hier auf eine Größe von maximal 8 KByte beschränkt. Wem das nicht ausreicht, der muss das SqlFacet-Attribut verwenden, das sich sowohl oberhalb der Funktion, als auch vor dem Übergabeparameter notieren lässt:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:acc8143a-b80f-40dd-a5ae-ac380ae4b65a" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">[SqlFunction]
[return: SqlFacet(MaxSize = -1)]
public static SqlString Foo([SqlFacet(MaxSize = -1)] String input) { ... }</pre>
</div>
<p>Problem gelöst: Die MaxSize-Angabe definiert, dass es keine maximale Größe für den Parameter oder die Rückgabe mehr geben soll. Nach dem erneuten Bereitstellen der Assembly im SQL Server sollte es keine TruncationException mehr geben. </p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/GpebJkLfTJo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/12/19/sqlclr-rckgabenlnge-von-userdefined-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/12/19/sqlclr-rckgabenlnge-von-userdefined-functions/</feedburner:origLink></item>
		<item>
		<title>#Java: Kein Java 1.4 und Java 5 für Snow Leopard</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/b0Gx3MwdtwM/</link>
		<comments>http://www.aspextra.de/2009/10/07/java-kein-java-1-4-und-java-5-fr-snow-leopard/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 16:03:18 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Java SDK]]></category>
		<category><![CDATA[Snow Leopard]]></category>
		<category><![CDATA[Sun]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/10/07/java-kein-java-1-4-und-java-5-fr-snow-leopard.html</guid>
		<description><![CDATA[Wem es noch nicht aufgefallen sein sollte: Java 1.4 und Java 5 sind EOL, End of lifecycle. Das ist für sich nicht weiter schlimm, im Archiv von Sun kann man sich die älteren JREs und SDKs problemlos herunter laden, aber wenn man Snow Leopard besitzt, schaut man ganz schön in die Röhre, denn Sun liefert(e) [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Wem es noch nicht aufgefallen sein sollte: Java 1.4 und Java 5 sind EOL, End of lifecycle. Das ist für sich nicht weiter schlimm, im Archiv von Sun kann man sich die älteren JREs und SDKs problemlos herunter laden, aber wenn man Snow Leopard besitzt, schaut man ganz schön in die Röhre, denn Sun liefert(e) Java für den Mac noch nie direkt aus, und Apple stellt die EOL-Versionen für Snow Leopard schlicht nicht zur Verfügung.</strong></p>
<p>Die JREs kann man dennoch installieren, im <a href="http://wiki.oneswarm.org/index.php/OS_X_10.6_Snow_Leopard">Wiki von OneSwarm</a> ist das anschaulich beschrieben und erklärt. Ohne Chance ist man (laut meinem derzeitigen Wissensstand) jedoch, wenn es um die SDKs geht, es sei denn, irgendjemand hätte noch eine gezippte Version davon auf der Platte.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/b0Gx3MwdtwM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/10/07/java-kein-java-1-4-und-java-5-fr-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/10/07/java-kein-java-1-4-und-java-5-fr-snow-leopard/</feedburner:origLink></item>
		<item>
		<title>#ASP.NET: UserControl dynamisch laden</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/FKJ_vQxJbSE/</link>
		<comments>http://www.aspextra.de/2009/08/11/asp-net-usercontrol-dynamisch-laden/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 06:45:42 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Tipp]]></category>
		<category><![CDATA[LoadControl]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/08/11/asp-net-usercontrol-dynamisch-laden.html</guid>
		<description><![CDATA[Webseiten sind nicht immer statisch verdrahtet. Manchmal benötigt man eine Möglichkeit, UserControls dynamisch nachzuladen. Mit Hilfe von ein wenig Code geht sowas ohne großen Aufwand. Gegeben sei ein einfaches UserControl TextDisplay.ascx, das eine TextBox anzeigt oder alternativ den eingegebenen Text darstellt: &#60;%@ Control Language="C#" ClassName="TextDisplayControl" %&#62; &#60;script runat="server"&#62; /// &#60;summary&#62; /// Zugriff auf den angezeigten [...]]]></description>
			<content:encoded><![CDATA[<p>Webseiten sind nicht immer statisch verdrahtet. Manchmal benötigt man eine Möglichkeit, UserControls dynamisch nachzuladen. Mit Hilfe von ein wenig Code geht sowas ohne großen Aufwand.</p>
<p>Gegeben sei ein einfaches UserControl TextDisplay.ascx, das eine TextBox anzeigt oder alternativ den eingegebenen Text darstellt:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:afaa0cc4-10f2-4528-8e6b-285505c464b5" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">&lt;%@ Control Language="C#" ClassName="TextDisplayControl" %&gt;
&lt;script runat="server"&gt;
   /// &lt;summary&gt;
   /// Zugriff auf den angezeigten Namen
   /// &lt;/summary&gt;
   public String Text
   {
      get
      {
         return tbName.Text;
      }
      set
      {
         tbName.Text = value;
      }
   }

   /// &lt;summary&gt;
   /// Behandelt das PreRender-Ereignis
   /// &lt;/summary&gt;
   protected override void OnPreRender(EventArgs e)
   {
      // Überprüfen, ob ein PostBack stattgefunden hat
      if(!IsPostBack)
      {
         // Initial das Eingabefeld anzeigen
         ToggleVisibility(true);
      }

      // Daten binden lassen
      DataBind();

      // Weiter verarbeiten lassen
      base.OnPreRender(e);
   }

   /// &lt;summary&gt;
   /// Schaltet die Sichtbarkeit der PlaceHolder um
   /// &lt;/summary&gt;
   private void ToggleVisibility(bool showEnterText)
   {
      // Anzeige umschalten
      phEnterText.Visible = showEnterText;
      phShowText.Visible = !showEnterText;
   }

   /// &lt;summary&gt;
   /// Aktiviert die Texteingabe
   /// &lt;/summary&gt;
   protected void EditText(object sender, EventArgs e)
   {
      // Eingabefeld anzeigen lassen
      ToggleVisibility(true);
   }

   /// &lt;summary&gt;
   /// Aktiviert die Textausgabe
   /// &lt;/summary&gt;
   protected void ShowText(object sender, EventArgs e)
   {
      // Ausgabefeld anzeigen lassen
      ToggleVisibility(false);
   }
&lt;/script&gt;
&lt;asp:PlaceHolder runat="server" ID="phEnterText"&gt;
   &lt;div&gt;Ihr Name&lt;/div&gt;
   &lt;div&gt;&lt;asp:TextBox runat="server" ID="tbName" /&gt;&lt;/div&gt;
   &lt;div&gt;&lt;asp:Button runat="server" ID="tbButtonShow"
      Text="Anzeigen" OnClick="ShowText" /&gt;&lt;/div&gt;
&lt;/asp:PlaceHolder&gt;
&lt;asp:PlaceHolder runat="server" ID="phShowText"&gt;
   &lt;div&gt;Hallo, &lt;asp:Label runat="server" Text="&lt;%# tbName.Text %&gt;" /&gt;&lt;/div&gt;
   &lt;div&gt;&lt;asp:Button runat="server" ID="tbButtonEdit"
      Text="Bearbeiten" OnClick="EditText" /&gt;&lt;/div&gt;
&lt;/asp:PlaceHolder&gt;</pre>
</div>
<p>Dieses Steuerelement verfügt über zwei Buttons, deren Ereignisbehandlungsmethoden ShowText und EditText die Umschaltung der beiden Platzhalter, in denen sich die Eingabe- bzw. Ausgabe-Elemente befinden, steuern. Dabei kommt der Standard-ASP.NET-Ereignisverarbeitungsmechanismus zu Einsatz.</p>
<p>In einer Page oder einem übergeordneten Steuerelement wird dieses Control nun dynamisch geladen. Dabei kommt die Methode LoadControl() der Page- bzw. Control-Klasse zum Einsatz. Diese nimmt als Parameter den relativen oder absoluten Pfad zum zu ladenden Steuerelement entgegen. Wichtig dabei ist, das sich das Steuerelement innerhalb des Applikationsverzeichnisses befinden muss &#8211; ein Steuerelement aus einem anderen Verzeichnis lässt sich so nicht laden.</p>
<p>Beim Init-Ereignis des ladenden Steuerelements findet der eigentliche Aufruf von LoadControl() statt. Bezogen auf die Ereignisreihenfolge ist Init eines der sehr am Anfang stehenden Ereignisse und möglicherweise nicht ideal bezogen auf das Auslesen von Informationen aus dem Benutzerkontext (Session), denn dieser steht hier noch nicht zur Verfügung. Soll jedoch die Ereignisbehandlung innerhalb des zu ladenden Steuerelements wie gewohnt ablaufen, ist der Eintritt des Init-Ereignisses der beste Zeitpunkt &#8211; spätere Events würden dazu führen, das innerhalb des geladenen Steuerelements unter Umständen keine ordnungsgemäße Abarbeitung der Lebenszyklen stattfinden kann (ViewState wird nicht richtig geladen, Events werden nicht korrekt geworfen, etc.).</p>
<p>Nachdem das Steuerelement geladen worden ist, liegt es als Instanz vom Typ Control vor, ist also eher generischen Charakter. Ist jedoch der Klassenname bekannt, kann die geladene Instanz in den konkreten Typ konvertiert werden. Damit sind sämtliche typspezifische Eigenschaften und Methoden erreichbar und können manipuliert werden.</p>
<p>Zuletzt muss das Steuerelement einem anderen, in der Seite befindlichen Steuerelement zur Anzeige zugewiesen werden. Dies geschieht mit Hilfe der Add()-Methode von dessen Controls-Auflistung.</p>
<p>Der Code einer Seite, die das Steuerelement TextDisplay.ascx lädt und einbindet, sieht letztlich so aus:</p>
<p><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:43b123ea-267b-4067-b1be-6b95007514c1" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">&lt;%@ Page Language="C#" %&gt;
&lt;script runat="server"&gt;

   /// &lt;summary&gt;
   /// Behandelt das Init-Ereignis der Seite
   /// &lt;/summary&gt;
   protected override void OnInit(EventArgs e)
   {
      // Laden des Controls
      Control textDisplay = LoadControl("~/TextDisplay.ascx");

      if(!IsPostBack)
      {
         // Control in den konkreten Typ umwandeln
         TextDisplayControl tdc = textDisplay as TextDisplayControl;

         // Initialen Text setzen
         tdc.Text = "Karsten";
      }

      // Control an den PlaceHolder anfügen
      phData.Controls.Add(textDisplay);

      base.OnInit(e);
   }

&lt;/script&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
   &lt;head runat="server"&gt;
      &lt;title&gt;Eingabeseite&lt;/title&gt;
   &lt;/head&gt;
   &lt;body&gt;
      &lt;form id="form1" runat="server"&gt;
         &lt;h1&gt;Hier können Sie Ihren Namen eingeben&lt;/h1&gt;
         &lt;div&gt;
            &lt;asp:PlaceHolder runat="server" ID="phData" /&gt;
         &lt;/div&gt;
      &lt;/form&gt;
   &lt;/body&gt;
&lt;/html&gt;
</pre>
</div>
<p>Falls Sie sich fragen, woher in Zeile 15 der Klassenname TextDisplayControl stammt: Der wurde in der Control-Deklaration mit Hilfe des Attributs ClassName definiert:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:88cbd3ee-277e-4dde-a3b9-024cecb82e89" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">&lt;%@ Control Language="C#" ClassName="TextDisplayControl" %&gt;</pre>
</div>
<p>Ruft ein Benutzer die Seite im Browser auf, erhält er initial folgende Ausgabe:</p>
<p><a href="http://www.aspextra.de/wp-content/uploads/2009/08/EingabeseiteOpera.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Eingabeseite - Opera" border="0" alt="Eingabeseite - Opera" src="http://www.aspextra.de/wp-content/uploads/2009/08/EingabeseiteOpera_thumb.png" width="524" height="292" /></a> </p>
<p>Gibt er einen Namen ein und betätigt die Schaltfläche Anzeigen, wird zur zweiten Ansicht gewechselt:</p>
<p><a href="http://www.aspextra.de/wp-content/uploads/2009/08/EingabeseiteOpera2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Eingabeseite - Opera (2)" border="0" alt="Eingabeseite - Opera (2)" src="http://www.aspextra.de/wp-content/uploads/2009/08/EingabeseiteOpera2_thumb.png" width="524" height="292" /></a> </p>
<p>Der Wechsel auf die Eingabeseite zurück geschieht durch Klick auf die Schaltfläche Bearbeiten.</p>
<p>Zusammenfassend bleibt festzuhalten: Steuerelemente lassen sich dynamisch über die Methode LoadControl() nachladen. Sie können anschließend in ihren konkreten Typ konvertiert werden. Wichtig ist, das dieser Prozess so zeitig wie möglich im Lebenszyklus der Seite stattfindet, damit die Ereignisse und Verarbeitungen des dynamisch nachgeladenen Steuerelements korrekt verarbeitet werden können.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/FKJ_vQxJbSE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/08/11/asp-net-usercontrol-dynamisch-laden/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/08/11/asp-net-usercontrol-dynamisch-laden/</feedburner:origLink></item>
		<item>
		<title>.NET CF: XSL-Transformationen einsetzen</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/5Qp_AECxbIk/</link>
		<comments>http://www.aspextra.de/2009/08/05/net-cf-xsl-transformationen-einsetzen/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 20:55:14 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET CF]]></category>
		<category><![CDATA[Tipp]]></category>
		<category><![CDATA[MSXML]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[XSL]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/08/05/net-cf-xsl-transformationen-einsetzen.html</guid>
		<description><![CDATA[Das .NET CF ist eingeschränkt, das weiß man. Diese Einschränkungen betreffen leider auch so alltägliche Dinge, wie etwa LINQ to SQL (geht nicht) oder XSL-Transformationen (geht auch nicht). Stop, Moment, zumindest XSL-Transformationen gehen. Jedenfalls mit einem kleinen Trick. Bei den meisten Windows Mobile-Geräten ab Version 6 (wenn nicht bei allen) befindet sich nämlich die MSXML-COM-Komponente [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Das .NET CF ist eingeschränkt, das weiß man. Diese Einschränkungen betreffen leider auch so alltägliche Dinge, wie etwa LINQ to SQL (geht nicht) oder XSL-Transformationen (geht auch nicht). Stop, Moment, zumindest XSL-Transformationen gehen. Jedenfalls mit einem kleinen Trick.</strong></p>
<p>Bei den meisten Windows Mobile-Geräten ab Version 6 (wenn nicht bei allen) befindet sich nämlich die MSXML-COM-Komponente auf den Maschinchen. Und diese Komponente kann angesprochen werden &#8211; nicht jedoch, ohne vorher die Komponente in das .NET CF-Projekt zu importieren. Leider geht das bei COM-Komponenten nicht direkt &#8211; aber es gibt den MIDL-Kompiler, der aus einer .idl-Datei eine .tlb-Datei zaubern kann, die sich wiederum als Referenz dem Projekt hinzufügen lässt.</p>
<p>Folgende Schritte müssen Sie ausführen, um MSXML zu verwenden:</p>
<ol>
<li>Öffnen Sie die Visual Studio-Eingabeaufforderung und wechseln Sie in das Verzeichnis [Programme]\Windows Mobile 6 SDK\PocketPC\Include\Armv4i</li>
<li>Lassen Sie die tlb-Datei erstellen, indem Sie
<p><em>midl /L . msxml2.idl</em>      </p>
<p>eingeben</li>
<li>Kopieren Sie die erzeugte msxml2.tlb-Datei in das Verzeichnis Ihrer .NET CF-Applikation</li>
<li>Fügen Sie die Datei Ihrem Projekt als Referenz über das &quot;Durchsuchen&quot;-Tab des Verweis-Dialogs hinzu</li>
</ol>
<p>Nun können Sie mit Hilfe von MSXML auf die gute, alte, herkömmliche Art und Weise mit XML arbeiten:</p>
<p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:6c18ca78-04d0-4be6-8867-2b305e4055c8" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">// Quelle laden
DOMDocument doc = new DOMDocumentClass();
doc.load("source.xml");

// XSL-Stylesheet laden
DOMDocument xsl = new DOMDocumentClass();
xsl.load("style.xsl");

// Transformation durchführen
string html = doc.transformNode(xsl);</pre>
</div>
<p>Na bitte, geht doch!</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/5Qp_AECxbIk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/08/05/net-cf-xsl-transformationen-einsetzen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/08/05/net-cf-xsl-transformationen-einsetzen/</feedburner:origLink></item>
		<item>
		<title>#.NET: #LINQ to SQL und XML-basierte Mappings</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/xv6a81ncRpw/</link>
		<comments>http://www.aspextra.de/2009/07/30/net-linq-to-sql-und-xml-basierte-mappings/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 12:34:29 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Tipp]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[LINQ to SQL]]></category>
		<category><![CDATA[O/R-Mapping]]></category>
		<category><![CDATA[XmlMappingSource]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/07/30/net-linq-to-sql-und-xml-basierte-mappings.html</guid>
		<description><![CDATA[Was von Anfang an bei LINQ to SQL gestört hat, ist die scheinbare Notwendigkeit, auf Mappings per Attribut zurückzugreifen. Stellen Sie sich ein klassisches Szenario vor: Es sollen mit den selben LINQ-Statements je nach Situation unterschiedliche Tabellen abgefragt werden (ich habe das zum Beispiel bei einem Kunden, der mit Navision arbeitet). Das geht mit Attributen [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Was von Anfang an bei LINQ to SQL gestört hat, ist die scheinbare Notwendigkeit, auf Mappings per Attribut zurückzugreifen. Stellen Sie sich ein klassisches Szenario vor: Es sollen mit den selben LINQ-Statements je nach Situation unterschiedliche Tabellen abgefragt werden (ich habe das zum Beispiel bei einem Kunden, der mit Navision arbeitet). Das geht mit Attributen schlicht nicht. Oder Sie möchten einfach keine Attribute nutzen, die ja eine fixe Verdrahtung mit LINQ to SQL bedeuten würden, was oftmals nicht wünschenswert ist.</strong></p>
<p>Zum Glück gibt es die <a href="http://msdn.microsoft.com/de-DE/library/system.data.linq.mapping.xmlmappingsource.aspx" target="_blank">XmlMappingSource</a>-Klasse. Die erlaubt es, die Mappings in XML-Dateien abzulegen und somit unabhängig von der Klasse zu halten, was in Bezug auf Wartbarkeit und Entkoppelung von Schichten ohnehin deutlich sinnvoller ist.</p>
<p>Die XmlMappingSource-Klasse verfügt über vier statische Methoden:</p>
<ul>
<li>FromReader(): Nimmt eine XmlReader-Instanz entgegen</li>
<li>FromStream(): Erwartet einen Stream</li>
<li>FromUrl(): Erwartet die Angabe eines URI </li>
<li>FromXml(): Akzeptiert eine als XML interpretierbare Zeichenkette</li>
</ul>
<p>Etwas umständlich ist, das nicht mehrere XML-Dateien zugewiesen werden können, aber da kann man sich ggf. mit kleineren Workarounds (Laden mehrerer Dateien, Überführen in ein Gesamt-XML) behelfen.</p>
<p>Um zu verdeutlichen, wie mit dem XML-basierten Mapping gearbeitet kann, soll im folgendenen Beispiel eine einfache Personen-Klasse verwendet werden:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8cfb73df-d2ac-4748-8f83-79439be88d55" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">using System;

namespace XML_LINQ_Sample.Model
{
   /// &lt;summary&gt;
   /// Repräsentiert eine Person
   /// &lt;/summary&gt;
   public class Person
   {
      /// &lt;summary&gt;
      /// Initialisierung der Klasse
      /// &lt;/summary&gt;
      public Person()
      {
         LastChanged = DateTime.Now;
      }

      /// &lt;summary&gt;
      /// Id der Person, Identity in der Tabelle
      /// &lt;/summary&gt;
      public int Id { get; set; }

      /// &lt;summary&gt;
      /// Vorname
      /// &lt;/summary&gt;
      public string FirstName { get; set; }

      /// &lt;summary&gt;
      /// Nachname
      /// &lt;/summary&gt;
      public string LastName { get; set; }

      /// &lt;summary&gt;
      /// E-Mail-Adresse
      /// &lt;/summary&gt;
      public string Email { get; set; }

      /// &lt;summary&gt;
      /// Datum der letzten Änderung
      /// &lt;/summary&gt;
      public DateTime LastChanged { get; set; }
   }
}
</pre>
</div>
<p>Das Mapping für diese Klasse kann nun wie folgt aussehen:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:3c65d0e1-1795-4bf4-9158-7e996d86413e" class="wlWriterEditableSmartContent">
<pre name="code" class="xml">&lt;Database Name="Samples"
          xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007"&gt;

   &lt;!-- Person --&gt;
   &lt;Table Name="Persons" Member="XML_LINQ_Sample.Model.Person"&gt;

      &lt;!-- Typ-Definition --&gt;
      &lt;Type Name="XML_LINQ_Sample.Model.Person"&gt;

         &lt;!-- ID --&gt;
         &lt;Column Name="Id" Member="Id" IsPrimaryKey="true" IsDbGenerated="true" /&gt;

         &lt;!-- Vorname --&gt;
         &lt;Column Name="FirstName" Member="FirstName" /&gt;

         &lt;!-- Nachname --&gt;
         &lt;Column Name="LastName" Member="LastName" /&gt;

         &lt;!-- Email --&gt;
         &lt;Column Name="EMail" Member="Email" /&gt;

         &lt;!-- Letzte Änderung --&gt;
         &lt;Column Name="LastChanged" Member="LastChanged" /&gt;
      &lt;/Type&gt;

   &lt;/Table&gt;

&lt;/Database&gt;</pre>
</div>
<p>Wichtig für dieses Mapping ist die Angabe des korrekten Namensraumes <a href="http://schemas.microsoft.com/linqtosql/mapping/2007">http://schemas.microsoft.com/linqtosql/mapping/2007</a>, da der Inhalt des XML-Dokuments sonst schlicht nicht ausgewertet werden könnte. Die einzelnen Typen werden innerhalb eines Table-Elements in einem Type-Element definiert. Eine Spalte definiert das Column-Element, wobei die beiden Attribute Name und Member Pflichtangaben sind. Zusätzlich werden beim ID-Element die beiden Attribute IsPrimaryKey und IsDbGenerated verwendet. Deren Aufgabe ist es, anzugeben, ob die Spalte den Primärschlüssel der Tabelle repräsentiert (IsPrimaryKey) und ob der jeweilige Wert vom Datenbanksystem automatisch generiert werden soll (IsDbGenerated).</p>
<p><strong>Tipp</strong>: Das XML-Dokument sollten Sie als Ressource ihrem Projekt hinzufügen, da dies die Handhabung deutlich erleichtert. In diesem Fall wird es unter dem Namen PersonMapping als Ressource gespeichert.</p>
<p>Innerhalb unseres Programms können Sie nun eine Methode definieren, die diese Ressource lädt und einem DataContext zuweist:</p>
<p><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:7c241412-7dce-4096-9dc9-4cec33db5e40" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">/// &lt;summary&gt;
/// Erzeugt einen DataContext
/// &lt;/summary&gt;
private static DataContext GetDataContext()
{
   // ConnectionString-Einstellungen abrufen
   ConnectionStringSettings connStr = ConfigurationManager.ConnectionStrings["Sample"];

   // DbProviderFactory abrufen
   DbProviderFactory factory = DbProviderFactories.GetFactory(connStr.ProviderName);

   // Connection erzeugen lassen
   DbConnection connection = factory.CreateConnection();
   connection.ConnectionString = connStr.ConnectionString;

   // MappingSource definieren
   XmlMappingSource source = XmlMappingSource.FromXml(Resources.PersonMapping);

   // DataContext zurückgeben
   return new DataContext(connection, source);
}</pre>
</div>
<p>Der &quot;magische Teil&quot; ist die Verwendung einer XmlMappingSource. Ansonsten verhält sich der DataContext, wie Sie es gewohnt sind:</p>
<p><div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:5b9a4373-c768-414e-ba6f-215bad766228" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">/// &lt;summary&gt;
/// Führt irgendwelche Operationen aus
/// &lt;/summary&gt;
public void PerformActions()
{

   // DataContext definieren
   using(DataContext dc = GetDataContext())
   {
      // Schema erzeugen lassen, wenn es
      // noch nicht existiert
      if(!dc.DatabaseExists())
      {
         dc.CreateDatabase();
      }

      // Tabelle referenzieren
      Table&lt;Person&gt; personTable = dc.GetTable&lt;Person&gt;();

      // Datensatz finden
      Person person = (
         from Person p in personTable
         where p.LastName.Equals("Samaschke") &amp;&amp;
               p.FirstName.Equals("Karsten")
         select p).FirstOrDefault();

      // Datensatz gefunden?
      if(null != person)
      {
         // Werte ändern
         person.Email = "name@adresse.de";
         person.LastChanged = DateTime.Now;
      }
      else
      {
         // Datensatz anlegen
         person = new Person();
         person.FirstName = "Karsten";
         person.LastName = "Samaschke";
         person.Email = "name@adresse.de";

         // Datensatz einfügen
         personTable.InsertOnSubmit(person);
      }

      // Änderungen speichern
      dc.SubmitChanges();
   }
}
</pre>
</div>
<p>Mit dem Umweg über die XmlMappingSource schlagen Sie letztlich mehrere Fliegen mit einer Klappe:</p>
<ul>
<li>Verwendbarkeit verschiedener Datenbanken oder Datenbanktabellen je nach Szenario</li>
<li>Verhinderung des Bindens von Klassen an ein bestimmtes O/R-Mapping-Framework</li>
<li>Bessere Wartbarkeit und Pflegbarkeit Ihres DataLayers</li>
</ul>
<p>Einziger echter Nachteil ist, das Microsoft diesen Ansatz zwar grundsätzlich dokumentiert, Sie aber bis auf die Klassenbeschreibung der <a href="http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.xmlmappingsource.aspx" target="_blank">XmlMappingSource</a> und die <a href="http://msdn.microsoft.com/en-us/library/bb386907.aspx" target="_blank">Definition des XML-Schemas für die Mapping-Dateien</a> keinerlei weitere Unterstützung von Seiten des Anbieters erhalten. Da die Elemente und Attribute jedoch den Standard-LINQ-Code-Attributen entsprechen, können Sie die <a href="http://msdn.microsoft.com/de-de/library/bb386971.aspx" target="_blank">dort getroffenen Aussagen</a> hier 1:1 übertragen.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/xv6a81ncRpw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/07/30/net-linq-to-sql-und-xml-basierte-mappings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/07/30/net-linq-to-sql-und-xml-basierte-mappings/</feedburner:origLink></item>
		<item>
		<title>#TIPP: #Fluent #Interfaces</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/Mf0YjT5tbTg/</link>
		<comments>http://www.aspextra.de/2009/07/29/tipp-fluent-interfaces/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 09:02:37 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Handwerk]]></category>
		<category><![CDATA[Tipp]]></category>
		<category><![CDATA[Fluent Interfaces]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/07/29/tipp-fluent-interfaces.html</guid>
		<description><![CDATA[Nicht ganz neu, aber ungemein praktisch ist die Idee von Fluent Interfaces. Der Gedanke dahinter ist sehr simpel: Alle Methoden haben eine Rückgabe vom Typ eines definierten Interfaces oder der jeweiligen Klasse. Der Effekt: Die Lesbarkeit wird gesteigert und der Schreibaufwand verringert sich. Im folgenden Beispiel seien ein Interface IConfiguration und ein Interface IConfigurationFluent definiert, [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Nicht ganz neu, aber ungemein praktisch ist die Idee von Fluent Interfaces. Der Gedanke dahinter ist sehr simpel: Alle Methoden haben eine Rückgabe vom Typ eines definierten Interfaces oder der jeweiligen Klasse. Der Effekt: Die Lesbarkeit wird gesteigert und der Schreibaufwand verringert sich.</strong></p>
<p>Im folgenden Beispiel seien ein Interface IConfiguration und ein Interface IConfigurationFluent definiert, die die gleiche Funktionalität abbilden:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1c1e81da-2e81-4972-973f-e1fc8582ee95" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">/// &lt;summary&gt;
/// Setzt Konfigurationsinformationen
/// &lt;/summary&gt;
public interface IConfiguration
{
   /// &lt;summary&gt;
   /// Breite setzen
   /// &lt;/summary&gt;
   void SetWidth(int width);

   /// &lt;summary&gt;
   /// Höhe setzen
   /// &lt;/summary&gt;
   void SetHeight(int height);

   /// &lt;summary&gt;
   /// Text setzen
   /// &lt;/summary&gt;
   void SetText(string text);

   /// &lt;summary&gt;
   /// Ausführen
   /// &lt;/summary&gt;
   void Execute();
}

/// &lt;summary&gt;
/// Setzt Konfigurationsinformationen auf angenehmere Art und Weise
/// &lt;/summary&gt;
public interface IConfigurationFluent
{
   /// &lt;summary&gt;
   /// Breite setzen
   /// &lt;/summary&gt;
   IConfigurationFluent SetWidth(int width);

   /// &lt;summary&gt;
   /// Höhe setzen
   /// &lt;/summary&gt;
   IConfigurationFluent SetHeight(int height);

   /// &lt;summary&gt;
   /// Text setzen
   /// &lt;/summary&gt;
   IConfigurationFluent SetText(string text);

   /// &lt;summary&gt;
   /// Ausführen
   /// &lt;/summary&gt;
   IConfigurationFluent Execute();
}</pre>
</div>
<p>Der zusätzliche Definitionsaufwand ist minimal, die Handhabung des Codes nimmt jedoch deutlich zu. Sehen wir uns an, wie man mit dem herkömmlichen Interface arbeitet:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:0ecfaf3f-83f5-46fa-8009-b93591bb41bd" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">/// &lt;summary&gt;
/// Konfiguriert ein Element auf die "klassische" Art
/// &lt;/summary&gt;
public void Configure(IConfiguration config)
{
   // Höhe setzen
   config.SetHeight(20);

   // Breite setzen
   config.SetWidth(40);

   // Text setzen
   config.SetText("Hallo, Welt");

   // Ausführen
   config.Execute();
}
</pre>
</div>
<p>Nichts dagegen einzuwenden. Störend ist nur, das Sie ständig &quot;config&quot; schreiben müssen und Operationen, die zusammen gehören, einzeln durchführen.</p>
<p>Hier ist der funktional gleichwertige Code unter Verwendung des Fluent-Interfaces:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:f4166a9b-312a-4406-8626-2137c370656f" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">/// &lt;summary&gt;
/// Konfiguriert ein Element auf die "fluente" Art
/// &lt;/summary&gt;
public void Configure(IConfigurationFluent config)
{
   // Höhe, Breite, Text setzen und Operation durchführen
   config.SetHeight(20)
         .SetWidth(40)
         .SetText("Hallo, Welt")
         .Execute();
}
</pre>
</div>
<p><strong>Hinweis</strong>: Da die implementierten Methoden alle die jeweilige Instanz wieder zurückgeben sollen, muss an deren Ende stets <em>return this;</em> eingefügt werden. Für die Methode SetHeight() könnte eine entsprechende Implementierung also so aussehen:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:157d94db-9c37-4620-a930-4d873dc90d89" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">/// &lt;summary&gt;
/// Setzt die Höhe
/// &lt;/summary&gt;
public IConfigurationFluent SetHeight(int height)
{
   // Wert setzen
   this.height = value;

   // Aktuelle Instanz zurück geben
   return this;
}</pre>
</div>
<p>Wie gesagt: Funktional ist dieser Code gleichwertig, in der alltäglichen Anwendung aber um einiges angenehmer, als der klassische Code. Aus genau diesem Grund wird dieser Ansatz von immer mehr Frameworks eingesetzt &#8211; bekanntester Fall ist das NHibernate-Framework, das sehr extensiv davon Gebrauch macht.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/Mf0YjT5tbTg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/07/29/tipp-fluent-interfaces/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/07/29/tipp-fluent-interfaces/</feedburner:origLink></item>
		<item>
		<title>#XML: Arbeit mit Namensräumen beim XmlDocument</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/8oUb2gmgZRg/</link>
		<comments>http://www.aspextra.de/2009/07/28/xml-arbeit-mit-namensrumen-beim-xmldocument/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 16:12:55 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Tipp]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[Namensräume]]></category>
		<category><![CDATA[NameTable]]></category>
		<category><![CDATA[XmlDocument]]></category>
		<category><![CDATA[XmlNamespaceManager]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/07/28/xml-arbeit-mit-namensrumen-beim-xmldocument.html</guid>
		<description><![CDATA[Viele XML-Dokumente, die Sie im Web herunterladen oder benutzen können, verfügen über einen Namensraum. Den müssen Sie angeben, wenn Sie bei .NET die XmlDocument-Klasse und deren Methoden SelectSingleNode() bzw. SelectNodes() verwenden möchten, um an die für Sie relevanten Informationen mit Hilfe von XPath-Ausdrücken zu gelangen. Die Frage ist nur, wo und wie man das machen [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Viele XML-Dokumente, die Sie im Web herunterladen oder benutzen können, verfügen über einen Namensraum. Den müssen Sie angeben, wenn Sie bei .NET die XmlDocument-Klasse und deren Methoden SelectSingleNode() bzw. SelectNodes() verwenden möchten, um an die für Sie relevanten Informationen mit Hilfe von XPath-Ausdrücken zu gelangen. Die Frage ist nur, wo und wie man das machen kann, denn das Dokument verfügt zwei über eine Eigenschaft NameTable, die kann jedoch scheinbar nicht sinnvoll verwendet werden.</strong></p>
<p>Stattdessen greifen Sie auf die Klasse XmlNamespaceManager zurück. Deren Konstruktor nimmt als Parameter die NameTable des Dokuments entgegen. Die Methode AddNamespace() erlaubt es Ihnen im Anschluß, die für Sie relevanten Namensräume zu definieren. Dabei ist zu beachten, das so ein Namensraum stets aus zwei Komponenten besteht: Einem Präfix (der eine Abkürzung für den Namensraum darstellt) und dem URI, dem eigentlichen Namensraum. Das Präfix ist dabei &#8211; im Vergleich zum originalen Dokument &#8211; frei wählbar, der URI muss dem Namensraum im zu verarbeitenden Dokument entsprechen. Sie erkennen die Namensräume stets anhand der xmlns- und xmlns:xx-Attribute, wobei ersteres einen Standardnamensraum darstellt, der ebenfalls per XmlNamespaceManager-Instanz bekannt gemacht werden muss.</p>
<p>Folgendes Beispiel verwendet die XmlNamespaceManager-Klasse um eine Abfrage auf bestimmte Knoten in einem fiktiven Dokument umzusetzen:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:13c43301-0fc1-4f6e-a2c1-51b7062925b9" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">// Dokument erzeugen
XmlDocument doc = new XmlDocument();

// Inhalt einladen
doc.Load("http://...");

// Namespace-Manager für die Verwaltung der Namensräume
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);

// Namensräume anfügen, wichtig sind die URIs
manager.AddNamespace("xs", "urn:sample"); //xmlns:xs="urn:sample"
manager.AddNamespace("xt", "urn:sample2"); //xmlns:xt="urn:sample2"

// Standard-Namensraum anfügen
manager.AddNamespace(string.Empty, "urn:default"); //xmlns="urn:default"

// Abfrage ausführen
XmlNodeList selected = doc.SelectNodes("//dummy[@xt:text='foo']/xs:name");</pre>
</div>
<p>Die einzige wirkliche Schwierigkeit bei der Arbeit mit Namensräumen im .NET-Framework besteht letztlich nur darin, diese zu identifizieren. Nachdem Sie diese Leistung erbracht haben, sollten die weiteren Schritte problemlos umsetzbar sein.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/8oUb2gmgZRg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/07/28/xml-arbeit-mit-namensrumen-beim-xmldocument/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/07/28/xml-arbeit-mit-namensrumen-beim-xmldocument/</feedburner:origLink></item>
		<item>
		<title>#Mobile: HttpWebRequest erfolgreich durchführen</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/7jLVeVEsAXw/</link>
		<comments>http://www.aspextra.de/2009/07/25/mobile-httpwebrequest-erfolgreich-durchfhren/#comments</comments>
		<pubDate>Sat, 25 Jul 2009 20:43:38 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET CF]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Stream]]></category>
		<category><![CDATA[StreamReader]]></category>
		<category><![CDATA[StreamWriter]]></category>
		<category><![CDATA[WebRequest]]></category>
		<category><![CDATA[WebResponse]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/07/25/mobile-httpwebrequest-erfolgreich-durchfhren.html</guid>
		<description><![CDATA[Das .NET Compact Framework &#8211; der kleine Bruder des &#34;normalen&#34; .NET-Frameworks &#8211; verfügt leider nicht über eine WebClient-Klasse. Stattdessen müssen Sie sich mit den auch vom WebClient verwendeten Klassen HttpWebRequest und HttpWebResponse &#34;herumschlagen&#34;. Wobei dies im Grunde sehr einfach ist. Angenommen, sie wollen das Versenden eines Formulars nachstellen, dann würden Sie folgenden Code verwenden können: [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Das .NET Compact Framework &#8211; der kleine Bruder des &quot;normalen&quot; .NET-Frameworks &#8211; verfügt leider nicht über eine WebClient-Klasse. Stattdessen müssen Sie sich mit den auch vom WebClient verwendeten Klassen HttpWebRequest und HttpWebResponse &quot;herumschlagen&quot;. Wobei dies im Grunde sehr einfach ist.</strong></p>
<p>Angenommen, sie wollen das Versenden eines Formulars nachstellen, dann würden Sie folgenden Code verwenden können:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1fd20447-d194-4713-9b06-731f3f65349f" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">// Parameter werden als Name-Wert-Parameter übertragen
string parameters = "name=wert&amp;name2=wert2";

// Request erzeugen
HttpWebRequest request = (HttpWebRequest) WebRequest.Create("http://...");

// Pufferung aktivieren (.NETCF-spezifisch)
request.AllowWriteStreamBuffering = true;

// Zugriffsmethode definieren
request.Method = "POST";

// Inhaltslänge übertragen
request.ContentLength = parameters.Length;</pre>
</div>
<p>Nachdem Sie so den WebRequest konfiguriert haben, müssen Sie die Daten übertragen. Sie können dies mit Hilfe der Stream-Implementierung erledigen, die Sie über die GetRequestStream()-Methode der WebRequest-Implementierung referenzieren können. Selbst und direkt in den Stream zu schreiben, wäre zwar möglich, aber wozu sich die Finger schmutzig machen, wenn Sie im System.IO-Namensraum bereits eine StreamWriter-Klasse haben, die die ganze Arbeit übernimmt?</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:72199d68-4276-4c48-80b2-bbcf1a86b13b" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">// StreamWriter zum Schreiben verwenden
StreamWriter sw = new StreamWriter(request.GetRequestStream());

// Informationen übertragen
sw.Write(parameters);

// Daten senden
sw.Flush();

// StreamWriter schließen
sw.Close();
</pre>
</div>
<p>Wichtig ist in diesem Kontext, das Sie per .Flush() und .Close() das Senden der Daten und das Schließen des StreamWriters explizit vornehmen, da Ihnen ansonsten beim Abrufen der Daten eine ProtocolViolationException um die Ohren fliegt.</p>
<p>Nun können die Daten abgerufen werden. Dies geschieht mit Hilfe einer WebResponse-Implementierung, die sie über die Methode GetResponse() des WebRequests erreichen können. Diese WebResponse-Implementierung verfügt über eine Methode GetResponseStream(), die eine Stream-Implementierung zurück gibt, die es erlaubt, die Rückgabe des Servers abzurufen. Auch hier haben Sie die Wahl: Entweder das Rad neu erfinden, oder einen StreamReader verwenden:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2cc87148-fb8d-4433-ac17-c0113149dd2a" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">// WebResponse-Implementierung abrufen
HttpWebResponse response = (HttpWebResponse) request.GetResponse();

// StreamReader zum Einlesen des HTMLs
StreamReader sr = new StreamReader(response.GetResponseStream());

// Rückgabe abrufen
string result = sr.ReadToEnd();

// Fertig
sr.Close();
</pre>
</div>
<p>Fertig. So richtig schwer war es eigentlich nicht. Um den Code noch besser nutzbar zu machen, empfiehlt es sich, ihn in einem Try-Catch-Block zu kapseln und die ggf. auftretenden Ausnahmen (keine Verbindung, falsche URL, sonstige Fehler) entsprechend abfangen zu lassen.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/7jLVeVEsAXw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/07/25/mobile-httpwebrequest-erfolgreich-durchfhren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/07/25/mobile-httpwebrequest-erfolgreich-durchfhren/</feedburner:origLink></item>
		<item>
		<title>#Mobile: Bug in IE6 Mobile / Webbrowser-Control beim .NET CF 3.5?</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/v1C427NQP0g/</link>
		<comments>http://www.aspextra.de/2009/07/21/mobile-bug-in-ie6-webbrowser-control-beim-net-cf-3-5/#comments</comments>
		<pubDate>Tue, 21 Jul 2009 10:41:03 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[.NET CF]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[IE6]]></category>
		<category><![CDATA[Webbrowser-Control]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/07/21/mobile-bug-in-ie6-webbrowser-control-beim-net-cf-3-5.html</guid>
		<description><![CDATA[Entweder bin ich nicht in der Lage, mit dem Webbrowser-Control vom .NET CompactFramework umzugehen, oder es gibt da tatsächlich sowas wie einen Bug, wenn man es mit dem IE6 Mobile nutzen muss (was ja nicht in der Hand des Entwicklers liegt). Folgendes Szenario funktioniert bei mir schlicht nicht, wenn ich es mit einem IE6 Mobile [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Entweder bin ich nicht in der Lage, mit dem Webbrowser-Control vom .NET CompactFramework umzugehen, oder es gibt da tatsächlich sowas wie einen Bug, wenn man es mit dem IE6 Mobile nutzen muss (was ja nicht in der Hand des Entwicklers liegt). Folgendes Szenario funktioniert bei mir schlicht nicht, wenn ich es mit einem IE6 Mobile im Emulator oder auch auf real existierenden Geräten (HTC Touch Pro2 beispielsweise) benutze:</strong></p>
<p>Gegeben sei ein Formular mit einem darauf befindlichen Webbrowser-Control namens webBrowser1. Es gibt einen Eventhandler, der an das Navigating-Ereignis gebunden ist und nichts anderes machen soll, als die anzuspringende Adresse auszugeben:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:cd475be7-14d5-40dc-8b05-6f933fb06396" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
   MessageBox.Show(e.Url.ToString());
}</pre>
</div>
<p>Beim Load-Ereignis des Formulars wird dem Webbrowser-Control über dessen .DocumentText-Eigenschaft ein einfacher HTML-Code zugewiesen:</p>
</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a12c98a0-90b3-4076-ba67-80fdd1a183b9" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">private void Form1_Load(object sender, EventArgs e)
{
   string html =
      "&lt;html&gt;&lt;head&gt;&lt;title&gt;Sample&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;a href=\"http://www.microsoft.de\"&gt;Microsoft.de&lt;/a&gt;&lt;/body&gt;&lt;/html&gt;";
   webBrowser1.DocumentText = html;
}</pre>
</div>
<p>Auf einem Gerät mit dem (alten) IE4 gibt es zwei Anzeigen der MessageBox:</p>
<p><a href="http://www.aspextra.de/wp-content/uploads/2009/07/WindowsMobile6Professional.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Windows Mobile 6 Professional" border="0" alt="Windows Mobile 6 Professional" src="http://www.aspextra.de/wp-content/uploads/2009/07/WindowsMobile6Professional_thumb.png" width="162" height="320" /></a> <a href="http://www.aspextra.de/wp-content/uploads/2009/07/WindowsMobile6Professional2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Windows Mobile 6 Professional (2)" border="0" alt="Windows Mobile 6 Professional (2)" src="http://www.aspextra.de/wp-content/uploads/2009/07/WindowsMobile6Professional2_thumb.png" width="162" height="320" /></a> </p>
<p>Wenn man es mit dem IE6 Mobile (etwa im Windows Mobile 6.5-Emulator) versucht, geschieht dies nicht &#8211; es wird nur die initiale MessageBox angezeigt:</p>
<p><a href="http://www.aspextra.de/wp-content/uploads/2009/07/WM6.5Professional240x400.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="WM 6.5 Professional - 240x400" border="0" alt="WM 6.5 Professional - 240x400" src="http://www.aspextra.de/wp-content/uploads/2009/07/WM6.5Professional240x400_thumb.png" width="142" height="320" /></a> <a href="http://www.aspextra.de/wp-content/uploads/2009/07/WM6.5Professional240x4002.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="WM 6.5 Professional - 240x400 (2)" border="0" alt="WM 6.5 Professional - 240x400 (2)" src="http://www.aspextra.de/wp-content/uploads/2009/07/WM6.5Professional240x4002_thumb.png" width="142" height="320" /></a> </p>
<p>Auch ein erneutes Binden des Ereignishandlers funktioniert nicht. Dabei &#8211; und das ist interessant &#8211; werden JavaScripts beispielsweise innerhalb der Webseite ausgeführt. Aber der Klick auf den Link führt zu keiner Reaktion &#8211; noch nicht einmal die referenzierte Webseite wird aufgerufen.</p>
<p>Bisher habe ich keinen Workaround darum gefunden. Ich weiß, dass das OpenCFFramework da was anbietet, aber ich sehe &#8211; wenn ich ehrlich bin &#8211; nicht wirklich ein, auf ein anderes Framework zu wechseln, wenn es sich doch um eine bereits in der Vergangenheit funktionierende Funktionalität handelt. </p>
<p>Nix da, ich nenne das einen Bug.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/v1C427NQP0g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/07/21/mobile-bug-in-ie6-webbrowser-control-beim-net-cf-3-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/07/21/mobile-bug-in-ie6-webbrowser-control-beim-net-cf-3-5/</feedburner:origLink></item>
		<item>
		<title>#ASP.NET: Ausgabe manipulieren</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/r9hpRvvj_Ro/</link>
		<comments>http://www.aspextra.de/2009/07/11/asp-net-ausgabe-manipulieren/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 22:12:03 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Tipp]]></category>
		<category><![CDATA[OutputStream]]></category>
		<category><![CDATA[Response.Filter]]></category>
		<category><![CDATA[Stream]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/07/11/asp-net-ausgabe-manipulieren.html</guid>
		<description><![CDATA[Angenommen, Sie würden eine Webseite betreiben, die etwa BB-Code oder anderen Pseudocode für Formatierungen von Ausgaben verwendet. Sie hätten dann die unangenehme Aufgabe, ein entsprechendes Umformatieren aller BB-Code-Tags in die entsprechenden HTML-Tags bei jeder Ausgabe vorzunehmen. Da wäre es doch angenehmer, dies zentral erledigen zu lassen. Für genau diesen Zweck ist die Eigenschaft Filter der [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Angenommen, Sie würden eine Webseite betreiben, die etwa BB-Code oder anderen Pseudocode für Formatierungen von Ausgaben verwendet. Sie hätten dann die unangenehme Aufgabe, ein entsprechendes Umformatieren aller BB-Code-Tags in die entsprechenden HTML-Tags bei jeder Ausgabe vorzunehmen. Da wäre es doch angenehmer, dies zentral erledigen zu lassen.</strong></p>
<p>Für genau diesen Zweck ist die Eigenschaft Filter der HttpResponse-Klasse geschaffen worden. Diese erlaubt es, eine eigene Stream-Implementierung zu definieren, die eine Ausgabe … naja, filtert. Dabei ist das Schwierigste, diese Implementierung zu entwickeln, jedenfalls dann, wenn man nicht weiß, wie man es anstellen soll.</p>
<p>Die Lösung: Einfach die vorhandene Stream-Implementierung im Konstruktor des eigenen Streams übergeben lassen, in einer Instanzvariablen speichern und dann überall verwenden. Der eigene Filter erbt dabei zwingend von der Basisklasse System.IO.Stream und implementiert die abstrakten Methoden dieser Klasse. </p>
<p> <span id="more-16"></span>
<p>Das sieht dann insgesamt etwa so aus:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:dc0cd8c2-d5bd-4af0-b1db-3e4dd39ce36c" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">using System.IO;
using System.Text;
using System.Text.RegularExpressions;

/// &lt;summary&gt;
/// Eigene Stream-Implementierung zur Manipulation der Ausgabe
/// &lt;/summary&gt;
public class CustomResponseFilter : Stream
{
   private Stream stream;

   /// &lt;summary&gt;
   /// Konstruktor der Klasse
   /// &lt;/summary&gt;
   public CustomResponseFilter(Stream stream)
	{
	   this.stream = stream;
   }

   #region Standard-Implementierung verwenden
   public override bool CanRead
   {
      get { return stream.CanRead; }
   }

   public override bool CanSeek
   {
      get { return stream.CanSeek; }
   }

   public override bool CanWrite
   {
      get { return stream.CanWrite; }
   }

   public override void Flush()
   {
      stream.Flush();
   }

   public override long Length
   {
      get { return stream.Length; }
   }

   public override long Position
   {
      get
      {
         return stream.Position;
      }
      set
      {
         stream.Position = value;
      }
   }

   public override int Read(byte[] buffer, int offset, int count)
   {
      return stream.Read(buffer, offset, count);
   }

   public override long Seek(long offset, SeekOrigin origin)
   {
      return stream.Seek(offset, origin);
   }

   public override void SetLength(long value)
   {
      stream.SetLength(value);
   }
   #endregion
</pre>
</div>
<p>Nun fehlt noch eine Methode, die für das Schreiben der Ausgabe notwendig und von der abstrakten Stream-Klasse auch erfordert wird: Write(). Und genau die beinhaltet nun den Code, der die Ausgabe manipulieren wird. Dabei wird folgende Vorgehensweise verwendet:</p>
<ul>
<li>Der übergebene Inhalt (ein Byte-Array) wird in eine Zeichenkette umgewandelt, um manipuliert werden zu können </li>
<li>Die Manipulation findet auf der Zeichenkette statt </li>
<li>Die Zeichenkette wird wieder in ein Byte-Array umgewandelt und per innerem Stream&#160; ausgegeben. </li>
</ul>
<p>Im Code sieht das dann für ein [URL …]-Tag so aus:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:0a148aeb-0128-4e8f-8db5-3407881bae1f" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">   /// &lt;summary&gt;
   /// Schreibt den Output
   /// &lt;/summary&gt;
   public override void Write(byte[] buffer, int offset, int count)
   {
      // Byte-Array in String umwandeln
      string output = Encoding.UTF8.GetString(buffer);

      // Zeichenkette suchen
      string pattern = "\\[URL ([^\\]]+?)\\]";
      string replacement = "&lt;a href=\"$1\" target=\"_blank\"&gt;";
      output = Regex.Replace(output, pattern, replacement,
         RegexOptions.IgnoreCase | RegexOptions.Compiled);

      // Schließendes Element suchen
      pattern = "\\[/URL\\]";
      replacement = "&lt;/a&gt;";
      output = Regex.Replace(output, pattern, replacement,
         RegexOptions.IgnoreCase | RegexOptions.Compiled);

      // Wieder in Byte-Array umwandeln
      byte[] result = Encoding.UTF8.GetBytes(output);

      // ...ausgeben lassen
      stream.Write(result, offset, count);
   }
}
</pre>
</div>
<p>Somit ist der eigene Filter für die Ausgabe definiert. Wichtig ist, das wir einen Konstruktor haben, der den standardmäßig definierten Outputstream als Parameter entgegen nimmt und diesen für alle Ausgabeoperationen intern verfügbar macht. </p>
<p>Damit dieser Filter dann auch funktioniert, muss er noch aktiviert werden. Dies geschieht durch Zuweisung an die Eigenschaft Filter der Response-Eigenschaft einer Webseite oder gleich in der global.asax beim BeginRequest-Ereignis. Hier ist es auf Ebene einer einzelnen Seite implementiert:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:75eb618d-1024-4463-bb20-9e5ec7ca4894" class="wlWriterEditableSmartContent">
<pre name="code" class="c#">&lt;%@ Page Language="C#" AutoEventWireup="true" %&gt;
&lt;script runat="server"&gt;
   protected void Page_Load(object sender, EventArgs e)
   {
      Response.Filter = new CustomResponseFilter(Response.Filter);
   }
&lt;/script&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
   &lt;head runat="server"&gt;
       &lt;title&gt;&lt;/title&gt;
   &lt;/head&gt;
   &lt;body&gt;
      &lt;form id="form1" runat="server"&gt;
         &lt;div&gt;
            &lt;h2&gt;BB-Code als Link&lt;/h2&gt;
            [URL http://www.aspextra.de]ASP.extra[/URL]
         &lt;/div&gt;
      &lt;/form&gt;
   &lt;/body&gt;
&lt;/html&gt;
</pre>
</div>
<p>Wenn Sie den Filter nicht aktiviert hätten, würden Sie folgende Ausgabe im Browser sehen:</p>
<p><a href="http://www.aspextra.de/wp-content/uploads/2009/07/httplocalhost5147501_OutputStreamDefault.aspxOpera1.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="httplocalhost5147501_OutputStreamDefault.aspx - Opera" border="0" alt="httplocalhost5147501_OutputStreamDefault.aspx - Opera" src="http://www.aspextra.de/wp-content/uploads/2009/07/httplocalhost5147501_OutputStreamDefault.aspxOpera_thumb1.png" width="492" height="384" /></a> </p>
<p>Ist der Filter aktivert, erscheint nicht etwa der BB-Code, sondern ein Link, der die entsprechende Webseite in einem neuen Fenster öffnet:</p>
<p><a href="http://www.aspextra.de/wp-content/uploads/2009/07/httplocalhost5147501_OutputStreamDefault.aspxOpera21.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="httplocalhost5147501_OutputStreamDefault.aspx - Opera (2)" border="0" alt="httplocalhost5147501_OutputStreamDefault.aspx - Opera (2)" src="http://www.aspextra.de/wp-content/uploads/2009/07/httplocalhost5147501_OutputStreamDefault.aspxOpera2_thumb1.png" width="492" height="384" /></a> </p>
<p>Den Code zu diesem Artikel können Sie hier herunterladen: <a href="http://www.aspextra.de/wp-content/uploads/2009/07/OutputStream4.zip" target="_blank">OutputStream.zip</a></p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/r9hpRvvj_Ro" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/07/11/asp-net-ausgabe-manipulieren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/07/11/asp-net-ausgabe-manipulieren/</feedburner:origLink></item>
		<item>
		<title>#Meinung: Warum Checked Exceptions in .NET fehlen</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/pLc4SeTpN-M/</link>
		<comments>http://www.aspextra.de/2009/07/10/warum-checked-exceptions-in-net-fehlen/#comments</comments>
		<pubDate>Thu, 09 Jul 2009 22:06:02 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Handwerk]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Meinung]]></category>
		<category><![CDATA[Exceptions]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/2009/07/10/warum-checked-exceptions-in-net-fehlen.html</guid>
		<description><![CDATA[Anders Hejlsberg ist seines Zeichens der Erfinder von C#. In einem Interview, das er vor mehreren Jahren gegeben hat, lässt er sich über Checked Exceptions bzw. den Verzicht auf diese Checked Exceptions aus. Zur Erklärung: Wenn innerhalb einer Methode einer .NET-Klasse eine Exception geworfen wird, dann muss ein Entwickler, der diese Methode aufruft, nichts machen. [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Anders Hejlsberg ist seines Zeichens der Erfinder von C#. <a href="http://www.artima.com/intv/handcuffs.html" target="_blank">In einem Interview</a>, das er vor mehreren Jahren gegeben hat, lässt er sich über Checked Exceptions bzw. den Verzicht auf diese Checked Exceptions aus.</strong></p>
<p>Zur Erklärung: Wenn innerhalb einer Methode einer .NET-Klasse eine Exception geworfen wird, dann muss ein Entwickler, der diese Methode aufruft, nichts machen. Er muss noch nicht mal irgendwie reagieren. Oftmals weiß er noch nicht einmal, das es in der Methode eine Exception geben könnte. Der Grund dafür liegt im Verzicht auf einen Mechanismus, der dem Entwickler zuverlässig mitteilt, das in dieser Methode eine bestimmte Exception auftreten kann und diese innerhalb der Methode auch nicht behandelt worden ist. Bei Java gibt es diesen Mechanismus – wenn man dort eine Methode definiert und innerhalb der Methode eine Exception per throw-Schlüsselwort wirft, muß man diese Exception per throws-Schlüsselwort auf Ebene der Methodendeklaration angeben. Das sieht dann etwa so aus:</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2353ecf4-93f1-41a2-871d-429d28ac74dc" class="wlWriterEditableSmartContent">
<pre name="code" class="java">public void tueWas(String input) throws MySuperDuperException, YourSuperDuperException { … }</pre>
</div>
<p>Ruft man jetzt diese Methode auf und kümmert sich nicht um MySuperDuperException und YourSuperDuperException, dann weist einen der Java-Compiler dezent mit einem echten Fehler darauf hin. Kompilieren geht schlicht nicht, das geht erst dann, wenn entweder auf der aufrufenden Methode ebenfalls per throws angegeben worden ist, das diese Exceptions nicht behandelt werden oder wenn man eben das Naheliegende macht: try-catch verwenden. So oder so, als Entwickler ist man gezwungen, sich mit diesen Exceptions auseinander zu setzen.</p>
<p>Anders Hejlsberg sieht das anders. Er führt drei Punkte an, die seiner Meinung nach gegen diese Checked Exceptions sprechen: Versionierung, Skalierbarkeit und Unübersichtlichkeit. Gehen wir diese Punkte einmal der Reihenfolge nach durch.</p>
<p><strong>1. Versionierung</strong></p>
<p>Hier sagt Hejlsberg, das Interfaces unveränderlich sein sollten. Wenn man nun in der Weiterentwicklung eines Interfaces eine neue Exception einführt, dann würde das zwangsläufig zu Inkompatibilitäten und zusätzlichem Entwicklungsaufwand führen. Und die meisten Entwickler würden sich ohnehin nicht darum kümmern. </p>
<p>Ich sage, dass das eine komplette Nicht-Aussage ist, denn man führt Exceptions nicht mal einfach so ein (es spricht ganz definitiv nicht für eine durchdachte API, wenn die bei jedem Release geändert wird) und ganz nebenbei kann ich einfach eine neue Exception definieren, die von einer existierenden (und per throws deklarierten Exception) erbt. Dann muss auch nix neu implementiert werden. Das Argument ist schlicht nicht stimmig. Das Einzige, was hier stimmt, ist die Aussage, dass sich Entwickler ohnehin nicht darum kümmern würden – was nun aber letztlich auch eher gegen-, als für sie spricht und Zeichen einer recht unprofessionellen Arbeitseinstellung ist.</p>
<p><strong>2. Skalierbarkeit</strong></p>
<p>Hejlsberg führt aus, das die Checked Exceptions dazu führen würden, das die Entwickler viel zu viele Exceptions zu behandeln hätten und stattdessen eher auf generische try-catch(Exception e)-Statements wechseln würden. Damit hat er grundsätzlich sicher recht – die Programmierer machen das tatsächlich so. Aber aus diesem Grund auf die Checked Exceptions verzichten, nur weil ein paar Zeitgenossen schlicht keine passende Arbeitseinstellung haben? Das ist kein Argument.</p>
<p>Weiterhin merkt er an, das Checked Exceptions tendenziell eher lokaler behandelt werden. In einer großen Applikation sollte es aber ein zentrales Fehlerhandling geben. Soweit folge ich seiner Argumentation noch. Aber: Auch in Java ist es möglich, Exceptions erneut zu werfen und sie – nach der lokalen Behandlung – dem zentralen Fehlermanagement zuzuführen. Insofern greift seine Aussage schlicht nicht. Dazu kommt, das der Ansatz, ohne Checked Exceptions zu arbeiten, eher zu globalen try-catch(Exception e)-Statements oder noch besser try-finally-Statements führt – Fehlerbehandlung und die gezielte Reaktion auf Ausnahmen sieht schlicht anders aus. Das ist – zugespitzt formuliert – schlicht schlechtes und amateurhaftes Programmieren, was am Ende des Tages die Applikation unzuverlässiger und langsamer macht. Nö, das Argument kann man so nicht stehen lassen.</p>
<p><strong>3. Unübersichtlichkeit</strong></p>
<p>Dieses Argument hängt mit dem Skalierbarkeitsargument zusammen: Es wird sehr unübersichtlich, jede mögliche Exceptionform zu behandeln. Aus diesem Grund gibt es bei .NET das try-finally-Konstrukt, was die Auseinandersetzung mit den verschiedenen Exceptions vermeiden helfe und somit der Übersichtlichkeit zugute komme. Sagt jedenfalls Anders Hejlsberg. Ich persönlich halte das für eine komplett falsche Strategie: Ich kann doch nicht schlicht die Fehler ignorieren, statt auf sie zu reagieren! Und selbst wenn meine Reaktion im Ignorieren bestünde, hätte ich mich wenigstens beim Schreiben des Codes damit auseinander gesetzt! Beim try-finally muß ich selbst das nicht (mehr) tun.</p>
<p>Zusammenfassend bleibt festzuhalten, das ich vom Verzicht auf die Checked Exceptions in .NET absolut nicht überzeugt bin. Je mehr Projekte ich mit .NET umsetze, um so mehr stört mich das. Ich meine, natürlich mache ich es so, wie man es sollte:</p>
<ul>
<li>Eigene Exception-Typen definieren </li>
<li>Exceptions werfen und das auch im Kommentar anzeigen </li>
<li>Exceptions so gezielt und so nah wie möglich abfangen </li>
</ul>
<p>Alles keine Frage, geschieht auch so. Aber irgendwie ist es – durch die Verwendung von Kommentaren und den Verzicht auf einen dedizierten Kompilerfehler – eben eine reine Kann-Geschichte. Damit sorge ich für Unsicherheiten und für unnötige Fehler, und genau das sollte ja eigentlich vermieden werden.</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/pLc4SeTpN-M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/07/10/warum-checked-exceptions-in-net-fehlen/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/07/10/warum-checked-exceptions-in-net-fehlen/</feedburner:origLink></item>
		<item>
		<title>Neustart!</title>
		<link>http://feedproxy.google.com/~r/aspextra/~3/85jvBysXxoU/</link>
		<comments>http://www.aspextra.de/2009/06/28/neustart/#comments</comments>
		<pubDate>Sun, 28 Jun 2009 14:54:00 +0000</pubDate>
		<dc:creator>ksamaschke</dc:creator>
				<category><![CDATA[Systemmitteilung]]></category>

		<guid isPermaLink="false">http://www.aspextra.de/?p=4</guid>
		<description><![CDATA[ASP.extra ist wieder da! Mehrere Jahre waren wir jetzt offline, aber jetzt beginnt ein vorsichtiger Neustart. Das Layout gehört sicher noch angepasst und die Inhalte müssen auch noch wieder wachsen, aber es beginnt wieder etwas Neues. Inhaltlich wird es hier bei ASP.extra &#8212; wie der Untertitel schon verrät &#8212; um Tekkie-Themen gehen: .NET, Java, ASP.NET, [...]]]></description>
			<content:encoded><![CDATA[<p><strong>ASP.extra ist wieder da! Mehrere Jahre waren wir jetzt offline, aber jetzt beginnt ein vorsichtiger Neustart. Das Layout gehört sicher noch angepasst und die Inhalte müssen auch noch wieder wachsen, aber es beginnt wieder etwas Neues.</strong></p>
<p>Inhaltlich wird es hier bei ASP.extra &#8212; wie der Untertitel schon verrät &#8212; um Tekkie-Themen gehen: .NET, Java, ASP.NET, JSPs, Servlets, JSF, Struts, ASP.NET MVC, &#8230;, um nur ein paar Themenbereiche zu nennen, in denen wir uns bewegen werden. Das Mitmachen ist einfach: Jeder Artikel / Beitrag kann kommentiert werden. Wer mag, kann sich registrieren und wird dann von uns ggf. als Autor zugelassen.</p>
<p>Also, auf ein Neues!</p>
<img src="http://feeds.feedburner.com/~r/aspextra/~4/85jvBysXxoU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.aspextra.de/2009/06/28/neustart/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.aspextra.de/2009/06/28/neustart/</feedburner:origLink></item>
	</channel>
</rss>
