<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Andre's Blog! - .NET</title>
    <link>http://blog.codemurai.de/</link>
    <description>.NET, C#, Infragistics</description>
    <language>de-de</language>
    <copyright>Andre Kraemer</copyright>
    <lastBuildDate>Wed, 14 Jul 2010 05:08:57 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.2.8279.16125</generator>
    <managingEditor>andrek@codemurai.de</managingEditor>
    <webMaster>andrek@codemurai.de</webMaster>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=f7a1970e-6a58-4924-8f12-6a0a367694d9</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,f7a1970e-6a58-4924-8f12-6a0a367694d9.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,f7a1970e-6a58-4924-8f12-6a0a367694d9.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=f7a1970e-6a58-4924-8f12-6a0a367694d9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Ja, ich gebe es offen und ehrlich zu! Ich habe sie noch nie wirklich genutzt, die
ASP.NET WebForms ObjectDataSource. Irgendwie hatte ich ein Unbehagen bei der Vorstellung
mir das alles bloß zusammen zu klicken und habe daher bisher einen Bogen um die
ObjectDataSource gemacht. Außerdem habe ich bisher auch noch niemanden getroffen,
der ernsthaft in Erwägung gezogen hätte die ObjectDataSource zu nutzen -
oder sich zumindest getraut hätte, dies zuzugeben ;-)
</p>
        <p>
Kürzlich war es dann aber soweit. meine Für eine kleine Demo startete ich
damit, die serverseitige ASP.NET MVC Implementierung meiner Beispielanwendung für
meinen jQuery Vortrag auf der dotnet Colgone nach Webforms zu konvertieren. Mein Ziel
war es dabei, wo immer es nur geht, den WebForms "Baukasten" zu nehmen.
Da ich bereits einen bestehenden Business Service hatte, der mir meine Objekte laden
und persistieren konnte, kreuzte sie nun also meinen Weg, die ObjectDataSource.
</p>
        <p>
Nach ein paar Klicks durch den Wizzard und einem beherztem F5 bestätigte sich
vorerst mein initiales Vorurteil: "Totaler Mist!".
</p>
        <p>
Mein Business Service hatte nämlich eine Abhängigkeit auf eine weitere Klasse,
die für die  Datenhaltung zuständig war. Diese Abhängigkeit fand
sich in meinem Quellcode in Form eines Konstruktor Parameters wieder. In meiner ASP.NET
MVC Implementierung war der DI Container StructureMap für das Auflösen dieser
Abhängigkeit zuständig.
</p>
        <p>
Die WebForms Variante brach die Ausführung des Codes nun allerdings mit einer
Exception ab und wies mich in freundlichem Gelb darauf hin, dass mein Business Objekt
keinen parameterlosen Konstruktor hätte.
</p>
        <p>
In der Hoffnung, eine Factory für mein Business Objekt angeben zu können
durchsuchte ich also die Eigenschaften der ObjectDataSource. Leider wurde ich nicht
fündig, fluchte ein wenig darüber, dass meine Anforderung doch gar nicht
so ungewöhnlich wäre und beendete Visual Studio frustriert.
</p>
        <p>
Glücklicherweise guckte ich ein wenig später doch noch mal nach einer Lösung.
So kann zwar keine Eigenschaft für eine Factory angegeben werden, stattdessen
wird jedoch ein Ereignis zur Verfügung gestellt, in dem ich das entsprechende
Business Objekt erstellen und meiner ObjectDataSource zuweisen kann.
</p>
        <p>
Konkret sieht dies wie folgt aus:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1c69fcd1-c0d7-484d-8dca-7c1033101aac" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">protected void AufgabenDataSource_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
{
    AufgabenService service = ObjectFactory.GetInstance&lt;AufgabenService&gt;();
    e.ObjectInstance = service;
}</pre>
        </div>
        <p>
Nun habe ich über die ObjectFactory zwar einen direkten Verweis innerhalb meiner
CodeBehind Datei auf den genutzten DI Container (in meinem Fall StructureMap), dies
ist mir aber immer noch lieber, als die Abhängigkeit zur Persistenzschicht in
meinem Business Service hart zu verdrahten.
</p>
        <h4>Und die Moral von der Geschicht ...
</h4>
        <p>
... lautet: Erst ausprobieren und dann (gegebenenfalls) meckern ;-)
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=f7a1970e-6a58-4924-8f12-6a0a367694d9" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Die ASP.NET ObjectDataSource und abhängige Business Objekte</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,f7a1970e-6a58-4924-8f12-6a0a367694d9.aspx</guid>
      <link>http://blog.codemurai.de/2010/07/14/DieASPNETObjectDataSourceUndAbh%c3%a4ngigeBusinessObjekte.aspx</link>
      <pubDate>Wed, 14 Jul 2010 05:08:57 GMT</pubDate>
      <description>&lt;p&gt;
Ja, ich gebe es offen und ehrlich zu! Ich habe sie noch nie wirklich genutzt, die
ASP.NET WebForms ObjectDataSource. Irgendwie hatte ich ein Unbehagen bei der Vorstellung
mir das alles blo&amp;#223; zusammen zu klicken und habe daher bisher einen Bogen um die
ObjectDataSource gemacht. Au&amp;#223;erdem habe ich bisher auch noch niemanden getroffen,
der ernsthaft in Erw&amp;#228;gung gezogen h&amp;#228;tte die ObjectDataSource zu nutzen -
oder sich zumindest getraut h&amp;#228;tte, dies zuzugeben ;-)
&lt;/p&gt;
&lt;p&gt;
K&amp;#252;rzlich war es dann aber soweit. meine F&amp;#252;r eine kleine Demo startete ich
damit, die serverseitige ASP.NET MVC Implementierung meiner Beispielanwendung f&amp;#252;r
meinen jQuery Vortrag auf der dotnet Colgone nach Webforms zu konvertieren. Mein Ziel
war es dabei, wo immer es nur geht, den WebForms &amp;quot;Baukasten&amp;quot; zu nehmen.
Da ich bereits einen bestehenden Business Service hatte, der mir meine Objekte laden
und persistieren konnte, kreuzte sie nun also meinen Weg, die ObjectDataSource.
&lt;/p&gt;
&lt;p&gt;
Nach ein paar Klicks durch den Wizzard und einem beherztem F5 best&amp;#228;tigte sich
vorerst mein initiales Vorurteil: &amp;quot;Totaler Mist!&amp;quot;.
&lt;/p&gt;
&lt;p&gt;
Mein Business Service hatte n&amp;#228;mlich eine Abh&amp;#228;ngigkeit auf eine weitere Klasse,
die f&amp;#252;r die&amp;#160; Datenhaltung zust&amp;#228;ndig war. Diese Abh&amp;#228;ngigkeit fand
sich in meinem Quellcode in Form eines Konstruktor Parameters wieder. In meiner ASP.NET
MVC Implementierung war der DI Container StructureMap f&amp;#252;r das Aufl&amp;#246;sen dieser
Abh&amp;#228;ngigkeit zust&amp;#228;ndig.
&lt;/p&gt;
&lt;p&gt;
Die WebForms Variante brach die Ausf&amp;#252;hrung des Codes nun allerdings mit einer
Exception ab und wies mich in freundlichem Gelb darauf hin, dass mein Business Objekt
keinen parameterlosen Konstruktor h&amp;#228;tte.
&lt;/p&gt;
&lt;p&gt;
In der Hoffnung, eine Factory f&amp;#252;r mein Business Objekt angeben zu k&amp;#246;nnen
durchsuchte ich also die Eigenschaften der ObjectDataSource. Leider wurde ich nicht
f&amp;#252;ndig, fluchte ein wenig dar&amp;#252;ber, dass meine Anforderung doch gar nicht
so ungew&amp;#246;hnlich w&amp;#228;re und beendete Visual Studio frustriert.
&lt;/p&gt;
&lt;p&gt;
Gl&amp;#252;cklicherweise guckte ich ein wenig sp&amp;#228;ter doch noch mal nach einer L&amp;#246;sung.
So kann zwar keine Eigenschaft f&amp;#252;r eine Factory angegeben werden, stattdessen
wird jedoch ein Ereignis zur Verf&amp;#252;gung gestellt, in dem ich das entsprechende
Business Objekt erstellen und meiner ObjectDataSource zuweisen kann.
&lt;/p&gt;
&lt;p&gt;
Konkret sieht dies wie folgt aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1c69fcd1-c0d7-484d-8dca-7c1033101aac" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;protected void AufgabenDataSource_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
{
    AufgabenService service = ObjectFactory.GetInstance&amp;lt;AufgabenService&amp;gt;();
    e.ObjectInstance = service;
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Nun habe ich &amp;#252;ber die ObjectFactory zwar einen direkten Verweis innerhalb meiner
CodeBehind Datei auf den genutzten DI Container (in meinem Fall StructureMap), dies
ist mir aber immer noch lieber, als die Abh&amp;#228;ngigkeit zur Persistenzschicht in
meinem Business Service hart zu verdrahten.
&lt;/p&gt;
&lt;h4&gt;Und die Moral von der Geschicht ...
&lt;/h4&gt;
&lt;p&gt;
... lautet: Erst ausprobieren und dann (gegebenenfalls) meckern ;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=f7a1970e-6a58-4924-8f12-6a0a367694d9" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,f7a1970e-6a58-4924-8f12-6a0a367694d9.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=1da3030d-9b73-42f4-a3a5-57f5c35a424a</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,1da3030d-9b73-42f4-a3a5-57f5c35a424a.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,1da3030d-9b73-42f4-a3a5-57f5c35a424a.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=1da3030d-9b73-42f4-a3a5-57f5c35a424a</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Wie <a href="http://blogs.infragistics.com/blogs/craig_shoemaker/" target="_blank">Craig
Shoemaker</a> bereits in seinem <a href="http://blogs.infragistics.com/blogs/craig_shoemaker/archive/2010/06/23/german-localized-strings-now-available-in-netadvantage-10-2.aspx" target="_blank">Blog
geschrieben hat</a>, werden die Infragistics NetAdvantage Controls für Silverlight
und WPF ab der Version 10.2 auch mit Deutschen Oberflächentexten ausgeliefert.
In diesem Beitrag möchte ich die Notwendigen Schritte noch einmal im Schnelldurchlauf
in deutscher Sprache am Beispiel von Silverlight erläutern.
</p>
        <h3>Initiales Setup
</h3>
        <p>
Mein Silverlightprojekt besteht aus einer einzigen Seite, in der ein XamGrid definiert
wurde:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4a894a0f-129e-4bbd-aa45-4d28a2fd0e8e" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;UserControl x:Class="NAGermanLocalization1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" xmlns:ig="http://schemas.infragistics.com/xaml"&gt;

    &lt;Grid x:Name="LayoutRoot" Background="White"&gt;
        &lt;ig:XamGrid HorizontalAlignment="Left" Name="xamGrid1" VerticalAlignment="Top"  AutoGenerateColumns="false"  &gt;
            &lt;ig:XamGrid.FilteringSettings&gt;
                &lt;ig:FilteringSettings AllowFiltering="FilterMenu" /&gt;
            &lt;/ig:XamGrid.FilteringSettings&gt;
            &lt;ig:XamGrid.GroupBySettings&gt;
                &lt;ig:GroupBySettings AllowGroupByArea="Top" /&gt;
            &lt;/ig:XamGrid.GroupBySettings&gt;
            &lt;ig:XamGrid.Columns&gt;
                &lt;ig:TextColumn Key="Id" /&gt;
                &lt;ig:TextColumn Key="Name"/&gt;
                &lt;ig:TextColumn Key="Vorname"/&gt;
                &lt;ig:TextColumn Key="Land" /&gt;
            &lt;/ig:XamGrid.Columns&gt;
        &lt;/ig:XamGrid&gt;
    &lt;/Grid&gt;
&lt;/UserControl&gt;</pre>
        </div>
        <p>
Für das Grid habe ich wie der vorherige Codeausschnitt zeigt Filtern und Gruppieren
aktiviert.
</p>
        <p>
Meine Codebehind Datei sieht ähnlich schmal aus:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:d688f5a1-80e2-4489-b77b-0d4b5c5bb51c" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">using System.Collections.Generic;
using System.Windows.Controls;

namespace NAGermanLocalization1
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            InitGrid();
        }

        private void InitGrid()
        {
 	        List&lt;Kunde&gt; kunden = new List&lt;Kunde&gt;();
            for (int i = 0; i&lt;10; i++)
            {
                Kunde kunde = new Kunde{Id = i, Name = string.Format("Name {0}", i), Vorname = string.Format("Vorname {0}", i), Land = "DE"};
                kunden.Add(kunde);
            }
            xamGrid1.ItemsSource = kunden;
        }
    }

    public class Kunde
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Vorname { get; set; }
        public string Land { get; set; }
    }
}</pre>
        </div>
        <p>
An der Oberfläche schaut das ganze nun wie folgt aus:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/GridVorher.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="149" alt="GridVorher" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/GridVorher_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
          <a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/DialogVorher.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="110" alt="DialogVorher" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/DialogVorher_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h4>Und einmal auf Deutsch bitte ...
</h4>
        <p>
Um das ganze nun zu lokalisieren, sind lediglich zwei Schritte erforderlich.
</p>
        <p>
Zunächst muss das Silverlight Projekt entladen und anschließend im Textmodus
editiert werden:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/unloadproject.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="244" alt="unloadproject" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/unloadproject_thumb.png" width="207" border="0" />
          </a>
          <a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/editproject.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="97" alt="editproject" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/editproject_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Der vorhandene leere Tag <em>SupportedCultures</em> muss mit dem Wert <em>de</em> versehen
werden.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/supportedcultures.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="140" alt="supportedcultures" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/supportedcultures_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Anschließend muss die Projektdatei gespeichert und erneut geladen werden. Als
letzter Schritt muss dann innerhalb der Webseite, die das Silverlight Control hostet
noch die Zeile <em>&lt;param name="uiculture" value="de" /&gt;</em> innerhalb
des Object Tags eingefügt werden:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/uiculture.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="90" alt="uiculture" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/uiculture_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Wenn nun nichts schief gegangen ist, sollten die Oberflächentexte nun auf Deutsch
erscheinen:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/GridNachher.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="142" alt="GridNachher" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/GridNachher_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
          <a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/DialogNachher.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="122" alt="DialogNachher" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/DialogNachher_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h3>
        </h3>
        <h3>Fazit
</h3>
        <p>
Lokalisierte Oberflächen werden mit Infragistics NetAdvantage 10.2 zum Kinderspiel,
da das umständliche Setzen der Oberflächentexte über die <a href="http://help.infragistics.com/NetAdvantage/WPF/2010.2/CLR4.0/?page=WPF_Customize_Assembly_Resource_Strings.html" target="_blank">runtime
resource-string customization</a> in Zukunft entfällt.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=1da3030d-9b73-42f4-a3a5-57f5c35a424a" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Deutsche Texte in Infragistics NetAdvantage 10.2</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,1da3030d-9b73-42f4-a3a5-57f5c35a424a.aspx</guid>
      <link>http://blog.codemurai.de/2010/06/30/DeutscheTexteInInfragisticsNetAdvantage102.aspx</link>
      <pubDate>Wed, 30 Jun 2010 21:53:59 GMT</pubDate>
      <description>&lt;p&gt;
Wie &lt;a href="http://blogs.infragistics.com/blogs/craig_shoemaker/" target="_blank"&gt;Craig
Shoemaker&lt;/a&gt; bereits in seinem &lt;a href="http://blogs.infragistics.com/blogs/craig_shoemaker/archive/2010/06/23/german-localized-strings-now-available-in-netadvantage-10-2.aspx" target="_blank"&gt;Blog
geschrieben hat&lt;/a&gt;, werden die Infragistics NetAdvantage Controls f&amp;#252;r Silverlight
und WPF ab der Version 10.2 auch mit Deutschen Oberfl&amp;#228;chentexten ausgeliefert.
In diesem Beitrag m&amp;#246;chte ich die Notwendigen Schritte noch einmal im Schnelldurchlauf
in deutscher Sprache am Beispiel von Silverlight erl&amp;#228;utern.
&lt;/p&gt;
&lt;h3&gt;Initiales Setup
&lt;/h3&gt;
&lt;p&gt;
Mein Silverlightprojekt besteht aus einer einzigen Seite, in der ein XamGrid definiert
wurde:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4a894a0f-129e-4bbd-aa45-4d28a2fd0e8e" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;UserControl x:Class="NAGermanLocalization1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" xmlns:ig="http://schemas.infragistics.com/xaml"&amp;gt;

    &amp;lt;Grid x:Name="LayoutRoot" Background="White"&amp;gt;
        &amp;lt;ig:XamGrid HorizontalAlignment="Left" Name="xamGrid1" VerticalAlignment="Top"  AutoGenerateColumns="false"  &amp;gt;
            &amp;lt;ig:XamGrid.FilteringSettings&amp;gt;
                &amp;lt;ig:FilteringSettings AllowFiltering="FilterMenu" /&amp;gt;
            &amp;lt;/ig:XamGrid.FilteringSettings&amp;gt;
            &amp;lt;ig:XamGrid.GroupBySettings&amp;gt;
                &amp;lt;ig:GroupBySettings AllowGroupByArea="Top" /&amp;gt;
            &amp;lt;/ig:XamGrid.GroupBySettings&amp;gt;
            &amp;lt;ig:XamGrid.Columns&amp;gt;
                &amp;lt;ig:TextColumn Key="Id" /&amp;gt;
                &amp;lt;ig:TextColumn Key="Name"/&amp;gt;
                &amp;lt;ig:TextColumn Key="Vorname"/&amp;gt;
                &amp;lt;ig:TextColumn Key="Land" /&amp;gt;
            &amp;lt;/ig:XamGrid.Columns&amp;gt;
        &amp;lt;/ig:XamGrid&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
F&amp;#252;r das Grid habe ich wie der vorherige Codeausschnitt zeigt Filtern und Gruppieren
aktiviert.
&lt;/p&gt;
&lt;p&gt;
Meine Codebehind Datei sieht &amp;#228;hnlich schmal aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:d688f5a1-80e2-4489-b77b-0d4b5c5bb51c" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;using System.Collections.Generic;
using System.Windows.Controls;

namespace NAGermanLocalization1
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            InitGrid();
        }

        private void InitGrid()
        {
 	        List&amp;lt;Kunde&amp;gt; kunden = new List&amp;lt;Kunde&amp;gt;();
            for (int i = 0; i&amp;lt;10; i++)
            {
                Kunde kunde = new Kunde{Id = i, Name = string.Format("Name {0}", i), Vorname = string.Format("Vorname {0}", i), Land = "DE"};
                kunden.Add(kunde);
            }
            xamGrid1.ItemsSource = kunden;
        }
    }

    public class Kunde
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Vorname { get; set; }
        public string Land { get; set; }
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
An der Oberfl&amp;#228;che schaut das ganze nun wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/GridVorher.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="149" alt="GridVorher" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/GridVorher_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/DialogVorher.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="110" alt="DialogVorher" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/DialogVorher_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;Und einmal auf Deutsch bitte ...
&lt;/h4&gt;
&lt;p&gt;
Um das ganze nun zu lokalisieren, sind lediglich zwei Schritte erforderlich.
&lt;/p&gt;
&lt;p&gt;
Zun&amp;#228;chst muss das Silverlight Projekt entladen und anschlie&amp;#223;end im Textmodus
editiert werden:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/unloadproject.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="244" alt="unloadproject" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/unloadproject_thumb.png" width="207" border="0" /&gt;&lt;/a&gt; &lt;a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/editproject.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="97" alt="editproject" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/editproject_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Der vorhandene leere Tag &lt;em&gt;SupportedCultures&lt;/em&gt; muss mit dem Wert &lt;em&gt;de&lt;/em&gt; versehen
werden.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/supportedcultures.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="140" alt="supportedcultures" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/supportedcultures_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Anschlie&amp;#223;end muss die Projektdatei gespeichert und erneut geladen werden. Als
letzter Schritt muss dann innerhalb der Webseite, die das Silverlight Control hostet
noch die Zeile &lt;em&gt;&amp;lt;param name=&amp;quot;uiculture&amp;quot; value=&amp;quot;de&amp;quot; /&amp;gt;&lt;/em&gt; innerhalb
des Object Tags eingef&amp;#252;gt werden:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/uiculture.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="90" alt="uiculture" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/uiculture_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Wenn nun nichts schief gegangen ist, sollten die Oberfl&amp;#228;chentexte nun auf Deutsch
erscheinen:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/GridNachher.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="142" alt="GridNachher" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/GridNachher_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/DialogNachher.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="122" alt="DialogNachher" src="http://blog.codemurai.de/images/DeutscheTexteinInfragisticsNetAdvantag.2_14FDF/DialogNachher_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;Fazit
&lt;/h3&gt;
&lt;p&gt;
Lokalisierte Oberfl&amp;#228;chen werden mit Infragistics NetAdvantage 10.2 zum Kinderspiel,
da das umst&amp;#228;ndliche Setzen der Oberfl&amp;#228;chentexte &amp;#252;ber die &lt;a href="http://help.infragistics.com/NetAdvantage/WPF/2010.2/CLR4.0/?page=WPF_Customize_Assembly_Resource_Strings.html" target="_blank"&gt;runtime
resource-string customization&lt;/a&gt; in Zukunft entf&amp;#228;llt.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=1da3030d-9b73-42f4-a3a5-57f5c35a424a" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,1da3030d-9b73-42f4-a3a5-57f5c35a424a.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>Silverlight</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=1275dc76-8b0d-41e8-978f-d9cc1e874b21</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,1275dc76-8b0d-41e8-978f-d9cc1e874b21.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,1275dc76-8b0d-41e8-978f-d9cc1e874b21.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=1275dc76-8b0d-41e8-978f-d9cc1e874b21</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Passend zur Fußball WM konnte ich einen virtuellen Hattrick landen. Kürzlich
ist nämlich mein dritter Artikel in Folge auf der deutschen ASP.NET Site <a href="http://www.asp.net/de">http://www.asp.net/de</a> veröffentlicht
worden. Cool :-)
</p>
        <p>
          <a href="http://blog.codemurai.de/images/Hattrick_94BF/aspnet_de.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="175" alt="aspnet_de" src="http://blog.codemurai.de/images/Hattrick_94BF/aspnet_de_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Nachdem ich die Artikel des Tages nun also "gestürmt" habe, frage ich
mich nur noch, wie ich mein Blog in den Feed links bekomme ...
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=1275dc76-8b0d-41e8-978f-d9cc1e874b21" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Hattrick!</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,1275dc76-8b0d-41e8-978f-d9cc1e874b21.aspx</guid>
      <link>http://blog.codemurai.de/2010/06/14/Hattrick.aspx</link>
      <pubDate>Mon, 14 Jun 2010 21:32:46 GMT</pubDate>
      <description>&lt;p&gt;
Passend zur Fu&amp;#223;ball WM konnte ich einen virtuellen Hattrick landen. K&amp;#252;rzlich
ist n&amp;#228;mlich mein dritter Artikel in Folge auf der deutschen ASP.NET Site &lt;a href="http://www.asp.net/de"&gt;http://www.asp.net/de&lt;/a&gt; ver&amp;#246;ffentlicht
worden. Cool :-)
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/Hattrick_94BF/aspnet_de.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="175" alt="aspnet_de" src="http://blog.codemurai.de/images/Hattrick_94BF/aspnet_de_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Nachdem ich die Artikel des Tages nun also &amp;quot;gest&amp;#252;rmt&amp;quot; habe, frage ich
mich nur noch, wie ich mein Blog in den Feed links bekomme ...
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=1275dc76-8b0d-41e8-978f-d9cc1e874b21" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,1275dc76-8b0d-41e8-978f-d9cc1e874b21.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>Community</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=751e9d96-b300-42a6-a20e-5ef07ab90418</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,751e9d96-b300-42a6-a20e-5ef07ab90418.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,751e9d96-b300-42a6-a20e-5ef07ab90418.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=751e9d96-b300-42a6-a20e-5ef07ab90418</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Das Beispielprojekt meines jQuery Vortrags während der dotnet Cologne kann ab
sofort <a title="André Krämers jQuery und ASP.NET MVC Beispielprojekt der dotnet Cologne" href="http://www.codemurai.de/downloads/akraemer_jquery.zip" target="_blank">hier</a> herunter
geladen werden.
</p>
        <p>
Es handelt sich dabei um ein kleines ASP.NET MVC 2 Projekt, in dem folgendes genutzt
wurde:
</p>
        <ul>
          <li>
ASP.NET MVC 2 ;-) 
</li>
          <li>
StructureMap als IOC Container 
</li>
          <li>
SQLite als leichtgewichtige In-Memory-DB 
</li>
          <li>
NHibernate für den Datenbankzugriff 
</li>
          <li>
jQuery für den Wow-Faktor ;-) 
</li>
        </ul>
        <p>
Die Solution liegt passend zur Veranstaltung im VS 2010 Format vor. Bei Bedarf kann
ich aber auch eine VS 2008 Solution bereit stellen.
</p>
        <p>
Hauptaugenmerk solltet ihr auf die Datei aufgabenlist.js setzen. Hier befindet sich
der relevante jQuery / JavaScript Code. Der ganze Rest ist nur "Infrastruktur",
damit ich jQuery an einem halbwegs realistischen Beispiel zeigen kann ;-)
</p>
        <p>
An Feedback zu den Quellcodes bin ich immer interessiert. Am besten über das
Kontaktformular, oder die während des Vortrags mitgeteilte E-Mail Adresse.
</p>
        <p>
Ich weiß übrigens, dass das ASP.NET MVC Projekt keine Unit Tests beinhaltet.
Angesichts der Projektgröße und der verfügbaren Zeit habe ich hier
ein wenig geschludert. <a href="http://blog.thomasbandt.de/39/de/blog.html" target="_blank">Thomas
Bandt</a> hat mich während des Vortrags übrigens auch darauf aufmerksam
gemacht, dass mein JavaScript Code nicht via Unit Tests geprüft wurde. Auch hier
gelobe ich Besserung :-)
</p>
        <h4>Literaturempfehlungen
</h4>
        <p>
Im Anschluss an den Vortrag wurde ich außerdem gefragt, welche Literatur ich
zu dem Thema empfehlen könnte.
</p>
        <p>
Nun, da sich jQuery hauptsächlich mit der Modifikation des DOMs, insbesondere
dem Ein- / Ausblenden sowie dynamischem CSS befasst, sollte man meiner Meinung nach
zunächst über solide (X)HTML und CSS Kenntnisse verfügen (kein Witz).
</p>
        <p>
Zu diesem Thema kann ich das Buch Head First HTML with CSS &amp; XHTML empfehlen:
</p>
        <iframe style="width: 120px; height: 240px" marginwidth="0" marginheight="0" src="http://rcm-de.amazon.de/e/cm?t=codemurai-21&amp;o=3&amp;p=8&amp;l=as1&amp;asins=059610197X&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" frameborder="0" scrolling="no">
        </iframe>
        <p>
Außerdem können generelle JavaScript Kenntnisse auch nicht schaden ;-) Hier
habe ich persönlich sehr gute Erfahrung mit dem Buch Professional JavaScript
for Web Developers gemacht.
</p>
        <iframe style="width: 120px; height: 240px" marginwidth="0" marginheight="0" src="http://rcm-de.amazon.de/e/cm?t=codemurai-21&amp;o=3&amp;p=8&amp;l=as1&amp;asins=047022780X&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" frameborder="0" scrolling="no">
        </iframe>
        <p>
Speziell zum Thema jQuery hat mir das Buch <em><a href="http://www.manning.com/bibeault2/" target="_blank">jQuery
in Action, Second Edition</a></em> sehr gut gefallen. Ich habe es mir im Rahmen des
Manning Early Access Program als E-Book bestellt. Wer lieber ein gedrucktes Exemplar
haben möchte, muss sich noch ein wenig gedulden, kann es aber dann auch z. B.
bei Amazon bestellen.
</p>
        <iframe style="width: 120px; height: 240px" marginwidth="0" marginheight="0" src="http://rcm-de.amazon.de/e/cm?t=codemurai-21&amp;o=3&amp;p=8&amp;l=as1&amp;asins=1935182323&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" frameborder="0" scrolling="no">
        </iframe>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=751e9d96-b300-42a6-a20e-5ef07ab90418" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Mein jQuery Vortrag auf der dotnet Cologne</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,751e9d96-b300-42a6-a20e-5ef07ab90418.aspx</guid>
      <link>http://blog.codemurai.de/2010/05/31/MeinJQueryVortragAufDerDotnetCologne.aspx</link>
      <pubDate>Mon, 31 May 2010 21:24:51 GMT</pubDate>
      <description>&lt;p&gt;
Das Beispielprojekt meines jQuery Vortrags w&amp;#228;hrend der dotnet Cologne kann ab
sofort &lt;a title="Andr&amp;#233; Kr&amp;#228;mers jQuery und ASP.NET MVC Beispielprojekt der dotnet Cologne" href="http://www.codemurai.de/downloads/akraemer_jquery.zip" target="_blank"&gt;hier&lt;/a&gt; herunter
geladen werden.
&lt;/p&gt;
&lt;p&gt;
Es handelt sich dabei um ein kleines ASP.NET MVC 2 Projekt, in dem folgendes genutzt
wurde:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
ASP.NET MVC 2 ;-) 
&lt;/li&gt;
&lt;li&gt;
StructureMap als IOC Container 
&lt;/li&gt;
&lt;li&gt;
SQLite als leichtgewichtige In-Memory-DB 
&lt;/li&gt;
&lt;li&gt;
NHibernate f&amp;#252;r den Datenbankzugriff 
&lt;/li&gt;
&lt;li&gt;
jQuery f&amp;#252;r den Wow-Faktor ;-) 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Die Solution liegt passend zur Veranstaltung im VS 2010 Format vor. Bei Bedarf kann
ich aber auch eine VS 2008 Solution bereit stellen.
&lt;/p&gt;
&lt;p&gt;
Hauptaugenmerk solltet ihr auf die Datei aufgabenlist.js setzen. Hier befindet sich
der relevante jQuery / JavaScript Code. Der ganze Rest ist nur &amp;quot;Infrastruktur&amp;quot;,
damit ich jQuery an einem halbwegs realistischen Beispiel zeigen kann ;-)
&lt;/p&gt;
&lt;p&gt;
An Feedback zu den Quellcodes bin ich immer interessiert. Am besten &amp;#252;ber das
Kontaktformular, oder die w&amp;#228;hrend des Vortrags mitgeteilte E-Mail Adresse.
&lt;/p&gt;
&lt;p&gt;
Ich wei&amp;#223; &amp;#252;brigens, dass das ASP.NET MVC Projekt keine Unit Tests beinhaltet.
Angesichts der Projektgr&amp;#246;&amp;#223;e und der verf&amp;#252;gbaren Zeit habe ich hier
ein wenig geschludert. &lt;a href="http://blog.thomasbandt.de/39/de/blog.html" target="_blank"&gt;Thomas
Bandt&lt;/a&gt; hat mich w&amp;#228;hrend des Vortrags &amp;#252;brigens auch darauf aufmerksam
gemacht, dass mein JavaScript Code nicht via Unit Tests gepr&amp;#252;ft wurde. Auch hier
gelobe ich Besserung :-)
&lt;/p&gt;
&lt;h4&gt;Literaturempfehlungen
&lt;/h4&gt;
&lt;p&gt;
Im Anschluss an den Vortrag wurde ich au&amp;#223;erdem gefragt, welche Literatur ich
zu dem Thema empfehlen k&amp;#246;nnte.
&lt;/p&gt;
&lt;p&gt;
Nun, da sich jQuery haupts&amp;#228;chlich mit der Modifikation des DOMs, insbesondere
dem Ein- / Ausblenden sowie dynamischem CSS befasst, sollte man meiner Meinung nach
zun&amp;#228;chst &amp;#252;ber solide (X)HTML und CSS Kenntnisse verf&amp;#252;gen (kein Witz).
&lt;/p&gt;
&lt;p&gt;
Zu diesem Thema kann ich das Buch Head First HTML with CSS &amp;amp; XHTML empfehlen:
&lt;/p&gt;
&lt;iframe style="width: 120px; height: 240px" marginwidth="0" marginheight="0" src="http://rcm-de.amazon.de/e/cm?t=codemurai-21&amp;amp;o=3&amp;amp;p=8&amp;amp;l=as1&amp;amp;asins=059610197X&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" frameborder="0" scrolling="no"&gt;
&lt;/iframe&gt;
&lt;p&gt;
Au&amp;#223;erdem k&amp;#246;nnen generelle JavaScript Kenntnisse auch nicht schaden ;-) Hier
habe ich pers&amp;#246;nlich sehr gute Erfahrung mit dem Buch Professional JavaScript
for Web Developers gemacht.
&lt;/p&gt;
&lt;iframe style="width: 120px; height: 240px" marginwidth="0" marginheight="0" src="http://rcm-de.amazon.de/e/cm?t=codemurai-21&amp;amp;o=3&amp;amp;p=8&amp;amp;l=as1&amp;amp;asins=047022780X&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" frameborder="0" scrolling="no"&gt;
&lt;/iframe&gt;
&lt;p&gt;
Speziell zum Thema jQuery hat mir das Buch &lt;em&gt;&lt;a href="http://www.manning.com/bibeault2/" target="_blank"&gt;jQuery
in Action, Second Edition&lt;/a&gt;&lt;/em&gt; sehr gut gefallen. Ich habe es mir im Rahmen des
Manning Early Access Program als E-Book bestellt. Wer lieber ein gedrucktes Exemplar
haben m&amp;#246;chte, muss sich noch ein wenig gedulden, kann es aber dann auch z. B.
bei Amazon bestellen.
&lt;/p&gt;
&lt;iframe style="width: 120px; height: 240px" marginwidth="0" marginheight="0" src="http://rcm-de.amazon.de/e/cm?t=codemurai-21&amp;amp;o=3&amp;amp;p=8&amp;amp;l=as1&amp;amp;asins=1935182323&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" frameborder="0" scrolling="no"&gt;
&lt;/iframe&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=751e9d96-b300-42a6-a20e-5ef07ab90418" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,751e9d96-b300-42a6-a20e-5ef07ab90418.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>Community</category>
      <category>DotNetGerman Bloggers</category>
      <category>jQuery</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=bbf8f523-d565-4c02-a329-87a515fc415f</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,bbf8f523-d565-4c02-a329-87a515fc415f.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,bbf8f523-d565-4c02-a329-87a515fc415f.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=bbf8f523-d565-4c02-a329-87a515fc415f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Letzten Freitag hatte ich die Freude, an der <a href="http://dotnet-cologne.de" target="_blank">dotnet
Cologne</a> teilzunehmen. Mit über 300 Teilnehmern war es ein wirklich riesiges
Event, dass sich vor "professionellen", oder besser gesagt kommerziellen
Konferenzen nicht verstecken muss.
</p>
        <h4>Der Teilnehmer
</h4>
        <p>
Vor Ort war ich in mehreren Rollen. Zum einen natürlich als Teilnehmer. In dieser
Rolle nutzte ich die Möglichkeit, endlich mal die Gesichter zu einigen Bekannten
aus der Community zu sehen und auch mal persönlich das ein oder andere Wort zu
wechseln. Außerdem hörte ich mir auch spannende Vorträge, unter anderem
von <a href="http://dotnet-cologne.de/Sprecher.ashx#J%C3%B6rg.Krause" target="_blank">Jörg
Krause</a> zu <a href="http://dotnet-cologne.de/Vortraege.ashx#SP-Dev" target="_blank">Sharepoint
als Entwicklungsplattform</a>, <a href="http://dotnet-cologne.de/Vortraege.ashx#SL4" target="_blank">Neues
in Silverlight 4</a> von <a href="http://dotnet-cologne.de/Sprecher.ashx#Stefan.Lange" target="_blank">Stefan
Lange</a> sowie <a href="http://dotnet-cologne.de/Vortraege.ashx#WebForms4" target="_blank">Neues
in ASP.NET 4.0</a> von <a href="http://dotnet-cologne.de/Sprecher.ashx#Jan.Welker" target="_blank">Jan
Welker</a>.
</p>
        <p>
Irritierend fand ich, dass gefühlte 90 % der Besucher von Jörg Krauses Sharepoint
Vortrag keinerlei Sharepoint Vorkenntnisse hatten und somit wohl nicht im geringsten
wussten, wie so eine Site, eine Sitecollection, ein Web, eine Liste, ein Webpart ...
an der Oberfläche wohl aussehen. Die gleiche Situation habe ich übrigens
auch mehrfach schon auf der Shareconnect (Basta Sharepoint Days) beobachtet. Vielleicht
wäre hier einfach mal ein "Was ich über Sharepoint wissen sollte, bevor
ich Visual Studio aufmache" Vortrag angebracht. Leider habe ich einen solchen
Vortrag bisher noch auf keiner (Entwickler-)Konferenz im Angebot gesehen. Nichts desto
trotz fand ich Jörgs Vortrag prima! Auch die anderen besuchten Vorträge
haben mir gut gefallen, daher mein Fazit als Teilnehmer:
</p>
        <p>
Voller Erfolg! Gute Vorträge, gute Kontaktmöglichkeiten zur Community, was
will man mehr.
</p>
        <h4>Der Aussteller
</h4>
        <p>
Unter den Sponsoren des Events war unter anderem auch die Firma <a href="http://www.infragistics.com" target="_blank">Infragistics</a>.
Wie auch auf anderen Konferenzen lies ich es mir als fleißiger <a href="http://blogs.infragistics.com/blogs/mvps/archive/2010/05/17/introducing-infragistics-mvp-andr-233-kr-228-mer.aspx" target="_blank">Infragistics
MVP</a>  in den Pausen natürlich nicht nehmen, <a href="http://blogs.infragistics.com/blogs/kiril_matev/default.aspx" target="_blank">Kiril</a> und
Nils tatkräftig zu unterstützen. Dies war auch bitter nötig, da der
Andrang am Stand weit höher war, als ich es von anderen Konferenzen gewohnt war.
Kamen wir normalerweise zu zweit immer ganz gut zurecht, waren dieses Mal sogar drei
Personen eigentlich schon fast zu wenig.
</p>
        <p>
Fazit als Aussteller: Tolle Veranstaltung! Viele Kontakte, interessante und zum Teil
sogar sehr trickreiche Fragen, genauso muss es sein!
</p>
        <h4>Der User Group Leader
</h4>
        <p>
Jeder der schon mal ein User Group Treffen besucht hat wird sich sicherlich fragen:
</p>
        <blockquote>
          <p>
Wo kommen eigentlich die Sprecher her?
</p>
        </blockquote>
        <p>
Nun ja, als sie ganz klein waren, wird sie voraussichtlich einer der beiden hier unten
gebracht haben.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/dotnetCologne2010waseinriesenSpa_14431/image.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="image" src="http://blog.codemurai.de/images/dotnetCologne2010waseinriesenSpa_14431/image_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
          <em>Foto: <a href="http://www.flickr.com/photos/valter/"><b>Valter Jacinto | Portugal</b></a>   <a title="http://www.flickr.com/photos/valter/87429062/sizes/m/" href="http://www.flickr.com/photos/valter/87429062/sizes/m/">http://www.flickr.com/photos/valter/87429062/sizes/m/</a><br />
Creative Commons License</em>
        </p>
        <p>
Irgendwann werden die Jungs und Mädels dann aber groß und spätestens
dann stellt sich für einen User Group Leiter die Frage: 
</p>
        <blockquote>
          <p>
Wo bekomme ich eigentlich Sprecher her?
</p>
        </blockquote>
        <p>
Ein besonders guter Ort, Sprecher für die eigene User Group zu finden ist selbstverständlich
eine Konferenz, denn dort treten Speaker häufig in Rudeln auf ;-)
</p>
        <p>
Also machte ich mich während der dotnet Cologne auf den Weg und zog Sprecher
für die nächsten Treffen der .<a href="http://www.dnug-koblenz.de" target="_blank">NET
User Group Koblenz</a> an Land.
</p>
        <p>
Die Ausbeute war übrigens mit zwei definitiven, einer relativ verbindlichen und
einer losen Zusage recht gut. Daher auch hier: dotnet Cologne, 12 Points ;-)
</p>
        <h4>Der Sprecher
</h4>
        <p>
Zu guter letzt (und angesichts der Agenda ist dies wörtlich gemeint), war ich
auch als Sprecher unterwegs. <a href="http://dotnet-cologne.de/Sprecher.ashx#Andre.Kraemer" target="_blank">Mein</a> Thema
war die <a href="http://dotnet-cologne.de/Vortraege.ashx#jQuery" target="_blank">Einführung
in jQuery</a> unter dem spontan geänderten Titel:
</p>
        <blockquote>
          <p>
jQuery - oder warum Sie JavaScript in Zukunft nicht mehr hassen werden.
</p>
        </blockquote>
        <p>
Den Verlauf des Vortrags würde ich wie folgt beschreiben
</p>
        <ul>
          <li>
Der Saal füllt sich, die Menge wird still. Ich will loslegen, aber mein Mikro
überlegt sich, dass es sich lieber in meinem T-Shirt verdreht. Kein Mensch hört
mich ... so ein Mist</li>
          <li>
Mikro Problem gelöst, schnell durch die Folien gejagt. Auf gehts zur Demo!</li>
          <li>
Meine ASP.NET MVC Anwendung reißt niemand vom Hocker und stößt kaum
auf Interesse</li>
          <li>
Ist zum Glück nicht schlimm, schließlich ist mein Thema ja auch jQuery und
nicht ASP.NET MVC ;-)</li>
          <li>
Die ersten UI Gimmicks (alternierende Tabellenzeilen, Hover Effekte) zaubern ein müdes
Lächeln auf die Gesichter der Menge - da muss wohl noch mehr her</li>
          <li>
Ich erstelle mit einer Zeile jQuery Code auf- und zuklappbare Bereiche in der Sidebar
der Anwendung. Im Publikum sehe ich die ersten funkelnden Augen</li>
          <li>
Auf der Welle muss ich weiter reiten, also jetzt schnell ein wenig Ajax;-)</li>
          <li>
In der Einleitung habe ich etwas vom Update Panel erzählt. Heißt dann wohl
ich sollte auch ein wenig WebForms zeigen. Ich entschließe mich also, im Firebug
mal zu zeigen, was über die Leitung geht wenn man Ajax mit dem Update Panel <strike>erlegt</strike> erledigt.
Als ich zum ViewState scrolle scheinen einige Teilnehmer zu glauben ich hätte
gerade die Matrix gehacked oder zumindest gedebugged.</li>
          <li>
Oh je, nur noch 3 Minuten Zeit und ich habe doch versprochen früher Schluss zu
machen - jetzt muss schnell etwas großartiges her. Ich greife also noch mal in
die Trickkiste und greife zu meinem größten Trumpf: 
<br /><strong>runde Ecken;-) 
<br /></strong>Puh, geschafft, die Zuschauer jubeln. Ein Glück, dass es runde Ecken
gibt ;-)</li>
        </ul>
        <p>
Mein Fazit als Sprecher lautet also:
</p>
        <p>
Wahnsinn! Auch wenn es nur ein Einsteiger Vortrag war und laut Handzeichen mindestens
die Hälfte der Anwesenden jQuery bereits kannte und nutzte war das Publikum allem
Anschein nach während des Vortrags voll dabei. So macht vortragen Spaß!
</p>
        <h4>Der Grillfreund
</h4>
        <p>
Zum Abschluss fand für einige Teilnehmer, Sprecher und Sponsoren dann noch die
durch Microsoft gesponsorte und durch Jan Welker gestifftete Grill-Party des dotnet
Forums statt. Essen und Getränke waren sehr lecker, die Gespräche spannend,
von daher auch hier mein Kompliment.
</p>
        <h4>Fazit
</h4>
        <p>
Der Besuch der dotnet Cologne hätte in keinster Weise besser laufen können.
Großes Lob und alle Achtung an die Organisatoren! Nächstes Jahr bin ich
- in welcher Form auch immer - sicherlich auch wieder mit dabei!
</p>
        <p>
 
</p>
        <p>
          <em>Hey, du hast dir die Zeit genommen, den ganzen Beitrag zu lesen, oder zumindest
bis hier hin zu scrollen. Nimm dir doch bitte auch noch die Zeit, ihn über den
unten stehenden Button bei dotnet-kicks.de zu kicken!</em>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=bbf8f523-d565-4c02-a329-87a515fc415f" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>dotnet Cologne 2010 - was ein riesen Spaß</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,bbf8f523-d565-4c02-a329-87a515fc415f.aspx</guid>
      <link>http://blog.codemurai.de/2010/05/31/dotnetCologne2010WasEinRiesenSpa%c3%9f.aspx</link>
      <pubDate>Mon, 31 May 2010 21:03:46 GMT</pubDate>
      <description>&lt;p&gt;
Letzten Freitag hatte ich die Freude, an der &lt;a href="http://dotnet-cologne.de" target="_blank"&gt;dotnet
Cologne&lt;/a&gt; teilzunehmen. Mit &amp;#252;ber 300 Teilnehmern war es ein wirklich riesiges
Event, dass sich vor &amp;quot;professionellen&amp;quot;, oder besser gesagt kommerziellen
Konferenzen nicht verstecken muss.
&lt;/p&gt;
&lt;h4&gt;Der Teilnehmer
&lt;/h4&gt;
&lt;p&gt;
Vor Ort war ich in mehreren Rollen. Zum einen nat&amp;#252;rlich als Teilnehmer. In dieser
Rolle nutzte ich die M&amp;#246;glichkeit, endlich mal die Gesichter zu einigen Bekannten
aus der Community zu sehen und auch mal pers&amp;#246;nlich das ein oder andere Wort zu
wechseln. Au&amp;#223;erdem h&amp;#246;rte ich mir auch spannende Vortr&amp;#228;ge, unter anderem
von &lt;a href="http://dotnet-cologne.de/Sprecher.ashx#J%C3%B6rg.Krause" target="_blank"&gt;J&amp;#246;rg
Krause&lt;/a&gt; zu &lt;a href="http://dotnet-cologne.de/Vortraege.ashx#SP-Dev" target="_blank"&gt;Sharepoint
als Entwicklungsplattform&lt;/a&gt;, &lt;a href="http://dotnet-cologne.de/Vortraege.ashx#SL4" target="_blank"&gt;Neues
in Silverlight 4&lt;/a&gt; von &lt;a href="http://dotnet-cologne.de/Sprecher.ashx#Stefan.Lange" target="_blank"&gt;Stefan
Lange&lt;/a&gt; sowie &lt;a href="http://dotnet-cologne.de/Vortraege.ashx#WebForms4" target="_blank"&gt;Neues
in ASP.NET 4.0&lt;/a&gt; von &lt;a href="http://dotnet-cologne.de/Sprecher.ashx#Jan.Welker" target="_blank"&gt;Jan
Welker&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Irritierend fand ich, dass gef&amp;#252;hlte 90 % der Besucher von J&amp;#246;rg Krauses Sharepoint
Vortrag keinerlei Sharepoint Vorkenntnisse hatten und somit wohl nicht im geringsten
wussten, wie so eine Site, eine Sitecollection, ein Web, eine Liste, ein Webpart ...
an der Oberfl&amp;#228;che wohl aussehen. Die gleiche Situation habe ich &amp;#252;brigens
auch mehrfach schon auf der Shareconnect (Basta Sharepoint Days) beobachtet. Vielleicht
w&amp;#228;re hier einfach mal ein &amp;quot;Was ich &amp;#252;ber Sharepoint wissen sollte, bevor
ich Visual Studio aufmache&amp;quot; Vortrag angebracht. Leider habe ich einen solchen
Vortrag bisher noch auf keiner (Entwickler-)Konferenz im Angebot gesehen. Nichts desto
trotz fand ich J&amp;#246;rgs Vortrag prima! Auch die anderen besuchten Vortr&amp;#228;ge
haben mir gut gefallen, daher mein Fazit als Teilnehmer:
&lt;/p&gt;
&lt;p&gt;
Voller Erfolg! Gute Vortr&amp;#228;ge, gute Kontaktm&amp;#246;glichkeiten zur Community, was
will man mehr.
&lt;/p&gt;
&lt;h4&gt;Der Aussteller
&lt;/h4&gt;
&lt;p&gt;
Unter den Sponsoren des Events war unter anderem auch die Firma &lt;a href="http://www.infragistics.com" target="_blank"&gt;Infragistics&lt;/a&gt;.
Wie auch auf anderen Konferenzen lies ich es mir als flei&amp;#223;iger &lt;a href="http://blogs.infragistics.com/blogs/mvps/archive/2010/05/17/introducing-infragistics-mvp-andr-233-kr-228-mer.aspx" target="_blank"&gt;Infragistics
MVP&lt;/a&gt;&amp;#160; in den Pausen nat&amp;#252;rlich nicht nehmen, &lt;a href="http://blogs.infragistics.com/blogs/kiril_matev/default.aspx" target="_blank"&gt;Kiril&lt;/a&gt; und
Nils tatkr&amp;#228;ftig zu unterst&amp;#252;tzen. Dies war auch bitter n&amp;#246;tig, da der
Andrang am Stand weit h&amp;#246;her war, als ich es von anderen Konferenzen gewohnt war.
Kamen wir normalerweise zu zweit immer ganz gut zurecht, waren dieses Mal sogar drei
Personen eigentlich schon fast zu wenig.
&lt;/p&gt;
&lt;p&gt;
Fazit als Aussteller: Tolle Veranstaltung! Viele Kontakte, interessante und zum Teil
sogar sehr trickreiche Fragen, genauso muss es sein!
&lt;/p&gt;
&lt;h4&gt;Der User Group Leader
&lt;/h4&gt;
&lt;p&gt;
Jeder der schon mal ein User Group Treffen besucht hat wird sich sicherlich fragen:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Wo kommen eigentlich die Sprecher her?
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Nun ja, als sie ganz klein waren, wird sie voraussichtlich einer der beiden hier unten
gebracht haben.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/dotnetCologne2010waseinriesenSpa_14431/image.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="image" src="http://blog.codemurai.de/images/dotnetCologne2010waseinriesenSpa_14431/image_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Foto: &lt;a href="http://www.flickr.com/photos/valter/"&gt;&lt;b&gt;Valter Jacinto | Portugal&lt;/b&gt;&lt;/a&gt;&amp;#160;&amp;#160; &lt;a title="http://www.flickr.com/photos/valter/87429062/sizes/m/" href="http://www.flickr.com/photos/valter/87429062/sizes/m/"&gt;http://www.flickr.com/photos/valter/87429062/sizes/m/&lt;/a&gt; 
&lt;br /&gt;
Creative Commons License&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Irgendwann werden die Jungs und M&amp;#228;dels dann aber gro&amp;#223; und sp&amp;#228;testens
dann stellt sich f&amp;#252;r einen User Group Leiter die Frage: 
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Wo bekomme ich eigentlich Sprecher her?
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ein besonders guter Ort, Sprecher f&amp;#252;r die eigene User Group zu finden ist selbstverst&amp;#228;ndlich
eine Konferenz, denn dort treten Speaker h&amp;#228;ufig in Rudeln auf ;-)
&lt;/p&gt;
&lt;p&gt;
Also machte ich mich w&amp;#228;hrend der dotnet Cologne auf den Weg und zog Sprecher
f&amp;#252;r die n&amp;#228;chsten Treffen der .&lt;a href="http://www.dnug-koblenz.de" target="_blank"&gt;NET
User Group Koblenz&lt;/a&gt; an Land.
&lt;/p&gt;
&lt;p&gt;
Die Ausbeute war &amp;#252;brigens mit zwei definitiven, einer relativ verbindlichen und
einer losen Zusage recht gut. Daher auch hier: dotnet Cologne, 12 Points ;-)
&lt;/p&gt;
&lt;h4&gt;Der Sprecher
&lt;/h4&gt;
&lt;p&gt;
Zu guter letzt (und angesichts der Agenda ist dies w&amp;#246;rtlich gemeint), war ich
auch als Sprecher unterwegs. &lt;a href="http://dotnet-cologne.de/Sprecher.ashx#Andre.Kraemer" target="_blank"&gt;Mein&lt;/a&gt; Thema
war die &lt;a href="http://dotnet-cologne.de/Vortraege.ashx#jQuery" target="_blank"&gt;Einf&amp;#252;hrung
in jQuery&lt;/a&gt; unter dem spontan ge&amp;#228;nderten Titel:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
jQuery - oder warum Sie JavaScript in Zukunft nicht mehr hassen werden.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Den Verlauf des Vortrags w&amp;#252;rde ich wie folgt beschreiben
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Der Saal f&amp;#252;llt sich, die Menge wird still. Ich will loslegen, aber mein Mikro
&amp;#252;berlegt sich, dass es sich lieber in meinem T-Shirt verdreht. Kein Mensch h&amp;#246;rt
mich ... so ein Mist&lt;/li&gt;
&lt;li&gt;
Mikro Problem gel&amp;#246;st, schnell durch die Folien gejagt. Auf gehts zur Demo!&lt;/li&gt;
&lt;li&gt;
Meine ASP.NET MVC Anwendung rei&amp;#223;t niemand vom Hocker und st&amp;#246;&amp;#223;t kaum
auf Interesse&lt;/li&gt;
&lt;li&gt;
Ist zum Gl&amp;#252;ck nicht schlimm, schlie&amp;#223;lich ist mein Thema ja auch jQuery und
nicht ASP.NET MVC ;-)&lt;/li&gt;
&lt;li&gt;
Die ersten UI Gimmicks (alternierende Tabellenzeilen, Hover Effekte) zaubern ein m&amp;#252;des
L&amp;#228;cheln auf die Gesichter der Menge - da muss wohl noch mehr her&lt;/li&gt;
&lt;li&gt;
Ich erstelle mit einer Zeile jQuery Code auf- und zuklappbare Bereiche in der Sidebar
der Anwendung. Im Publikum sehe ich die ersten funkelnden Augen&lt;/li&gt;
&lt;li&gt;
Auf der Welle muss ich weiter reiten, also jetzt schnell ein wenig Ajax;-)&lt;/li&gt;
&lt;li&gt;
In der Einleitung habe ich etwas vom Update Panel erz&amp;#228;hlt. Hei&amp;#223;t dann wohl
ich sollte auch ein wenig WebForms zeigen. Ich entschlie&amp;#223;e mich also, im Firebug
mal zu zeigen, was &amp;#252;ber die Leitung geht wenn man Ajax mit dem Update Panel &lt;strike&gt;erlegt&lt;/strike&gt; erledigt.
Als ich zum ViewState scrolle scheinen einige Teilnehmer zu glauben ich h&amp;#228;tte
gerade die Matrix gehacked oder zumindest gedebugged.&lt;/li&gt;
&lt;li&gt;
Oh je, nur noch 3 Minuten Zeit und ich habe doch versprochen fr&amp;#252;her Schluss zu
machen - jetzt muss schnell etwas gro&amp;#223;artiges her. Ich greife also noch mal in
die Trickkiste und greife zu meinem gr&amp;#246;&amp;#223;ten Trumpf: 
&lt;br /&gt;
&lt;strong&gt;runde Ecken;-) 
&lt;br /&gt;
&lt;/strong&gt;Puh, geschafft, die Zuschauer jubeln. Ein Gl&amp;#252;ck, dass es runde Ecken
gibt ;-)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Mein Fazit als Sprecher lautet also:
&lt;/p&gt;
&lt;p&gt;
Wahnsinn! Auch wenn es nur ein Einsteiger Vortrag war und laut Handzeichen mindestens
die H&amp;#228;lfte der Anwesenden jQuery bereits kannte und nutzte war das Publikum allem
Anschein nach w&amp;#228;hrend des Vortrags voll dabei. So macht vortragen Spa&amp;#223;!
&lt;/p&gt;
&lt;h4&gt;Der Grillfreund
&lt;/h4&gt;
&lt;p&gt;
Zum Abschluss fand f&amp;#252;r einige Teilnehmer, Sprecher und Sponsoren dann noch die
durch Microsoft gesponsorte und durch Jan Welker gestifftete Grill-Party des dotnet
Forums statt. Essen und Getr&amp;#228;nke waren sehr lecker, die Gespr&amp;#228;che spannend,
von daher auch hier mein Kompliment.
&lt;/p&gt;
&lt;h4&gt;Fazit
&lt;/h4&gt;
&lt;p&gt;
Der Besuch der dotnet Cologne h&amp;#228;tte in keinster Weise besser laufen k&amp;#246;nnen.
Gro&amp;#223;es Lob und alle Achtung an die Organisatoren! N&amp;#228;chstes Jahr bin ich
- in welcher Form auch immer - sicherlich auch wieder mit dabei!
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Hey, du hast dir die Zeit genommen, den ganzen Beitrag zu lesen, oder zumindest
bis hier hin zu scrollen. Nimm dir doch bitte auch noch die Zeit, ihn &amp;#252;ber den
unten stehenden Button bei dotnet-kicks.de zu kicken!&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=bbf8f523-d565-4c02-a329-87a515fc415f" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,bbf8f523-d565-4c02-a329-87a515fc415f.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>Community</category>
      <category>DotNetGerman Bloggers</category>
      <category>jQuery</category>
      <category>Vorträge</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=9f3f8c59-f02f-414e-a8e6-74385d6cddd6</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,9f3f8c59-f02f-414e-a8e6-74385d6cddd6.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,9f3f8c59-f02f-414e-a8e6-74385d6cddd6.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=9f3f8c59-f02f-414e-a8e6-74385d6cddd6</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Habe ich für meine Blog Beiträge gefunden. Zumindest die englischen, die
einen Bezug zu den <a title="NetAdvantage for .NET" href="http://www.infragistics.com/dotnet/netadvantage.aspx" target="_blank">Infragistics
NetAdvantage Controls</a> haben. 
</p>
        <p>
Seit kurzem gibt auf der Infragistics Homepage nämlich <a title="Infragistics MVPs" href="http://blogs.infragistics.com/blogs/mvps/default.aspx" target="_blank">einen
MVP Blog</a>, für das ich einer der Autoren bin.
</p>
        <p>
Selbstverständlich gibt es auch schon einen <a title="Introducing Infragistics MVP André Krämer" href="http://blogs.infragistics.com/blogs/mvps/archive/2010/05/17/introducing-infragistics-mvp-andr-233-kr-228-mer.aspx" target="_blank">ersten
Blog Post von mir</a>. Dieser beinhaltet neben einer kurzen (OK, langen ;-)) Vorstellung
ein kleines jQuery Script, welches hilfreich beim Einsatz des Infragistics ASP.NET
Aikido WebDropdown Controls ist.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/EinzweitesZuhause_E6B7/igmvpblog.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="131" alt="igmvpblog" src="http://blog.codemurai.de/images/EinzweitesZuhause_E6B7/igmvpblog_thumb.png" width="244" border="0" />
          </a>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=9f3f8c59-f02f-414e-a8e6-74385d6cddd6" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Ein zweites Zuhause</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,9f3f8c59-f02f-414e-a8e6-74385d6cddd6.aspx</guid>
      <link>http://blog.codemurai.de/2010/05/23/EinZweitesZuhause.aspx</link>
      <pubDate>Sun, 23 May 2010 14:24:47 GMT</pubDate>
      <description>&lt;p&gt;
Habe ich f&amp;#252;r meine Blog Beitr&amp;#228;ge gefunden. Zumindest die englischen, die
einen Bezug zu den &lt;a title="NetAdvantage for .NET" href="http://www.infragistics.com/dotnet/netadvantage.aspx" target="_blank"&gt;Infragistics
NetAdvantage Controls&lt;/a&gt; haben. 
&lt;/p&gt;
&lt;p&gt;
Seit kurzem gibt auf der Infragistics Homepage n&amp;#228;mlich &lt;a title="Infragistics MVPs" href="http://blogs.infragistics.com/blogs/mvps/default.aspx" target="_blank"&gt;einen
MVP Blog&lt;/a&gt;, f&amp;#252;r das ich einer der Autoren bin.
&lt;/p&gt;
&lt;p&gt;
Selbstverst&amp;#228;ndlich gibt es auch schon einen &lt;a title="Introducing Infragistics MVP Andr&amp;#233; Kr&amp;#228;mer" href="http://blogs.infragistics.com/blogs/mvps/archive/2010/05/17/introducing-infragistics-mvp-andr-233-kr-228-mer.aspx" target="_blank"&gt;ersten
Blog Post von mir&lt;/a&gt;. Dieser beinhaltet neben einer kurzen (OK, langen ;-)) Vorstellung
ein kleines jQuery Script, welches hilfreich beim Einsatz des Infragistics ASP.NET
Aikido WebDropdown Controls ist.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/EinzweitesZuhause_E6B7/igmvpblog.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="131" alt="igmvpblog" src="http://blog.codemurai.de/images/EinzweitesZuhause_E6B7/igmvpblog_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=9f3f8c59-f02f-414e-a8e6-74385d6cddd6" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,9f3f8c59-f02f-414e-a8e6-74385d6cddd6.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>jQuery</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=4da40177-7c66-4c22-b1f1-7c214bc54f6f</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,4da40177-7c66-4c22-b1f1-7c214bc54f6f.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,4da40177-7c66-4c22-b1f1-7c214bc54f6f.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=4da40177-7c66-4c22-b1f1-7c214bc54f6f</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Vor ein paar Wochen haben unter anderem <a href="http://blogs.msdn.com/dparys/archive/2010/03/05/was-hast-du-vor-ber-zehn-jahren-programmiert.aspx" target="_blank">Darius</a>, <a href="http://blog.alexonasp.net/post/2010/03/05/Was-hast-Du-vor-uber-zehn-Jahren-programmiert.aspx" target="_blank">Alex</a> und <a href="http://blog.thomasbandt.de/39/2324/de/blog/re-was-hast-du-vor-ueber-zehn-jahren-programmiert.html" target="_blank">Thomas</a> darüber
geblogged, was sie vor 10 Jahren programmiert haben.
</p>
        <p>
Natürlich kam ich auch ins Grübeln und so fiel mir ein, dass ich zu dieser
Zeit meine Zeit meist mit VB 6 Desktop Anwendungen, Outlook Formularanwendungen, oder
aber PHP oder Classic ASP Webanwendungen verbracht habe. Allerdings habe ich seitdem
mehrfach den Arbeitgeber gewechselt und die Source Codes daher auch nicht mehr im
Zugriff. Somit war das Thema, einen Blogeintrag zu dieser Frage zu schreiben für
mich eigentlich erledigt.
</p>
        <h4>Eigentlich ...
</h4>
        <p>
Aber auch nur eigentlich, denn lustigerweise schickte mir letzte Woche ein ehemaliger
Kollege aus heiterem Himmel einen alten Screenshot, den er irgendwo gefunden hatte.
</p>
        <p>
Bei diesem Screenshot handelte es sich um einen Gag Screen einer Anwendung, die wir
1999 für die Finanzbuchhaltung der Nürburgring GmbH geschrieben hatten.
Das Bild öffnete sich übrigens, wenn ich mich recht erinnere beim Klick
auf ein Label. In den vier Jahren, in denen ich die Anwendung anschließend noch
weiter betreut habe, kam allerdings nie eine Anfrage zu dieser Bildschirmmaske. Daher
gehe ich mal davon aus, dass es niemand gefunden hat :-)
</p>
        <p>
Auf dem Bild zu sehen sind übrigens mein damaliger Kollege, der ein ehemaliger
Schulkamerad und mein späterer WG Mitbewohner war, und ich. Das Bild wurde allerdings
nicht während der Arbeit, sondern während eine Pre-Game Grill Party eines
Spiels der Frankfurt Galaxy aufgenommen. Zu rätseln, wer von uns beiden wer ist,
überlasse ich den Lesern dieses Blogs.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/Washastduvor10Jahrenprogrammiert_146B8/programmierer.jpg">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="242" alt="programmierer" src="http://blog.codemurai.de/images/Washastduvor10Jahrenprogrammiert_146B8/programmierer_thumb.jpg" width="244" border="0" />
          </a>
        </p>
        <p>
Schöne Erinnerung! Vielen Dank für das Bild Oliver!
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=4da40177-7c66-4c22-b1f1-7c214bc54f6f" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Was hast du vor 10 Jahren programmiert</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,4da40177-7c66-4c22-b1f1-7c214bc54f6f.aspx</guid>
      <link>http://blog.codemurai.de/2010/05/17/WasHastDuVor10JahrenProgrammiert.aspx</link>
      <pubDate>Mon, 17 May 2010 21:14:13 GMT</pubDate>
      <description>&lt;p&gt;
Vor ein paar Wochen haben unter anderem &lt;a href="http://blogs.msdn.com/dparys/archive/2010/03/05/was-hast-du-vor-ber-zehn-jahren-programmiert.aspx" target="_blank"&gt;Darius&lt;/a&gt;, &lt;a href="http://blog.alexonasp.net/post/2010/03/05/Was-hast-Du-vor-uber-zehn-Jahren-programmiert.aspx" target="_blank"&gt;Alex&lt;/a&gt; und &lt;a href="http://blog.thomasbandt.de/39/2324/de/blog/re-was-hast-du-vor-ueber-zehn-jahren-programmiert.html" target="_blank"&gt;Thomas&lt;/a&gt; dar&amp;#252;ber
geblogged, was sie vor 10 Jahren programmiert haben.
&lt;/p&gt;
&lt;p&gt;
Nat&amp;#252;rlich kam ich auch ins Gr&amp;#252;beln und so fiel mir ein, dass ich zu dieser
Zeit meine Zeit meist mit VB 6 Desktop Anwendungen, Outlook Formularanwendungen, oder
aber PHP oder Classic ASP Webanwendungen verbracht habe. Allerdings habe ich seitdem
mehrfach den Arbeitgeber gewechselt und die Source Codes daher auch nicht mehr im
Zugriff. Somit war das Thema, einen Blogeintrag zu dieser Frage zu schreiben f&amp;#252;r
mich eigentlich erledigt.
&lt;/p&gt;
&lt;h4&gt;Eigentlich ...
&lt;/h4&gt;
&lt;p&gt;
Aber auch nur eigentlich, denn lustigerweise schickte mir letzte Woche ein ehemaliger
Kollege aus heiterem Himmel einen alten Screenshot, den er irgendwo gefunden hatte.
&lt;/p&gt;
&lt;p&gt;
Bei diesem Screenshot handelte es sich um einen Gag Screen einer Anwendung, die wir
1999 f&amp;#252;r die Finanzbuchhaltung der N&amp;#252;rburgring GmbH geschrieben hatten.
Das Bild &amp;#246;ffnete sich &amp;#252;brigens, wenn ich mich recht erinnere beim Klick
auf ein Label. In den vier Jahren, in denen ich die Anwendung anschlie&amp;#223;end noch
weiter betreut habe, kam allerdings nie eine Anfrage zu dieser Bildschirmmaske. Daher
gehe ich mal davon aus, dass es niemand gefunden hat :-)
&lt;/p&gt;
&lt;p&gt;
Auf dem Bild zu sehen sind &amp;#252;brigens mein damaliger Kollege, der ein ehemaliger
Schulkamerad und mein sp&amp;#228;terer WG Mitbewohner war, und ich. Das Bild wurde allerdings
nicht w&amp;#228;hrend der Arbeit, sondern w&amp;#228;hrend eine Pre-Game Grill Party eines
Spiels der Frankfurt Galaxy aufgenommen. Zu r&amp;#228;tseln, wer von uns beiden wer ist,
&amp;#252;berlasse ich den Lesern dieses Blogs.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/Washastduvor10Jahrenprogrammiert_146B8/programmierer.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="242" alt="programmierer" src="http://blog.codemurai.de/images/Washastduvor10Jahrenprogrammiert_146B8/programmierer_thumb.jpg" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Sch&amp;#246;ne Erinnerung! Vielen Dank f&amp;#252;r das Bild Oliver!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=4da40177-7c66-4c22-b1f1-7c214bc54f6f" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,4da40177-7c66-4c22-b1f1-7c214bc54f6f.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Fun</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=dfbe0604-ff45-4a2a-899f-5bd37db4310a</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,dfbe0604-ff45-4a2a-899f-5bd37db4310a.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,dfbe0604-ff45-4a2a-899f-5bd37db4310a.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=dfbe0604-ff45-4a2a-899f-5bd37db4310a</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Moderne Webseiten beinhalten in der heutigen Zeit einen hohen Anteil clientseitiger
Quellcodes in Form von JavaScript. Für diesen Anwender führt dies im Idealfall
zu einer verbesserten Benutzbarkeit der Applikation, da diese neben netten UI Effekten
nun meist durch Ajax auch weitaus flüssiger bedienbar ist.
</p>
        <p>
Bei vielen Entwicklern solcher dynamischer Webseiten führt der vermehrte JavaScript
Anteil allerdings häufig zu Wein- und/oder Schreikrämpfen, denn nur die
wenigsten mögen JavaScript wirklich. Die Ursachen für diese Antipathie liegen
jedoch selten an JavaScript als Sprache selbst, sondern in den meisten Fällen
eher an der unterschiedlichen Implementation des DOMs / BOMs durch die verschiedenen
Browserhersteller. Diese Inkonsistenz führt nämlich dazu, dass JavaScript
Code, der in einem Browser bzw. einer Version eines Browsers problemlos läuft
im nächsten Browser Fehler verursacht und schlichtweg nicht läuft.
</p>
        <p>
Weiter wird häufig bemängelt, das Selektionen fernab von einem einfachen <em>document.getElementById(IdMeinesElements)</em> relativ
kompliziert sind. Als Beispiel wären hier zu nennen: alle Elemente mit einer
bestimmten Klasse, ungerade Zeilen einer Tabelle, das aktivierte Element einer RadioButtonGroup
usw.
</p>
        <h4>Und nun?
</h4>
        <p>
Nun gibt es folgende Strategien mit diesen Problemen umzugehen:
</p>
        <ol>
          <li>
Man drückt sich immer davor JavaScript zu schreiben und wälzt dies auf einen
Kollegen ab 
</li>
          <li>
Man kopiert sich irgendwoher JavaScript Codeschnippsel, die angeben browserunabhängig
zu sein und hofft, das dem auch so ist 
</li>
          <li>
Man investiert Unmengen Zeit in die eigene browserübergreifende Implementierung
diverser Funktionalitäten 
</li>
          <li>
Man bedient sich eines der am Markt verfügbaren JavaScript Frameworks 
</li>
        </ol>
        <p>
Strategie Nr. 1 mag eine Weile ganz gut funktionieren, früher oder später
wird aber der Zeitpunkt kommen, an dem man sich nicht mehr drücken kann (ich
spreche da aus eigener Erfahrung ;-)). 
</p>
        <p>
Strategie Nr. 2 funktioniert immer dann, wenn der Umfang des benötigten JavaScript
Codes überschaubar ist. Gemeinsam mit der Applikation wird aber auch irgendwann
der zusammenkopierte Code wachsen und die Wartbarkeit entsprechend sinken.
</p>
        <p>
Strategie Nr. 3 ist sicherlich eine prima Idee für alle die außerdem auch
ein eigenes Logging Framework, einen eigenen OR Mapper usw implementiert haben, oder
kurz gesagt für alle die gerne das Rad neu erfinden ;-)
</p>
        <p>
Gangbar scheint also nur Strategie Nr. 4 zu sein. Schaut man sich nun am Markt um,
stößt man unweigerlich auf <a href="http://www.jquery.com" target="_blank">jQuery</a>.
Die freie JavaScript Library adressiert unter anderem genau die zuvor genannten Probleme
und hat in letzter Zeit einen wahren Hype verursacht. Dieser Rummel wurde sicherlich
auch dadurch verstärkt, dass Microsoft jQuery <a title="jQuery and Microsoft, Scott Gu" href="http://weblogs.asp.net/scottgu/archive/2008/09/28/jquery-and-microsoft.aspx" target="_blank">offiziell
supportet, mit Visual Studio ausliefert</a> und die Arbeiten an der <a title="Microsoft, jQuery, and Templating" href="http://stephenwalther.com/blog/archive/2010/03/16/microsoft-jquery-and-templating.aspx" target="_blank">hauseigenen
JavaScript Bibliothek ASP.NET Ajax Library zugunsten von jQuery eingestellt hat</a>.
</p>
        <p>
Wie legen wir nun aber mit jQuery los? Genau diese Frage möchte ich in diesem
und den folgenden Blog Posts beantworten. Da jQuery in einem neuen ASP.NET MVC Projekt
automatisch hinzugefügt wird und ASP.NET MVC Entwickler somit sowieso jQuery
gewöhnt sind, soll als Beispiel zunächst eine Webforms Anwendung dienen. 
</p>
        <h4>Auf die Plätze, fertig, los!
</h4>
        <p>
Wenn man jQuery benutzen möchte, besteht der erste Schritt darin, die freie JavaScript
Library in seine Seite einzubinden. Dazu lädt man unter <a href="http://www.jQuery.com">http://www.jQuery.com</a> einfach
die aktuelle Version der Bibliothek herunter und kopiert diese anschließend zum
Beispiel in einen Unterordner Scripts seiner Webanwendung. jQuery ist übrigens
in einer für Menschen lesbaren (z. B. jQuery-1.4.2.js) und in einer verkleinerten
Version (z, B. jQuery-1.4.2.<strong>min</strong>.js) verfügbar. In der verkleinerten
Version sind unnötige Leerzeichen, Zeilenumbrüche und Kommentare entfernt.
Außerdem wurden die Namen der Variablen und nicht öffentlichen Funktionen
auf ein oder zwei Buchstaben verkürzt. Sinn dieser Maßnahme ist es die zum
Client übertragene Datenmenge zu reduzieren. So ist die verkleinerte Version
knappe 100 kb kleiner als die lesbare Variante. Für Produktivszenarien sollte
demnach also in jedem Fall die <strong>.min</strong> Version genutzt werden, wohingegen
während der Entwicklungszeit eher die lesbare Variante eingebunden werden sollte.
So kann man den Scriptcode im Fall der Fälle nämlich noch debuggen.
</p>
        <p>
So, genug der Vorrede und zurück zur Praxis. Tatsächlich einbinden können
wir jQuery nun über folgende Zeile:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:fd54cf52-9c20-4284-8728-d8c32de15538" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;script src="Scripts/jquery-1.4.2.js" type="text/javascript"&gt;&lt;/script&gt;</pre>
        </div>
        <p>
Platzieren sollte man diese Zeile übrigens innerhalb des Kopfbereichs der Seite:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:67bf7f48-7248-498b-8fde-1d7de66e1b54" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %&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;script src="Scripts/jquery-1.4.2.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/head&gt;</pre>
        </div>
        <h4>Prima, aber was mache ich nun damit?
</h4>
        <p>
Gute Frage! Jetzt haben wir jQuery zwar eingebunden, aber wie geht es jetzt weiter.
Dazu sollten wir zunächst kurz einen Blick darauf werfen, was wir normalerweise
mit JavaScript machen. In den meißten Fällen reduziert sich dies auf:
</p>
        <ul>
          <li>
Elemente aus dem DOM zu selektieren 
</li>
          <li>
Selektierte Elemente zu manipulieren (ein- / ausblenden, Styledefinitionen zu verändern...) 
</li>
          <li>
Code bei bestimmten Ereignissen ausführen (z. B. click event) 
</li>
          <li>
Neue Elemente dem DOM hinzuzufügen 
</li>
          <li>
Elemente aus dem DOM zu löschen 
</li>
          <li>
AJAX Aufrufe zum Server zu machen und die Antwort zu Verarbeiten 
</li>
        </ul>
        <p>
Als kleinen Einstieg picken wir uns exemplarisch die ersten drei Punkte heraus. Wir
werden also DOM Elemente selektieren und diese manipulieren. Geschehen wird dies bei
dem Klick auf einen Button. 
</p>
        <p>
Dazu werden wir eine Meldungszeile, ähnlich wie man sie von Stackoverflow kennt
nachbauen.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/LebendigeASP.NETWebseitenmitjQuery_10249/01_so_message.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="50" alt="01_so_message" src="http://blog.codemurai.de/images/LebendigeASP.NETWebseitenmitjQuery_10249/01_so_message_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Der erste Schritt besteht in der Erstellung eines HTML und CSS Grundgerüsts:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:e7391c73-ddaa-4dc8-95d0-82ca57f8e1a8" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %&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;jQuery Demo&lt;/title&gt;

    &lt;style type="text/css"&gt;
        body
        {
            margin: 0px;
        }
        #message
        {
            background-color: #FFFF88;
            border-bottom: solid 1px #000000;
            font-weight: bold;
            text-align: center;
            padding: 8px;
            margin: 0px;
            display:none;
            font-family: Arial, Verdana, Sans-Serif;
        }
        #message a
        {
            float: right;
            border: solid 3px black;
            font-family: Arial, Verdana, Sans-Serif;
            font-weight: bold;
            text-decoration: none;
            color: Black;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id="form1" runat="server"&gt;
    &lt;div id="message"&gt;&lt;span&gt;Dummy Nachricht&lt;/span&gt;&lt;a href="Default.aspx"&gt;X&lt;/a&gt;
    &lt;/div&gt;
    &lt;div id="content"&gt;
        &lt;p&gt;
            Dies ist eine jQuery Demowebsite&lt;/p&gt;
        &lt;button id="showMessage"&gt;
            Klick mich&lt;/button&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
        </div>
        <p>
Wie man sieht, wird ein DIV Element  mit dem Namen "<em>message</em>"
erstellt, dass als Unterlemente ein SPAN Element und einen Link enthält. Über
CSS wird dieses DIV Element noch ein wenig gestyled und initial ausgeblendet. Außerdem
ist auf der Seite noch ein Button definiert. Ein Klick auf diesen Button soll der
Auslöser sein, um die Meldung anzuzeigen.
</p>
        <p>
Wie aber genau sieht nun der Code aus, um die Nachricht - mit verändertem Text
- anzuzeigen?
</p>
        <p>
Mit der Hilfe von jQuery ist dies garnicht so schwer:
</p>
        <p>
        </p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:aa05f6d1-1274-4e12-a697-a83bf6a1f0ea" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">$("#showMessage").click(function(evt) {
    evt.preventDefault();
    $("#message span").text("Du hast den Button geklickt. Klicke nun auf das X, um die Nachricht auszublenden.");
    $("#message").fadeIn(2000);
});</pre>
        </div>
Auf den ersten Blick mag der Code etwas verwirrend aussehen. Vor allem durch die vielen
$-Zeichen. Daher ein paar erklärende Worte:
<p>
In Zeile 1 selektieren wir mit dem Befehl: <em>$("#showMessage")</em> zunächst
das DOM Element mit der ID showMessage, also unseren Button. Das $-Zeichen ist übrigens
ein Alias für die jQuery Funktion. Statt $("message") hätte ich
also auch jQuery("$message") schreiben können. Die Rückgabe des
Aufrufs - unabhängig ob via jQuery(...) oder $(...) ist ein Objekt vom Typ jQuery.
Dieses Objekt beinhaltet die selektieren DOM Elemente bzw. das selektierte DOM Element
sowie einige weitere Funktionen.
</p><p>
In unserem Fall bekommen wir also ein Objekt vom Typ jQuery zurück, dass das
DOM Element <em>showMessage</em> beinhaltet. Für dieses DOM Element wird nun
eine anonyme Funktion als Handler für das Ereignis Click registriert.
</p><p>
In Zeile 2 wird mit dem Befehl <em>evt.preventDefault();</em> nun die Standardaktion
die der Browser bei diesem Ereignis, also z. B. das posten des Formulars nach Klick
auf den Button, verhindert.
</p><p>
In Zeile 3 werden anschließend alle span Elemente innerhalb des DOM Elements
mit der Id message selektiert. In unserem Fall ist dies also genau eins. Für
dieses span Element wird mit der Funktion <em>text</em> jetzt ein neuer Text vergeben.
Außerdem wird das Element mit der Id <em>message</em> in Zeile 4 langsam (über
einen Zeitraum von zwei Sekunden) eingeblendet.
</p><p>
Der Quellcode zum Ausblenden der Nachricht sieht ähnlich aus:
</p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b47b458c-59e6-4c64-8f66-e11367f7fe31" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre name="code" class="js">$("#message a").click( function(evt) {
     evt.preventDefault();
     $("#message").fadeOut("slow");
 });</pre></div><p>
In Zeile 1 wird an alle A-Elemente innerhalb des DOM Elements mit der Id <em>message </em>ein
Eventhandler für das Ereignis Click angehangen. Dieser verhindert in Zeile 2
die Standardaktion des Links und blendet in Zeile 3 unsere Nachrichtenzeile wieder
aus. Dieses mal wird statt einer Angabe in Millisekunden der String "slow"
als Argument übergeben. Dieser ist in den jQuery Quellcodes mit einem Wert von
600 ms hinterlegt.
</p><h4>Perfekt, aber wo schreibe ich den Code nun rein?
</h4><p>
So, jetzt wo wir eigentlich den ganzen Quellcode fertig haben stellt sich natürlich
die Frage, wie wir ihn in unsere Seite einbinden. Eine naive Implementierung sähe
wie folgt aus:
</p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:23b3a952-2853-4417-aadf-7b8609a9995e" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre name="code" class="js">&lt;head&gt;
&lt;!-- ... --&gt;
&lt;script type="text/javascript"&gt;
    $("#showMessage").click(function(evt) {
        evt.preventDefault();
        $("#message span").text("Du hast den Button geklickt. Klicke nun auf das X, um die Nachricht auszublenden.");
        $("#message").fadeIn(2000);
    });
    $("#message a").click( function(evt) {
        evt.preventDefault();
        $("#message").fadeOut("slow");
    });
&lt;/script&gt;
&lt;!-- ... --&gt;
&lt;/head&gt;</pre></div><p>
Der Code würde also einfach in ein Scripttag innerhalb des Head Tags kopiert
werden. <strong>Dies läuft so nicht</strong>! Der Grund ist, dass mit diesem
Code versucht wird, ein Eventhandler an ein DOM Element zu binden, das es zu diesem
Zeitpunkt noch garnicht gibt.
</p><p>
Wie sieht aber die Lösung für das Problem aus?
</p><h4>Alles zu seiner Zeit
</h4><p>
Wie wir zuvor gesehen haben, ist unser Code wirkungslos, wenn wir ihn ausführen
ehe es ein entsprechendes DOM Element gibt. Daher sollten wir ihn erst auslösen,
sobald das DOM vollständig initialisiert ist.
</p><p>
Ein weg dies zu erreichen wäre es, den Code aufzurufen wenn das Ereignis <em>window.onload</em> eintritt:
</p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:c9e7a5e3-3a80-4f97-bb46-1ed999da3e0e" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre name="code" class="js">window.onload = function() {
  $("#showMessage").click(function(evt) {
     evt.preventDefault();
     // Restlicher Code hier
  });
}</pre></div><p>
Diese Variante würde bereits fehlerfrei funktionieren. Allerdings wird das Ereignis
onload erst ausgelöst, wenn das DOM vollständig initialisiert wurde <strong>und</strong> alle
externen Ressourcen, wie zum Beispiel Bilder oder Stylesheets geladen wurden. Dies
kann von Fall zu Fall recht lange dauern, so dass der Anwender den Button bereits
anklicken könnte, ohne dass unser Script ausgeführt wird. Zum Glück
bietet jQuery einen besseren Ansatz, nämlich <em>$(document).ready</em>. In dieser
Variante wird das Ereignis ready ausgelöst, sobald das DOM vollständig initialisiert
wurde, aber <strong>bevor</strong> externe Ressourcen geladen wurden.
</p><p>
Das vollständige Beispiel mit $(document).ready sieht dann wie folgt aus:
</p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4e437cd3-4422-4027-bf2d-6573920a764c" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre name="code" class="xml">&lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %&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;jQuery Demo&lt;/title&gt;

    &lt;script src="Scripts/jquery-1.4.1.js" type="text/javascript"&gt;&lt;/script&gt;

    &lt;style type="text/css"&gt;
        body
        {
            margin: 0px;
        }
        #message
        {
            background-color: #FFFF88;
            border-bottom: solid 1px #000000;
            font-weight: bold;
            text-align: center;
            padding: 8px;
            margin: 0px;
            display:none;
            font-family: Arial, Verdana, Sans-Serif;
        }
        #message a
        {
            float: right;
            border: solid 3px black;
            font-family: Arial, Verdana, Sans-Serif;
            font-weight: bold;
            text-decoration: none;
            color: Black;
        }
    &lt;/style&gt;

    &lt;script type="text/javascript"&gt;
        $(document).ready(function() {
            $("#showMessage").click(function(evt) {
                evt.preventDefault();
                $("#message span").text("Du hast den Button geklickt. Klicke nun auf das X, um die Nachricht auszublenden.");
                $("#message").fadeIn(2000);
            });
            $("#message a").click(function(evt) {
                evt.preventDefault();
                $("#message").fadeOut("slow");
            }
        }
      });
    &lt;/script&gt;

&lt;/head&gt;
&lt;body&gt;
    &lt;form id="form1" runat="server"&gt;
    &lt;div id="message"&gt;&lt;span&gt;Dummy Nachricht&lt;/span&gt;&lt;a href="Default.aspx"&gt;X&lt;/a&gt;
    &lt;/div&gt;
    &lt;div id="content"&gt;
        &lt;p&gt;
            Dies ist eine jQuery Demowebsite&lt;/p&gt;
        &lt;button id="showMessage"&gt;
            Klick mich&lt;/button&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></div><h4>Ausblick und Fazit
</h4><p>
Wie dieser Blog Eintrag gezeigt hat, ist jQuery eine recht komfortabel zu bediene
JavaScript Library, mit der sich mit wenigen Zeilen Script Code interessante Effekte
erzielen lassen. Neben der intuitiven und Browser unabhängigen API besticht die
Bibliothek vor allem durch die Fülle an Funktionen und erhältlichen Plug-Ins.
Selbstverständlich konnte ich hier nur einen kurzen (ersten) Einblick verschaffen.
Da ich das Thema Clientseitige Entwicklung in (ASP.NET) Webanwendungen jedoch für
sehr interessant halte, habe ich vor in der nächsten Zeit weitere Einträge
zum Thema jQuery mit folgenden Schwerpunkten zu schreiben:
</p><ul><li>
Nutzen von Content Delivery Networks (CDNs)</li><li>
jQuery Selektoren</li><li>
Möglichkeiten der DOM Manipulation</li><li>
jQuery und Firebug</li><li>
jQuery Plugins selber entwickeln</li><li>
jQuery UI</li><li>
jQuery Utility Funktionen</li><li>
jQuery und Ajax für Webforms und ASP.NET MVC</li></ul><p>
Eventuell werde ich im Anschluss an die Artikel auch kurze Video Tutorials bereitstellen.
</p><p>
Bevor ich allerdings loslege würde mich natürlich interessieren, ob das
Thema für euch überhaupt von Interesse ist. Am liebsten in Form eines kurzen
Kommentars.
</p><p>
Sollte jemand von euch übrigens das Verlangen haben, das Thema jQuery, oder auch
generell ASP.NET mit mir persönlich in lockerer Atmosphäre zu diskutieren:
Am 28. Mai werde ich einen <strong>Einsteigervortrag</strong> zu jQuery auf der <a title="Homepage der dotnet Cologne 2010" href="http://dotnet-cologne.de/" target="_blank">dotnet
Cologne 2010</a> halten. Über zahlreiche Besucher des Vortrags und natürlich
auch spannende Diskussionen danach würde ich mich sehr freuen.
</p><p><img src="http://www.dotnet-cologne.de/public/Upload/Werbung/dc2010_Sprecher_180x80.png" /></p><p>
In den Pausen findet man ihr mich übrigens wahrscheinlich im Ausstellerbereich
am Stand der Firma <a title="Homepage der Firma Infragistics" href="http://www.infragistics.com" target="_blank">Infragistics</a>.
Dort wäre ich dann zusätzlich auch für den ein oder anderen Plausch
über die <a href="http://www.infragistics.com/dotnet/netadvantage.aspx" target="_blank">Infragistics
NetAdvantage</a> Komponenten zu haben.
</p><p><em></em></p><p><em>War dieser Artikel hilfreich für dich? Dann kicke ihn doch bitte bei dotnet-kicks.de!</em></p><img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=dfbe0604-ff45-4a2a-899f-5bd37db4310a" /><br /><hr /><a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Lebendige ASP.NET Webseiten mit jQuery</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,dfbe0604-ff45-4a2a-899f-5bd37db4310a.aspx</guid>
      <link>http://blog.codemurai.de/2010/05/04/LebendigeASPNETWebseitenMitJQuery.aspx</link>
      <pubDate>Tue, 04 May 2010 17:47:09 GMT</pubDate>
      <description>&lt;p&gt;
Moderne Webseiten beinhalten in der heutigen Zeit einen hohen Anteil clientseitiger
Quellcodes in Form von JavaScript. F&amp;#252;r diesen Anwender f&amp;#252;hrt dies im Idealfall
zu einer verbesserten Benutzbarkeit der Applikation, da diese neben netten UI Effekten
nun meist durch Ajax auch weitaus fl&amp;#252;ssiger bedienbar ist.
&lt;/p&gt;
&lt;p&gt;
Bei vielen Entwicklern solcher dynamischer Webseiten f&amp;#252;hrt der vermehrte JavaScript
Anteil allerdings h&amp;#228;ufig zu Wein- und/oder Schreikr&amp;#228;mpfen, denn nur die
wenigsten m&amp;#246;gen JavaScript wirklich. Die Ursachen f&amp;#252;r diese Antipathie liegen
jedoch selten an JavaScript als Sprache selbst, sondern in den meisten F&amp;#228;llen
eher an der unterschiedlichen Implementation des DOMs / BOMs durch die verschiedenen
Browserhersteller. Diese Inkonsistenz f&amp;#252;hrt n&amp;#228;mlich dazu, dass JavaScript
Code, der in einem Browser bzw. einer Version eines Browsers problemlos l&amp;#228;uft
im n&amp;#228;chsten Browser Fehler verursacht und schlichtweg nicht l&amp;#228;uft.
&lt;/p&gt;
&lt;p&gt;
Weiter wird h&amp;#228;ufig bem&amp;#228;ngelt, das Selektionen fernab von einem einfachen &lt;em&gt;document.getElementById(IdMeinesElements)&lt;/em&gt; relativ
kompliziert sind. Als Beispiel w&amp;#228;ren hier zu nennen: alle Elemente mit einer
bestimmten Klasse, ungerade Zeilen einer Tabelle, das aktivierte Element einer RadioButtonGroup
usw.
&lt;/p&gt;
&lt;h4&gt;Und nun?
&lt;/h4&gt;
&lt;p&gt;
Nun gibt es folgende Strategien mit diesen Problemen umzugehen:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Man dr&amp;#252;ckt sich immer davor JavaScript zu schreiben und w&amp;#228;lzt dies auf einen
Kollegen ab 
&lt;/li&gt;
&lt;li&gt;
Man kopiert sich irgendwoher JavaScript Codeschnippsel, die angeben browserunabh&amp;#228;ngig
zu sein und hofft, das dem auch so ist 
&lt;/li&gt;
&lt;li&gt;
Man investiert Unmengen Zeit in die eigene browser&amp;#252;bergreifende Implementierung
diverser Funktionalit&amp;#228;ten 
&lt;/li&gt;
&lt;li&gt;
Man bedient sich eines der am Markt verf&amp;#252;gbaren JavaScript Frameworks 
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Strategie Nr. 1 mag eine Weile ganz gut funktionieren, fr&amp;#252;her oder sp&amp;#228;ter
wird aber der Zeitpunkt kommen, an dem man sich nicht mehr dr&amp;#252;cken kann (ich
spreche da aus eigener Erfahrung ;-)). 
&lt;/p&gt;
&lt;p&gt;
Strategie Nr. 2 funktioniert immer dann, wenn der Umfang des ben&amp;#246;tigten JavaScript
Codes &amp;#252;berschaubar ist. Gemeinsam mit der Applikation wird aber auch irgendwann
der zusammenkopierte Code wachsen und die Wartbarkeit entsprechend sinken.
&lt;/p&gt;
&lt;p&gt;
Strategie Nr. 3 ist sicherlich eine prima Idee f&amp;#252;r alle die au&amp;#223;erdem auch
ein eigenes Logging Framework, einen eigenen OR Mapper usw implementiert haben, oder
kurz gesagt f&amp;#252;r alle die gerne das Rad neu erfinden ;-)
&lt;/p&gt;
&lt;p&gt;
Gangbar scheint also nur Strategie Nr. 4 zu sein. Schaut man sich nun am Markt um,
st&amp;#246;&amp;#223;t man unweigerlich auf &lt;a href="http://www.jquery.com" target="_blank"&gt;jQuery&lt;/a&gt;.
Die freie JavaScript Library adressiert unter anderem genau die zuvor genannten Probleme
und hat in letzter Zeit einen wahren Hype verursacht. Dieser Rummel wurde sicherlich
auch dadurch verst&amp;#228;rkt, dass Microsoft jQuery &lt;a title="jQuery and Microsoft, Scott Gu" href="http://weblogs.asp.net/scottgu/archive/2008/09/28/jquery-and-microsoft.aspx" target="_blank"&gt;offiziell
supportet, mit Visual Studio ausliefert&lt;/a&gt; und die Arbeiten an der &lt;a title="Microsoft, jQuery, and Templating" href="http://stephenwalther.com/blog/archive/2010/03/16/microsoft-jquery-and-templating.aspx" target="_blank"&gt;hauseigenen
JavaScript Bibliothek ASP.NET Ajax Library zugunsten von jQuery eingestellt hat&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Wie legen wir nun aber mit jQuery los? Genau diese Frage m&amp;#246;chte ich in diesem
und den folgenden Blog Posts beantworten. Da jQuery in einem neuen ASP.NET MVC Projekt
automatisch hinzugef&amp;#252;gt wird und ASP.NET MVC Entwickler somit sowieso jQuery
gew&amp;#246;hnt sind, soll als Beispiel zun&amp;#228;chst eine Webforms Anwendung dienen. 
&lt;/p&gt;
&lt;h4&gt;Auf die Pl&amp;#228;tze, fertig, los!
&lt;/h4&gt;
&lt;p&gt;
Wenn man jQuery benutzen m&amp;#246;chte, besteht der erste Schritt darin, die freie JavaScript
Library in seine Seite einzubinden. Dazu l&amp;#228;dt man unter &lt;a href="http://www.jQuery.com"&gt;http://www.jQuery.com&lt;/a&gt; einfach
die aktuelle Version der Bibliothek herunter und kopiert diese anschlie&amp;#223;end zum
Beispiel in einen Unterordner Scripts seiner Webanwendung. jQuery ist &amp;#252;brigens
in einer f&amp;#252;r Menschen lesbaren (z. B. jQuery-1.4.2.js) und in einer verkleinerten
Version (z, B. jQuery-1.4.2.&lt;strong&gt;min&lt;/strong&gt;.js) verf&amp;#252;gbar. In der verkleinerten
Version sind unn&amp;#246;tige Leerzeichen, Zeilenumbr&amp;#252;che und Kommentare entfernt.
Au&amp;#223;erdem wurden die Namen der Variablen und nicht &amp;#246;ffentlichen Funktionen
auf ein oder zwei Buchstaben verk&amp;#252;rzt. Sinn dieser Ma&amp;#223;nahme ist es die zum
Client &amp;#252;bertragene Datenmenge zu reduzieren. So ist die verkleinerte Version
knappe 100 kb kleiner als die lesbare Variante. F&amp;#252;r Produktivszenarien sollte
demnach also in jedem Fall die &lt;strong&gt;.min&lt;/strong&gt; Version genutzt werden, wohingegen
w&amp;#228;hrend der Entwicklungszeit eher die lesbare Variante eingebunden werden sollte.
So kann man den Scriptcode im Fall der F&amp;#228;lle n&amp;#228;mlich noch debuggen.
&lt;/p&gt;
&lt;p&gt;
So, genug der Vorrede und zur&amp;#252;ck zur Praxis. Tats&amp;#228;chlich einbinden k&amp;#246;nnen
wir jQuery nun &amp;#252;ber folgende Zeile:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:fd54cf52-9c20-4284-8728-d8c32de15538" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;script src="Scripts/jquery-1.4.2.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Platzieren sollte man diese Zeile &amp;#252;brigens innerhalb des Kopfbereichs der Seite:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:67bf7f48-7248-498b-8fde-1d7de66e1b54" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %&amp;gt;
&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
&amp;lt;head runat="server"&amp;gt;
    &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
    &amp;lt;script src="Scripts/jquery-1.4.2.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4&gt;Prima, aber was mache ich nun damit?
&lt;/h4&gt;
&lt;p&gt;
Gute Frage! Jetzt haben wir jQuery zwar eingebunden, aber wie geht es jetzt weiter.
Dazu sollten wir zun&amp;#228;chst kurz einen Blick darauf werfen, was wir normalerweise
mit JavaScript machen. In den mei&amp;#223;ten F&amp;#228;llen reduziert sich dies auf:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Elemente aus dem DOM zu selektieren 
&lt;/li&gt;
&lt;li&gt;
Selektierte Elemente zu manipulieren (ein- / ausblenden, Styledefinitionen zu ver&amp;#228;ndern...) 
&lt;/li&gt;
&lt;li&gt;
Code bei bestimmten Ereignissen ausf&amp;#252;hren (z. B. click event) 
&lt;/li&gt;
&lt;li&gt;
Neue Elemente dem DOM hinzuzuf&amp;#252;gen 
&lt;/li&gt;
&lt;li&gt;
Elemente aus dem DOM zu l&amp;#246;schen 
&lt;/li&gt;
&lt;li&gt;
AJAX Aufrufe zum Server zu machen und die Antwort zu Verarbeiten 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Als kleinen Einstieg picken wir uns exemplarisch die ersten drei Punkte heraus. Wir
werden also DOM Elemente selektieren und diese manipulieren. Geschehen wird dies bei
dem Klick auf einen Button. 
&lt;/p&gt;
&lt;p&gt;
Dazu werden wir eine Meldungszeile, &amp;#228;hnlich wie man sie von Stackoverflow kennt
nachbauen.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/LebendigeASP.NETWebseitenmitjQuery_10249/01_so_message.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="50" alt="01_so_message" src="http://blog.codemurai.de/images/LebendigeASP.NETWebseitenmitjQuery_10249/01_so_message_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Der erste Schritt besteht in der Erstellung eines HTML und CSS Grundger&amp;#252;sts:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:e7391c73-ddaa-4dc8-95d0-82ca57f8e1a8" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %&amp;gt;

&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
&amp;lt;head runat="server"&amp;gt;
    &amp;lt;title&amp;gt;jQuery Demo&amp;lt;/title&amp;gt;

    &amp;lt;style type="text/css"&amp;gt;
        body
        {
            margin: 0px;
        }
        #message
        {
            background-color: #FFFF88;
            border-bottom: solid 1px #000000;
            font-weight: bold;
            text-align: center;
            padding: 8px;
            margin: 0px;
            display:none;
            font-family: Arial, Verdana, Sans-Serif;
        }
        #message a
        {
            float: right;
            border: solid 3px black;
            font-family: Arial, Verdana, Sans-Serif;
            font-weight: bold;
            text-decoration: none;
            color: Black;
        }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id="form1" runat="server"&amp;gt;
    &amp;lt;div id="message"&amp;gt;&amp;lt;span&amp;gt;Dummy Nachricht&amp;lt;/span&amp;gt;&amp;lt;a href="Default.aspx"&amp;gt;X&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div id="content"&amp;gt;
        &amp;lt;p&amp;gt;
            Dies ist eine jQuery Demowebsite&amp;lt;/p&amp;gt;
        &amp;lt;button id="showMessage"&amp;gt;
            Klick mich&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Wie man sieht, wird ein DIV Element&amp;#160; mit dem Namen &amp;quot;&lt;em&gt;message&lt;/em&gt;&amp;quot;
erstellt, dass als Unterlemente ein SPAN Element und einen Link enth&amp;#228;lt. &amp;#220;ber
CSS wird dieses DIV Element noch ein wenig gestyled und initial ausgeblendet. Au&amp;#223;erdem
ist auf der Seite noch ein Button definiert. Ein Klick auf diesen Button soll der
Ausl&amp;#246;ser sein, um die Meldung anzuzeigen.
&lt;/p&gt;
&lt;p&gt;
Wie aber genau sieht nun der Code aus, um die Nachricht - mit ver&amp;#228;ndertem Text
- anzuzeigen?
&lt;/p&gt;
&lt;p&gt;
Mit der Hilfe von jQuery ist dies garnicht so schwer:
&lt;/p&gt;
&lt;p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:aa05f6d1-1274-4e12-a697-a83bf6a1f0ea" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;$("#showMessage").click(function(evt) {
    evt.preventDefault();
    $("#message span").text("Du hast den Button geklickt. Klicke nun auf das X, um die Nachricht auszublenden.");
    $("#message").fadeIn(2000);
});&lt;/pre&gt;
&lt;/div&gt;
Auf den ersten Blick mag der Code etwas verwirrend aussehen. Vor allem durch die vielen
$-Zeichen. Daher ein paar erkl&amp;#228;rende Worte:&gt;
&lt;p&gt;
In Zeile 1 selektieren wir mit dem Befehl: &lt;em&gt;$(&amp;quot;#showMessage&amp;quot;)&lt;/em&gt; zun&amp;#228;chst
das DOM Element mit der ID showMessage, also unseren Button. Das $-Zeichen ist &amp;#252;brigens
ein Alias f&amp;#252;r die jQuery Funktion. Statt $(&amp;quot;message&amp;quot;) h&amp;#228;tte ich
also auch jQuery(&amp;quot;$message&amp;quot;) schreiben k&amp;#246;nnen. Die R&amp;#252;ckgabe des
Aufrufs - unabh&amp;#228;ngig ob via jQuery(...) oder $(...) ist ein Objekt vom Typ jQuery.
Dieses Objekt beinhaltet die selektieren DOM Elemente bzw. das selektierte DOM Element
sowie einige weitere Funktionen.
&lt;/p&gt;
&lt;p&gt;
In unserem Fall bekommen wir also ein Objekt vom Typ jQuery zur&amp;#252;ck, dass das
DOM Element &lt;em&gt;showMessage&lt;/em&gt; beinhaltet. F&amp;#252;r dieses DOM Element wird nun
eine anonyme Funktion als Handler f&amp;#252;r das Ereignis Click registriert.
&lt;/p&gt;
&lt;p&gt;
In Zeile 2 wird mit dem Befehl &lt;em&gt;evt.preventDefault();&lt;/em&gt; nun die Standardaktion
die der Browser bei diesem Ereignis, also z. B. das posten des Formulars nach Klick
auf den Button, verhindert.
&lt;/p&gt;
&lt;p&gt;
In Zeile 3 werden anschlie&amp;#223;end alle span Elemente innerhalb des DOM Elements
mit der Id message selektiert. In unserem Fall ist dies also genau eins. F&amp;#252;r
dieses span Element wird mit der Funktion &lt;em&gt;text&lt;/em&gt; jetzt ein neuer Text vergeben.
Au&amp;#223;erdem wird das Element mit der Id &lt;em&gt;message&lt;/em&gt; in Zeile 4 langsam (&amp;#252;ber
einen Zeitraum von zwei Sekunden) eingeblendet.
&lt;/p&gt;
&lt;p&gt;
Der Quellcode zum Ausblenden der Nachricht sieht &amp;#228;hnlich aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b47b458c-59e6-4c64-8f66-e11367f7fe31" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;$("#message a").click( function(evt) {
     evt.preventDefault();
     $("#message").fadeOut("slow");
 });&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
In Zeile 1 wird an alle A-Elemente innerhalb des DOM Elements mit der Id &lt;em&gt;message &lt;/em&gt;ein
Eventhandler f&amp;#252;r das Ereignis Click angehangen. Dieser verhindert in Zeile 2
die Standardaktion des Links und blendet in Zeile 3 unsere Nachrichtenzeile wieder
aus. Dieses mal wird statt einer Angabe in Millisekunden der String &amp;quot;slow&amp;quot;
als Argument &amp;#252;bergeben. Dieser ist in den jQuery Quellcodes mit einem Wert von
600 ms hinterlegt.
&lt;/p&gt;
&lt;h4&gt;Perfekt, aber wo schreibe ich den Code nun rein?
&lt;/h4&gt;
&lt;p&gt;
So, jetzt wo wir eigentlich den ganzen Quellcode fertig haben stellt sich nat&amp;#252;rlich
die Frage, wie wir ihn in unsere Seite einbinden. Eine naive Implementierung s&amp;#228;he
wie folgt aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:23b3a952-2853-4417-aadf-7b8609a9995e" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;&amp;lt;head&amp;gt;
&amp;lt;!-- ... --&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
    $("#showMessage").click(function(evt) {
        evt.preventDefault();
        $("#message span").text("Du hast den Button geklickt. Klicke nun auf das X, um die Nachricht auszublenden.");
        $("#message").fadeIn(2000);
    });
    $("#message a").click( function(evt) {
        evt.preventDefault();
        $("#message").fadeOut("slow");
    });
&amp;lt;/script&amp;gt;
&amp;lt;!-- ... --&amp;gt;
&amp;lt;/head&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Der Code w&amp;#252;rde also einfach in ein Scripttag innerhalb des Head Tags kopiert
werden. &lt;strong&gt;Dies l&amp;#228;uft so nicht&lt;/strong&gt;! Der Grund ist, dass mit diesem
Code versucht wird, ein Eventhandler an ein DOM Element zu binden, das es zu diesem
Zeitpunkt noch garnicht gibt.
&lt;/p&gt;
&lt;p&gt;
Wie sieht aber die L&amp;#246;sung f&amp;#252;r das Problem aus?
&lt;/p&gt;
&lt;h4&gt;Alles zu seiner Zeit
&lt;/h4&gt;
&lt;p&gt;
Wie wir zuvor gesehen haben, ist unser Code wirkungslos, wenn wir ihn ausf&amp;#252;hren
ehe es ein entsprechendes DOM Element gibt. Daher sollten wir ihn erst ausl&amp;#246;sen,
sobald das DOM vollst&amp;#228;ndig initialisiert ist.
&lt;/p&gt;
&lt;p&gt;
Ein weg dies zu erreichen w&amp;#228;re es, den Code aufzurufen wenn das Ereignis &lt;em&gt;window.onload&lt;/em&gt; eintritt:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:c9e7a5e3-3a80-4f97-bb46-1ed999da3e0e" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;window.onload = function() {
  $("#showMessage").click(function(evt) {
     evt.preventDefault();
     // Restlicher Code hier
  });
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Diese Variante w&amp;#252;rde bereits fehlerfrei funktionieren. Allerdings wird das Ereignis
onload erst ausgel&amp;#246;st, wenn das DOM vollst&amp;#228;ndig initialisiert wurde &lt;strong&gt;und&lt;/strong&gt; alle
externen Ressourcen, wie zum Beispiel Bilder oder Stylesheets geladen wurden. Dies
kann von Fall zu Fall recht lange dauern, so dass der Anwender den Button bereits
anklicken k&amp;#246;nnte, ohne dass unser Script ausgef&amp;#252;hrt wird. Zum Gl&amp;#252;ck
bietet jQuery einen besseren Ansatz, n&amp;#228;mlich &lt;em&gt;$(document).ready&lt;/em&gt;. In dieser
Variante wird das Ereignis ready ausgel&amp;#246;st, sobald das DOM vollst&amp;#228;ndig initialisiert
wurde, aber &lt;strong&gt;bevor&lt;/strong&gt; externe Ressourcen geladen wurden.
&lt;/p&gt;
&lt;p&gt;
Das vollst&amp;#228;ndige Beispiel mit $(document).ready sieht dann wie folgt aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4e437cd3-4422-4027-bf2d-6573920a764c" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %&amp;gt;

&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
&amp;lt;head runat="server"&amp;gt;
    &amp;lt;title&amp;gt;jQuery Demo&amp;lt;/title&amp;gt;

    &amp;lt;script src="Scripts/jquery-1.4.1.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;

    &amp;lt;style type="text/css"&amp;gt;
        body
        {
            margin: 0px;
        }
        #message
        {
            background-color: #FFFF88;
            border-bottom: solid 1px #000000;
            font-weight: bold;
            text-align: center;
            padding: 8px;
            margin: 0px;
            display:none;
            font-family: Arial, Verdana, Sans-Serif;
        }
        #message a
        {
            float: right;
            border: solid 3px black;
            font-family: Arial, Verdana, Sans-Serif;
            font-weight: bold;
            text-decoration: none;
            color: Black;
        }
    &amp;lt;/style&amp;gt;

    &amp;lt;script type="text/javascript"&amp;gt;
        $(document).ready(function() {
            $("#showMessage").click(function(evt) {
                evt.preventDefault();
                $("#message span").text("Du hast den Button geklickt. Klicke nun auf das X, um die Nachricht auszublenden.");
                $("#message").fadeIn(2000);
            });
            $("#message a").click(function(evt) {
                evt.preventDefault();
                $("#message").fadeOut("slow");
            }
        }
      });
    &amp;lt;/script&amp;gt;

&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id="form1" runat="server"&amp;gt;
    &amp;lt;div id="message"&amp;gt;&amp;lt;span&amp;gt;Dummy Nachricht&amp;lt;/span&amp;gt;&amp;lt;a href="Default.aspx"&amp;gt;X&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div id="content"&amp;gt;
        &amp;lt;p&amp;gt;
            Dies ist eine jQuery Demowebsite&amp;lt;/p&amp;gt;
        &amp;lt;button id="showMessage"&amp;gt;
            Klick mich&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4&gt;Ausblick und Fazit
&lt;/h4&gt;
&lt;p&gt;
Wie dieser Blog Eintrag gezeigt hat, ist jQuery eine recht komfortabel zu bediene
JavaScript Library, mit der sich mit wenigen Zeilen Script Code interessante Effekte
erzielen lassen. Neben der intuitiven und Browser unabh&amp;#228;ngigen API besticht die
Bibliothek vor allem durch die F&amp;#252;lle an Funktionen und erh&amp;#228;ltlichen Plug-Ins.
Selbstverst&amp;#228;ndlich konnte ich hier nur einen kurzen (ersten) Einblick verschaffen.
Da ich das Thema Clientseitige Entwicklung in (ASP.NET) Webanwendungen jedoch f&amp;#252;r
sehr interessant halte, habe ich vor in der n&amp;#228;chsten Zeit weitere Eintr&amp;#228;ge
zum Thema jQuery mit folgenden Schwerpunkten zu schreiben:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Nutzen von Content Delivery Networks (CDNs)&lt;/li&gt;
&lt;li&gt;
jQuery Selektoren&lt;/li&gt;
&lt;li&gt;
M&amp;#246;glichkeiten der DOM Manipulation&lt;/li&gt;
&lt;li&gt;
jQuery und Firebug&lt;/li&gt;
&lt;li&gt;
jQuery Plugins selber entwickeln&lt;/li&gt;
&lt;li&gt;
jQuery UI&lt;/li&gt;
&lt;li&gt;
jQuery Utility Funktionen&lt;/li&gt;
&lt;li&gt;
jQuery und Ajax f&amp;#252;r Webforms und ASP.NET MVC&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Eventuell werde ich im Anschluss an die Artikel auch kurze Video Tutorials bereitstellen.
&lt;/p&gt;
&lt;p&gt;
Bevor ich allerdings loslege w&amp;#252;rde mich nat&amp;#252;rlich interessieren, ob das
Thema f&amp;#252;r euch &amp;#252;berhaupt von Interesse ist. Am liebsten in Form eines kurzen
Kommentars.
&lt;/p&gt;
&lt;p&gt;
Sollte jemand von euch &amp;#252;brigens das Verlangen haben, das Thema jQuery, oder auch
generell ASP.NET mit mir pers&amp;#246;nlich in lockerer Atmosph&amp;#228;re zu diskutieren:
Am 28. Mai werde ich einen &lt;strong&gt;Einsteigervortrag&lt;/strong&gt; zu jQuery auf der &lt;a title="Homepage der dotnet Cologne 2010" href="http://dotnet-cologne.de/" target="_blank"&gt;dotnet
Cologne 2010&lt;/a&gt; halten. &amp;#220;ber zahlreiche Besucher des Vortrags und nat&amp;#252;rlich
auch spannende Diskussionen danach w&amp;#252;rde ich mich sehr freuen.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://www.dotnet-cologne.de/public/Upload/Werbung/dc2010_Sprecher_180x80.png" /&gt; 
&lt;/p&gt;
&lt;p&gt;
In den Pausen findet man ihr mich &amp;#252;brigens wahrscheinlich im Ausstellerbereich
am Stand der Firma &lt;a title="Homepage der Firma Infragistics" href="http://www.infragistics.com" target="_blank"&gt;Infragistics&lt;/a&gt;.
Dort w&amp;#228;re ich dann zus&amp;#228;tzlich auch f&amp;#252;r den ein oder anderen Plausch
&amp;#252;ber die &lt;a href="http://www.infragistics.com/dotnet/netadvantage.aspx" target="_blank"&gt;Infragistics
NetAdvantage&lt;/a&gt; Komponenten zu haben.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;War dieser Artikel hilfreich f&amp;#252;r dich? Dann kicke ihn doch bitte bei dotnet-kicks.de!&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=dfbe0604-ff45-4a2a-899f-5bd37db4310a" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,dfbe0604-ff45-4a2a-899f-5bd37db4310a.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>Community</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>jQuery</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=fff85777-809d-498a-99bd-ebec22e8836a</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,fff85777-809d-498a-99bd-ebec22e8836a.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,fff85777-809d-498a-99bd-ebec22e8836a.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=fff85777-809d-498a-99bd-ebec22e8836a</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Startet man eine ASP.NET Anwendung zum ersten Mal, kommt man nicht gerade in einen
Geschwindigkeitsrausch. Dies liegt zum Beispiel daran, dass der IIS den ASP.NET Worker
Prozess hochfahren muss. Außerdem läuft eventuell im Ereignis Application_Start
hinterlegter Initialisierungscode und schließlich müssen die vorliegenden
Assemblies noch durch den JITer in nativen Code überführt werden.
</p>
        <p>
All dies führt dazu, dass man relativ selten so etwas wie "rasend schnell"
hört, wenn vom ersten Zugriff auf eine ASP.NET Anwendung gesprochen wird.
</p>
        <p>
Glücklicherweise ist all dies nach dem ersten Request einer Seite kein Problem
mehr. Der Worker Prozess ist da, der Initialisierungscode lief und die Just In Time
Compilation lief auch.
</p>
        <p>
Zu einem Problem wird die Situation jedoch, wenn man seine ASP.NET Anwendung während
der Entwicklung als ein Bestandteil des Nightly Builds automatisch deployed und auch
seinem Kunden Zugriff auf diesen täglich frischen Applikationsstand gibt.
</p>
        <p>
Da Kunden morgens nämlich meist früher als Entwickler im Büro sind,
sind sie auch die ersten, die die Webanwendung öffnen, um zu sehen, was am Vortrag
umgesetzt wurde. Ist dieser erste Zugriff nun aus den oben genannten Gründen
langsam, ist negatives Feedback des Kundens zur Applikationsperformance - oder sogar
noch schlimmer: im Stillen sinkendes vertrauen in Applikation und Entwickler nicht
selten die Folge.
</p>
        <p>
Um dieses Problem zu umgehen, habe ich ein kleines Powershell Script geschrieben,
das nach Angabe einer URL die einzelnen Seiten einer Webapplikation ansurft.  
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:13a155dd-e9ed-40c8-bb17-f188662f62ca" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">function warmup-site( [string] $rootUrl){
	
	$proxy = New-Object System.Net.WebProxy("mein.firmen.proxy:8080")
	$proxy.UseDefaultCredentials = 1
	
	$wc = New-Object System.Net.WebClient
	$wc.Proxy = $proxy
	
	$pages = @("default.aspx", "seite1.aspx", "seite2.aspx", "subfolder/seite3.aspx")

	# Jede Seite 3 Mal ansurfen, um Sie "warmzuklicken"
	for ($i=0; $i -lt 3; $i++){
		foreach($page in $pages){
			trap [System.Net.WebException] {
			  write-error $("TRAPPED: " + $_.Exception.ToString());
			  continue;
		   	}
			$content = $wc.DownloadString($rootUrl+$page)
			write $("URL " + $rootUrl+$page + " angesurft");
		}
	}

}

warmup-site("http://meine.url/")</pre>
        </div>
        <p>
Bisher gebe ich die einzelnen Seiten die angefragt werden sollen noch manuell innerhalb
des Arrays $pages an. Im nächsten Schritt würde ich jedoch lieber nur noch
die URL der Sitemap angeben, diese auslesen und dann sämtliche in der Sitemap
aufgeführten URLs anfragen. Da ich jedoch noch Powershell Neuling bin, könnte
es noch ein wenig dauern, bis ich die Lösung so weit automatisiert habe. Sollte
einer der Leser nun sagen: "Das ist doch ein Dreizeiler, den ich in der Kaffeepause
aus dem Ärmel schütteln könnte", dann würde ich darum bitten
genau diesen Dreizeiler über die Kommentarfunktion meines Blogs hier einzustellen
;-)
</p>
        <h4>
        </h4>
        <h4>Was bringts?
</h4>
        <p>
Die Anwendung startet beim ersten Request nun bedeutend schneller. Somit ist der Kunde
beruhigt und wir können uns auf die wichtigen Sachen des Projekts konzentrieren
;-)
</p>
        <p>
Habe übrigens gesehen, dass es ab dem IIS 7 (oder 7.5?) von Hause aus eine Warmup
gibt. Hat jemand von euch Erfahrung damit? Im Moment ist es für mich zwar noch
nicht akut, da wir den IIS 6 nutzen, wäre aber Interessant für die Zukunft
ein paar Erfahrungsberichte zur Hand zu haben.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=fff85777-809d-498a-99bd-ebec22e8836a" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>ASP.NET Anwendungen mit der Powershell warmklicken</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,fff85777-809d-498a-99bd-ebec22e8836a.aspx</guid>
      <link>http://blog.codemurai.de/2010/04/13/ASPNETAnwendungenMitDerPowershellWarmklicken.aspx</link>
      <pubDate>Tue, 13 Apr 2010 07:05:44 GMT</pubDate>
      <description>&lt;p&gt;
Startet man eine ASP.NET Anwendung zum ersten Mal, kommt man nicht gerade in einen
Geschwindigkeitsrausch. Dies liegt zum Beispiel daran, dass der IIS den ASP.NET Worker
Prozess hochfahren muss. Au&amp;#223;erdem l&amp;#228;uft eventuell im Ereignis Application_Start
hinterlegter Initialisierungscode und schlie&amp;#223;lich m&amp;#252;ssen die vorliegenden
Assemblies noch durch den JITer in nativen Code &amp;#252;berf&amp;#252;hrt werden.
&lt;/p&gt;
&lt;p&gt;
All dies f&amp;#252;hrt dazu, dass man relativ selten so etwas wie &amp;quot;rasend schnell&amp;quot;
h&amp;#246;rt, wenn vom ersten Zugriff auf eine ASP.NET Anwendung gesprochen wird.
&lt;/p&gt;
&lt;p&gt;
Gl&amp;#252;cklicherweise ist all dies nach dem ersten Request einer Seite kein Problem
mehr. Der Worker Prozess ist da, der Initialisierungscode lief und die Just In Time
Compilation lief auch.
&lt;/p&gt;
&lt;p&gt;
Zu einem Problem wird die Situation jedoch, wenn man seine ASP.NET Anwendung w&amp;#228;hrend
der Entwicklung als ein Bestandteil des Nightly Builds automatisch deployed und auch
seinem Kunden Zugriff auf diesen t&amp;#228;glich frischen Applikationsstand gibt.
&lt;/p&gt;
&lt;p&gt;
Da Kunden morgens n&amp;#228;mlich meist fr&amp;#252;her als Entwickler im B&amp;#252;ro sind,
sind sie auch die ersten, die die Webanwendung &amp;#246;ffnen, um zu sehen, was am Vortrag
umgesetzt wurde. Ist dieser erste Zugriff nun aus den oben genannten Gr&amp;#252;nden
langsam, ist negatives Feedback des Kundens zur Applikationsperformance - oder sogar
noch schlimmer: im Stillen sinkendes vertrauen in Applikation und Entwickler nicht
selten die Folge.
&lt;/p&gt;
&lt;p&gt;
Um dieses Problem zu umgehen, habe ich ein kleines Powershell Script geschrieben,
das nach Angabe einer URL die einzelnen Seiten einer Webapplikation ansurft.&amp;#160; 
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:13a155dd-e9ed-40c8-bb17-f188662f62ca" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;function warmup-site( [string] $rootUrl){
	
	$proxy = New-Object System.Net.WebProxy("mein.firmen.proxy:8080")
	$proxy.UseDefaultCredentials = 1
	
	$wc = New-Object System.Net.WebClient
	$wc.Proxy = $proxy
	
	$pages = @("default.aspx", "seite1.aspx", "seite2.aspx", "subfolder/seite3.aspx")

	# Jede Seite 3 Mal ansurfen, um Sie "warmzuklicken"
	for ($i=0; $i -lt 3; $i++){
		foreach($page in $pages){
			trap [System.Net.WebException] {
			  write-error $("TRAPPED: " + $_.Exception.ToString());
			  continue;
		   	}
			$content = $wc.DownloadString($rootUrl+$page)
			write $("URL " + $rootUrl+$page + " angesurft");
		}
	}

}

warmup-site("http://meine.url/")&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Bisher gebe ich die einzelnen Seiten die angefragt werden sollen noch manuell innerhalb
des Arrays $pages an. Im n&amp;#228;chsten Schritt w&amp;#252;rde ich jedoch lieber nur noch
die URL der Sitemap angeben, diese auslesen und dann s&amp;#228;mtliche in der Sitemap
aufgef&amp;#252;hrten URLs anfragen. Da ich jedoch noch Powershell Neuling bin, k&amp;#246;nnte
es noch ein wenig dauern, bis ich die L&amp;#246;sung so weit automatisiert habe. Sollte
einer der Leser nun sagen: &amp;quot;Das ist doch ein Dreizeiler, den ich in der Kaffeepause
aus dem &amp;#196;rmel sch&amp;#252;tteln k&amp;#246;nnte&amp;quot;, dann w&amp;#252;rde ich darum bitten
genau diesen Dreizeiler &amp;#252;ber die Kommentarfunktion meines Blogs hier einzustellen
;-)
&lt;/p&gt;
&lt;h4&gt;
&lt;/h4&gt;
&lt;h4&gt;Was bringts?
&lt;/h4&gt;
&lt;p&gt;
Die Anwendung startet beim ersten Request nun bedeutend schneller. Somit ist der Kunde
beruhigt und wir k&amp;#246;nnen uns auf die wichtigen Sachen des Projekts konzentrieren
;-)
&lt;/p&gt;
&lt;p&gt;
Habe &amp;#252;brigens gesehen, dass es ab dem IIS 7 (oder 7.5?) von Hause aus eine Warmup
gibt. Hat jemand von euch Erfahrung damit? Im Moment ist es f&amp;#252;r mich zwar noch
nicht akut, da wir den IIS 6 nutzen, w&amp;#228;re aber Interessant f&amp;#252;r die Zukunft
ein paar Erfahrungsberichte zur Hand zu haben.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=fff85777-809d-498a-99bd-ebec22e8836a" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,fff85777-809d-498a-99bd-ebec22e8836a.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=7ae782d9-ff80-4204-ba22-90cd086cc45f</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,7ae782d9-ff80-4204-ba22-90cd086cc45f.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,7ae782d9-ff80-4204-ba22-90cd086cc45f.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=7ae782d9-ff80-4204-ba22-90cd086cc45f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Vor einiger Zeit habe ich ein kleines <a href="http://blog.codemurai.de/2009/09/04/WinDbgTutorialFehlerursachenFindenTeil1EinerSerie.aspx" target="_blank">Einsteigertutorial
zum Umgang mit WinDbg</a> geschrieben. Etwas später folgte dann auch ein <a href="http://blog.codemurai.de/2010/03/19/WinDbgVideotutorial.aspx" target="_blank">kurzes
Video</a> hierzu.
</p>
        <p>
Sowohl im Tutorial als auch im Video war eine Windows Forms Anwendung das Ziel meiner
Debuggingaktivitäten. In einem kurzen Nebensatz erwähnte ich, dass die Zielanwendung
bei der gezeigten Vorgehensweise, nämlich dem direkten Anhängen an den Prozess
der Wahl, zumindest zeitweise blockiert wird. 
</p>
        <p>
In einer Windows Forms Anwendung mag dies kein Problem sein, schließlich bin
ich ja alleine auf dem System. Unschön wird es jedoch, wenn man Probleme in einer
produktiven ASP.NET Anwendung sucht. Verständlicherweise reagieren hier nämlich
die wenigsten Anwender erfreut, wenn die Website steht weil gerade jemand im Hintergrund
daran herumfummelt. Außerdem ist es je nach IT Richtlinie auch problematisch
den lokalen Administrator des Kundens davon zu überzeugen, dass man mal gerade
physikalisch oder auch nur per Remote Desktop an seinen Webserver will.
</p>
        <h4>Und nun?
</h4>
        <p>
Abhilfe schafft hier die VBScript Datei adplus.vbs innerhalb des WinDbg Verzeichnisses.
Sie ermöglicht es, ein aktuelles Speicherabbild des problematischen Prozesses
in Form einer *.DMP Datei zu erstellen. Diese kann wiederum in WinDbg geöffnet
und analysiert werden.
</p>
        <p>
Adplus kann in zwei verschiedenen Modi genutzt werden: <strong>hang</strong> und <strong>crash</strong>.
</p>
        <p>
Im hang Modus wird einmalig ein aktueller Memory Dump des Prozesses zum Zeitpunkt
der Ausführung des Scripts gezogen. Dieser Modus eignet sich besonders wenn die
Applikation "hängt" ;-), also in Deadlock Szenarien, oder aber auch
um Memory Leaks zu finden. Zur besseren Analyse sollten im Fall ein Memory Leaks jedoch
mehrere Dumps bei verschieden hoher Speicherauslastung gezogen werden.
</p>
        <p>
Der Befehl zum Erzeugen eines Dumps im hang Modus lautet übrigens:
</p>
        <p>
          <font face="Courier New">adplus.vbs -hang -p <em>processId</em></font>
        </p>
        <p>
Die Id des Prozesses kann entweder über den Taskmanager, oder aber im Fall einer
ASP.NET Anwendung die in einem IIS 6 gehostet wird, über den Befehl IISAPP gefunden
werden.
</p>
        <p>
Alternativ zum Parameter <strong>-p</strong> kann über den Parameter <strong>-pn </strong>auch
ein Prozessname angegeben werden. Im Fall einer ASP.NET Anwendung wäre dies also
W3WP.exe (Windows Server mit IIS) bzw. WebDev.WebServer.exe im Falle des lokalen Entwicklungsservers.
Außerdem kann über den optionalen Parameter <strong>-o</strong> auch ein
dediziertes Ausgabeverzeichnis angegeben werden. Standardmäßig wird nämlich
sonst ein Unterverzeichnis, unterhalb des Ordners aus dem adplus heraus aufgerufen
wurde, angelegt.
</p>
        <p>
Innerhalb des Zielverzeichnisses wird nun eine Datei mit der Endung .DMP angelegt.
Diese kann in WinDbg über den Menüpunkt <em>File -&gt; Open Crash Dump</em> ...
geöffnet und mit den bereits <a href="http://blog.codemurai.de/2009/09/04/WinDbgTutorialFehlerursachenFindenTeil1EinerSerie.aspx" target="_blank">bekannten
Befehlen</a> analysiert werden.
</p>
        <p>
Der zweite Modus neben <strong>hang</strong> ist der Modus <strong>crash</strong>.
</p>
        <p>
Der Aufruf erfolgt hier ähnlich zum hand Modus, mit dem einzigen Unterschied,
dass statt <strong>-hang</strong><strong>-crash</strong> übergeben wird.
</p>
        <p>
          <font face="Courier New">adplus.vbs -crash -p <em>processId</em></font>
        </p>
        <p>
Im Crash Modus bleibt der Debugger so lange am entsprechenden Prozess angehangen,
bis dieser unfreiwillig beendet wird. Tritt dieser Fall ein, wird ein Dump auf die
Festplatte geschrieben. Außerdem werden Dumps geschrieben, wenn ein zuvor definierter
Breakpoint erreicht wird, oder aber eine access violation Exception auftritt.
</p>
        <h4>Fazit
</h4>
        <p>
Mit adplus liegt ein leichtgewichtiges Skript zur Hand, dass bei der Problemanalyse
innerhalb produktiver Umgebungen enorm helfen kann. Gerade in Umgebungen, in denen
das Live-System nicht durch Debugging blockiert werden darf, oder aber der Administrator
keinen Zugriff auf das System gewährt, kann das Skript seine stärken Ausspielen.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=7ae782d9-ff80-4204-ba22-90cd086cc45f" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Wie ziehe ich mir eigentlich einen Memory Dump meiner Anwendung</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,7ae782d9-ff80-4204-ba22-90cd086cc45f.aspx</guid>
      <link>http://blog.codemurai.de/2010/04/12/WieZieheIchMirEigentlichEinenMemoryDumpMeinerAnwendung.aspx</link>
      <pubDate>Mon, 12 Apr 2010 20:07:04 GMT</pubDate>
      <description>&lt;p&gt;
Vor einiger Zeit habe ich ein kleines &lt;a href="http://blog.codemurai.de/2009/09/04/WinDbgTutorialFehlerursachenFindenTeil1EinerSerie.aspx" target="_blank"&gt;Einsteigertutorial
zum Umgang mit WinDbg&lt;/a&gt; geschrieben. Etwas sp&amp;#228;ter folgte dann auch ein &lt;a href="http://blog.codemurai.de/2010/03/19/WinDbgVideotutorial.aspx" target="_blank"&gt;kurzes
Video&lt;/a&gt; hierzu.
&lt;/p&gt;
&lt;p&gt;
Sowohl im Tutorial als auch im Video war eine Windows Forms Anwendung das Ziel meiner
Debuggingaktivit&amp;#228;ten. In einem kurzen Nebensatz erw&amp;#228;hnte ich, dass die Zielanwendung
bei der gezeigten Vorgehensweise, n&amp;#228;mlich dem direkten Anh&amp;#228;ngen an den Prozess
der Wahl, zumindest zeitweise blockiert wird. 
&lt;/p&gt;
&lt;p&gt;
In einer Windows Forms Anwendung mag dies kein Problem sein, schlie&amp;#223;lich bin
ich ja alleine auf dem System. Unsch&amp;#246;n wird es jedoch, wenn man Probleme in einer
produktiven ASP.NET Anwendung sucht. Verst&amp;#228;ndlicherweise reagieren hier n&amp;#228;mlich
die wenigsten Anwender erfreut, wenn die Website steht weil gerade jemand im Hintergrund
daran herumfummelt. Au&amp;#223;erdem ist es je nach IT Richtlinie auch problematisch
den lokalen Administrator des Kundens davon zu &amp;#252;berzeugen, dass man mal gerade
physikalisch oder auch nur per Remote Desktop an seinen Webserver will.
&lt;/p&gt;
&lt;h4&gt;Und nun?
&lt;/h4&gt;
&lt;p&gt;
Abhilfe schafft hier die VBScript Datei adplus.vbs innerhalb des WinDbg Verzeichnisses.
Sie erm&amp;#246;glicht es, ein aktuelles Speicherabbild des problematischen Prozesses
in Form einer *.DMP Datei zu erstellen. Diese kann wiederum in WinDbg ge&amp;#246;ffnet
und analysiert werden.
&lt;/p&gt;
&lt;p&gt;
Adplus kann in zwei verschiedenen Modi genutzt werden: &lt;strong&gt;hang&lt;/strong&gt; und &lt;strong&gt;crash&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
Im hang Modus wird einmalig ein aktueller Memory Dump des Prozesses zum Zeitpunkt
der Ausf&amp;#252;hrung des Scripts gezogen. Dieser Modus eignet sich besonders wenn die
Applikation &amp;quot;h&amp;#228;ngt&amp;quot; ;-), also in Deadlock Szenarien, oder aber auch
um Memory Leaks zu finden. Zur besseren Analyse sollten im Fall ein Memory Leaks jedoch
mehrere Dumps bei verschieden hoher Speicherauslastung gezogen werden.
&lt;/p&gt;
&lt;p&gt;
Der Befehl zum Erzeugen eines Dumps im hang Modus lautet &amp;#252;brigens:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;adplus.vbs -hang -p &lt;em&gt;processId&lt;/em&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Die Id des Prozesses kann entweder &amp;#252;ber den Taskmanager, oder aber im Fall einer
ASP.NET Anwendung die in einem IIS 6 gehostet wird, &amp;#252;ber den Befehl IISAPP gefunden
werden.
&lt;/p&gt;
&lt;p&gt;
Alternativ zum Parameter &lt;strong&gt;-p&lt;/strong&gt; kann &amp;#252;ber den Parameter &lt;strong&gt;-pn &lt;/strong&gt;auch
ein Prozessname angegeben werden. Im Fall einer ASP.NET Anwendung w&amp;#228;re dies also
W3WP.exe (Windows Server mit IIS) bzw. WebDev.WebServer.exe im Falle des lokalen Entwicklungsservers.
Au&amp;#223;erdem kann &amp;#252;ber den optionalen Parameter &lt;strong&gt;-o&lt;/strong&gt; auch ein
dediziertes Ausgabeverzeichnis angegeben werden. Standardm&amp;#228;&amp;#223;ig wird n&amp;#228;mlich
sonst ein Unterverzeichnis, unterhalb des Ordners aus dem adplus heraus aufgerufen
wurde, angelegt.
&lt;/p&gt;
&lt;p&gt;
Innerhalb des Zielverzeichnisses wird nun eine Datei mit der Endung .DMP angelegt.
Diese kann in WinDbg &amp;#252;ber den Men&amp;#252;punkt &lt;em&gt;File -&amp;gt; Open Crash Dump&lt;/em&gt; ...
ge&amp;#246;ffnet und mit den bereits &lt;a href="http://blog.codemurai.de/2009/09/04/WinDbgTutorialFehlerursachenFindenTeil1EinerSerie.aspx" target="_blank"&gt;bekannten
Befehlen&lt;/a&gt; analysiert werden.
&lt;/p&gt;
&lt;p&gt;
Der zweite Modus neben &lt;strong&gt;hang&lt;/strong&gt; ist der Modus &lt;strong&gt;crash&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
Der Aufruf erfolgt hier &amp;#228;hnlich zum hand Modus, mit dem einzigen Unterschied,
dass statt &lt;strong&gt;-hang&lt;/strong&gt; &lt;strong&gt;-crash&lt;/strong&gt; &amp;#252;bergeben wird.
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;adplus.vbs -crash -p &lt;em&gt;processId&lt;/em&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Im Crash Modus bleibt der Debugger so lange am entsprechenden Prozess angehangen,
bis dieser unfreiwillig beendet wird. Tritt dieser Fall ein, wird ein Dump auf die
Festplatte geschrieben. Au&amp;#223;erdem werden Dumps geschrieben, wenn ein zuvor definierter
Breakpoint erreicht wird, oder aber eine access violation Exception auftritt.
&lt;/p&gt;
&lt;h4&gt;Fazit
&lt;/h4&gt;
&lt;p&gt;
Mit adplus liegt ein leichtgewichtiges Skript zur Hand, dass bei der Problemanalyse
innerhalb produktiver Umgebungen enorm helfen kann. Gerade in Umgebungen, in denen
das Live-System nicht durch Debugging blockiert werden darf, oder aber der Administrator
keinen Zugriff auf das System gew&amp;#228;hrt, kann das Skript seine st&amp;#228;rken Ausspielen.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=7ae782d9-ff80-4204-ba22-90cd086cc45f" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,7ae782d9-ff80-4204-ba22-90cd086cc45f.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>WinDbg</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=d0c039a5-107f-4175-a6f0-1d7da007c6c3</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,d0c039a5-107f-4175-a6f0-1d7da007c6c3.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,d0c039a5-107f-4175-a6f0-1d7da007c6c3.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=d0c039a5-107f-4175-a6f0-1d7da007c6c3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One of the many benifits as an <a title="Annoncing the infragistics MVP program" href="http://blogs.infragistics.com/blogs/tony_lombardo/archive/2009/03/31/announcing-the-infragistics-mvp-program.aspx" target="_blank">Infragistics
MVP</a> is that you get quite early involved in product development in order to give
feedback.
</p>
        <p>
This could either be feedback on a new feature, an API change, or a brand new product!
</p>
        <p>
Last spring it was time to give feedback again. There was an email on the Infragistics
NDA mailing list which announced that work on a new product - <a href="http://www.infragistics.com/whats-hot/default.aspx" target="_blank">Infragistics
NetAdvantage for Powershell</a> - had been started. Being an absolute Powershell fan,
I felt really excited to offer my help with alpha and beta testing, giving feedback,
etc.
</p>
        <p>
After some great discussions between the director of product management <a href="http://blogs.infragistics.com/blogs/jason_berres/default.aspx" target="_blank">Joseph
Berres</a>, lead developer <a href="http://blogs.infragistics.com/blogs/ambrose_little/default.aspx" target="_blank">Ambrose
J. Tall</a> and some Infragistis MVPs, the team managed to finish a first proof of
concept prototype in early September. Some weeks later I met <a href="http://blogs.infragistics.com/blogs/ux/default.aspx" target="_blank">Dr.
Tony Komischke</a>, Director of User Experience at Infragistics, at the Basta conference
in Germany. There he gave me a first demo of the product. At this point he was able
to show me an early Version of the powershell grid: Infragistics NetAdvantage for
Powershell <strong>powerGrid</strong>. I would have loved to see the charting component <em><strong>powerChart</strong>,</em> too.
Unfortunately it hadn't been ready for presentation at that time.
</p>
        <p>
To my question how the idea for a whole powershell suite had been born, Tony Komischke
gave me a quite interesting answer:
</p>
        <blockquote>
          <p>
It was actually one of our internal IT guys who had the idea. During a meeting he
complained that lately more and more server products came to market without an usable
admin UI. Instead he had to struggle with some colourless command line tools. 
</p>
        </blockquote>
        <blockquote>
          <p>
This situation started the whole thing. We all thought that Windows administrators
love decent UIs and don't want to work with a boring command line. If they liked the
command line, they would have become Linux administrators!
</p>
          <p>
And that's the point of Infragistics NetAdvantage for Powershell. With this product,
we give administrators back what they deserve!
</p>
        </blockquote>
        <p>
Since Basta conference some time went by. The product has nearly arrived at its final
state. Starting with tomorrow, registered users will be able to download at CTP Version
of it in the download area of Infrastics' homepage.
</p>
        <p>
The first webinars on NetAdvantage for Powershell will be made available approximately
next week by Infragistics new media evangelist <a href="http://blogs.infragistics.com/blogs/craig_shoemaker/default.aspx" target="_blank">Jeff
Shoemaker</a>.
</p>
        <p>
During the quaterly Infragistics MVP call, Mr Beres stated: 
</p>
        <p>
"We really wanted to show off our high end visualizations in a DOS window"
said Beres.  "PowerShell gave us a great opportunity to mix data analytics
with the new features in the Command Window, like colorization" he continued.
</p>
        <p>
As an Infragistics MVP I already enjoyed testing the product. Below you're going to
find some impressions:
</p>
        <h6>The powershell standard output
</h6>
        <p>
          <a href="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/01_original.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="01_original" src="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/01_original_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h6>Output as PowerGrid. Notice the usage of the <a href="http://quince.infragistics.com/#/ByMap$tab=1&amp;tag=Grid/ViewPattern$pattern=Sortable+Table" target="_blank">sortable
table pattern</a> as well as table and column borders.
</h6>
        <p>
          <a href="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/02_powerGrid.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="87" alt="02_powerGrid" src="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/02_powerGrid_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
The <a href="http://quince.infragistics.com/#/Search$text=round/ViewPattern$pattern=Corner+Treatments" target="_blank">corner
treatements pattern</a> which includes curves in all rectangle corners didn't make
it into the CTP as there were some performance issues with GDI+ and the gpu's hardware
acceleration.
</p>
        <h6>Output as PowerChart. I've chosen a bar chart as output type
</h6>
        <p>
          <a href="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/03_powerChart.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="03_powerChart" src="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/03_powerChart_thumb.png" width="244" border="0" />
          </a>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=d0c039a5-107f-4175-a6f0-1d7da007c6c3" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Infragistics announces NetAdvantage for Powershell</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,d0c039a5-107f-4175-a6f0-1d7da007c6c3.aspx</guid>
      <link>http://blog.codemurai.de/2010/04/01/InfragisticsAnnouncesNetAdvantageForPowershell.aspx</link>
      <pubDate>Thu, 01 Apr 2010 05:19:21 GMT</pubDate>
      <description>&lt;p&gt;
One of the many benifits as an &lt;a title="Annoncing the infragistics MVP program" href="http://blogs.infragistics.com/blogs/tony_lombardo/archive/2009/03/31/announcing-the-infragistics-mvp-program.aspx" target="_blank"&gt;Infragistics
MVP&lt;/a&gt; is that you get quite early involved in product development in order to give
feedback.
&lt;/p&gt;
&lt;p&gt;
This could either be feedback on a new feature, an API change, or a brand new product!
&lt;/p&gt;
&lt;p&gt;
Last spring it was time to give feedback again. There was an email on the Infragistics
NDA mailing list which announced that work on a new product - &lt;a href="http://www.infragistics.com/whats-hot/default.aspx" target="_blank"&gt;Infragistics
NetAdvantage for Powershell&lt;/a&gt; - had been started. Being an absolute Powershell fan,
I felt really excited to offer my help with alpha and beta testing, giving feedback,
etc.
&lt;/p&gt;
&lt;p&gt;
After some great discussions between the director of product management &lt;a href="http://blogs.infragistics.com/blogs/jason_berres/default.aspx" target="_blank"&gt;Joseph
Berres&lt;/a&gt;, lead developer &lt;a href="http://blogs.infragistics.com/blogs/ambrose_little/default.aspx" target="_blank"&gt;Ambrose
J. Tall&lt;/a&gt; and some Infragistis MVPs, the team managed to finish a first proof of
concept prototype in early September. Some weeks later I met &lt;a href="http://blogs.infragistics.com/blogs/ux/default.aspx" target="_blank"&gt;Dr.
Tony Komischke&lt;/a&gt;, Director of User Experience at Infragistics, at the Basta conference
in Germany. There he gave me a first demo of the product. At this point he was able
to show me an early Version of the powershell grid: Infragistics NetAdvantage for
Powershell &lt;strong&gt;powerGrid&lt;/strong&gt;. I would have loved to see the charting component &lt;em&gt;&lt;strong&gt;powerChart&lt;/strong&gt;,&lt;/em&gt; too.
Unfortunately it hadn't been ready for presentation at that time.
&lt;/p&gt;
&lt;p&gt;
To my question how the idea for a whole powershell suite had been born, Tony Komischke
gave me a quite interesting answer:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
It was actually one of our internal IT guys who had the idea. During a meeting he
complained that lately more and more server products came to market without an usable
admin UI. Instead he had to struggle with some colourless command line tools. 
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
This situation started the whole thing. We all thought that Windows administrators
love decent UIs and don't want to work with a boring command line. If they liked the
command line, they would have become Linux administrators!
&lt;/p&gt;
&lt;p&gt;
And that's the point of Infragistics NetAdvantage for Powershell. With this product,
we give administrators back what they deserve!
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Since Basta conference some time went by. The product has nearly arrived at its final
state. Starting with tomorrow, registered users will be able to download at CTP Version
of it in the download area of Infrastics' homepage.
&lt;/p&gt;
&lt;p&gt;
The first webinars on NetAdvantage for Powershell will be made available approximately
next week by Infragistics new media evangelist &lt;a href="http://blogs.infragistics.com/blogs/craig_shoemaker/default.aspx" target="_blank"&gt;Jeff
Shoemaker&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
During the quaterly Infragistics MVP call, Mr Beres stated: 
&lt;/p&gt;
&lt;p&gt;
&amp;quot;We really wanted to show off our high end visualizations in a DOS window&amp;quot;
said Beres.&amp;#160; &amp;quot;PowerShell gave us a great opportunity to mix data analytics
with the new features in the Command Window, like colorization&amp;quot; he continued.
&lt;/p&gt;
&lt;p&gt;
As an Infragistics MVP I already enjoyed testing the product. Below you're going to
find some impressions:
&lt;/p&gt;
&lt;h6&gt;The powershell standard output
&lt;/h6&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/01_original.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="01_original" src="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/01_original_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h6&gt;Output as PowerGrid. Notice the usage of the &lt;a href="http://quince.infragistics.com/#/ByMap$tab=1&amp;amp;tag=Grid/ViewPattern$pattern=Sortable+Table" target="_blank"&gt;sortable
table pattern&lt;/a&gt; as well as table and column borders.
&lt;/h6&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/02_powerGrid.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="87" alt="02_powerGrid" src="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/02_powerGrid_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
The &lt;a href="http://quince.infragistics.com/#/Search$text=round/ViewPattern$pattern=Corner+Treatments" target="_blank"&gt;corner
treatements pattern&lt;/a&gt; which includes curves in all rectangle corners didn't make
it into the CTP as there were some performance issues with GDI+ and the gpu's hardware
acceleration.
&lt;/p&gt;
&lt;h6&gt;Output as PowerChart. I've chosen a bar chart as output type
&lt;/h6&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/03_powerChart.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="03_powerChart" src="http://blog.codemurai.de/images/InfragisticsannouncesNetAdvantageforPowe_5EF1/03_powerChart_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=d0c039a5-107f-4175-a6f0-1d7da007c6c3" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,d0c039a5-107f-4175-a6f0-1d7da007c6c3.aspx</comments>
      <category>.NET</category>
      <category>english posts</category>
      <category>Infragistics</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=8dce2f58-82cb-44de-b672-49d412172e4a</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,8dce2f58-82cb-44de-b672-49d412172e4a.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,8dce2f58-82cb-44de-b672-49d412172e4a.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=8dce2f58-82cb-44de-b672-49d412172e4a</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Einer der vielen Vorteile als <a title="Announcing the Infragistics MVP program" href="http://blogs.infragistics.com/blogs/tony_lombardo/archive/2009/03/31/announcing-the-infragistics-mvp-program.aspx" target="_blank">Infragistics
MVP</a> ist es, dass man als relativ früh in die Produktentwicklung involviert
wird, um Feedback geben zu können.
</p>
        <p>
Dies kann entweder Feedback über neue Features, API Veränderungen, oder
aber auch ganz neue Produkte sein.
</p>
        <p>
Letztes Frühjahr war es wieder so weit. Über der Infragistics NDA Mailing
Liste kam eine E-Mail, in der die ersten Arbeiten an einem neuen Produkt, nämlich <a href="http://www.infragistics.com/whats-hot/default.aspx" target="_blank">NetAdvantage
for Powershell</a>, angekündigt wurden. Als absoluter Powershell Fan ergriff
ich natürlich die Gunst der Stunde und bot meine Hilfe in Form von Alpha Tests,
Feedback, etc an.
</p>
        <p>
Nach regem Austausch zwischen dem Director of Product Management <a href="http://blogs.infragistics.com/blogs/jason_beres/default.aspx" target="_blank">Joseph
Berres</a>, dem leitenden Entwickler <a href="http://blogs.infragistics.com/blogs/ambrose_little/default.aspx" target="_blank">Ambrose
J. Tall</a> und einigen Infragistics MVPs stand Anfang September der erste, wenn auch
etwas wacklige Proof-Of-Concept Prototyp. Diesen konnte ich mir dann auch auf der
Basta von <a href="http://blogs.infragistics.com/blogs/ux/default.aspx" target="_blank">Dr.
Tony Komischke</a>, Director of User Experience bei Infragistics, vorführen lassen.
Zeigen konnte er mir eine erste Version des Powershell Grids: Infragistics NetAdvantage
for Powershell <strong>powerGrid</strong>. Sehr gerne gesehen hätte ich damals
auch die Charting Komponente <strong>powerChart</strong>. Leider war diese zu diesem
Zeitpunkt jedoch noch nicht in einem vorzeigbaren Stadium.
</p>
        <p>
Sehr interessant fand ich übrigens Tony Komischkes Antwort auf meine Frage wie
die Idee für eine Powershellproduktsuite aufkam:
</p>
        <blockquote>
          <p>
Die Idee hatte einer unserer internen IT Mitarbeiter. Er beschwerte sich während
eines Meetings, dass in letzter Zeit immer mehr Serverprodukte mit abgespeckter grafischer
Administrationsoberfläche auf den Markt kämen. Stattdessen müsste er
sich nun mit farblosen Kommandozeilenwerkzeugen herumschlagen.
</p>
          <p>
Diese Situation war der eigentliche Auslöser. Schnell war uns klar, dass Windows
Administratoren ansprechende GUIs und keine fade Kommandozeile möchten. Würden
Sie Kommandozeilen mögen, wären Sie schließlich Linux Administratoren
geworden.
</p>
          <p>
An diesem Punkt setzt NetAdvantage for Powershell. Mit diesem Produkt gibt Infragistics
Windows Administratoren zurück, was sie verdienen!
</p>
        </blockquote>
        <p>
Seit der Basta ist einige Zeit vergangen. Das Produkt nähert sich seiner endgültigen
Form und steht ab morgen registrierten Benutzern als CTP im Downloadbereich der Infragistics
Homepage zur Verfügung.
</p>
        <p>
Erste Trainingsvideos wird Infragistics New Media Evangelist <a href="http://blogs.infragistics.com/blogs/craig_shoemaker/default.aspx" target="_blank">Jeff
Shoemaker</a> voraussichtlich kommende Woche online stellen.
</p>
        <p>
Als Infragistics MVP hatte ich die Freude, das Produkt bereits ausgiebig zu testen.
Anbei einige Impressionen:
</p>
        <h6>Die Standardausgabe der Powershell.
</h6>
        <p>
          <a href="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/01_original.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="01_original" src="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/01_original_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h6>Ausgabe als PowerGrid. Sehr schön umgesetzt wurden das <a href="http://quince.infragistics.com/#/ByMap$tab=1&amp;tag=Grid/ViewPattern$pattern=Sortable+Table" target="_blank">Sortable-Table-Pattern</a> sowie
die Tabellenlinien.
</h6>
        <p>
          <a href="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/02_powerGrid.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="87" alt="02_powerGrid" src="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/02_powerGrid_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h6>Ausgabe als PowerChart. Als Anzeigeform habe ich ein Balkendiagramm gewählt.
</h6>
        <p>
          <a href="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/03_powerChart.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="03_powerChart" src="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/03_powerChart_thumb.png" width="244" border="0" />
          </a>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=8dce2f58-82cb-44de-b672-49d412172e4a" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Infragistics kündigt NetAdvantage for Powershell CTP an</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,8dce2f58-82cb-44de-b672-49d412172e4a.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/31/InfragisticsK%c3%bcndigtNetAdvantageForPowershellCTPAn.aspx</link>
      <pubDate>Wed, 31 Mar 2010 22:43:49 GMT</pubDate>
      <description>&lt;p&gt;
Einer der vielen Vorteile als &lt;a title="Announcing the Infragistics MVP program" href="http://blogs.infragistics.com/blogs/tony_lombardo/archive/2009/03/31/announcing-the-infragistics-mvp-program.aspx" target="_blank"&gt;Infragistics
MVP&lt;/a&gt; ist es, dass man als relativ fr&amp;#252;h in die Produktentwicklung involviert
wird, um Feedback geben zu k&amp;#246;nnen.
&lt;/p&gt;
&lt;p&gt;
Dies kann entweder Feedback &amp;#252;ber neue Features, API Ver&amp;#228;nderungen, oder
aber auch ganz neue Produkte sein.
&lt;/p&gt;
&lt;p&gt;
Letztes Fr&amp;#252;hjahr war es wieder so weit. &amp;#220;ber der Infragistics NDA Mailing
Liste kam eine E-Mail, in der die ersten Arbeiten an einem neuen Produkt, n&amp;#228;mlich &lt;a href="http://www.infragistics.com/whats-hot/default.aspx" target="_blank"&gt;NetAdvantage
for Powershell&lt;/a&gt;, angek&amp;#252;ndigt wurden. Als absoluter Powershell Fan ergriff
ich nat&amp;#252;rlich die Gunst der Stunde und bot meine Hilfe in Form von Alpha Tests,
Feedback, etc an.
&lt;/p&gt;
&lt;p&gt;
Nach regem Austausch zwischen dem Director of Product Management &lt;a href="http://blogs.infragistics.com/blogs/jason_beres/default.aspx" target="_blank"&gt;Joseph
Berres&lt;/a&gt;, dem leitenden Entwickler &lt;a href="http://blogs.infragistics.com/blogs/ambrose_little/default.aspx" target="_blank"&gt;Ambrose
J. Tall&lt;/a&gt; und einigen Infragistics MVPs stand Anfang September der erste, wenn auch
etwas wacklige Proof-Of-Concept Prototyp. Diesen konnte ich mir dann auch auf der
Basta von &lt;a href="http://blogs.infragistics.com/blogs/ux/default.aspx" target="_blank"&gt;Dr.
Tony Komischke&lt;/a&gt;, Director of User Experience bei Infragistics, vorf&amp;#252;hren lassen.
Zeigen konnte er mir eine erste Version des Powershell Grids: Infragistics NetAdvantage
for Powershell &lt;strong&gt;powerGrid&lt;/strong&gt;. Sehr gerne gesehen h&amp;#228;tte ich damals
auch die Charting Komponente &lt;strong&gt;powerChart&lt;/strong&gt;. Leider war diese zu diesem
Zeitpunkt jedoch noch nicht in einem vorzeigbaren Stadium.
&lt;/p&gt;
&lt;p&gt;
Sehr interessant fand ich &amp;#252;brigens Tony Komischkes Antwort auf meine Frage wie
die Idee f&amp;#252;r eine Powershellproduktsuite aufkam:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Die Idee hatte einer unserer internen IT Mitarbeiter. Er beschwerte sich w&amp;#228;hrend
eines Meetings, dass in letzter Zeit immer mehr Serverprodukte mit abgespeckter grafischer
Administrationsoberfl&amp;#228;che auf den Markt k&amp;#228;men. Stattdessen m&amp;#252;sste er
sich nun mit farblosen Kommandozeilenwerkzeugen herumschlagen.
&lt;/p&gt;
&lt;p&gt;
Diese Situation war der eigentliche Ausl&amp;#246;ser. Schnell war uns klar, dass Windows
Administratoren ansprechende GUIs und keine fade Kommandozeile m&amp;#246;chten. W&amp;#252;rden
Sie Kommandozeilen m&amp;#246;gen, w&amp;#228;ren Sie schlie&amp;#223;lich Linux Administratoren
geworden.
&lt;/p&gt;
&lt;p&gt;
An diesem Punkt setzt NetAdvantage for Powershell. Mit diesem Produkt gibt Infragistics
Windows Administratoren zur&amp;#252;ck, was sie verdienen!
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Seit der Basta ist einige Zeit vergangen. Das Produkt n&amp;#228;hert sich seiner endg&amp;#252;ltigen
Form und steht ab morgen registrierten Benutzern als CTP im Downloadbereich der Infragistics
Homepage zur Verf&amp;#252;gung.
&lt;/p&gt;
&lt;p&gt;
Erste Trainingsvideos wird Infragistics New Media Evangelist &lt;a href="http://blogs.infragistics.com/blogs/craig_shoemaker/default.aspx" target="_blank"&gt;Jeff
Shoemaker&lt;/a&gt; voraussichtlich kommende Woche online stellen.
&lt;/p&gt;
&lt;p&gt;
Als Infragistics MVP hatte ich die Freude, das Produkt bereits ausgiebig zu testen.
Anbei einige Impressionen:
&lt;/p&gt;
&lt;h6&gt;Die Standardausgabe der Powershell.
&lt;/h6&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/01_original.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="01_original" src="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/01_original_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h6&gt;Ausgabe als PowerGrid. Sehr sch&amp;#246;n umgesetzt wurden das &lt;a href="http://quince.infragistics.com/#/ByMap$tab=1&amp;amp;tag=Grid/ViewPattern$pattern=Sortable+Table" target="_blank"&gt;Sortable-Table-Pattern&lt;/a&gt; sowie
die Tabellenlinien.
&lt;/h6&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/02_powerGrid.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="87" alt="02_powerGrid" src="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/02_powerGrid_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h6&gt;Ausgabe als PowerChart. Als Anzeigeform habe ich ein Balkendiagramm gew&amp;#228;hlt.
&lt;/h6&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/03_powerChart.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="65" alt="03_powerChart" src="http://blog.codemurai.de/images/InfragisticskndigtNetAdvantageforPowersh_7775/03_powerChart_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=8dce2f58-82cb-44de-b672-49d412172e4a" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,8dce2f58-82cb-44de-b672-49d412172e4a.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=7227fb13-ec6d-43fa-8bba-5e8dfeb98adb</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,7227fb13-ec6d-43fa-8bba-5e8dfeb98adb.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,7227fb13-ec6d-43fa-8bba-5e8dfeb98adb.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=7227fb13-ec6d-43fa-8bba-5e8dfeb98adb</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 5) Scriptservices, Page Methods und jQuery" href="http://blog.codemurai.de/2010/03/01/ASPNETWebformsAnwendungenUndAjaxTeil5ScriptservicesPageMethodsUndJQuery.aspx" target="_blank">Teil
5</a> meiner ASP.NET Webforms und Ajax Serie wies <a title="Weblog von René Drescher-Hackel" href="http://weblog.drescher-hackel.de/" target="_blank">René
Drescher-Hackel</a> mich darauf hin, dass ich einen Big Player vollkommen außer
acht gelassen habe: <a title="AjaxPro Homepage" href="http://ajaxpro.info/" target="_blank">AjaxPro</a> von
Michael <a title="Blog von Michael Schwarz" href="http://weblogs.asp.net/mschwarz" target="_blank">Schwarz</a>.
</p>
        <p>
Das wollte ich natürlich nicht auf mir sitzen lassen. Daher befassen wir uns
heute mit:
</p>
        <h4>AjaxPro :-)
</h4>
        <p>
          <a title="AjaxPro Homepage" href="http://ajaxpro.info/" target="_blank">AjaxPro</a> ist
eine freie Library von Michael Schwarz, die Ajax unter ASP.NET ohne Postbacks ermöglicht.
Vergleichbar ist AjaxPro somit am ehesten mit den in Teil 4 vorgestellten PageMethods.
Ein großer Vorteil gegenüber diesen ist jedoch die Möglichkeit, AjaxPro
auch unter ASP.NET 1.1 einsetzen zu können (ja - ich kenne wirklich noch aktive
ASP.NET 1.1 Projekte ;-)). Angemerkt werden sollte noch, dass AjaxPro keiner Weiterentwicklung
mehr unterliegt. Michael Schwarz schrieb in in seinem Blog, dass er die <a title="Future of Ajax.NET Professional" href="http://weblogs.asp.net/mschwarz/archive/2008/01/04/future-of-ajax-net-professional.aspx" target="_blank">Arbeit
an der Library einstellt</a>. Als Alternative empfiehlt er den <a title="How to... move from AjaxPro to ASP.NET AJAX PageMethods" href="http://weblogs.asp.net/mschwarz/archive/2008/01/08/how-to-move-from-ajaxpro-to-asp-net-ajax-pagemethods.aspx" target="_blank">Einsatz
von PageMethods</a>.
</p>
        <h4>Lost gehts
</h4>
        <p>
AjaxPro ist relativ einfach eingebunden. Es genügt einen Verweis auf die Datei
AjaxPro.2.dll hinzuzufügen.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/01addreference.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="185" alt="01addreference" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/01addreference_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Weiter muss AjaxPro in der Datei web.config des Webprojekts bekannt gemacht werden.
Dies geschieht über das Hinzufügen eines entsprechenden Http-Handlers:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:3ee373ad-8293-4b5c-bb1a-9390fc37d646" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;httpHandlers&gt;
   ...
   &lt;add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2"/&gt;
&lt;/httpHandlers&gt;</pre>
        </div>
        <p>
Anschließend müssen die Methoden einer Seite, die später via Ajax aufgerufen
werden sollen, mit dem Attribut AjaxMethod annotiert werden. Dies funktioniert also
ähnlich wie die bereits vorgestellten PageMethods. Der Quellcode dieses Beitrags
basiert übrigens wieder auf dem Quellcode der vorherigen Teile dieser Serie.
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:04a3dedf-3354-4b43-b525-0cb2e6b72e03" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">public partial class Teil7 : Page
{
    [AjaxPro.AjaxMethod]
    public string ReadStaticFile()
    {
        string fileContent;
        using (var reader = 
            new StreamReader(
                System.Web.HttpContext.Current.Server.MapPath("~/static.html")))
        {
            fileContent = reader.ReadToEnd();
        }
        return fileContent;
    }
}</pre>
        </div>
        <p>
Ein netter Nebeneffekt im Vergleich zu Pagemethods ist übrigens, dass die entsprechende
Methode zwar statisch sein kann, dies aber nicht muss. Außerdem muss sich die
Methode noch nicht einmal zwingend innerhalb einer Webseite (ASPX-Datei) befinden.
Stattdessen kann Sie Mitglied einer beliebigen öffentlichen Klasse sein.
</p>
        <p>
Um diese Methode nun komfortabel per JavaScript aufrufen zu können, muss die
zugehörige Klasse noch als AjaxTyp registriert werden. Dies geschieht in der
Methode Page_Load der Klasse <em>Teil7</em>.
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:304ad116-121d-4d11-aa0b-44f68d31a504" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">protected void Page_Load(object sender, System.EventArgs e)
{
    AjaxPro.Utility.RegisterTypeForAjax(typeof(Teil7));
}</pre>
        </div>
        <p>
        </p>
        <p>
Der Aufruf innerhalb der Seite kann nun wie folgt erfolgen:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8aa21e74-9a8a-4d66-94fb-9ee7eed736eb" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;a href="#" id="StaticFileLink" onclick="Teil7.ReadStaticFile(ajaxdemo_callback)"&gt;Hier klicken zum Request einer statischen Datei&lt;/a&gt;&lt;br /&gt;</pre>
        </div>
        <p>
Bei dem übergebenen Parametger ajaxdemo_callback handelt es sich um eine Callback
Funktion, die die Antwort des Servers verarbeitet. In unserem Beispiel sieht sie wie
folgt aus:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:56236038-c567-4626-b21e-38984dd22301" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">&lt;script type="text/javascript"&gt;
    function ajaxdemo_callback(result) {
       var content = document.getElementById('content');
       content.innerHTML = result.value;
    }
&lt;/script&gt;</pre>
        </div>
        <p>
Die Seite ist nun funktionsfähig und kann gestartet werden. Ein Blick in die
Firebug Ausgabe zeigt, dass neben der eigentlichen Seite automatisch noch 4 JavaScript
Dateien geladen wurden. Diese sind für die Serverkommunikation zuständig
und haben eine Gesamtgröße von <strong>nur 25 kb</strong>! Im Vergleich
zu den zuvor vorgestellten Lösungen ist dies das beste Ergebnis!
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/02_initialesladen.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="58" alt="02_initialesladen" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/02_initialesladen_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Auch beim Aufruf der serverseitigen Methode schlägt sich AjaxPro gut. Hier gehen
lediglich 111 Byte über die Leitung:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/03_ajaxcall.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="167" alt="03_ajaxcall" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/03_ajaxcall_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Der Aufruf selbst hat eine Datei mit der Endung *.ashx innerhalb des Pfads /ajaxpro
zum Ziel. In meinem Beispiel lautet die URL: http://localhost:2800/AjaxDemo/ajaxpro/Teil7,App_Web_mke8f-yp.ashx.
Er wird somit durch den zuvor in der web.config eingetragenen Http-Handler behandelt.
Außerdem ist innerhalb der URL, wie man sehen kann, der Name der Klasse in der
sich die entsprechende Methode befindet kodiert. Die Methode selbst wird im Header
des Aufrufs als Attribut X-AjaxPro-Method übergeben. 
</p>
        <h4>Webservices
</h4>
        <p>
Nachdem sich PageMethods relativ einfach aufrufen ließen, stellt sich nun natürlich
die Frage, wie die Methoden eines Webservices aufgerufen werden können.
</p>
        <p>
Eine Variante wäre es, die Methoden innerhalb des Webservices nicht nur mit dem
Attribut [WebMethod] zu anotieren, sondern zusätzlich auch mit [AjaxPro.AjaxMethod]
zu versehen. Diese Variante ist selbstverständlich nur für eigene und nicht
für externe Webservices möglich.
</p>
        <p>
Ein allgemeingültiger Ansatz besteht darin, händisch Proxy-Methoden innerhalb
der Seite für die gewünschten Webservice Methoden anzulegen.
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b8b11c48-5d9e-4f1d-9c9c-2840b33193e9" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">[AjaxPro.AjaxMethod]
public string CallHelloWorldService()
{
    return new AjaxDemoService().HelloWorld();
}

[AjaxPro.AjaxMethod]
public string CallEchoService(int value)
{

    return new AjaxDemoService().Echo(value);
}</pre>
        </div>
        <p>
        </p>
        <p>
        </p>
        <p>
Auf dem Client birgt der zusätzliche Code keine Überraschungen. Der Aufruf
der serverseitigen Methoden erfolgt analog des ersten Beispiels. Die einzige Besonderheit
ist der Aufruf der Methode CallEchoService, da diese einen Parameter erwartet.
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:90c0eff3-56d8-4cbc-abe0-72a81ff77c1e" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">&lt;script type="text/javascript"&gt;
    function callEchoService() {
        var echoTextBox = document.getElementById('EchoTextBox');
        var value = echoTextBox.value;
        Teil7.CallEchoService(value, ajaxdemo_callback);
    }

    function ajaxdemo_callback(result) {
        var content = document.getElementById('content');
        content.innerHTML = result.value;
    }
&lt;/script&gt;</pre>
        </div>
        <p>
Wie der Beispielcode zeigt, wird der erwartete Parameter einfach vor die Angabe der
JavaScript Callback Funktion gepackt.
</p>
        <h4>Fazit
</h4>
        <p>
AjaxPro ist eine kleine und leichtgewichtige Ajax Library, die ohne unnötigen
Ballast daher kommt. Durch die Ähnlichkeit zu Pagemethods und Scriptservices
fiel mir die Einarbeitung ziemlich leicht und nahm kaum mehr als eine halbe Stunde
in Anspruch.
</p>
        <p>
Trotz dieser Vorteile kann ich mir nicht vorstellen, AjaxPro als Standardwerkzeug
in aktuellen Projekten zu nutzen. Stattdessen werde ich wohl weiterhin auf jQuery
setzen. Der Grund für diese Entscheidung liegt ganz einfach darin, dass ich jQuery
zu UI Manipulationszwecken meist sowieso schon auf meinen Seiten referenziert habe.
Daher ist es naheliegend für AjaxRequests auch zu jQuery zu greifen.
</p>
        <p>
Sehr gut vorstellen könnte ich mir jedoch, AjaxPro in ASP.NET 1.1 Projekten zu
nutzen, die sich noch in Pflege befinden. In diesen fehlt die Möglichkeit, PageMethods
und Scriptservices einzusetzen, so das AjaxPro dort das perfekte Werkzeug wäre.
</p>
        <p>
An dieser Stelle auch noch einmal vielen Dank an <a title="Weblog von René Drescher-Hackel" href="http://weblog.drescher-hackel.de/" target="_blank">René</a> für
den hilfreichen Tipp.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=7227fb13-ec6d-43fa-8bba-5e8dfeb98adb" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>ASP.NET Webforms Anwendungen und Ajax (Teil 7) - AjaxPro</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,7227fb13-ec6d-43fa-8bba-5e8dfeb98adb.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/29/ASPNETWebformsAnwendungenUndAjaxTeil7AjaxPro.aspx</link>
      <pubDate>Mon, 29 Mar 2010 20:12:04 GMT</pubDate>
      <description>&lt;p&gt;
In &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 5) Scriptservices, Page Methods und jQuery" href="http://blog.codemurai.de/2010/03/01/ASPNETWebformsAnwendungenUndAjaxTeil5ScriptservicesPageMethodsUndJQuery.aspx" target="_blank"&gt;Teil
5&lt;/a&gt; meiner ASP.NET Webforms und Ajax Serie wies &lt;a title="Weblog von Ren&amp;#233; Drescher-Hackel" href="http://weblog.drescher-hackel.de/" target="_blank"&gt;Ren&amp;#233;
Drescher-Hackel&lt;/a&gt; mich darauf hin, dass ich einen Big Player vollkommen au&amp;#223;er
acht gelassen habe: &lt;a title="AjaxPro Homepage" href="http://ajaxpro.info/" target="_blank"&gt;AjaxPro&lt;/a&gt; von
Michael &lt;a title="Blog von Michael Schwarz" href="http://weblogs.asp.net/mschwarz" target="_blank"&gt;Schwarz&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Das wollte ich nat&amp;#252;rlich nicht auf mir sitzen lassen. Daher befassen wir uns
heute mit:
&lt;/p&gt;
&lt;h4&gt;AjaxPro :-)
&lt;/h4&gt;
&lt;p&gt;
&lt;a title="AjaxPro Homepage" href="http://ajaxpro.info/" target="_blank"&gt;AjaxPro&lt;/a&gt; ist
eine freie Library von Michael Schwarz, die Ajax unter ASP.NET ohne Postbacks erm&amp;#246;glicht.
Vergleichbar ist AjaxPro somit am ehesten mit den in Teil 4 vorgestellten PageMethods.
Ein gro&amp;#223;er Vorteil gegen&amp;#252;ber diesen ist jedoch die M&amp;#246;glichkeit, AjaxPro
auch unter ASP.NET 1.1 einsetzen zu k&amp;#246;nnen (ja - ich kenne wirklich noch aktive
ASP.NET 1.1 Projekte ;-)). Angemerkt werden sollte noch, dass AjaxPro keiner Weiterentwicklung
mehr unterliegt. Michael Schwarz schrieb in in seinem Blog, dass er die &lt;a title="Future of Ajax.NET Professional" href="http://weblogs.asp.net/mschwarz/archive/2008/01/04/future-of-ajax-net-professional.aspx" target="_blank"&gt;Arbeit
an der Library einstellt&lt;/a&gt;. Als Alternative empfiehlt er den &lt;a title="How to... move from AjaxPro to ASP.NET AJAX PageMethods" href="http://weblogs.asp.net/mschwarz/archive/2008/01/08/how-to-move-from-ajaxpro-to-asp-net-ajax-pagemethods.aspx" target="_blank"&gt;Einsatz
von PageMethods&lt;/a&gt;.
&lt;/p&gt;
&lt;h4&gt;Lost gehts
&lt;/h4&gt;
&lt;p&gt;
AjaxPro ist relativ einfach eingebunden. Es gen&amp;#252;gt einen Verweis auf die Datei
AjaxPro.2.dll hinzuzuf&amp;#252;gen.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/01addreference.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="185" alt="01addreference" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/01addreference_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Weiter muss AjaxPro in der Datei web.config des Webprojekts bekannt gemacht werden.
Dies geschieht &amp;#252;ber das Hinzuf&amp;#252;gen eines entsprechenden Http-Handlers:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:3ee373ad-8293-4b5c-bb1a-9390fc37d646" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;httpHandlers&amp;gt;
   ...
   &amp;lt;add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2"/&amp;gt;
&amp;lt;/httpHandlers&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Anschlie&amp;#223;end m&amp;#252;ssen die Methoden einer Seite, die sp&amp;#228;ter via Ajax aufgerufen
werden sollen, mit dem Attribut AjaxMethod annotiert werden. Dies funktioniert also
&amp;#228;hnlich wie die bereits vorgestellten PageMethods. Der Quellcode dieses Beitrags
basiert &amp;#252;brigens wieder auf dem Quellcode der vorherigen Teile dieser Serie.
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:04a3dedf-3354-4b43-b525-0cb2e6b72e03" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;public partial class Teil7 : Page
{
    [AjaxPro.AjaxMethod]
    public string ReadStaticFile()
    {
        string fileContent;
        using (var reader = 
            new StreamReader(
                System.Web.HttpContext.Current.Server.MapPath("~/static.html")))
        {
            fileContent = reader.ReadToEnd();
        }
        return fileContent;
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Ein netter Nebeneffekt im Vergleich zu Pagemethods ist &amp;#252;brigens, dass die entsprechende
Methode zwar statisch sein kann, dies aber nicht muss. Au&amp;#223;erdem muss sich die
Methode noch nicht einmal zwingend innerhalb einer Webseite (ASPX-Datei) befinden.
Stattdessen kann Sie Mitglied einer beliebigen &amp;#246;ffentlichen Klasse sein.
&lt;/p&gt;
&lt;p&gt;
Um diese Methode nun komfortabel per JavaScript aufrufen zu k&amp;#246;nnen, muss die
zugeh&amp;#246;rige Klasse noch als AjaxTyp registriert werden. Dies geschieht in der
Methode Page_Load der Klasse &lt;em&gt;Teil7&lt;/em&gt;.
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:304ad116-121d-4d11-aa0b-44f68d31a504" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;protected void Page_Load(object sender, System.EventArgs e)
{
    AjaxPro.Utility.RegisterTypeForAjax(typeof(Teil7));
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Der Aufruf innerhalb der Seite kann nun wie folgt erfolgen:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8aa21e74-9a8a-4d66-94fb-9ee7eed736eb" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;a href="#" id="StaticFileLink" onclick="Teil7.ReadStaticFile(ajaxdemo_callback)"&amp;gt;Hier klicken zum Request einer statischen Datei&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Bei dem &amp;#252;bergebenen Parametger ajaxdemo_callback handelt es sich um eine Callback
Funktion, die die Antwort des Servers verarbeitet. In unserem Beispiel sieht sie wie
folgt aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:56236038-c567-4626-b21e-38984dd22301" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;&amp;lt;script type="text/javascript"&amp;gt;
    function ajaxdemo_callback(result) {
       var content = document.getElementById('content');
       content.innerHTML = result.value;
    }
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Die Seite ist nun funktionsf&amp;#228;hig und kann gestartet werden. Ein Blick in die
Firebug Ausgabe zeigt, dass neben der eigentlichen Seite automatisch noch 4 JavaScript
Dateien geladen wurden. Diese sind f&amp;#252;r die Serverkommunikation zust&amp;#228;ndig
und haben eine Gesamtgr&amp;#246;&amp;#223;e von &lt;strong&gt;nur 25 kb&lt;/strong&gt;! Im Vergleich
zu den zuvor vorgestellten L&amp;#246;sungen ist dies das beste Ergebnis!
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/02_initialesladen.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="58" alt="02_initialesladen" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/02_initialesladen_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Auch beim Aufruf der serverseitigen Methode schl&amp;#228;gt sich AjaxPro gut. Hier gehen
lediglich 111 Byte &amp;#252;ber die Leitung:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/03_ajaxcall.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="167" alt="03_ajaxcall" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil7Aj_6DF2/03_ajaxcall_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Der Aufruf selbst hat eine Datei mit der Endung *.ashx innerhalb des Pfads /ajaxpro
zum Ziel. In meinem Beispiel lautet die URL: http://localhost:2800/AjaxDemo/ajaxpro/Teil7,App_Web_mke8f-yp.ashx.
Er wird somit durch den zuvor in der web.config eingetragenen Http-Handler behandelt.
Au&amp;#223;erdem ist innerhalb der URL, wie man sehen kann, der Name der Klasse in der
sich die entsprechende Methode befindet kodiert. Die Methode selbst wird im Header
des Aufrufs als Attribut X-AjaxPro-Method &amp;#252;bergeben. 
&lt;/p&gt;
&lt;h4&gt;Webservices
&lt;/h4&gt;
&lt;p&gt;
Nachdem sich PageMethods relativ einfach aufrufen lie&amp;#223;en, stellt sich nun nat&amp;#252;rlich
die Frage, wie die Methoden eines Webservices aufgerufen werden k&amp;#246;nnen.
&lt;/p&gt;
&lt;p&gt;
Eine Variante w&amp;#228;re es, die Methoden innerhalb des Webservices nicht nur mit dem
Attribut [WebMethod] zu anotieren, sondern zus&amp;#228;tzlich auch mit [AjaxPro.AjaxMethod]
zu versehen. Diese Variante ist selbstverst&amp;#228;ndlich nur f&amp;#252;r eigene und nicht
f&amp;#252;r externe Webservices m&amp;#246;glich.
&lt;/p&gt;
&lt;p&gt;
Ein allgemeing&amp;#252;ltiger Ansatz besteht darin, h&amp;#228;ndisch Proxy-Methoden innerhalb
der Seite f&amp;#252;r die gew&amp;#252;nschten Webservice Methoden anzulegen.
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b8b11c48-5d9e-4f1d-9c9c-2840b33193e9" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;[AjaxPro.AjaxMethod]
public string CallHelloWorldService()
{
    return new AjaxDemoService().HelloWorld();
}

[AjaxPro.AjaxMethod]
public string CallEchoService(int value)
{

    return new AjaxDemoService().Echo(value);
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Auf dem Client birgt der zus&amp;#228;tzliche Code keine &amp;#220;berraschungen. Der Aufruf
der serverseitigen Methoden erfolgt analog des ersten Beispiels. Die einzige Besonderheit
ist der Aufruf der Methode CallEchoService, da diese einen Parameter erwartet.
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:90c0eff3-56d8-4cbc-abe0-72a81ff77c1e" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;&amp;lt;script type="text/javascript"&amp;gt;
    function callEchoService() {
        var echoTextBox = document.getElementById('EchoTextBox');
        var value = echoTextBox.value;
        Teil7.CallEchoService(value, ajaxdemo_callback);
    }

    function ajaxdemo_callback(result) {
        var content = document.getElementById('content');
        content.innerHTML = result.value;
    }
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Wie der Beispielcode zeigt, wird der erwartete Parameter einfach vor die Angabe der
JavaScript Callback Funktion gepackt.
&lt;/p&gt;
&lt;h4&gt;Fazit
&lt;/h4&gt;
&lt;p&gt;
AjaxPro ist eine kleine und leichtgewichtige Ajax Library, die ohne unn&amp;#246;tigen
Ballast daher kommt. Durch die &amp;#196;hnlichkeit zu Pagemethods und Scriptservices
fiel mir die Einarbeitung ziemlich leicht und nahm kaum mehr als eine halbe Stunde
in Anspruch.
&lt;/p&gt;
&lt;p&gt;
Trotz dieser Vorteile kann ich mir nicht vorstellen, AjaxPro als Standardwerkzeug
in aktuellen Projekten zu nutzen. Stattdessen werde ich wohl weiterhin auf jQuery
setzen. Der Grund f&amp;#252;r diese Entscheidung liegt ganz einfach darin, dass ich jQuery
zu UI Manipulationszwecken meist sowieso schon auf meinen Seiten referenziert habe.
Daher ist es naheliegend f&amp;#252;r AjaxRequests auch zu jQuery zu greifen.
&lt;/p&gt;
&lt;p&gt;
Sehr gut vorstellen k&amp;#246;nnte ich mir jedoch, AjaxPro in ASP.NET 1.1 Projekten zu
nutzen, die sich noch in Pflege befinden. In diesen fehlt die M&amp;#246;glichkeit, PageMethods
und Scriptservices einzusetzen, so das AjaxPro dort das perfekte Werkzeug w&amp;#228;re.
&lt;/p&gt;
&lt;p&gt;
An dieser Stelle auch noch einmal vielen Dank an &lt;a title="Weblog von Ren&amp;#233; Drescher-Hackel" href="http://weblog.drescher-hackel.de/" target="_blank"&gt;Ren&amp;#233;&lt;/a&gt; f&amp;#252;r
den hilfreichen Tipp.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=7227fb13-ec6d-43fa-8bba-5e8dfeb98adb" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,7227fb13-ec6d-43fa-8bba-5e8dfeb98adb.aspx</comments>
      <category>.NET</category>
      <category>Ajax</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=0563b42b-487d-4fc2-90ca-f9fecb9e9541</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,0563b42b-487d-4fc2-90ca-f9fecb9e9541.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,0563b42b-487d-4fc2-90ca-f9fecb9e9541.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=0563b42b-487d-4fc2-90ca-f9fecb9e9541</wfw:commentRss>
      <slash:comments>7</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Von Administratoren geliebt, von Entwicklern verflucht: Das Transportsystem von SAP.
Prinzipiell kann man sich das so vorstellen, dass dieses System vorsieht, dass der
Quellcode nur an einer Stelle, nämlich im SAP Entwicklungssystem erstellt und
modifiziert wird.
</p>
        <p>
Anschließend wird ein sogenannter Transport (so was ähnliches wie ein Setuppaket)
erstellt. Dieses kann dann je Konfiguration erst mal nur in das Testsystem eingespielt
werden. Dort wird das Paket auf seine Funktionstüchtigkeit getestet. Wurden diese
Tests bestanden, wird es in das Integrationssystem "transportiert". Dort
wird das Zusammenspiel mit anderen Anpassungen getestet, es wird also geprüft,
ob das Paket nichts anderes kaputt macht ;-)
</p>
        <p>
War auch dieser Test erfolgreich, wird der Transport aus dem Integrationssystem in
das Produktionssystem transportiert. Ein direktes Einspielen von Transporten in das
Produktionssystem beziehungsweise sogar ein direktes Ändern der Quellcodes ist
nicht vorgesehen.
</p>
        <p>
Auch wenn diese Vorgehensweise zunächst recht streng, bürokratisch und viel
zu aufwändig wirkt, hat sie durchaus ihren Sinn. Dieser zugegeben etwas starre
Prozess sorgt dafür, dass SAP Produktionssysteme normalerweise immer stabil und
möglichst fehlerfrei sein sollten. Er trägt also Maßgeblich zu SAPs
gutem Ruf bei!
</p>
        <h4>Warum erzähle ich das eigentlich?
</h4>
        <p>
Ok, nette Einführung, aber ist das hier nicht eigentlich ein auf .NET fokussierter
Blog? <strong>Ja :-)</strong> Also keine Sorge, ich bin nicht ins Lager der SAP Consultants
gewechselt ;-) Allerdings habe ich von ungefähr 2005 bis 2008 die SAP Schnittstelle
meines ehemaligen Arbeitgebers gemeinsam mit einem Kollegen weiterentwickelt. Da blieb
der ein oder andere Blick unter die Haube diverser SAP Systeme nicht aus.
</p>
        <p>
Nun aber zurück zum Thema: 
</p>
        <p>
In meiner beruflichen Laufbahn war ich an einigen (ASP).NET Projekte beteiligt, die
von einem SAP transportähnlichen System sehr profitiert hätten. Überspitzt
gesagt sah es dort nämlich häufig so aus, dass ein Entwickler nach einer
Quellcodeänderung Visual Studio genutzt hat um einen neuen Releasestand zu erstellen
und diesen dann schnell auf den produktiven Webserver gepackt hat. Selbstverständlich
wurde das ganze vorher <em>nicht</em> in einem Test- oder Integrationssystem installiert
und unter Umständen wusste der Kunde und/oder Projektleiter sogar nichts von
dem adhoc Update.
</p>
        <h4>Agil != Chaos !!!
</h4>
        <p>
Der Entwickler handelte unter dem Deckmantel der <em>agilen Entwicklung</em> nach
dem Prinzip "<em>nach mir die Sinnflut</em>", einfach drauf damit, wird
schon klappen. In diesem Zusammenhang finde ich es übrigens immer wieder äußerst
verwunderlich, wie viele Entwickler unkoordiniertes und schlampiges Vorgehen einfach
als <em>agil</em> bezeichnen, um ihr Chaos damit zu entschuldigen. Agil ist allerdings
alles andere als chaotisch, unprofessionell, unkoordiniert oder schlampig. Aber gut,
dass ist ein anderes Thema - ich schweife schon wieder aus ;-)
</p>
        <p>
In einem meiner aktuellen Projekte wollte ich einer solchen Vorgehensweise direkt
einen Riegel vorschieben. Nicht dass die Entwickler dieses Projekts chaotisch wären,
das ist ganz und gar nicht der Fall, aber wir wollen ja auch niemanden in Versuchung
führen ;-)
</p>
        <h4>Ich hatte einen Traum ...
</h4>
        <p>
Meine Ziele lautete also wie folgt:
</p>
        <ol>
          <li>
Releasestände einer Software sollen automatisch auf einem dedizierten Buildrechner
und nicht auf einem Entwickler-PC erstellt werden. 
</li>
          <li>
Jedes Release hat eine eindeutige Versionsnummer. Kompilate auf dem Entwicklerrechner
haben jedoch immer die Nummer 1.0.0.0 (dazu später mehr) 
</li>
          <li>
Jedes Release soll ein Set an Unit Tests durchlaufen haben. 
</li>
          <li>
Jedes Release soll mit einer bestimmten <em>Qualität</em> als Metadatum versehen
werden. 
</li>
          <li>
In Abhängigkeit von dieser Qualität und der vorherigen Qualität soll
die Software bei bestimmten Statusübergängen automatisch auf bestimmte Systeme
verteilt werden. 
</li>
          <li>
Das Qualitätsmetadatum wird durch einen dedizierten Personenkreis gesetzt (zum
Beispiel QM-Manager oder Projektmanager, Softwarearchitekt oder Chefentwickler) 
</li>
        </ol>
        <p>
Realisiert werden sollte das ganze mit Visual Studio 2008 und dem Team Foundation
Server. Die Punkte 1 - 3 stellen in einer solchen Umgebung kein Problem dar. 
</p>
        <p>
          <strong>Punkt Nr. 1</strong> erledigen wir durch Teambuild. Hier läuft ein Buildagent
auf einem dedizierten Rechner. Durchgeführt werden sowohl Continuous Integration
Builds, als auch Nightly Builds.
</p>
        <p>
          <strong>Punkt Nr. 2</strong> haben wir durch ein einfaches Build Target in unserem
Buildscript erledigt. Die Versionsnummer haben wir wie folgt aufgebaut:
</p>
        <ul>
          <li>
Major: Fixer Wert 
</li>
          <li>
Minor: Fixer Wert 
</li>
          <li>
Build: Aktueller Changeset des Teamprojekts im TFS 
</li>
          <li>
Revision: Fortlaufende Nummer 
</li>
        </ul>
        <p>
Diese Nummer wird nur während des Builds durch Teambuild erzeugt. Entwicklerbuilds
haben immer die Version 1.0.0.0. So fange ich ab, dass ein Entwickler doch einfach
mal auf seinem Rechner eine Version baut und versucht zu deployen. Natürlich
ist dies nur ein <em>weicher</em> Schutz. Mit ein wenig Aufwand lässt sich das
System natürlich leicht umgehen indem ein Entwickler eine korrekte Versionsnummer
erzeugt. Allerdings ist der Aufwand schon wieder so hoch, dass sich dann doch lohnt,
den vorgesehenen Prozess einzuhalten ;-)
</p>
        <p>
Sollte jemand Interesse an diesem Teil des Buildscripts haben: Einfach einen Kommentar
posten.
</p>
        <p>
          <strong>Punkt Nr. 3</strong> ist natürlich auch kein Problem. Aufgrund der guten
VS Integration haben wir uns für MS Test für dieses Projekt entschieden.
Diese Tests als Bestandteil des Buildprozess laufen zu lassen war demnach kein Problem.
</p>
        <p>
Punkt Nr. 4 ist auch bereits von Haus aus mit dem TFS möglich. Jeder Build der
durch Teambuild durchgeführt wird hat ein Metadatum Buildqualität. Die möglichen
Werte der Buildqualität lassen sich frei definieren. Auch lässt sich über
entsprechende Rechte einschränken, wer diese Qualität setzen darf. Wir haben
bei uns die Werte <em>"Entwicklung"</em>, <em>"Test"</em>, <em>"Integration"</em>, <em>"Produktion"</em> und <em>"Abgelehnt"</em> definiert.
</p>
        <p>
Punkt Nr. 5 kann mit TFS Bordmitteln erst mal nicht realisiert werden. Hier kommt
nun das Open Source Projekt <a title="TFS Deployer Codeplex Seite" href="http://www.codeplex.com/tfsdeployer" target="_blank">TFS
Deployer</a> ins Spiel. TFS Deployer installiert man als Windowsdienst. Nach entsprechender
Konfiguration lauscht er nun auf eine Änderung der Buildqualität. Dazu muss
der Benutzer unter dem der Dienst läuft allerdings in der TFS Gruppe Valid Users
sein und für das entsprechende Temaprojekt zumindest Leserechte haben. Bemerkt
TFS Deployer nun einen Statusübergang, für den er ein Deploymentscript hat,
führ er dieses automatisch aus.
</p>
        <p>
Angelehnt an die Einführung von <a title="Installation of TFSDeployer" href="http://traceofthought.net/misc/tfsdeployersetup.htm" target="_blank">Dave
Comfort und Scott Colestock</a> kann man sich das ganze nun wie folgt vorstellen:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/TransportsystemalaSAPmitTFSundASP.NET_6C94/tfsdeployer.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="125" alt="tfsdeployer" src="http://blog.codemurai.de/images/TransportsystemalaSAPmitTFSundASP.NET_6C94/tfsdeployer_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Konkret sieht dies so aus, dass innerhalb der TFS Quellcodeverwaltung unterhalb des
Verzeichnisses der Builddefinition ein Verzeichnis Deployment angelegt wird, also
zum Beispiel <em>$/TeamProjekt/TeamBuildTypes/MeinProjektNightlyBuild/Deployment</em>.
In diesem Verzeichnis wird nun die Datei <em>DeploymentMappings.xml</em> angelegt.
In dieser Datei wird für jeden gewünschten Statusübergang festgelegt,
welches Powershellscript auf welchem Computer ablaufen soll. Die Datei DeploymentMappings
kann zum Beispiel wie folgt aussehen:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4496125c-e9e5-486e-bd3b-1d3e5d0bf992" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;DeploymentMappings xmlns="http://www.readify.net/TFSDeployer/DeploymentMappings20061026"&gt;
  &lt;Mapping xmlns=""
           Computer="tfsbuildserver"
           OriginalQuality="*"
           NewQuality="Entwicklung"
           Script="EntwicklerDrop.ps1"
           RunnerType="PowerShell"
           NotificationAddress="someone@mycompany.com;someoneelse@mycompany.com" /&gt;
  &lt;Mapping xmlns=""
           Computer="tfsbuildserver"
           OriginalQuality="Entwicklung"
           NewQuality="Test"
           Script="EntwicklungNachTest.ps1"
           RunnerType="PowerShell"
           NotificationAddress="someone@mycompany.com;someoneelse@mycompany.com" /&gt;
  &lt;Mapping xmlns=""
           Computer="tfsbuildserver"
           OriginalQuality="Test"
           NewQuality="Integration"
           Script="TestNachIntegration.ps1"
           RunnerType="PowerShell"
           NotificationAddress="someone@mycompany.com;someoneelse@mycompany.com" /&gt;
  &lt;Mapping xmlns=""
           Computer="tfsbuildserver"
           OriginalQuality="Integration"
           NewQuality="Produktion"
           Script="TestNachIntegration.ps1"
           RunnerType="PowerShell"
           NotificationAddress="someone@mycompany.com;someoneelse@mycompany.com" /&gt;
&lt;/DeploymentMappings&gt;</pre>
        </div>
        <p>
In diesem Script werden vier Statusübergänge definiert. Erst vom leeren
Zustand nach Entwicklung, dann weiter nach Test, Integration und Produktion. Jeder
dieser Status entspricht einem Build-Quality Eintrag im TFS. Diese sind wie angemerkt
frei definierbar. Über die Eigenschaft Script wird nun definiert, welches Powershellscript
ausgeführt werden soll. Diese Powershellscripte müssen übrigens im
selben Ordner liegen, wie die Datei DeploymentMappings.xml.
</p>
        <p>
Tritt nun einer der definierten Statusübergänge auf, ruft TFS Deployer das
gewünschte Script im Kontext des Service Users auf und übergibt ein <a title="Beschreibung der Builddata Klasse in der MSDN" href="http://go2.wordpress.com/?id=725X1342&amp;site=notgartner.wordpress.com&amp;url=http%3A%2F%2Fmsdn2.microsoft.com%2Fen-us%2Flibrary%2Fmicrosoft.teamfoundation.build.proxy.builddata_members.aspx" target="_blank">BuildData
Objekt</a>. Die verschiedenen des Eigenschaften BulidData Objekts können dann
über die Variable $TfsDeployerBuildData zugegriffen werden.
</p>
        <p>
In unserer Umgebung nutzen wir übrigens eine modifzierte Variante des Beispiels
der Seite <a title="Using TFSDeployer for Staging Builds" href="http://www.tfsbuild.com/Default.aspx?Page=UsingTFSDeployer&amp;AspxAutoDetectCookieSupport=1" target="_blank">Team
Foundation Server Build Recipes</a>.
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:3c299590-9f70-4c04-bc36-f88833c85fb0" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">function publish-site( [string] $sourcepath, [string] $destinationpath, [bool] $renameconfig, [bool] $deleteexisting) {
	$droplocation = $TfsDeployerBuildData.DropLocation
	
	$websourcepath = $droplocation + $sourcepath
	$webdestinationpath = $destinationpath
	
	new-item -force -path $webdestinationpath -itemtype "directory"
	if ($deleteexisting) {
		get-childitem $webdestinationpath | remove-item -force -recurse
	}
	get-childitem $websourcepath | copy-item -force -recurse -destination $webdestinationpath

	if ($renameconfig) {
		$configFile = $webdestinationpath + "web.production.config"
		remove-item $configFile -force
		$configFile = $webdestinationpath + "web.development.config"
		remove-item $configFile -force
		$configFile = $webdestinationpath + integration.config"
		remove-item $configFile -force


		$configFile = $webdestinationpath + "web.test.config"
		$configFileDest = $webdestinationpath + "web.config"
		move-item $configFile $configFileDest -force
	}
}

publish-site "\Release\_PublishedWebsites\MyWebApplication\" "\\MeinWebServer\MeineFreigabe\" 1 1

</pre>
        </div>
        <p>
Dies funktioniert in unserer Umgebung recht gut, da wir vom Build Server direkten
Zugriff auf die verschiedenen Web Server (Entwicklung, Test, Integration, Produktion)
haben. Für jede Webapplikation besteht auf den Servern eine Windows Freigabe,
die direkt auf das Wurzelverzeichnis der Applikation zeigt. Zugriffsrechte hat hier
nun der Benutzer, unter der TFS Deployer Dienst läuft. So stellen wir sicher,
dass keiner der Entwickler "mal schnell" etwas patcht ;-) Noch sicherer
wäre es natürlich gewesen, den TFS Deployer Dienst direkt auf dem Web Server
laufen zu lassen, und ihm lesenden Zugriff auf die erstellen Binaries des Buildprozesses
zu geben. 
</p>
        <p>
Als Erweiterung zum Standardscript <em>wärmen</em> wir nach dem Deployment Vorgang
die Applikation noch auf, indem wir einige Seiten ansurfen. Somit ist sichergestellt,
dass der Workerprozess beim ersten Zugriff durch einen Benutzer schon da ist und die
entsprechenden Seiten auch schon kompiliert wurden.
</p>
        <p>
Den Übergang von "Nichts" zu "Entwicklung" machen wir übrigens
automatisch als letzten Schritt unseres Buildscripts. Somit wird der Nightly Build
Automatisch in die Entwicklungsumgebung gejagt.
</p>
        <h4>Und was hat man nun davon?
</h4>
        <p>
Mit dem TFS Deployer haben Nutzer des TFS eine einfache Möglichkeit, benannte
Softwarestände automatisch in verschiedene Umgebungen zu verteilen. Die dadurch
entstehende Nachvollziehbarkeit lässt aus meiner Erfahrung Kunden und somit auch
die Projektverantwortlichen im internen Team besser schlafen.
</p>
        <p>
Ein wenig schade ist, dass man innerhalb des TFS zwar verschiedene Buildqualitäten,
jedoch keine Regeln für gültige Übergänge anlegen kann. Da unsere
Scripte jedoch auf festen Übergängen definieren bedeutet dies, dass derjenige,
der die Buildqualität setzt, genau wissen muss welche Übergänge gültig
sind. Schaltet er nämlich zum Beispiel von Test direkt auf Produktion passiert
nämlich nichts.
</p>
        <p>
Angeregt zu diesem Blog Post hat mich übrigens <a href="http://code-inside.de" target="_blank">Robert
Mühsigs</a> Posts <a href="http://code-inside.de/blog/2010/03/19/howtocode-builddeploymentwtf-oder-auch-automatisierung-mit-msbuild/" target="_blank">Build
/ Deployment / WTF</a>.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=0563b42b-487d-4fc2-90ca-f9fecb9e9541" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Transportsystem alla SAP mit TFS und ASP.NET</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,0563b42b-487d-4fc2-90ca-f9fecb9e9541.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/25/TransportsystemAllaSAPMitTFSUndASPNET.aspx</link>
      <pubDate>Thu, 25 Mar 2010 06:11:43 GMT</pubDate>
      <description>&lt;p&gt;
Von Administratoren geliebt, von Entwicklern verflucht: Das Transportsystem von SAP.
Prinzipiell kann man sich das so vorstellen, dass dieses System vorsieht, dass der
Quellcode nur an einer Stelle, n&amp;#228;mlich im SAP Entwicklungssystem erstellt und
modifiziert wird.
&lt;/p&gt;
&lt;p&gt;
Anschlie&amp;#223;end wird ein sogenannter Transport (so was &amp;#228;hnliches wie ein Setuppaket)
erstellt. Dieses kann dann je Konfiguration erst mal nur in das Testsystem eingespielt
werden. Dort wird das Paket auf seine Funktionst&amp;#252;chtigkeit getestet. Wurden diese
Tests bestanden, wird es in das Integrationssystem &amp;quot;transportiert&amp;quot;. Dort
wird das Zusammenspiel mit anderen Anpassungen getestet, es wird also gepr&amp;#252;ft,
ob das Paket nichts anderes kaputt macht ;-)
&lt;/p&gt;
&lt;p&gt;
War auch dieser Test erfolgreich, wird der Transport aus dem Integrationssystem in
das Produktionssystem transportiert. Ein direktes Einspielen von Transporten in das
Produktionssystem beziehungsweise sogar ein direktes &amp;#196;ndern der Quellcodes ist
nicht vorgesehen.
&lt;/p&gt;
&lt;p&gt;
Auch wenn diese Vorgehensweise zun&amp;#228;chst recht streng, b&amp;#252;rokratisch und viel
zu aufw&amp;#228;ndig wirkt, hat sie durchaus ihren Sinn. Dieser zugegeben etwas starre
Prozess sorgt daf&amp;#252;r, dass SAP Produktionssysteme normalerweise immer stabil und
m&amp;#246;glichst fehlerfrei sein sollten. Er tr&amp;#228;gt also Ma&amp;#223;geblich zu SAPs
gutem Ruf bei!
&lt;/p&gt;
&lt;h4&gt;Warum erz&amp;#228;hle ich das eigentlich?
&lt;/h4&gt;
&lt;p&gt;
Ok, nette Einf&amp;#252;hrung, aber ist das hier nicht eigentlich ein auf .NET fokussierter
Blog? &lt;strong&gt;Ja :-)&lt;/strong&gt; Also keine Sorge, ich bin nicht ins Lager der SAP Consultants
gewechselt ;-) Allerdings habe ich von ungef&amp;#228;hr 2005 bis 2008 die SAP Schnittstelle
meines ehemaligen Arbeitgebers gemeinsam mit einem Kollegen weiterentwickelt. Da blieb
der ein oder andere Blick unter die Haube diverser SAP Systeme nicht aus.
&lt;/p&gt;
&lt;p&gt;
Nun aber zur&amp;#252;ck zum Thema: 
&lt;/p&gt;
&lt;p&gt;
In meiner beruflichen Laufbahn war ich an einigen (ASP).NET Projekte beteiligt, die
von einem SAP transport&amp;#228;hnlichen System sehr profitiert h&amp;#228;tten. &amp;#220;berspitzt
gesagt sah es dort n&amp;#228;mlich h&amp;#228;ufig so aus, dass ein Entwickler nach einer
Quellcode&amp;#228;nderung Visual Studio genutzt hat um einen neuen Releasestand zu erstellen
und diesen dann schnell auf den produktiven Webserver gepackt hat. Selbstverst&amp;#228;ndlich
wurde das ganze vorher &lt;em&gt;nicht&lt;/em&gt; in einem Test- oder Integrationssystem installiert
und unter Umst&amp;#228;nden wusste der Kunde und/oder Projektleiter sogar nichts von
dem adhoc Update.
&lt;/p&gt;
&lt;h4&gt;Agil != Chaos !!!
&lt;/h4&gt;
&lt;p&gt;
Der Entwickler handelte unter dem Deckmantel der &lt;em&gt;agilen Entwicklung&lt;/em&gt; nach
dem Prinzip &amp;quot;&lt;em&gt;nach mir die Sinnflut&lt;/em&gt;&amp;quot;, einfach drauf damit, wird
schon klappen. In diesem Zusammenhang finde ich es &amp;#252;brigens immer wieder &amp;#228;u&amp;#223;erst
verwunderlich, wie viele Entwickler unkoordiniertes und schlampiges Vorgehen einfach
als &lt;em&gt;agil&lt;/em&gt; bezeichnen, um ihr Chaos damit zu entschuldigen. Agil ist allerdings
alles andere als chaotisch, unprofessionell, unkoordiniert oder schlampig. Aber gut,
dass ist ein anderes Thema - ich schweife schon wieder aus ;-)
&lt;/p&gt;
&lt;p&gt;
In einem meiner aktuellen Projekte wollte ich einer solchen Vorgehensweise direkt
einen Riegel vorschieben. Nicht dass die Entwickler dieses Projekts chaotisch w&amp;#228;ren,
das ist ganz und gar nicht der Fall, aber wir wollen ja auch niemanden in Versuchung
f&amp;#252;hren ;-)
&lt;/p&gt;
&lt;h4&gt;Ich hatte einen Traum ...
&lt;/h4&gt;
&lt;p&gt;
Meine Ziele lautete also wie folgt:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Releasest&amp;#228;nde einer Software sollen automatisch auf einem dedizierten Buildrechner
und nicht auf einem Entwickler-PC erstellt werden. 
&lt;/li&gt;
&lt;li&gt;
Jedes Release hat eine eindeutige Versionsnummer. Kompilate auf dem Entwicklerrechner
haben jedoch immer die Nummer 1.0.0.0 (dazu sp&amp;#228;ter mehr) 
&lt;/li&gt;
&lt;li&gt;
Jedes Release soll ein Set an Unit Tests durchlaufen haben. 
&lt;/li&gt;
&lt;li&gt;
Jedes Release soll mit einer bestimmten &lt;em&gt;Qualit&amp;#228;t&lt;/em&gt; als Metadatum versehen
werden. 
&lt;/li&gt;
&lt;li&gt;
In Abh&amp;#228;ngigkeit von dieser Qualit&amp;#228;t und der vorherigen Qualit&amp;#228;t soll
die Software bei bestimmten Status&amp;#252;berg&amp;#228;ngen automatisch auf bestimmte Systeme
verteilt werden. 
&lt;/li&gt;
&lt;li&gt;
Das Qualit&amp;#228;tsmetadatum wird durch einen dedizierten Personenkreis gesetzt (zum
Beispiel QM-Manager oder Projektmanager, Softwarearchitekt oder Chefentwickler) 
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Realisiert werden sollte das ganze mit Visual Studio 2008 und dem Team Foundation
Server. Die Punkte 1 - 3 stellen in einer solchen Umgebung kein Problem dar. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Punkt Nr. 1&lt;/strong&gt; erledigen wir durch Teambuild. Hier l&amp;#228;uft ein Buildagent
auf einem dedizierten Rechner. Durchgef&amp;#252;hrt werden sowohl Continuous Integration
Builds, als auch Nightly Builds.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Punkt Nr. 2&lt;/strong&gt; haben wir durch ein einfaches Build Target in unserem
Buildscript erledigt. Die Versionsnummer haben wir wie folgt aufgebaut:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Major: Fixer Wert 
&lt;/li&gt;
&lt;li&gt;
Minor: Fixer Wert 
&lt;/li&gt;
&lt;li&gt;
Build: Aktueller Changeset des Teamprojekts im TFS 
&lt;/li&gt;
&lt;li&gt;
Revision: Fortlaufende Nummer 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Diese Nummer wird nur w&amp;#228;hrend des Builds durch Teambuild erzeugt. Entwicklerbuilds
haben immer die Version 1.0.0.0. So fange ich ab, dass ein Entwickler doch einfach
mal auf seinem Rechner eine Version baut und versucht zu deployen. Nat&amp;#252;rlich
ist dies nur ein &lt;em&gt;weicher&lt;/em&gt; Schutz. Mit ein wenig Aufwand l&amp;#228;sst sich das
System nat&amp;#252;rlich leicht umgehen indem ein Entwickler eine korrekte Versionsnummer
erzeugt. Allerdings ist der Aufwand schon wieder so hoch, dass sich dann doch lohnt,
den vorgesehenen Prozess einzuhalten ;-)
&lt;/p&gt;
&lt;p&gt;
Sollte jemand Interesse an diesem Teil des Buildscripts haben: Einfach einen Kommentar
posten.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Punkt Nr. 3&lt;/strong&gt; ist nat&amp;#252;rlich auch kein Problem. Aufgrund der guten
VS Integration haben wir uns f&amp;#252;r MS Test f&amp;#252;r dieses Projekt entschieden.
Diese Tests als Bestandteil des Buildprozess laufen zu lassen war demnach kein Problem.
&lt;/p&gt;
&lt;p&gt;
Punkt Nr. 4 ist auch bereits von Haus aus mit dem TFS m&amp;#246;glich. Jeder Build der
durch Teambuild durchgef&amp;#252;hrt wird hat ein Metadatum Buildqualit&amp;#228;t. Die m&amp;#246;glichen
Werte der Buildqualit&amp;#228;t lassen sich frei definieren. Auch l&amp;#228;sst sich &amp;#252;ber
entsprechende Rechte einschr&amp;#228;nken, wer diese Qualit&amp;#228;t setzen darf. Wir haben
bei uns die Werte &lt;em&gt;&amp;quot;Entwicklung&amp;quot;&lt;/em&gt;, &lt;em&gt;&amp;quot;Test&amp;quot;&lt;/em&gt;, &lt;em&gt;&amp;quot;Integration&amp;quot;&lt;/em&gt;, &lt;em&gt;&amp;quot;Produktion&amp;quot;&lt;/em&gt; und &lt;em&gt;&amp;quot;Abgelehnt&amp;quot;&lt;/em&gt; definiert.
&lt;/p&gt;
&lt;p&gt;
Punkt Nr. 5 kann mit TFS Bordmitteln erst mal nicht realisiert werden. Hier kommt
nun das Open Source Projekt &lt;a title="TFS Deployer Codeplex Seite" href="http://www.codeplex.com/tfsdeployer" target="_blank"&gt;TFS
Deployer&lt;/a&gt; ins Spiel. TFS Deployer installiert man als Windowsdienst. Nach entsprechender
Konfiguration lauscht er nun auf eine &amp;#196;nderung der Buildqualit&amp;#228;t. Dazu muss
der Benutzer unter dem der Dienst l&amp;#228;uft allerdings in der TFS Gruppe Valid Users
sein und f&amp;#252;r das entsprechende Temaprojekt zumindest Leserechte haben. Bemerkt
TFS Deployer nun einen Status&amp;#252;bergang, f&amp;#252;r den er ein Deploymentscript hat,
f&amp;#252;hr er dieses automatisch aus.
&lt;/p&gt;
&lt;p&gt;
Angelehnt an die Einf&amp;#252;hrung von &lt;a title="Installation of TFSDeployer" href="http://traceofthought.net/misc/tfsdeployersetup.htm" target="_blank"&gt;Dave
Comfort und Scott Colestock&lt;/a&gt; kann man sich das ganze nun wie folgt vorstellen:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/TransportsystemalaSAPmitTFSundASP.NET_6C94/tfsdeployer.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="125" alt="tfsdeployer" src="http://blog.codemurai.de/images/TransportsystemalaSAPmitTFSundASP.NET_6C94/tfsdeployer_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Konkret sieht dies so aus, dass innerhalb der TFS Quellcodeverwaltung unterhalb des
Verzeichnisses der Builddefinition ein Verzeichnis Deployment angelegt wird, also
zum Beispiel &lt;em&gt;$/TeamProjekt/TeamBuildTypes/MeinProjektNightlyBuild/Deployment&lt;/em&gt;.
In diesem Verzeichnis wird nun die Datei &lt;em&gt;DeploymentMappings.xml&lt;/em&gt; angelegt.
In dieser Datei wird f&amp;#252;r jeden gew&amp;#252;nschten Status&amp;#252;bergang festgelegt,
welches Powershellscript auf welchem Computer ablaufen soll. Die Datei DeploymentMappings
kann zum Beispiel wie folgt aussehen:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4496125c-e9e5-486e-bd3b-1d3e5d0bf992" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;DeploymentMappings xmlns="http://www.readify.net/TFSDeployer/DeploymentMappings20061026"&amp;gt;
  &amp;lt;Mapping xmlns=""
           Computer="tfsbuildserver"
           OriginalQuality="*"
           NewQuality="Entwicklung"
           Script="EntwicklerDrop.ps1"
           RunnerType="PowerShell"
           NotificationAddress="someone@mycompany.com;someoneelse@mycompany.com" /&amp;gt;
  &amp;lt;Mapping xmlns=""
           Computer="tfsbuildserver"
           OriginalQuality="Entwicklung"
           NewQuality="Test"
           Script="EntwicklungNachTest.ps1"
           RunnerType="PowerShell"
           NotificationAddress="someone@mycompany.com;someoneelse@mycompany.com" /&amp;gt;
  &amp;lt;Mapping xmlns=""
           Computer="tfsbuildserver"
           OriginalQuality="Test"
           NewQuality="Integration"
           Script="TestNachIntegration.ps1"
           RunnerType="PowerShell"
           NotificationAddress="someone@mycompany.com;someoneelse@mycompany.com" /&amp;gt;
  &amp;lt;Mapping xmlns=""
           Computer="tfsbuildserver"
           OriginalQuality="Integration"
           NewQuality="Produktion"
           Script="TestNachIntegration.ps1"
           RunnerType="PowerShell"
           NotificationAddress="someone@mycompany.com;someoneelse@mycompany.com" /&amp;gt;
&amp;lt;/DeploymentMappings&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
In diesem Script werden vier Status&amp;#252;berg&amp;#228;nge definiert. Erst vom leeren
Zustand nach Entwicklung, dann weiter nach Test, Integration und Produktion. Jeder
dieser Status entspricht einem Build-Quality Eintrag im TFS. Diese sind wie angemerkt
frei definierbar. &amp;#220;ber die Eigenschaft Script wird nun definiert, welches Powershellscript
ausgef&amp;#252;hrt werden soll. Diese Powershellscripte m&amp;#252;ssen &amp;#252;brigens im
selben Ordner liegen, wie die Datei DeploymentMappings.xml.
&lt;/p&gt;
&lt;p&gt;
Tritt nun einer der definierten Status&amp;#252;berg&amp;#228;nge auf, ruft TFS Deployer das
gew&amp;#252;nschte Script im Kontext des Service Users auf und &amp;#252;bergibt ein &lt;a title="Beschreibung der Builddata Klasse in der MSDN" href="http://go2.wordpress.com/?id=725X1342&amp;amp;site=notgartner.wordpress.com&amp;amp;url=http%3A%2F%2Fmsdn2.microsoft.com%2Fen-us%2Flibrary%2Fmicrosoft.teamfoundation.build.proxy.builddata_members.aspx" target="_blank"&gt;BuildData
Objekt&lt;/a&gt;. Die verschiedenen des Eigenschaften BulidData Objekts k&amp;#246;nnen dann
&amp;#252;ber die Variable $TfsDeployerBuildData zugegriffen werden.
&lt;/p&gt;
&lt;p&gt;
In unserer Umgebung nutzen wir &amp;#252;brigens eine modifzierte Variante des Beispiels
der Seite &lt;a title="Using TFSDeployer for Staging Builds" href="http://www.tfsbuild.com/Default.aspx?Page=UsingTFSDeployer&amp;amp;AspxAutoDetectCookieSupport=1" target="_blank"&gt;Team
Foundation Server Build Recipes&lt;/a&gt;.
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:3c299590-9f70-4c04-bc36-f88833c85fb0" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;function publish-site( [string] $sourcepath, [string] $destinationpath, [bool] $renameconfig, [bool] $deleteexisting) {
	$droplocation = $TfsDeployerBuildData.DropLocation
	
	$websourcepath = $droplocation + $sourcepath
	$webdestinationpath = $destinationpath
	
	new-item -force -path $webdestinationpath -itemtype "directory"
	if ($deleteexisting) {
		get-childitem $webdestinationpath | remove-item -force -recurse
	}
	get-childitem $websourcepath | copy-item -force -recurse -destination $webdestinationpath

	if ($renameconfig) {
		$configFile = $webdestinationpath + "web.production.config"
		remove-item $configFile -force
		$configFile = $webdestinationpath + "web.development.config"
		remove-item $configFile -force
		$configFile = $webdestinationpath + integration.config"
		remove-item $configFile -force


		$configFile = $webdestinationpath + "web.test.config"
		$configFileDest = $webdestinationpath + "web.config"
		move-item $configFile $configFileDest -force
	}
}

publish-site "\Release\_PublishedWebsites\MyWebApplication\" "\\MeinWebServer\MeineFreigabe\" 1 1

&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Dies funktioniert in unserer Umgebung recht gut, da wir vom Build Server direkten
Zugriff auf die verschiedenen Web Server (Entwicklung, Test, Integration, Produktion)
haben. F&amp;#252;r jede Webapplikation besteht auf den Servern eine Windows Freigabe,
die direkt auf das Wurzelverzeichnis der Applikation zeigt. Zugriffsrechte hat hier
nun der Benutzer, unter der TFS Deployer Dienst l&amp;#228;uft. So stellen wir sicher,
dass keiner der Entwickler &amp;quot;mal schnell&amp;quot; etwas patcht ;-) Noch sicherer
w&amp;#228;re es nat&amp;#252;rlich gewesen, den TFS Deployer Dienst direkt auf dem Web Server
laufen zu lassen, und ihm lesenden Zugriff auf die erstellen Binaries des Buildprozesses
zu geben. 
&lt;/p&gt;
&lt;p&gt;
Als Erweiterung zum Standardscript &lt;em&gt;w&amp;#228;rmen&lt;/em&gt; wir nach dem Deployment Vorgang
die Applikation noch auf, indem wir einige Seiten ansurfen. Somit ist sichergestellt,
dass der Workerprozess beim ersten Zugriff durch einen Benutzer schon da ist und die
entsprechenden Seiten auch schon kompiliert wurden.
&lt;/p&gt;
&lt;p&gt;
Den &amp;#220;bergang von &amp;quot;Nichts&amp;quot; zu &amp;quot;Entwicklung&amp;quot; machen wir &amp;#252;brigens
automatisch als letzten Schritt unseres Buildscripts. Somit wird der Nightly Build
Automatisch in die Entwicklungsumgebung gejagt.
&lt;/p&gt;
&lt;h4&gt;Und was hat man nun davon?
&lt;/h4&gt;
&lt;p&gt;
Mit dem TFS Deployer haben Nutzer des TFS eine einfache M&amp;#246;glichkeit, benannte
Softwarest&amp;#228;nde automatisch in verschiedene Umgebungen zu verteilen. Die dadurch
entstehende Nachvollziehbarkeit l&amp;#228;sst aus meiner Erfahrung Kunden und somit auch
die Projektverantwortlichen im internen Team besser schlafen.
&lt;/p&gt;
&lt;p&gt;
Ein wenig schade ist, dass man innerhalb des TFS zwar verschiedene Buildqualit&amp;#228;ten,
jedoch keine Regeln f&amp;#252;r g&amp;#252;ltige &amp;#220;berg&amp;#228;nge anlegen kann. Da unsere
Scripte jedoch auf festen &amp;#220;berg&amp;#228;ngen definieren bedeutet dies, dass derjenige,
der die Buildqualit&amp;#228;t setzt, genau wissen muss welche &amp;#220;berg&amp;#228;nge g&amp;#252;ltig
sind. Schaltet er n&amp;#228;mlich zum Beispiel von Test direkt auf Produktion passiert
n&amp;#228;mlich nichts.
&lt;/p&gt;
&lt;p&gt;
Angeregt zu diesem Blog Post hat mich &amp;#252;brigens &lt;a href="http://code-inside.de" target="_blank"&gt;Robert
M&amp;#252;hsigs&lt;/a&gt; Posts &lt;a href="http://code-inside.de/blog/2010/03/19/howtocode-builddeploymentwtf-oder-auch-automatisierung-mit-msbuild/" target="_blank"&gt;Build
/ Deployment / WTF&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=0563b42b-487d-4fc2-90ca-f9fecb9e9541" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,0563b42b-487d-4fc2-90ca-f9fecb9e9541.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>TFS</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=f0b839c5-a1c4-41ce-863b-e234d4651c9e</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,f0b839c5-a1c4-41ce-863b-e234d4651c9e.aspx</pingback:target>
      <dc:creator>Admin</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,f0b839c5-a1c4-41ce-863b-e234d4651c9e.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=f0b839c5-a1c4-41ce-863b-e234d4651c9e</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">Cool, mein <a href="http://blog.codemurai.de/2010/01/22/DieGeschichteDesViewStatesIstEineGeschichteMit.aspx">Blogeintrag
zum Thema Viewstate</a> hat es auf die<a href="http://www.asp.net/de/"> offizielle
Microsoft ASP.NET</a> Seite geschaft. Nun ja, zumindest auf die deutsche Variante
davon :-)<br /><p></p><img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=f0b839c5-a1c4-41ce-863b-e234d4651c9e" /><br /><hr /><a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Artikel auf der offiziellen Microsoft ASP.NET Seite</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,f0b839c5-a1c4-41ce-863b-e234d4651c9e.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/23/ArtikelAufDerOffiziellenMicrosoftASPNETSeite.aspx</link>
      <pubDate>Tue, 23 Mar 2010 14:20:14 GMT</pubDate>
      <description>Cool, mein &lt;a href="http://blog.codemurai.de/2010/01/22/DieGeschichteDesViewStatesIstEineGeschichteMit.aspx"&gt;Blogeintrag
zum Thema Viewstate&lt;/a&gt; hat es auf die&lt;a href="http://www.asp.net/de/"&gt; offizielle
Microsoft ASP.NET&lt;/a&gt; Seite geschaft. Nun ja, zumindest auf die deutsche Variante
davon :-)&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=f0b839c5-a1c4-41ce-863b-e234d4651c9e" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,f0b839c5-a1c4-41ce-863b-e234d4651c9e.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=256a855d-b79d-424a-8f0e-5b6138c7ea42</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,256a855d-b79d-424a-8f0e-5b6138c7ea42.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,256a855d-b79d-424a-8f0e-5b6138c7ea42.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=256a855d-b79d-424a-8f0e-5b6138c7ea42</wfw:commentRss>
      <slash:comments>10</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Vor einiger Zeit habe ich ein kurzes Tutorial zur Bedienung der Windows Debugging
Tools hier in <a title="WinDbg Tutorial" href="http://blog.codemurai.de/2009/09/04/WinDbgTutorialFehlerursachenFindenTeil1EinerSerie.aspx" target="_blank">meinem
Blog veröffentlicht</a>.
</p>
        <p>
Dieses Tutorial traf auf großen Anklang. Zumindest wenn ich meinen Statistiken
trauen darf. Denn laut diesen kommen die meisten Besucher durch eine Google Suche
nach WinDbg auf mein Blog.
</p>
        <p>
Um dieser Tatsache gerecht zu werden, habe ich mich dazu entschlossen das ursprüngliche
Tutorial nun auch als Video bereit zu stellen. Ich hoffe damit auch Gregor zufrieden
zu stellen, der meinte dass die geschriebene Variante doch etwas schwierig zu befolgen
wäre ;-) 
</p>
        <p>
          <object id="csSWF" height="498" width="640" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">
            <param name="_cx" value="16933" />
            <param name="_cy" value="13176" />
            <param name="FlashVars" value="" />
            <param name="Movie" value="http://www.codementor.de/media/windbg/1/windbg1_controller.swf" />
            <param name="Src" value="http://www.codementor.de/media/windbg/1/windbg1_controller.swf" />
            <param name="WMode" value="Window" />
            <param name="Play" value="0" />
            <param name="Loop" value="-1" />
            <param name="Quality" value="High" />
            <param name="SAlign" value="" />
            <param name="Menu" value="-1" />
            <param name="Base" value="" />
            <param name="AllowScriptAccess" value="always" />
            <param name="Scale" value="ShowAll" />
            <param name="DeviceFont" value="0" />
            <param name="EmbedMovie" value="0" />
            <param name="BGColor" value="1A1A1A" />
            <param name="SWRemote" value="" />
            <param name="MovieData" value="" />
            <param name="SeamlessTabbing" value="1" />
            <param name="Profile" value="0" />
            <param name="ProfileAddress" value="" />
            <param name="ProfilePort" value="0" />
            <param name="AllowNetworking" value="all" />
            <param name="AllowFullScreen" value="true" />
            <!--[if !IE]>-->
            <object type="application/x-shockwave-flash" data="http://www.codementor.de/media/windbg/1/windbg1_controller.swf" width="640" height="498">
              <param name="quality" value="best" />
              <param name="bgcolor" value="#1a1a1a" />
              <param name="allowfullscreen" value="true" />
              <param name="scale" value="showall" />
              <param name="allowscriptaccess" value="always" />
              <param name="flashvars" value="autostart=false&amp;thumb=http://www.codementor.de/media/windbg/1/FirstFrame.png&amp;thumbscale=45&amp;color=0x000000,0x000000" />
              <!--<![endif]-->
              <div id="noUpdate">
                <p>
The Camtasia Studio video content presented here requires a more recent version of
the Adobe Flash Player. If you are you using a browser with JavaScript disabled please
enable it now. Otherwise, please update your version of the free Flash Player by <a href="http://www.adobe.com/go/getflashplayer">downloading
here</a>.
</p>
              </div>
              <!--[if !IE]>-->
            </object>
            <!--<![endif]-->
          </object>
        </p>
        <p>
Über Kommentare und Rückfragen würde ich mich sowohl hier auf meinem
Blog, als auch unter der im Video angegebenen E-Mail Adresse sehr freuen.
</p>
        <p>
          <em>War dieser Eintrag hilfreich für dich? Dann kicke ihn doch bitte.</em>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=256a855d-b79d-424a-8f0e-5b6138c7ea42" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>WinDbg Videotutorial</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,256a855d-b79d-424a-8f0e-5b6138c7ea42.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/19/WinDbgVideotutorial.aspx</link>
      <pubDate>Fri, 19 Mar 2010 00:19:48 GMT</pubDate>
      <description>&lt;p&gt;
Vor einiger Zeit habe ich ein kurzes Tutorial zur Bedienung der Windows Debugging
Tools hier in &lt;a title="WinDbg Tutorial" href="http://blog.codemurai.de/2009/09/04/WinDbgTutorialFehlerursachenFindenTeil1EinerSerie.aspx" target="_blank"&gt;meinem
Blog ver&amp;#246;ffentlicht&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Dieses Tutorial traf auf gro&amp;#223;en Anklang. Zumindest wenn ich meinen Statistiken
trauen darf. Denn laut diesen kommen die meisten Besucher durch eine Google Suche
nach WinDbg auf mein Blog.
&lt;/p&gt;
&lt;p&gt;
Um dieser Tatsache gerecht zu werden, habe ich mich dazu entschlossen das urspr&amp;#252;ngliche
Tutorial nun auch als Video bereit zu stellen. Ich hoffe damit auch Gregor zufrieden
zu stellen, der meinte dass die geschriebene Variante doch etwas schwierig zu befolgen
w&amp;#228;re ;-) 
&lt;/p&gt;
&lt;p&gt;
&lt;object id="csSWF" height="498" width="640" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;
&lt;param name="_cx" value="16933"&gt;
&lt;param name="_cy" value="13176"&gt;
&lt;param name="FlashVars" value=""&gt;
&lt;param name="Movie" value="http://www.codementor.de/media/windbg/1/windbg1_controller.swf"&gt;
&lt;param name="Src" value="http://www.codementor.de/media/windbg/1/windbg1_controller.swf"&gt;
&lt;param name="WMode" value="Window"&gt;
&lt;param name="Play" value="0"&gt;
&lt;param name="Loop" value="-1"&gt;
&lt;param name="Quality" value="High"&gt;
&lt;param name="SAlign" value=""&gt;
&lt;param name="Menu" value="-1"&gt;
&lt;param name="Base" value=""&gt;
&lt;param name="AllowScriptAccess" value="always"&gt;
&lt;param name="Scale" value="ShowAll"&gt;
&lt;param name="DeviceFont" value="0"&gt;
&lt;param name="EmbedMovie" value="0"&gt;
&lt;param name="BGColor" value="1A1A1A"&gt;
&lt;param name="SWRemote" value=""&gt;
&lt;param name="MovieData" value=""&gt;
&lt;param name="SeamlessTabbing" value="1"&gt;
&lt;param name="Profile" value="0"&gt;
&lt;param name="ProfileAddress" value=""&gt;
&lt;param name="ProfilePort" value="0"&gt;
&lt;param name="AllowNetworking" value="all"&gt;
&lt;param name="AllowFullScreen" value="true"&gt;
&lt;!--[if !IE]&gt;--&gt;
&lt;object type="application/x-shockwave-flash" data="http://www.codementor.de/media/windbg/1/windbg1_controller.swf" width="640" height="498"&gt;
&lt;param name="quality" value="best" /&gt;
&lt;param name="bgcolor" value="#1a1a1a" /&gt;
&lt;param name="allowfullscreen" value="true" /&gt;
&lt;param name="scale" value="showall" /&gt;
&lt;param name="allowscriptaccess" value="always" /&gt;
&lt;param name="flashvars" value="autostart=false&amp;amp;thumb=http://www.codementor.de/media/windbg/1/FirstFrame.png&amp;amp;thumbscale=45&amp;amp;color=0x000000,0x000000" /&gt;
&lt;!--&lt;![endif]--&gt;
&lt;div id="noUpdate"&gt;
&lt;p&gt;
The Camtasia Studio video content presented here requires a more recent version of
the Adobe Flash Player. If you are you using a browser with JavaScript disabled please
enable it now. Otherwise, please update your version of the free Flash Player by &lt;a href="http://www.adobe.com/go/getflashplayer"&gt;downloading
here&lt;/a&gt;.
&lt;/p&gt;
&lt;/div&gt;
&lt;!--[if !IE]&gt;--&gt;
&lt;/object&gt;
&lt;!--&lt;![endif]--&gt;
&lt;/object&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;#220;ber Kommentare und R&amp;#252;ckfragen w&amp;#252;rde ich mich sowohl hier auf meinem
Blog, als auch unter der im Video angegebenen E-Mail Adresse sehr freuen.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;War dieser Eintrag hilfreich f&amp;#252;r dich? Dann kicke ihn doch bitte.&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=256a855d-b79d-424a-8f0e-5b6138c7ea42" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,256a855d-b79d-424a-8f0e-5b6138c7ea42.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Tutorials</category>
      <category>WinDbg</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=8291e19a-6861-4446-af5e-c1faa9352c95</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,8291e19a-6861-4446-af5e-c1faa9352c95.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,8291e19a-6861-4446-af5e-c1faa9352c95.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=8291e19a-6861-4446-af5e-c1faa9352c95</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Wie <a title="Stephen Walters Blog" href="http://stephenwalther.com/" target="_blank">Stephen
Walter</a> in seinem Blog angekündigt hat, stoppt Microsoft die Entwicklung des
eigenen <a href="http://ajax.codeplex.com" target="_blank">clientseitigen ASP.NET
Ajax Libra</a>ry und steuert stattdessen <a href="http://blog.jquery.com/2010/03/16/microsoft-to-expand-its-collaboration-with-the-jquery-community/" target="_blank">Code
zu jQuery</a> bei. Bedeutet Microsoft hat jQuery nicht "übernommen",
sondern steuert wie jeder andere einfach nur Quellcode bei bzw. schlägt Features
vor, die anschließend durch das jQuery Team geprüft werden.
</p>
        <p>
Da die Beta der <a href="http://ajax.codeplex.com" target="_blank">ASP.NET Ajax Library</a> nun
bereits seit November verfügbar war, überraschte mich diese Ankündigung
ein wenig. Andererseits fragte ich mich, je tiefer ich mich mit der Library beschäftigte,
sowieso weshalb man den clientseitigen Teil neben jQuery überhaupt brauchen würde.
</p>
        <p>
Jedem der sich nun genötigt fühlt, jQuery zu lernen, dem kann ich nur wärmstens <a title="Blog von Dave Ward mit vielen Tipps und Tricks zu jQuery" href="http://encosia.com/" target="_blank">Dave
Wards Blog</a> empfehlen. Außerdem ist seine <a href="http://tekpub.com/view/jquery/1" target="_blank">Tekpub
jQuery Serie</a> die er gemeinsam mit James Avery aufzeichnet natürlich auch
Pflichtprogramm.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=8291e19a-6861-4446-af5e-c1faa9352c95" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Microsoft, Ajax und JQuery</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,8291e19a-6861-4446-af5e-c1faa9352c95.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/17/MicrosoftAjaxUndJQuery.aspx</link>
      <pubDate>Wed, 17 Mar 2010 09:41:29 GMT</pubDate>
      <description>&lt;p&gt;
Wie &lt;a title="Stephen Walters Blog" href="http://stephenwalther.com/" target="_blank"&gt;Stephen
Walter&lt;/a&gt; in seinem Blog angek&amp;#252;ndigt hat, stoppt Microsoft die Entwicklung des
eigenen &lt;a href="http://ajax.codeplex.com" target="_blank"&gt;clientseitigen ASP.NET
Ajax Libra&lt;/a&gt;ry und steuert stattdessen &lt;a href="http://blog.jquery.com/2010/03/16/microsoft-to-expand-its-collaboration-with-the-jquery-community/" target="_blank"&gt;Code
zu jQuery&lt;/a&gt; bei. Bedeutet Microsoft hat jQuery nicht &amp;quot;&amp;#252;bernommen&amp;quot;,
sondern steuert wie jeder andere einfach nur Quellcode bei bzw. schl&amp;#228;gt Features
vor, die anschlie&amp;#223;end durch das jQuery Team gepr&amp;#252;ft werden.
&lt;/p&gt;
&lt;p&gt;
Da die Beta der &lt;a href="http://ajax.codeplex.com" target="_blank"&gt;ASP.NET Ajax Library&lt;/a&gt; nun
bereits seit November verf&amp;#252;gbar war, &amp;#252;berraschte mich diese Ank&amp;#252;ndigung
ein wenig. Andererseits fragte ich mich, je tiefer ich mich mit der Library besch&amp;#228;ftigte,
sowieso weshalb man den clientseitigen Teil neben jQuery &amp;#252;berhaupt brauchen w&amp;#252;rde.
&lt;/p&gt;
&lt;p&gt;
Jedem der sich nun gen&amp;#246;tigt f&amp;#252;hlt, jQuery zu lernen, dem kann ich nur w&amp;#228;rmstens &lt;a title="Blog von Dave Ward mit vielen Tipps und Tricks zu jQuery" href="http://encosia.com/" target="_blank"&gt;Dave
Wards Blog&lt;/a&gt; empfehlen. Au&amp;#223;erdem ist seine &lt;a href="http://tekpub.com/view/jquery/1" target="_blank"&gt;Tekpub
jQuery Serie&lt;/a&gt; die er gemeinsam mit James Avery aufzeichnet nat&amp;#252;rlich auch
Pflichtprogramm.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=8291e19a-6861-4446-af5e-c1faa9352c95" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,8291e19a-6861-4446-af5e-c1faa9352c95.aspx</comments>
      <category>.NET</category>
      <category>Ajax</category>
      <category>DotNetGerman Bloggers</category>
      <category>jQuery</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=6d714381-7ea3-45cb-a24f-53ea984974d6</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,6d714381-7ea3-45cb-a24f-53ea984974d6.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,6d714381-7ea3-45cb-a24f-53ea984974d6.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=6d714381-7ea3-45cb-a24f-53ea984974d6</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In den letzten 5 Einträgen meines Blogs habe ich über verschiedene Möglichkeiten
geschrieben Ajax in einer ASP.NET Webforms zu implementieren.
</p>
        <p>
Angefangen mit dem manuellen Weg über das <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 1)" href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank">XmlHttpRequest
Objekt</a> ging es weiter zu <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks" href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank">Client
Callbacks</a>, dem <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel" href="http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx" target="_blank">Updatepanel</a>,
dem <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 4) Scriptservices, Page Methods und das ASP.NET AJAX Framework" href="http://blog.codemurai.de/2010/02/18/ASPNETWebformsAnwendungenUndAjaxTeil4ScriptservicesPageMethodsUndDasASPNETAJAXFramework.aspx" target="_blank">ASP.NET
Ajax Framework</a> sowie <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 5) Scriptservices, Page Methods und jQuery" href="http://blog.codemurai.de/2010/03/01/ASPNETWebformsAnwendungenUndAjaxTeil5ScriptservicesPageMethodsUndJQuery.aspx" target="_blank">jQuery</a>.
</p>
        <p>
Der Fokus meiner Beiträge lag darauf nicht nur einfach zu zeigen welche Möglichkeiten
es gibt, sondern zusätzlich auch zu zeigen, welche Datenmengen über die
Leitung gehen und ob bzw. welche Teile des ASP.NET Page Life Cycles durchlaufen werden.
</p>
        <p>
Ich hoffe dass ich bei dem ein oder anderen Leser für manchen Aha Effekt sorgen
konnte. Zumindest ging es mir persönlich bei der ersten detaillierten Auseinandersetzung
mit dem Thema so. Schließlich ist man als ASP.NET Webforms Entwickler traditionell
doch eher auf dem Server zu Hause und realisiert vorerst garnicht welchen Overhead
Client Callbacks oder das Updatepanel mit sich bringen.
</p>
        <p>
Mein persönliches Fazit ist, dass Updatepanel und Client Callbacks korrekt eingesetzt
in einigen Fällen vielleicht berechtigte Alternativen sind, in den meisten Fällen
jedoch zum Ajax Framework oder jQuery gegriffen werden sollte.
</p>
        <p>
Meine zurzeit favorisierte Lösung ist - ähnlich wie bei vielen anderen sicherlich
auch - der Einsatz von jQuery.
</p>
        <p>
Da mein letztes Beispiel noch ein wenig aufgebläht war, möchte ich an dieser
Stelle zwei kurze Tipps geben, die die Arbeit mit jQuery und Ajax ein wenig erleichtern.
</p>
        <p>
Der erste Punkt beschäftigt sich mit der großen Redundanz zwischen den verschiedenen
Ajax Aufrufen:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8bf35d42-2e9f-4ae1-942a-b756979a3204" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">$("#StaticFileLink").click(function(e) {
    e.preventDefault();
    $.ajax({
        type: "POST",
        url: "Teil5.aspx/ReadStaticFile",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(msg) {
            $("#content").html(msg.d);
        }
    });
});

$("#HelloWorldLink").click(function(e) {
    e.preventDefault();
    $.ajax({
        type: "POST",
        url: "AjaxDemoService.asmx/HelloWorld",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(msg) {
            $("#content").html(msg.d);
        }
    });
});

$("#EchoLink").click(function(e) {
    e.preventDefault();
    var number = $("#EchoTextBox").val();
    var jsonData = "{ 'number' : '" + number + "'}";
    $.ajax({
        type: "POST",
        url: "AjaxDemoService.asmx/Echo",
        data: jsonData,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(msg) {
            $("#content").html(msg.d);
        }
    });
});</pre>
        </div>
        <p>
Bereits beim ersten Blick auf den Quellcode fällt auf, dass die Werte einiger
Parameter statisch zu sein scheinen. So haben folgende Parameter stets einen fixen
Wert:
</p>
        <ul>
          <li>
type 
</li>
          <li>
contentType 
</li>
          <li>
dataType 
</li>
        </ul>
        <p>
Außerdem ist zumindest in den ersten beiden Aufrufen auch der Eintrag für
data gleich.
</p>
        <p>
Ein Weg um diese Redundanz herum zu kommen wäre eine eigene Funktion, die nur
die Variablen Parameter entgegen nimmt.
</p>
        <h4>Standardwerte setzen
</h4>
        <p>
Eine andere Alternative besteht darin, Standardwerte für jQuery Ajax Aufrufe
zu setzen. Dies sähe dann so aus:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:bbeda73f-39c7-4163-87ba-bb7344706009" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">&lt;script type="text/javascript"&gt;
    $(document).ready(function() {
        $.ajaxSetup({
            type: "POST",
            data: "{}",
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
        $("#StaticFileLink").click(function(e) {
            e.preventDefault();
            $.ajax({
                url: "Teil6.aspx/ReadStaticFile",
                success: function(msg) {
                    $("#content").html(msg.d);
                }
            });
        });

        $("#HelloWorldLink").click(function(e) {
            e.preventDefault();
            $.ajax({
                url: "AjaxDemoService.asmx/HelloWorld",
                success: function(msg) {
                    $("#content").html(msg.d);
                }
            });
        });

        $("#EchoLink").click(function(e) {
            e.preventDefault();
            var number = $("#EchoTextBox").val();
            var jsonData = "{ 'number' : '" + number + "'}";
            $.ajax({
                url: "AjaxDemoService.asmx/Echo",
                data: jsonData,
                success: function(msg) {
                    $("#content").html(msg.d);
                }
            });
        });
    });
&lt;/script&gt;</pre>
        </div>
        <p>
Neu hinzugekommen sind die Zeilen 2 - 8. Diese setzen Standardwerte für alle
folgenden Ajax Aufrufe. Diese Variante kann einiges an Code sparen, ist allerdings
mit Vorsicht zu genießen. Sollte nämlich zum Beispiel ein jQuery Plug-In
auf der Seite genutzt werden, dass auch die $.ajax Funktion nutzt, könnte es
zu Seiteneffekten kommen. Konkret wäre dies der Fall, wenn einer der per .ajaxSetup
gesetzten Parameter nicht überschrieben, aber mit einem anderen Wert erwartet
wäre. Typischerweise würde dies für den contentType oder oder dataType
geschehen.
</p>
        <h4>Serialisieren - einfach gemacht
</h4>
        <p>
Eine weitere Unschönheit des gezeigten Quellcodes besteht darin, dass die String
Variante des in JSON notierten Objekts data von Hand zusammen gebaut wurde. Dies ist
natürlich nicht sonderlich schick. Abhilfe schafft die Funktion stringify des
Objekts JSON. Einige Browser wie <a title="JSON in Firefox 3.5" href="https://developer.mozilla.org/en/JSON#JSON.c2.a0in_Firefox_3.5" target="_blank">Firefox
ab Version 3.5</a> oder <a title="Native JSON in IE8" href="http://blogs.msdn.com/ie/archive/2008/09/10/native-json-in-ie8.aspx" target="_blank">IE
ab der Version 8</a> haben bereits ein eingebautes Objekt JSON. Für alle anderen
gibt es unter <a title="http://www.json.org/js.html" href="http://www.json.org/js.html">http://www.json.org/js.html</a> eine
JavaScript Library zum Download, die entsprechenden Support nachrüstet, falls
noch nicht vorhanden.
</p>
        <p>
Konkret sähe dies dann wie folgt aus:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:dde58bec-9ed2-45cb-bb4e-402c8835d2d1" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">&lt;script src="scripts/json2.js" type="text/javascript"&gt;&lt;/script&gt;

[ ... ]


$("#EchoLink").click(function(e) {
    e.preventDefault();
    var number = $("#EchoTextBox").val();
    var jsonData = { 'number': number };
    var jsonString = JSON.stringify(jsonData);
    $.ajax({
        url: "AjaxDemoService.asmx/Echo",
        data: jsonString,
        success: function(msg) {
            $("#content").html(msg.d);
        }
    });</pre>
        </div>
        <p>
Wie man sieht, wird nun in Zeile 9 zuerst ein JavaScript Objekt jsonData in JSON Notation
erzeugt. Dies wird anschließend über JSON.stringify in Zeile 10 in einen
String konvertiert. Bei diesem konkreten Beispiel mag der Vorteil noch nicht auf der
Hand liegen, spätestens bei komplexen Objekten lernt man die Funktion stringify
jedoch schnell zu schätzen.
</p>
        <p>
Bei der Recherche zu den Beiträgen dieser Serie bin ich übrigens auf einen
sehr gut geschriebenen Eintrag von <a title="ASP.NET Update Panel, Callback und jQuery Webservice - Drei Ajax Techniken im Überblick" href="http://www.aspnetzone.de/blogs/robertobez/archive/2009/11/02/asp-net-Ajax-UpdatePanel-Callback-jQuery-Webservice.aspx" target="_blank">Roberto
Bez</a> gestolpert. Roberto stellt in seinem Blog Post die verschiedenen Varianten
kompakt gegenüber. Die Lektüre des Artikels kann ich jedem Ajax interessierten
Webforms Entwickler wärmstens empfehlen.
</p>
        <p>
Weiter hat <a title="Blog von René Drescher-Hackel" href="http://weblog.drescher-hackel.de" target="_blank">René
Drescher-Hackel</a> in einem Kommentar zu meinem letzen Beitrag, dass mit <a href="http://www.ajaxpro.info/" target="_blank">Ajax.NET
Professional (AJAX.PRO)</a> eine weitere effiziente Alternative zur Verfügung
steht. Ich muss gestehen, dass mir die Existenz dieses Frameworks bis jetzt vollkommen
entgangen ist. Gelobe allerdings Besserung und werde es mir gerne ansehen und mein
Beispiel damit umsetzen.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=6d714381-7ea3-45cb-a24f-53ea984974d6" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>ASP.NET Webforms Anwendungen und Ajax (Teil 6) kleine Tipps die das Leben leichter machen.</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,6d714381-7ea3-45cb-a24f-53ea984974d6.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/11/ASPNETWebformsAnwendungenUndAjaxTeil6KleineTippsDieDasLebenLeichterMachen.aspx</link>
      <pubDate>Thu, 11 Mar 2010 20:44:25 GMT</pubDate>
      <description>&lt;p&gt;
In den letzten 5 Eintr&amp;#228;gen meines Blogs habe ich &amp;#252;ber verschiedene M&amp;#246;glichkeiten
geschrieben Ajax in einer ASP.NET Webforms zu implementieren.
&lt;/p&gt;
&lt;p&gt;
Angefangen mit dem manuellen Weg &amp;#252;ber das &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 1)" href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank"&gt;XmlHttpRequest
Objekt&lt;/a&gt; ging es weiter zu &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks" href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank"&gt;Client
Callbacks&lt;/a&gt;, dem &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel" href="http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx" target="_blank"&gt;Updatepanel&lt;/a&gt;,
dem &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 4) Scriptservices, Page Methods und das ASP.NET AJAX Framework" href="http://blog.codemurai.de/2010/02/18/ASPNETWebformsAnwendungenUndAjaxTeil4ScriptservicesPageMethodsUndDasASPNETAJAXFramework.aspx" target="_blank"&gt;ASP.NET
Ajax Framework&lt;/a&gt; sowie &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 5) Scriptservices, Page Methods und jQuery" href="http://blog.codemurai.de/2010/03/01/ASPNETWebformsAnwendungenUndAjaxTeil5ScriptservicesPageMethodsUndJQuery.aspx" target="_blank"&gt;jQuery&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Der Fokus meiner Beitr&amp;#228;ge lag darauf nicht nur einfach zu zeigen welche M&amp;#246;glichkeiten
es gibt, sondern zus&amp;#228;tzlich auch zu zeigen, welche Datenmengen &amp;#252;ber die
Leitung gehen und ob bzw. welche Teile des ASP.NET Page Life Cycles durchlaufen werden.
&lt;/p&gt;
&lt;p&gt;
Ich hoffe dass ich bei dem ein oder anderen Leser f&amp;#252;r manchen Aha Effekt sorgen
konnte. Zumindest ging es mir pers&amp;#246;nlich bei der ersten detaillierten Auseinandersetzung
mit dem Thema so. Schlie&amp;#223;lich ist man als ASP.NET Webforms Entwickler traditionell
doch eher auf dem Server zu Hause und realisiert vorerst garnicht welchen Overhead
Client Callbacks oder das Updatepanel mit sich bringen.
&lt;/p&gt;
&lt;p&gt;
Mein pers&amp;#246;nliches Fazit ist, dass Updatepanel und Client Callbacks korrekt eingesetzt
in einigen F&amp;#228;llen vielleicht berechtigte Alternativen sind, in den meisten F&amp;#228;llen
jedoch zum Ajax Framework oder jQuery gegriffen werden sollte.
&lt;/p&gt;
&lt;p&gt;
Meine zurzeit favorisierte L&amp;#246;sung ist - &amp;#228;hnlich wie bei vielen anderen sicherlich
auch - der Einsatz von jQuery.
&lt;/p&gt;
&lt;p&gt;
Da mein letztes Beispiel noch ein wenig aufgebl&amp;#228;ht war, m&amp;#246;chte ich an dieser
Stelle zwei kurze Tipps geben, die die Arbeit mit jQuery und Ajax ein wenig erleichtern.
&lt;/p&gt;
&lt;p&gt;
Der erste Punkt besch&amp;#228;ftigt sich mit der gro&amp;#223;en Redundanz zwischen den verschiedenen
Ajax Aufrufen:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8bf35d42-2e9f-4ae1-942a-b756979a3204" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;$("#StaticFileLink").click(function(e) {
    e.preventDefault();
    $.ajax({
        type: "POST",
        url: "Teil5.aspx/ReadStaticFile",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(msg) {
            $("#content").html(msg.d);
        }
    });
});

$("#HelloWorldLink").click(function(e) {
    e.preventDefault();
    $.ajax({
        type: "POST",
        url: "AjaxDemoService.asmx/HelloWorld",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(msg) {
            $("#content").html(msg.d);
        }
    });
});

$("#EchoLink").click(function(e) {
    e.preventDefault();
    var number = $("#EchoTextBox").val();
    var jsonData = "{ 'number' : '" + number + "'}";
    $.ajax({
        type: "POST",
        url: "AjaxDemoService.asmx/Echo",
        data: jsonData,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(msg) {
            $("#content").html(msg.d);
        }
    });
});&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Bereits beim ersten Blick auf den Quellcode f&amp;#228;llt auf, dass die Werte einiger
Parameter statisch zu sein scheinen. So haben folgende Parameter stets einen fixen
Wert:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
type 
&lt;/li&gt;
&lt;li&gt;
contentType 
&lt;/li&gt;
&lt;li&gt;
dataType 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Au&amp;#223;erdem ist zumindest in den ersten beiden Aufrufen auch der Eintrag f&amp;#252;r
data gleich.
&lt;/p&gt;
&lt;p&gt;
Ein Weg um diese Redundanz herum zu kommen w&amp;#228;re eine eigene Funktion, die nur
die Variablen Parameter entgegen nimmt.
&lt;/p&gt;
&lt;h4&gt;Standardwerte setzen
&lt;/h4&gt;
&lt;p&gt;
Eine andere Alternative besteht darin, Standardwerte f&amp;#252;r jQuery Ajax Aufrufe
zu setzen. Dies s&amp;#228;he dann so aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:bbeda73f-39c7-4163-87ba-bb7344706009" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;&amp;lt;script type="text/javascript"&amp;gt;
    $(document).ready(function() {
        $.ajaxSetup({
            type: "POST",
            data: "{}",
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
        $("#StaticFileLink").click(function(e) {
            e.preventDefault();
            $.ajax({
                url: "Teil6.aspx/ReadStaticFile",
                success: function(msg) {
                    $("#content").html(msg.d);
                }
            });
        });

        $("#HelloWorldLink").click(function(e) {
            e.preventDefault();
            $.ajax({
                url: "AjaxDemoService.asmx/HelloWorld",
                success: function(msg) {
                    $("#content").html(msg.d);
                }
            });
        });

        $("#EchoLink").click(function(e) {
            e.preventDefault();
            var number = $("#EchoTextBox").val();
            var jsonData = "{ 'number' : '" + number + "'}";
            $.ajax({
                url: "AjaxDemoService.asmx/Echo",
                data: jsonData,
                success: function(msg) {
                    $("#content").html(msg.d);
                }
            });
        });
    });
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Neu hinzugekommen sind die Zeilen 2 - 8. Diese setzen Standardwerte f&amp;#252;r alle
folgenden Ajax Aufrufe. Diese Variante kann einiges an Code sparen, ist allerdings
mit Vorsicht zu genie&amp;#223;en. Sollte n&amp;#228;mlich zum Beispiel ein jQuery Plug-In
auf der Seite genutzt werden, dass auch die $.ajax Funktion nutzt, k&amp;#246;nnte es
zu Seiteneffekten kommen. Konkret w&amp;#228;re dies der Fall, wenn einer der per .ajaxSetup
gesetzten Parameter nicht &amp;#252;berschrieben, aber mit einem anderen Wert erwartet
w&amp;#228;re. Typischerweise w&amp;#252;rde dies f&amp;#252;r den contentType oder oder dataType
geschehen.
&lt;/p&gt;
&lt;h4&gt;Serialisieren - einfach gemacht
&lt;/h4&gt;
&lt;p&gt;
Eine weitere Unsch&amp;#246;nheit des gezeigten Quellcodes besteht darin, dass die String
Variante des in JSON notierten Objekts data von Hand zusammen gebaut wurde. Dies ist
nat&amp;#252;rlich nicht sonderlich schick. Abhilfe schafft die Funktion stringify des
Objekts JSON. Einige Browser wie &lt;a title="JSON in Firefox 3.5" href="https://developer.mozilla.org/en/JSON#JSON.c2.a0in_Firefox_3.5" target="_blank"&gt;Firefox
ab Version 3.5&lt;/a&gt; oder &lt;a title="Native JSON in IE8" href="http://blogs.msdn.com/ie/archive/2008/09/10/native-json-in-ie8.aspx" target="_blank"&gt;IE
ab der Version 8&lt;/a&gt; haben bereits ein eingebautes Objekt JSON. F&amp;#252;r alle anderen
gibt es unter &lt;a title="http://www.json.org/js.html" href="http://www.json.org/js.html"&gt;http://www.json.org/js.html&lt;/a&gt; eine
JavaScript Library zum Download, die entsprechenden Support nachr&amp;#252;stet, falls
noch nicht vorhanden.
&lt;/p&gt;
&lt;p&gt;
Konkret s&amp;#228;he dies dann wie folgt aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:dde58bec-9ed2-45cb-bb4e-402c8835d2d1" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;&amp;lt;script src="scripts/json2.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;

[ ... ]


$("#EchoLink").click(function(e) {
    e.preventDefault();
    var number = $("#EchoTextBox").val();
    var jsonData = { 'number': number };
    var jsonString = JSON.stringify(jsonData);
    $.ajax({
        url: "AjaxDemoService.asmx/Echo",
        data: jsonString,
        success: function(msg) {
            $("#content").html(msg.d);
        }
    });&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Wie man sieht, wird nun in Zeile 9 zuerst ein JavaScript Objekt jsonData in JSON Notation
erzeugt. Dies wird anschlie&amp;#223;end &amp;#252;ber JSON.stringify in Zeile 10 in einen
String konvertiert. Bei diesem konkreten Beispiel mag der Vorteil noch nicht auf der
Hand liegen, sp&amp;#228;testens bei komplexen Objekten lernt man die Funktion stringify
jedoch schnell zu sch&amp;#228;tzen.
&lt;/p&gt;
&lt;p&gt;
Bei der Recherche zu den Beitr&amp;#228;gen dieser Serie bin ich &amp;#252;brigens auf einen
sehr gut geschriebenen Eintrag von &lt;a title="ASP.NET Update Panel, Callback und jQuery Webservice - Drei Ajax Techniken im &amp;#220;berblick" href="http://www.aspnetzone.de/blogs/robertobez/archive/2009/11/02/asp-net-Ajax-UpdatePanel-Callback-jQuery-Webservice.aspx" target="_blank"&gt;Roberto
Bez&lt;/a&gt; gestolpert. Roberto stellt in seinem Blog Post die verschiedenen Varianten
kompakt gegen&amp;#252;ber. Die Lekt&amp;#252;re des Artikels kann ich jedem Ajax interessierten
Webforms Entwickler w&amp;#228;rmstens empfehlen.
&lt;/p&gt;
&lt;p&gt;
Weiter hat &lt;a title="Blog von Ren&amp;#233; Drescher-Hackel" href="http://weblog.drescher-hackel.de" target="_blank"&gt;Ren&amp;#233;
Drescher-Hackel&lt;/a&gt; in einem Kommentar zu meinem letzen Beitrag, dass mit &lt;a href="http://www.ajaxpro.info/" target="_blank"&gt;Ajax.NET
Professional (AJAX.PRO)&lt;/a&gt; eine weitere effiziente Alternative zur Verf&amp;#252;gung
steht. Ich muss gestehen, dass mir die Existenz dieses Frameworks bis jetzt vollkommen
entgangen ist. Gelobe allerdings Besserung und werde es mir gerne ansehen und mein
Beispiel damit umsetzen.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=6d714381-7ea3-45cb-a24f-53ea984974d6" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,6d714381-7ea3-45cb-a24f-53ea984974d6.aspx</comments>
      <category>.NET</category>
      <category>Ajax</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=91af6697-e6e7-4765-8e24-1bf02130e039</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,91af6697-e6e7-4765-8e24-1bf02130e039.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,91af6697-e6e7-4765-8e24-1bf02130e039.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=91af6697-e6e7-4765-8e24-1bf02130e039</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Eigentlich altbekannt, trotzdem bin ich gerade mal wieder darauf hereingefallen und
schreibe des deshalb hier auf:
</p>
        <p>
Ich wollte in einer ASP.NET Webforms Anwendung ein Servercontrol serverseitig über 
</p>
        <p>
        </p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:714a717f-e6ba-4ed9-9248-e32dce897ab0" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">meinControl.Visible = false;</pre>
        </div>
        <p>
ausblenden, um es nach einer Nutzeraktion auf dem Client wieder einzublenden:
</p>
        <p>
        </p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:be23a1a1-8783-4a3b-880b-45a8e951a7f1" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">$(Id$="MeinControl").show();</pre>
        </div>
        <p>
Leider funktioniert das allerdings nicht, da ein serverseitiges Visible = false dafür
sorgte, dass das Control erst garnicht gerendert wurde und somit auf dem Client nicht
verfügbar war.
</p>
        <p>
Die simple Lösung im Codebehind:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:f1cf8f3e-c820-450e-a132-3e68285fbc55" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">meinControl.Style.Add(HtmlTextWriterStyle.Display, "none");</pre>
        </div>
        <p>
Dann klappts auch mit dem Einblenden ;-)
</p>
        <p>
          <em>War dieser Beitrag hilfreich? Dann kick ihn doch bitte.</em>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=91af6697-e6e7-4765-8e24-1bf02130e039" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Vorsicht mit Visible = false</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,91af6697-e6e7-4765-8e24-1bf02130e039.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/11/VorsichtMitVisibleFalse.aspx</link>
      <pubDate>Thu, 11 Mar 2010 18:41:16 GMT</pubDate>
      <description>&lt;p&gt;
Eigentlich altbekannt, trotzdem bin ich gerade mal wieder darauf hereingefallen und
schreibe des deshalb hier auf:
&lt;/p&gt;
&lt;p&gt;
Ich wollte in einer ASP.NET Webforms Anwendung ein Servercontrol serverseitig &amp;#252;ber 
&lt;/p&gt;
&lt;p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:714a717f-e6ba-4ed9-9248-e32dce897ab0" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;meinControl.Visible = false;&lt;/pre&gt;
&lt;/div&gt;
&gt;
&lt;p&gt;
ausblenden, um es nach einer Nutzeraktion auf dem Client wieder einzublenden:
&lt;/p&gt;
&lt;p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:be23a1a1-8783-4a3b-880b-45a8e951a7f1" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;$(Id$="MeinControl").show();&lt;/pre&gt;
&lt;/div&gt;
&gt;
&lt;p&gt;
Leider funktioniert das allerdings nicht, da ein serverseitiges Visible = false daf&amp;#252;r
sorgte, dass das Control erst garnicht gerendert wurde und somit auf dem Client nicht
verf&amp;#252;gbar war.
&lt;/p&gt;
&lt;p&gt;
Die simple L&amp;#246;sung im Codebehind:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:f1cf8f3e-c820-450e-a132-3e68285fbc55" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;meinControl.Style.Add(HtmlTextWriterStyle.Display, "none");&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Dann klappts auch mit dem Einblenden ;-)
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;War dieser Beitrag hilfreich? Dann kick ihn doch bitte.&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=91af6697-e6e7-4765-8e24-1bf02130e039" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,91af6697-e6e7-4765-8e24-1bf02130e039.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=3ff7deed-4185-4b1c-85f2-416c877b9b2d</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,3ff7deed-4185-4b1c-85f2-416c877b9b2d.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,3ff7deed-4185-4b1c-85f2-416c877b9b2d.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=3ff7deed-4185-4b1c-85f2-416c877b9b2d</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Im <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 4) Scriptservices, Page Methods und das ASP.NET AJAX Framework" href="http://blog.codemurai.de/2010/02/18/ASPNETWebformsAnwendungenUndAjaxTeil4ScriptservicesPageMethodsUndDasASPNETAJAXFramework.aspx" target="_blank">vierten
Teil dieser Serie</a> habe ich gezeigt, wie Pagemethods und Scriptservices mit dem
ASP.NET Ajax Framework angesprochen werden können. Im Vergleich zu den vorherigen
Teilen, die auf <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks" href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank">Client
Callbacks</a> bzw. das <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel" href="http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx" target="_blank">Updatepanel</a> setzen,
konnte über diesen Weg die übertragene Datenmenge erheblich verkleinert
werden, da unter anderem der Viewstate nicht mehr übertragen werden musste. Außerdem
wurde serverseitig nicht mehr der komplette Page Life Cycle durchlaufen, was weitere
Performanceverbesserungen mit sich brachte.
</p>
        <p>
Im Gegenzug zu diesen Verbesserungen mussten wir allerdings in Kauf nehmen, dass beim
ersten Request drei zusätzliche JavaScript Dateien des Ajax Frameworks mit einer
Gesamtgröße von 85 kb geladen wurden.
</p>
        <p>
Hält man im Hinterkopf, dass der Viewstate einer Seite schnell 50 kb und mehr
beträgt und dieser bei jedem Ajax Request der vorherigen Methoden hin und her
übertragen wurde, lassen sich diese 85 kb jedoch sicherlich leicht verschmerzen.
</p>
        <p>
Doch wie sieht es aus, wenn neben dem Ajax Framework auch jQuery in die Seite eingebunden
wurde, um die Oberfläche zu tunen?
</p>
        <p>
In diesem Fall stellt sich die Situation anders dar, nun ist das ASP.NET Ajax Framework
clientseitig nämlich reiner Ballast. Zumindest wenn es darum geht Pagemethods
und Scriptservcies aufzurufen. Das kann jQuery nämlich auch.
</p>
        <h4>Also weg damit!
</h4>
        <p>
Wie müssen wir aber vorgehen, um Pagemethods und Scriptservices aus jQuery rufen
zu können?
</p>
        <p>
Zunächst kopieren wir den kompletten Code unseres letzten Beispiels. Wenn wir
nun einen Blick auf den Code werfen sehen wir in der *.aspx Datei einen ScriptManager. 
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:507f16c9-2bcd-4883-ba7f-59b558189ea4" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="True"&gt;
  &lt;Services&gt;
    &lt;asp:ServiceReference Path="~/AjaxDemoService.asmx" /&gt;
  &lt;/Services&gt;
&lt;/asp:ScriptManager&gt;</pre>
        </div>
        <p>
Dieser war notwendig, damit das ASP.NET Ajax Framework die JavaScript Proxies erstellte,
die uns Aufrufe in der Form <em>PageMethods.Methodenname</em> bzw. <em>WebServiceName.Methodenname</em> erlaubten.
</p>
        <p>
Der ScriptManager ist allerdings überflüssig wenn man Pagemethods und Scriptservices
via jQuery rufen möchte. <strong>Daher fliegt er raus</strong>. Weiter entfernen
wir den bestehenden inline JavaScript Code der Seite und räumen Sie noch ein
wenig auf. Das Ergebnis sieht wie folgt aus:
</p>
        <p>
        </p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:6e43b782-f30a-4500-8414-d1df043c09bb" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="Teil5.aspx.cs" Inherits="Teil5" %&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;ASP.NET Webforms Anwendungen und Ajax (Teil 5): Scriptservices mit jQuery&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;form id="form1" runat="server"&gt;
            &lt;h1&gt;
                ASP.NET Webforms Anwendungen und Ajax (Teil 5): Scriptservices mit jQuery&lt;/h1&gt;
            &lt;p&gt;
                &lt;a href="#" id="StaticFileLink"&gt;Hier klicken zum Request einer statischen Datei&lt;/a&gt;&lt;br /&gt;
                &lt;a href="#" id="HelloWorldLink"&gt;Hier für Hello World WebService klicken &lt;/a&gt;&lt;br /&gt;
                &lt;a href="#" id="EchoLink"&gt;Hier für Echo WebService klicken. Geben Sie bitte vorher eine
                    Zahl in nebenstehendem Feld ein: &lt;/a&gt;&amp;nbsp;
                &lt;input type="text" id="EchoTextBox" value="4711" /&gt;
            &lt;/p&gt;
            &lt;div id="content"&gt;
                Bitte klicken Sie auf einen der Links, damit dieser Bereich gefüllt wird.
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>
        </div>
        <p>
        </p>
        <p>
Der <a href="http://blog.codemurai.de/2010/02/18/ASPNETWebformsAnwendungenUndAjaxTeil4ScriptservicesPageMethodsUndDasASPNETAJAXFramework.aspx" target="_blank">serverseitige
Code</a> des vorherigen Beispiels wurde übrigens nicht verändert.
</p>
        <p>
Unsere Seite umfasst nun schlanke 1,6 kb, wie die folgende Abbildung zeigt:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/5AS.NETWebformsAnwendungenundAjaxTeil4Sc_7BF4/01_Seite.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="105" alt="01_Seite" src="http://blog.codemurai.de/images/5AS.NETWebformsAnwendungenundAjaxTeil4Sc_7BF4/01_Seite_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Allerdings kann sie auch noch nichts ;-) 
</p>
        <p>
Darum werden wir uns aber in den nächsten Schritten kümmern.
</p>
        <h4>jQuery let's go
</h4>
        <p>
Als erstes benötigen wir eine Referenz auf jQuery. Diese erhalten wir über
folgenden Script Tag, den wir innerhalb des Head Bereichs der Seite einfügen:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:387edf3a-5ca5-4775-9e98-e3f1e0d9c5a7" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;script src="scripts/jquery-1.3.2.min.js" type="text/javascript"&gt;&lt;/script&gt; </pre>
        </div>
        <p>
Als nächstes fügen wir den Code ein, um den Link zur Anzeige der statischen
Datei zum fliegen zu bekommen. Dieser sieht wie folgt aus:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:6ad27a95-ec14-4472-a147-62e75b649b81" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">&lt;script type ="text/javascript"&gt;
    $(document).ready(function() {
        $("#StaticFileLink").click(function(e) {
            e.preventDefault();
            $.ajax({
                type: "POST",
                url: "Teil5.aspx/ReadStaticFile",
                data: "{}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function(result) {
                    $("#content").html(result.d);
                }
            });
        });
	 });
&lt;/script&gt;</pre>
        </div>
        <p>
Relevant für uns sind die Zeilen 5 - 14. Da es jedoch vielleicht den ein oder
anderen Leser gibt, der noch nie mit jQuery gearbeitet hat, möchte ich auch zu
den anderen Zeilen ein paar Worte verlieren.
</p>
        <p>
Auffällig sind zunächst die vielen $-Zeichen innerhalb des Codes. Dabei
handelt es sich um einen Alias für die Funktion <em>jQuery</em>. Überall
wo ein $ steht, könnte man sich also auch <em>jQuery</em> denken.
</p>
        <p>
Die Funktion jQuery nimmt ein DOM Element bzw. einen CSS Selektor als Argument entgegen.
In <strong>Zeile 2</strong> wird das DOM Element <em>document</em>, also eine Referenz
auf unser eigentliches HTML Dokument übergeben. Anschließend wird an das
Ereignis <em>ready</em> eine anonyme Funktion gehangen. Das Ereignis <em>ready</em> tritt
übrigens auf, sobald das DOM vollständig initialisiert wurde, jedoch ehe
weitere Inhalte wie Beispielsweise Bilder herunter geladen wurden. Somit hat man innerhalb
des <em>ready</em> Ereignisses zwar Zugriff auf das vollständig initialisierte
DOM, muss aber nicht den kompletten Seitenaufbau abwarten.
</p>
        <p>
In <strong>Zeile 3</strong> wird die <em>jQuery</em> Funktion mit dem CSS Selektor <em>#StaticFileLink</em> gefüllt,
um das DOM Element mit der ID StaticFileLink, also unseren Link, zu selektieren. An
das Ereignis <em>click</em> des Links wird wieder eine anonyme Funktion gehangen.
</p>
        <p>
In Zeile 4 wird über <em>e.preventDefault();</em> die Standardaktion des Links
verhindert. In unserem Fall also, dass beim Klick auf dem Link dem Inhalt des <em>href</em> Attributs
gefolgt wird. Stattdessen wird ab der Zeile 5 definiert, dass ein <a title="Dokumentation der jQuery Funktion ajax" href="http://api.jquery.com/jQuery.ajax/" target="_blank">ajax</a> Aufruf
gefeuert werden muss.
</p>
        <p>
Dabei werden folgende Werte an die verschiedenen Parameter der Funktion <a title="Dokumentation der jQuery Funktion ajax" href="http://api.jquery.com/jQuery.ajax/" target="_blank">ajax</a> übergeben:
</p>
        <table cellspacing="0" cellpadding="2" width="100%" border="1">
          <thead>
            <tr>
              <th valign="top" width="133">
Parameter</th>
              <th valign="top" width="133">
Wert</th>
              <th valign="top">
Erklärung</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td valign="top" width="133">
type</td>
              <td valign="top" width="133">
                <strong>POST</strong> (fix)</td>
              <td valign="top">
Ajax Anfragen an Pagemethods oder Scriptsservices müssen aus Sicherheitsgründen
immer vom Typ POST sein, um JSON hijacking Angriffe abzuwehren. Eine sehr gute Beschreibung
hierzu gibt es <a title="Beschreibung einer JSON Sicherheitslücke" href="http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx" target="_blank">im
Blog von Phil Haack</a>.</td>
            </tr>
            <tr>
              <td valign="top" width="133">
url</td>
              <td valign="top" width="133">
{Seitenname.aspx}/{Methodenname}</td>
              <td valign="top">
Ziel des Ajax Aufrufs. Im Falle einer Page Method nach dem Schema <em>{Seitenname.<strong>aspx</strong>}/{Methodenname}</em>,
im Fall von ScriptServices <em>{Servicename.<strong>asmx</strong>}/{Methodenname}</em>.
Wichtig ist, dass die entsprechende Methode im Falle von Pagemethods statisch ist
und mit dem Attribut <em>WebMethod</em> dekoriert wurde. Im Falle eines ScriptServices
ist auf die Dekorierung des Services mit dem Attribut <em>ScriptService</em> zu achten.</td>
            </tr>
            <tr>
              <td valign="top" width="133">
data</td>
              <td valign="top" width="133">
JSON String</td>
              <td valign="top">
Erwartet die Methode Parameter, sind diese hier als JSON String, und nicht als JSON
Objekt zu übergeben! Falls die Methode keine Parameter erwartet, sollte stets
ein leeres JSON Objekt übergeben werden (also <em>"{}"</em>). Andernfalls
übergibt jQuery als contentType statt <em>application/json</em> automatisch <em>text/html</em>.</td>
            </tr>
            <tr>
              <td valign="top" width="133">
contentType</td>
              <td valign="top" width="133">
application/json; charset=utf-8 (fix)</td>
              <td valign="top">
Als Content Type ist stets <em>application/json; charset=utf-8</em> zu übergeben.
Dies ist das Zeichen für das ASP.NET Ajax Framework, serverseitig die Anfrage
an den ScriptService Handler und nicht an den Soap Webservice Handler weiterzuleiten.</td>
            </tr>
            <tr>
              <td valign="top" width="133">
dataType</td>
              <td valign="top" width="133">
json (fix).</td>
              <td valign="top">
Gibt den Datentyp der Antwort an. Gültige Antworten sind unter anderem json,
script, xml oder text. Im Fall von Pagemethods und ScriptServices kommt immer JSON
zurück.</td>
            </tr>
            <tr>
              <td valign="top" width="133">
succes</td>
              <td valign="top" width="133">
Anonyme Funktion bzw. Funktionsname</td>
              <td valign="top">
Eine Anonyme Funktion bzw. der Name einer Funktion, die die Rückgabe der Methode
verarbeitet. 
<br />
Im Falle von PageMethods und ScriptServices wird die Antwort aus Sicherheitsgründen
übrigens immer in ein Objekt Namens <em>d </em>verpackt (siehe auch Zeile 12
des Scripts). Die Ursache hierfür ist ähnlich wie beim Parameter type und
wird auch näher in <a title="JSON Hijacking erklärt" href="http://haacked.com/archive/2009/06/25/json-hijacking.aspx" target="_blank">Phil
Haacks Blog Eintrag</a> erklärt.</td>
            </tr>
          </tbody>
        </table>
        <p>
Der Aufruf des Services sollte somit ausreichend erklärt sein. Einzig Zeile 12
bedarf noch einer kleinen Erklärung:
</p>
        <p>
Via $("#Content") holt jQuery sich eine Referenz auf den Zielbereich in
mithilfe der Funktion html die Antwort des Ajax Requests geschrieben wird.
</p>
        <p>
Der Code zum Aufruf der beiden Webservice Methoden sieht erwartungsgemäß
ähnlich aus:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:df55179d-b395-4780-8763-c85b0906a6fa" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">            $("#HelloWorldLink").click(function(e) {
                e.preventDefault();
                $.ajax({
                    type: "POST",
                    url: "AjaxDemoService.asmx/HelloWorld",
                    data: "{}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function(msg) {
                        $("#content").html(msg.d);
                    }
                });
            });

            $("#EchoLink").click(function(e) {
                e.preventDefault();
                var number = $("#EchoTextBox").val();
                var jsonData = "{ 'number' : '" + number + "'}";
                $.ajax({
                    type: "POST",
                    url: "AjaxDemoService.asmx/Echo",
                    data: jsonData,
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function(msg) {
                        $("#content").html(msg.d);
                    }
                });
            });</pre>
        </div>
        <p>
Erklärenswert ist einzig Zeile 18. Hier wird ein Json String zusammen gesetzt,
der später an die entsprechende Methode des Webservices übergeben wird.
Dies geht im Falle eines Arguments noch ganz gut, wird aber spätestens bei zwei
oder mehr Argumenten sehr lästig. Abhilfe schafft hier die Methode <em>stringify</em> des
Objekts <em>JSON</em>. Die Methode überführt ein Json Objekt in einen entsprechenden
String. Moderne Browser bringen dieses Objekt inkl. passender Methode gleich mit.
In allen anderen Fällen hilft der JSON Parser / Stringifier <a title="JSON in JavaScript" href="http://www.json.org/js.html" target="_blank">Json2</a>.
</p>
        <p>
Das Ergebnis der Mühe sieht im Live-Betrieb dann übrigens wie folgt aus:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/5AS.NETWebformsAnwendungenundAjaxTeil4Sc_7BF4/02_AjaxRequest.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="159" alt="02_AjaxRequest" src="http://blog.codemurai.de/images/5AS.NETWebformsAnwendungenundAjaxTeil4Sc_7BF4/02_AjaxRequest_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Zum Download der jQuery Library ist, wie auf der Abbildung gezeigt, ein weiterer Request
notwendig, der knapp 58 kb umfasst. Dies sind fast 30 kb weniger als es im vorherigen
Beispiel auf Basis des ASP.NET AJAX (client) Frameworks der Fall waren.
</p>
        <h4>Fazit
</h4>
        <p>
Ajax Aufrufe werden mithilfe des jQuery Frameworks zum Kinderspiel. Gerade wenn man
jQuery bereits für Oberflächenmanipulationen in einer Seite nutzt, lohnt
sich die Anwendung von jQuery für Ajax Aufrufe anstatt der Nutzung des ASP.NET
Ajax (Client) Frameworks.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=3ff7deed-4185-4b1c-85f2-416c877b9b2d" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>ASP.NET Webforms Anwendungen und Ajax (Teil 5) Scriptservices, Page Methods und jQuery</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,3ff7deed-4185-4b1c-85f2-416c877b9b2d.aspx</guid>
      <link>http://blog.codemurai.de/2010/03/01/ASPNETWebformsAnwendungenUndAjaxTeil5ScriptservicesPageMethodsUndJQuery.aspx</link>
      <pubDate>Mon, 01 Mar 2010 22:33:55 GMT</pubDate>
      <description>&lt;p&gt;
Im &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 4) Scriptservices, Page Methods und das ASP.NET AJAX Framework" href="http://blog.codemurai.de/2010/02/18/ASPNETWebformsAnwendungenUndAjaxTeil4ScriptservicesPageMethodsUndDasASPNETAJAXFramework.aspx" target="_blank"&gt;vierten
Teil dieser Serie&lt;/a&gt; habe ich gezeigt, wie Pagemethods und Scriptservices mit dem
ASP.NET Ajax Framework angesprochen werden k&amp;#246;nnen. Im Vergleich zu den vorherigen
Teilen, die auf &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks" href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank"&gt;Client
Callbacks&lt;/a&gt; bzw. das &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel" href="http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx" target="_blank"&gt;Updatepanel&lt;/a&gt; setzen,
konnte &amp;#252;ber diesen Weg die &amp;#252;bertragene Datenmenge erheblich verkleinert
werden, da unter anderem der Viewstate nicht mehr &amp;#252;bertragen werden musste. Au&amp;#223;erdem
wurde serverseitig nicht mehr der komplette Page Life Cycle durchlaufen, was weitere
Performanceverbesserungen mit sich brachte.
&lt;/p&gt;
&lt;p&gt;
Im Gegenzug zu diesen Verbesserungen mussten wir allerdings in Kauf nehmen, dass beim
ersten Request drei zus&amp;#228;tzliche JavaScript Dateien des Ajax Frameworks mit einer
Gesamtgr&amp;#246;&amp;#223;e von 85 kb geladen wurden.
&lt;/p&gt;
&lt;p&gt;
H&amp;#228;lt man im Hinterkopf, dass der Viewstate einer Seite schnell 50 kb und mehr
betr&amp;#228;gt und dieser bei jedem Ajax Request der vorherigen Methoden hin und her
&amp;#252;bertragen wurde, lassen sich diese 85 kb jedoch sicherlich leicht verschmerzen.
&lt;/p&gt;
&lt;p&gt;
Doch wie sieht es aus, wenn neben dem Ajax Framework auch jQuery in die Seite eingebunden
wurde, um die Oberfl&amp;#228;che zu tunen?
&lt;/p&gt;
&lt;p&gt;
In diesem Fall stellt sich die Situation anders dar, nun ist das ASP.NET Ajax Framework
clientseitig n&amp;#228;mlich reiner Ballast. Zumindest wenn es darum geht Pagemethods
und Scriptservcies aufzurufen. Das kann jQuery n&amp;#228;mlich auch.
&lt;/p&gt;
&lt;h4&gt;Also weg damit!
&lt;/h4&gt;
&lt;p&gt;
Wie m&amp;#252;ssen wir aber vorgehen, um Pagemethods und Scriptservices aus jQuery rufen
zu k&amp;#246;nnen?
&lt;/p&gt;
&lt;p&gt;
Zun&amp;#228;chst kopieren wir den kompletten Code unseres letzten Beispiels. Wenn wir
nun einen Blick auf den Code werfen sehen wir in der *.aspx Datei einen ScriptManager. 
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:507f16c9-2bcd-4883-ba7f-59b558189ea4" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="True"&amp;gt;
  &amp;lt;Services&amp;gt;
    &amp;lt;asp:ServiceReference Path="~/AjaxDemoService.asmx" /&amp;gt;
  &amp;lt;/Services&amp;gt;
&amp;lt;/asp:ScriptManager&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Dieser war notwendig, damit das ASP.NET Ajax Framework die JavaScript Proxies erstellte,
die uns Aufrufe in der Form &lt;em&gt;PageMethods.Methodenname&lt;/em&gt; bzw. &lt;em&gt;WebServiceName.Methodenname&lt;/em&gt; erlaubten.
&lt;/p&gt;
&lt;p&gt;
Der ScriptManager ist allerdings &amp;#252;berfl&amp;#252;ssig wenn man Pagemethods und Scriptservices
via jQuery rufen m&amp;#246;chte. &lt;strong&gt;Daher fliegt er raus&lt;/strong&gt;. Weiter entfernen
wir den bestehenden inline JavaScript Code der Seite und r&amp;#228;umen Sie noch ein
wenig auf. Das Ergebnis sieht wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:6e43b782-f30a-4500-8414-d1df043c09bb" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="Teil5.aspx.cs" Inherits="Teil5" %&amp;gt;
&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
    &amp;lt;head runat="server"&amp;gt;
        &amp;lt;title&amp;gt;ASP.NET Webforms Anwendungen und Ajax (Teil 5): Scriptservices mit jQuery&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;form id="form1" runat="server"&amp;gt;
            &amp;lt;h1&amp;gt;
                ASP.NET Webforms Anwendungen und Ajax (Teil 5): Scriptservices mit jQuery&amp;lt;/h1&amp;gt;
            &amp;lt;p&amp;gt;
                &amp;lt;a href="#" id="StaticFileLink"&amp;gt;Hier klicken zum Request einer statischen Datei&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;
                &amp;lt;a href="#" id="HelloWorldLink"&amp;gt;Hier für Hello World WebService klicken &amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;
                &amp;lt;a href="#" id="EchoLink"&amp;gt;Hier für Echo WebService klicken. Geben Sie bitte vorher eine
                    Zahl in nebenstehendem Feld ein: &amp;lt;/a&amp;gt;&amp;amp;nbsp;
                &amp;lt;input type="text" id="EchoTextBox" value="4711" /&amp;gt;
            &amp;lt;/p&amp;gt;
            &amp;lt;div id="content"&amp;gt;
                Bitte klicken Sie auf einen der Links, damit dieser Bereich gefüllt wird.
            &amp;lt;/div&amp;gt;
        &amp;lt;/form&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Der &lt;a href="http://blog.codemurai.de/2010/02/18/ASPNETWebformsAnwendungenUndAjaxTeil4ScriptservicesPageMethodsUndDasASPNETAJAXFramework.aspx" target="_blank"&gt;serverseitige
Code&lt;/a&gt; des vorherigen Beispiels wurde &amp;#252;brigens nicht ver&amp;#228;ndert.
&lt;/p&gt;
&lt;p&gt;
Unsere Seite umfasst nun schlanke 1,6 kb, wie die folgende Abbildung zeigt:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/5AS.NETWebformsAnwendungenundAjaxTeil4Sc_7BF4/01_Seite.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="105" alt="01_Seite" src="http://blog.codemurai.de/images/5AS.NETWebformsAnwendungenundAjaxTeil4Sc_7BF4/01_Seite_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Allerdings kann sie auch noch nichts ;-) 
&lt;/p&gt;
&lt;p&gt;
Darum werden wir uns aber in den n&amp;#228;chsten Schritten k&amp;#252;mmern.
&lt;/p&gt;
&lt;h4&gt;jQuery let's go
&lt;/h4&gt;
&lt;p&gt;
Als erstes ben&amp;#246;tigen wir eine Referenz auf jQuery. Diese erhalten wir &amp;#252;ber
folgenden Script Tag, den wir innerhalb des Head Bereichs der Seite einf&amp;#252;gen:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:387edf3a-5ca5-4775-9e98-e3f1e0d9c5a7" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;script src="scripts/jquery-1.3.2.min.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt; &lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Als n&amp;#228;chstes f&amp;#252;gen wir den Code ein, um den Link zur Anzeige der statischen
Datei zum fliegen zu bekommen. Dieser sieht wie folgt aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:6ad27a95-ec14-4472-a147-62e75b649b81" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;&amp;lt;script type ="text/javascript"&amp;gt;
    $(document).ready(function() {
        $("#StaticFileLink").click(function(e) {
            e.preventDefault();
            $.ajax({
                type: "POST",
                url: "Teil5.aspx/ReadStaticFile",
                data: "{}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function(result) {
                    $("#content").html(result.d);
                }
            });
        });
	 });
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Relevant f&amp;#252;r uns sind die Zeilen 5 - 14. Da es jedoch vielleicht den ein oder
anderen Leser gibt, der noch nie mit jQuery gearbeitet hat, m&amp;#246;chte ich auch zu
den anderen Zeilen ein paar Worte verlieren.
&lt;/p&gt;
&lt;p&gt;
Auff&amp;#228;llig sind zun&amp;#228;chst die vielen $-Zeichen innerhalb des Codes. Dabei
handelt es sich um einen Alias f&amp;#252;r die Funktion &lt;em&gt;jQuery&lt;/em&gt;. &amp;#220;berall
wo ein $ steht, k&amp;#246;nnte man sich also auch &lt;em&gt;jQuery&lt;/em&gt; denken.
&lt;/p&gt;
&lt;p&gt;
Die Funktion jQuery nimmt ein DOM Element bzw. einen CSS Selektor als Argument entgegen.
In &lt;strong&gt;Zeile 2&lt;/strong&gt; wird das DOM Element &lt;em&gt;document&lt;/em&gt;, also eine Referenz
auf unser eigentliches HTML Dokument &amp;#252;bergeben. Anschlie&amp;#223;end wird an das
Ereignis &lt;em&gt;ready&lt;/em&gt; eine anonyme Funktion gehangen. Das Ereignis &lt;em&gt;ready&lt;/em&gt; tritt
&amp;#252;brigens auf, sobald das DOM vollst&amp;#228;ndig initialisiert wurde, jedoch ehe
weitere Inhalte wie Beispielsweise Bilder herunter geladen wurden. Somit hat man innerhalb
des &lt;em&gt;ready&lt;/em&gt; Ereignisses zwar Zugriff auf das vollst&amp;#228;ndig initialisierte
DOM, muss aber nicht den kompletten Seitenaufbau abwarten.
&lt;/p&gt;
&lt;p&gt;
In &lt;strong&gt;Zeile 3&lt;/strong&gt; wird die &lt;em&gt;jQuery&lt;/em&gt; Funktion mit dem CSS Selektor &lt;em&gt;#StaticFileLink&lt;/em&gt; gef&amp;#252;llt,
um das DOM Element mit der ID StaticFileLink, also unseren Link, zu selektieren. An
das Ereignis &lt;em&gt;click&lt;/em&gt; des Links wird wieder eine anonyme Funktion gehangen.
&lt;/p&gt;
&lt;p&gt;
In Zeile 4 wird &amp;#252;ber &lt;em&gt;e.preventDefault();&lt;/em&gt; die Standardaktion des Links
verhindert. In unserem Fall also, dass beim Klick auf dem Link dem Inhalt des &lt;em&gt;href&lt;/em&gt; Attributs
gefolgt wird. Stattdessen wird ab der Zeile 5 definiert, dass ein &lt;a title="Dokumentation der jQuery Funktion ajax" href="http://api.jquery.com/jQuery.ajax/" target="_blank"&gt;ajax&lt;/a&gt; Aufruf
gefeuert werden muss.
&lt;/p&gt;
&lt;p&gt;
Dabei werden folgende Werte an die verschiedenen Parameter der Funktion &lt;a title="Dokumentation der jQuery Funktion ajax" href="http://api.jquery.com/jQuery.ajax/" target="_blank"&gt;ajax&lt;/a&gt; &amp;#252;bergeben:
&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="2" width="100%" border="1"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th valign="top" width="133"&gt;
Parameter&lt;/th&gt;
&lt;th valign="top" width="133"&gt;
Wert&lt;/th&gt;
&lt;th valign="top"&gt;
Erkl&amp;#228;rung&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;
type&lt;/td&gt;
&lt;td valign="top" width="133"&gt;
&lt;strong&gt;POST&lt;/strong&gt; (fix)&lt;/td&gt;
&lt;td valign="top"&gt;
Ajax Anfragen an Pagemethods oder Scriptsservices m&amp;#252;ssen aus Sicherheitsgr&amp;#252;nden
immer vom Typ POST sein, um JSON hijacking Angriffe abzuwehren. Eine sehr gute Beschreibung
hierzu gibt es &lt;a title="Beschreibung einer JSON Sicherheitsl&amp;#252;cke" href="http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx" target="_blank"&gt;im
Blog von Phil Haack&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;
url&lt;/td&gt;
&lt;td valign="top" width="133"&gt;
{Seitenname.aspx}/{Methodenname}&lt;/td&gt;
&lt;td valign="top"&gt;
Ziel des Ajax Aufrufs. Im Falle einer Page Method nach dem Schema &lt;em&gt;{Seitenname.&lt;strong&gt;aspx&lt;/strong&gt;}/{Methodenname}&lt;/em&gt;,
im Fall von ScriptServices &lt;em&gt;{Servicename.&lt;strong&gt;asmx&lt;/strong&gt;}/{Methodenname}&lt;/em&gt;.
Wichtig ist, dass die entsprechende Methode im Falle von Pagemethods statisch ist
und mit dem Attribut &lt;em&gt;WebMethod&lt;/em&gt; dekoriert wurde. Im Falle eines ScriptServices
ist auf die Dekorierung des Services mit dem Attribut &lt;em&gt;ScriptService&lt;/em&gt; zu achten.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;
data&lt;/td&gt;
&lt;td valign="top" width="133"&gt;
JSON String&lt;/td&gt;
&lt;td valign="top"&gt;
Erwartet die Methode Parameter, sind diese hier als JSON String, und nicht als JSON
Objekt zu &amp;#252;bergeben! Falls die Methode keine Parameter erwartet, sollte stets
ein leeres JSON Objekt &amp;#252;bergeben werden (also &lt;em&gt;&amp;quot;{}&amp;quot;&lt;/em&gt;). Andernfalls
&amp;#252;bergibt jQuery als contentType statt &lt;em&gt;application/json&lt;/em&gt; automatisch &lt;em&gt;text/html&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;
contentType&lt;/td&gt;
&lt;td valign="top" width="133"&gt;
application/json; charset=utf-8 (fix)&lt;/td&gt;
&lt;td valign="top"&gt;
Als Content Type ist stets &lt;em&gt;application/json; charset=utf-8&lt;/em&gt; zu &amp;#252;bergeben.
Dies ist das Zeichen f&amp;#252;r das ASP.NET Ajax Framework, serverseitig die Anfrage
an den ScriptService Handler und nicht an den Soap Webservice Handler weiterzuleiten.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;
dataType&lt;/td&gt;
&lt;td valign="top" width="133"&gt;
json (fix).&lt;/td&gt;
&lt;td valign="top"&gt;
Gibt den Datentyp der Antwort an. G&amp;#252;ltige Antworten sind unter anderem json,
script, xml oder text. Im Fall von Pagemethods und ScriptServices kommt immer JSON
zur&amp;#252;ck.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;
succes&lt;/td&gt;
&lt;td valign="top" width="133"&gt;
Anonyme Funktion bzw. Funktionsname&lt;/td&gt;
&lt;td valign="top"&gt;
Eine Anonyme Funktion bzw. der Name einer Funktion, die die R&amp;#252;ckgabe der Methode
verarbeitet. 
&lt;br /&gt;
Im Falle von PageMethods und ScriptServices wird die Antwort aus Sicherheitsgr&amp;#252;nden
&amp;#252;brigens immer in ein Objekt Namens &lt;em&gt;d &lt;/em&gt;verpackt (siehe auch Zeile 12
des Scripts). Die Ursache hierf&amp;#252;r ist &amp;#228;hnlich wie beim Parameter type und
wird auch n&amp;#228;her in &lt;a title="JSON Hijacking erkl&amp;#228;rt" href="http://haacked.com/archive/2009/06/25/json-hijacking.aspx" target="_blank"&gt;Phil
Haacks Blog Eintrag&lt;/a&gt; erkl&amp;#228;rt.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Der Aufruf des Services sollte somit ausreichend erkl&amp;#228;rt sein. Einzig Zeile 12
bedarf noch einer kleinen Erkl&amp;#228;rung:
&lt;/p&gt;
&lt;p&gt;
Via $(&amp;quot;#Content&amp;quot;) holt jQuery sich eine Referenz auf den Zielbereich in
mithilfe der Funktion html die Antwort des Ajax Requests geschrieben wird.
&lt;/p&gt;
&lt;p&gt;
Der Code zum Aufruf der beiden Webservice Methoden sieht erwartungsgem&amp;#228;&amp;#223;
&amp;#228;hnlich aus:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:df55179d-b395-4780-8763-c85b0906a6fa" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;            $("#HelloWorldLink").click(function(e) {
                e.preventDefault();
                $.ajax({
                    type: "POST",
                    url: "AjaxDemoService.asmx/HelloWorld",
                    data: "{}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function(msg) {
                        $("#content").html(msg.d);
                    }
                });
            });

            $("#EchoLink").click(function(e) {
                e.preventDefault();
                var number = $("#EchoTextBox").val();
                var jsonData = "{ 'number' : '" + number + "'}";
                $.ajax({
                    type: "POST",
                    url: "AjaxDemoService.asmx/Echo",
                    data: jsonData,
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function(msg) {
                        $("#content").html(msg.d);
                    }
                });
            });&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Erkl&amp;#228;renswert ist einzig Zeile 18. Hier wird ein Json String zusammen gesetzt,
der sp&amp;#228;ter an die entsprechende Methode des Webservices &amp;#252;bergeben wird.
Dies geht im Falle eines Arguments noch ganz gut, wird aber sp&amp;#228;testens bei zwei
oder mehr Argumenten sehr l&amp;#228;stig. Abhilfe schafft hier die Methode &lt;em&gt;stringify&lt;/em&gt; des
Objekts &lt;em&gt;JSON&lt;/em&gt;. Die Methode &amp;#252;berf&amp;#252;hrt ein Json Objekt in einen entsprechenden
String. Moderne Browser bringen dieses Objekt inkl. passender Methode gleich mit.
In allen anderen F&amp;#228;llen hilft der JSON Parser / Stringifier &lt;a title="JSON in JavaScript" href="http://www.json.org/js.html" target="_blank"&gt;Json2&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Das Ergebnis der M&amp;#252;he sieht im Live-Betrieb dann &amp;#252;brigens wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/5AS.NETWebformsAnwendungenundAjaxTeil4Sc_7BF4/02_AjaxRequest.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="159" alt="02_AjaxRequest" src="http://blog.codemurai.de/images/5AS.NETWebformsAnwendungenundAjaxTeil4Sc_7BF4/02_AjaxRequest_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Zum Download der jQuery Library ist, wie auf der Abbildung gezeigt, ein weiterer Request
notwendig, der knapp 58 kb umfasst. Dies sind fast 30 kb weniger als es im vorherigen
Beispiel auf Basis des ASP.NET AJAX (client) Frameworks der Fall waren.
&lt;/p&gt;
&lt;h4&gt;Fazit
&lt;/h4&gt;
&lt;p&gt;
Ajax Aufrufe werden mithilfe des jQuery Frameworks zum Kinderspiel. Gerade wenn man
jQuery bereits f&amp;#252;r Oberfl&amp;#228;chenmanipulationen in einer Seite nutzt, lohnt
sich die Anwendung von jQuery f&amp;#252;r Ajax Aufrufe anstatt der Nutzung des ASP.NET
Ajax (Client) Frameworks.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=3ff7deed-4185-4b1c-85f2-416c877b9b2d" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,3ff7deed-4185-4b1c-85f2-416c877b9b2d.aspx</comments>
      <category>.NET</category>
      <category>Ajax</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=762299a1-efea-490c-b27e-d0fa137677bf</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,762299a1-efea-490c-b27e-d0fa137677bf.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,762299a1-efea-490c-b27e-d0fa137677bf.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=762299a1-efea-490c-b27e-d0fa137677bf</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <style type="text/css">







.cf { font-family: courier new; font-size: 10pt; color: black; background: white; border: solid 1px; }
.cl { margin: 0px; }
.cln { color: #2b91af; }
.cb1 { color: blue; }
.cb2 { color: #2b91af; }
.cb3 { color: #a31515; }
.cb4 { color: #a31515; }
.cb5 { color: red; }
.cb6 { color: #a31515; }
.cb7 { color: red; }
.cb8 { color: green; }</style>
        <p>
Nachdem ich in <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 1)" href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank">Teil
1</a> der Serie den manuellen Ansatz zur AJAX Implementierung gezeigt habe und in
den Teilen <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks" href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank">2</a> und <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel" href="http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx" target="_blank">3</a> auf
(halb-)automatische Alternativen einging, möchte ich dieses Mal einen anderen
Weg zeigen, ASP.NET Scriptservices in Verbindung mit ASP.NET AJAX.
</p>
        <p>
Rekapitulieren wir noch einmal:
</p>
        <p>
          <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 1)" href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank">Teil
1</a> der Serie zeigte einen manuellen Ansatz, der hauptsächlich damit kämpfte,
dass man innerhalb des JavaScript Codes selbst darauf achten musste, die verschiedenen
Besonderheiten der unterschiedlichen Browser zu berücksichtigen. Dies geschah
in den Teilen <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks" href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank">2</a> und <a title="ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel" href="http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx" target="_blank">3</a> zwar
automatisch hinter den Kulissen, dafür hatten wir bei diesen Alternativen jedoch
das Problem, dass bei jedem AJAX Request sowohl der komplette ViewState übertragen
wurde und vor allem auf dem Server auch der komplette Page Life Cycle durchlebt wurde.
</p>
        <h4>Leichtgewichtig durch die Ajax Welt
</h4>
        <p>
Heute möchte ich deshalb einen Ansatz zeigen, der die Vorteile der bisher vorgestellten
Ansätze vereint, jedoch nicht über die selben Nachteile verfügt.
</p>
        <p>
Konkret bedeutet dies, dass die Implementierung auf Clientseite browserübergreifend
stattfinden wird, zwischen Client und Server nur die wirklich notwendigen Daten übertragen
werden und der Page Life Cycle auf der Serverseite nicht durchlaufen wird.
</p>
        <h4>Page Methods
</h4>
        <p>
Der erste Schritt Richtung einer leichtgewichtigen Implementierung führt über
die sogenannten <em>Page Methods</em>. Page Methods sind statische Methoden einer
*.aspx Seite, die mit dem <em><a title="Verfügbarmachen von Webdiensten für Clientskript" href="http://msdn.microsoft.com/de-de/library/bb398998.aspx" target="_blank">[WebMethod]</a></em> Attribut
annotiert werden. Für den Client erscheinen Page Methods wie normale Methoden
eines Web Services.
</p>
        <p>
Ausgehend vom Beispielcode der letzten drei Teile der Serie passe ich den Servercode
für die Methode, die den Inhalt einer Datei zurückliefert also wie folgt
an:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:79133c5c-df74-4b9b-b3ad-77395ad61c02" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="c#">using System.IO;
using System.Web.UI;
using System.Web.Services;

public partial class Teil4 : Page
{
	[WebMethod]
    public static string ReadStaticFile()
    {

	     string fileContent;
         using (var reader =
             new StreamReader(
                 System.Web.HttpContext.Current.Server.MapPath("~/static.html")))
         {

             fileContent = reader.ReadToEnd();
         }
         return fileContent;
     }
}</pre>
        </div>
        <p>
Als einzige Neuerung im Vergleich zur vorherigen Version fällt das zuvor beschriebene
Attribut <em>[WebMethod]</em> auf.
</p>
        <p>
Um die Methode ReadStaticFile nun clientseitig über das ASP.NET Ajax Framwork
nutzen zu können, müssen wir innerhalb der *.aspx Seite bei unserem ScriptManager
noch die Eigenschaft <em>EnablePageMethods</em> mit dem Wert <em>true</em> versehen.
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:febf8d8f-146e-4477-8838-b8c3eb92e5bb" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="xml">&lt;asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="True"/&gt;</pre>
        </div>
        <p>
Als Ergebnis rendert der Server bei einem Aufruf der Seite nun folgenden Java Script
Code inline in die Seite hinein:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:94b51a16-300f-47c9-8981-b75edc9c9d74" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js:firstline[67]"> &lt;script type="text/javascript"&gt;
         //&lt;![CDATA[
         var PageMethods = function() {

            PageMethods.initializeBase(this);
            this._timeout = 0;
            this._userContext = null;
            this._succeeded = null;
            this._failed = null;
         }
         PageMethods.prototype = {
             _get_path: function() {
                 var p = this.get_path();
                 if (p) return p;
                 else return PageMethods._staticInstance.get_path();
             },
             ReadStaticFile: function(succeededCallback, failedCallback, userContext) {
                 /// &lt;param name="succeededCallback" type="Function" optional="true" mayBeNull="true"&gt;&lt;/param&gt;
                 /// &lt;param name="failedCallback" type="Function" optional="true" mayBeNull="true"&gt;&lt;/param&gt;
                 /// &lt;param name="userContext" optional="true" mayBeNull="true"&gt;&lt;/param&gt;
                 return this._invoke(this._get_path(), 'ReadStaticFile', false, {}, succeededCallback, failedCallback, userContext);
             } 
         }
         // und vieles mehr ;-)</pre>
        </div>
        <p>
Wie man sieht, wird ein JavaScript Objekt <em>PageMethods</em> angelegt, welches über
eine Funktion <em>ReadStaticFile</em> verfügt. Die Funktion hat also genau denselben
Namen wie unsere serverseitige Funktion. Weiter nimmt Sie drei optionale Parameter
entgegen:
</p>
        <ul>
          <li>
            <strong>succeededCallBack</strong>: Funktion, die aufgerufen wird, wenn die Ajax Anfrage <em>erfolgreich</em> beendet
wurde 
</li>
          <li>
            <strong>failedCallBack</strong>: Funktion, die aufgerufen wird, wenn die Ajax Anfrage <em>fehlerhaft</em> beendet
wurde 
</li>
          <li>
            <strong>userContext</strong>: Der Inhalt dieser Variable wird an die Funktionen succeededCallBack
bzw. faildCallBack durchgereicht. 
</li>
        </ul>
        <p>
Der clientseitige Aufruf der Page Method gestaltet sich nun relativ einfach. Als erstes
fügen wir der *.aspx Seite einen neuen ClientScriptBlock hinzu:
</p>
        <div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2f3175ac-a7e9-4aa3-96f6-8e08f9196470" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
          <pre name="code" class="js">&lt;script type="text/javascript"&gt;       
  function getStaticFile() {
    PageMethods.ReadStaticFile(onSuccess, onError, "MeinKontext");
  }

  function onSuccess(result, userContext, methodName) {
    var contentDiv = $get('content');
    if (userContext) {
      result += "&lt;p&gt;Der UserContext war: &lt;strong&gt;" + userContext + "&lt;/strong&gt;&lt;/p&gt;";
    }

    result += "&lt;p&gt;Der Methoden Name war: &lt;strong&gt;" + methodName + "&lt;/strong&gt;&lt;/p&gt;";
    contentDiv.innerHTML = result;
  } 

  function onError(result) {
    var contentDiv = $get('content');
    contentDiv.innerHTML = result;
  }

&lt;/script&gt;</pre>
        </div>
        <p>
Einstiegspunkt für unseren späteren Code (Click Ereignis unseres Links)
ist die Funktion <em>getStaticFile</em>. Sie ruft die Methode <em>ReadStaticFile</em> des
Objekts <em>PageMethods</em>. Als Argumente übergeben wir zum einen die Funktionen
für die erfolgreiche bzw. fehlerhafte Behandlung der Ajax Anfrage sowie als drittes
die Zeichenfolge <em>"MeinKontext".</em></p>
        <p>
Die Funktion onSuccess ist nun die Funktion, die die (erfolgreiche) Antwort des Servers
verarbeitet. Sie nimmt neben der eigentlichen Antwort des Servers, auch den zuvor
übergebenen userContext entgegen. Außerdem wird der Name der aufgerufenen
Servermethode im Parameter <em>methodName</em> übergeben. Da JavaScript relativ
flexibel ist, was die Anzahl der Parameter angeht und Funktionen <strong>einzig durch
ihren Namen</strong> und nicht anhand ihrer Signatur identifiziert, können die
beiden letzten Parameter übrigens auch problemlos weg gelassen werden.
</p>
        <p>
Innerhalb der Methode onSuccess holen wir uns via <em><a title="Sys.UI.DomElement $get-Methode" href="http://msdn.microsoft.com/de-de/library/bb397717.aspx" target="_blank">$get</a></em> zunächst
eine Referenz auf das Div Element in das wir später unser Ergebnis schreiben
möchten. <em><a title="Sys.UI.DomElement $get-Methode" href="http://msdn.microsoft.com/de-de/library/bb397717.aspx" target="_blank">$get</a></em> ist
übrigens eine Funktion des <a title="Clientreferenz" href="http://msdn.microsoft.com/de-de/library/bb397536.aspx" target="_blank">ASP.NET
Ajax Client Frameworks</a>. Sie ist (vereinfacht gesagt) die Kurzschreibweise für
die JavaScript Funktion <em>document.getElementById</em>.
</p>
        <p>
Weiter werden noch userContext (falls vorhanden) und der aufgerufene Methodenname
an das Ergebnis angehangen. Im letzten Schritt wird das komplette Ergebnis schließlich
in unser Container Div geschrieben.
</p>
        <p>
Der Aufruf  der Funktion <em>getStaticFile</em> geschieht schließlich im
Event onclick eines HTML Links (a Tag).
</p>
        <div class="cf">
          <p class="cl">
            <span class="cln">   17</span>     <span class="cb1">&lt;</span><span class="cb6">p</span><span class="cb1">&gt;</span></p>
          <p class="cl">
            <span class="cln">   18</span>         <span class="cb1">&lt;</span><span class="cb6">a</span><span class="cb7">href</span><span class="cb1">="#"</span><span class="cb7">onclick</span><span class="cb1">="getStaticFile()"&gt;</span>Hier
klicken zum Request einer statischen Datei
</p>
          <p class="cl">
            <span class="cln">   19</span>         <span class="cb1">&lt;/</span><span class="cb6">a</span><span class="cb1">&gt;</span></p>
          <p class="cl">
            <span class="cln">  // ....</span>
          </p>
          <p class="cl">
            <span class="cln">
            </span>
            <span class="cln">   27</span>     <span class="cb1">&lt;/</span><span class="cb6">p</span><span class="cb1">&gt;</span></p>
          <p class="cl">
            <span class="cln">   28</span>     <span class="cb1">&lt;</span><span class="cb6">div</span><span class="cb7">id</span><span class="cb1">="content"&gt;</span></p>
          <p class="cl">
            <span class="cln">   29</span>        
Bitte klicken Sie auf einen der Links, damit dieser Bereich gefüllt wird.
</p>
          <p class="cl">
            <span class="cln">   30</span>      <span class="cb1">&lt;/</span><span class="cb6">div</span><span class="cb1">&gt;</span></p>
        </div>
        <h4>Schweres Leichtgewicht
</h4>
        <p>
Ruft man die Seite nun im Browser auf, fällt auf, dass neben der eigentlichen
Seite auch drei JavaScript Dateien des Microsoft ASP.NET Ajax Client Frameworks geladen
werden.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/01_initialerRequest.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="Erster Request der Seite" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/01_initialerRequest_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Die erste Anfrage umfasst nun also 93 kb, von denen sich 85 kb auf die MS AJAX Script
Dateien verteilen.
</p>
        <p>
Seinen Vorteil spielt die Herangehensweise jedoch bei den Ajax Anfragen aus. Wie man
im folgenden Screenshot sieht, gehen hier gerade einmal 127 Byte über die Leitung.
Weiter erkannt man deutlich, dass während des Posts kein ViewState mehr zum Server
übertragen wird.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/02_ajaxpost.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="28" alt="02_ajaxpost" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/02_ajaxpost_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Auch die Antwort ist relativ schmal und beschränkt sich auf das nötigste:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/03_ajaxantwort.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="31" alt="03_ajaxantwort" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/03_ajaxantwort_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Die Antwort ist übrigens im <a title="Einführung in JSON" href="http://www.json.org/json-de.html" target="_blank">JSON
(Java Script Object Notation)</a> Format serialisiert. Hätte unser Post Daten
in Form von Argumenten für unsere Page Method enthalten, wären diese auch
automatisch im JSON Format serialisiert worden. Eine etwas besser lesbare Variante
der JSON formatierten Antwort enthalt der Tab JSON des Firebugs:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/04_ajaxjson.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="28" alt="04_ajaxjson" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/04_ajaxjson_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
In unserem Beispiel ist die Antwort zwar noch recht übersichtlich, so dass wir
den Tab JSON eigentlich nicht benötigen würden, spätestens bei der
Rückgabe komplexer Objektstrukturen lernt an den Tab jedoch schnell zu schätzen
;-)
</p>
        <h4>Es geht noch besser!
</h4>
        <p>
Obwohl die bisherige Implementierung bereits ganz gut ist, gibt es noch zwei Kritikpunkte.
Zum einen erscheint die Plazierung einer statischen Methode innerhalb der *.aspx Seite
ein wenig eigenartig. Da sie weder auf <strike>Instanz</strike> Exemplar-Felder, noch
auf Exemplar-Methoden der Seite zugreifen kann, ist sie innerhalb der Seite eigentlich
fehl am Platz.
</p>
        <p>
Außerdem stört mich der automatisch generierte JavaScript Script Block innerhalb
der Seite, der die Proxies für die PageMethod Aufrufe zur Verfügung stellt.
Lieber wäre mir die Variante einer eingelinkten externen JavaScript Datei.
</p>
        <p>
Beide Punkte können wir glücklicherweise recht einfach lösen, nämlich
durch den Einsatz von Script Services. Script Services sind normale Web Services,
die mit dem ScriptService Attribut annotiert werden. Erstellt man einen Web Service
mit Visual Studio 2008, ist dieses Attribut sogar bereits über der Klasse enthalten.
Allerdings wird es automatisch auskommentiert.
</p>
        <p>
Um einen Web Service nun also als Script Service zur Verfügung zu stellen, genügt
es den Kommentar, wie in Zeile 13 des folgenden Listings gezeigt, zu entfernen.
</p>
        <div class="cf">
          <p class="cl">
            <span class="cln">   11</span> [<span class="cb2">WebServiceBinding</span>(ConformsTo
= <span class="cb2">WsiProfiles</span>.BasicProfile1_1)]
</p>
          <p class="cl">
            <span class="cln">   12</span> <span class="cb8">// To allow this Web
Service to be called from script, using ASP.NET AJAX, uncomment the following line. </span></p>
          <p class="cl">
            <span class="cln">   13</span> [System.Web.Script.Services.<span class="cb2">ScriptService</span>]
</p>
          <p class="cl">
            <span class="cln">   14</span> <span class="cb1">public</span><span class="cb1">class</span><span class="cb2">AjaxDemoService</span> : <span class="cb2">WebService</span> {
</p>
          <p class="cl">
            <span class="cln">   15</span> 
</p>
          <p class="cl">
            <span class="cln">   16</span>     [<span class="cb2">WebMethod</span>]
</p>
          <p class="cl">
            <span class="cln">   17</span>     <span class="cb1">public</span><span class="cb1">string</span> HelloWorld()
{
</p>
          <p class="cl">
            <span class="cln">   18</span>         <span class="cb1">return</span><span class="cb5">"Hello
World"</span>;
</p>
          <p class="cl">
            <span class="cln">   19</span>     }
</p>
          <p class="cl">
            <span class="cln">   20</span> 
</p>
          <p class="cl">
            <span class="cln">   21</span>     [<span class="cb2">WebMethod</span>]
</p>
          <p class="cl">
            <span class="cln">   22</span>     <span class="cb1">public</span><span class="cb1">string</span> Echo(<span class="cb1">int</span> number)
</p>
          <p class="cl">
            <span class="cln">   23</span>     {
</p>
          <p class="cl">
            <span class="cln">   24</span>         <span class="cb1">return</span><span class="cb1">string</span>.Format(<span class="cb5">"Sie
haben {0} eingegeben."</span>, number);
</p>
          <p class="cl">
            <span class="cln">   25</span>     }   
</p>
          <p class="cl">
            <span class="cln">   26</span> }
</p>
        </div>
        <p>
Prinzipiell reicht dies aus, um den Service via Ajax anzusprechen. Um uns das Leben
jedoch ein wenig einfacher zu machen, lassen wir das ASP.NET Ajax Framework für
uns - analog zur Page Method Lösung - JavaScript Proxies für unsere Methoden
Aufrufe erstellen. Dazu fügen wir innerhalb des ScriptManager Tags der Seite
ein Kind Element <em>&lt;Services&gt;</em> ein. Diesem Element fügen wir als
weiteres Kind Element eine <em>ServiceReference</em> ein, deren Pfad auf unseren Service
verweißt.
</p>
        <div class="cf">
          <p class="cl">
            <span class="cln">   10</span>     <span class="cb1">&lt;</span><span class="cb3">asp</span><span class="cb1">:</span><span class="cb3">ScriptManager</span><span class="cb7">ID</span><span class="cb1">="ScriptManager1"</span><span class="cb7">runat</span><span class="cb1">="server"</span><span class="cb7">EnablePageMethods</span><span class="cb1">="True"&gt;</span></p>
          <p class="cl">
            <span class="cln">   11</span>         <span class="cb1">&lt;</span><span class="cb3">Services</span><span class="cb1">&gt;</span></p>
          <p class="cl">
            <span class="cln">   12</span>             <span class="cb1">&lt;</span><span class="cb3">asp</span><span class="cb1">:</span><span class="cb3">ServiceReference</span><span class="cb7">Path</span><span class="cb1">="~/AjaxDemoService.asmx"</span><span class="cb1">/&gt;</span></p>
          <p class="cl">
            <span class="cln">   13</span>         <span class="cb1">&lt;/</span><span class="cb3">Services</span><span class="cb1">&gt;</span></p>
          <p class="cl">
            <span class="cln">   14</span>     <span class="cb1">&lt;/</span><span class="cb3">asp</span><span class="cb1">:</span><span class="cb3">ScriptManager</span><span class="cb1">&gt;</span></p>
        </div>
        <p>
An dieser Stelle sei noch einmal darauf hingewiesen, dass dieser Schritt reine Bequemlichkeit
und nicht zwingend erforderlich ist. Ohne ihn könnten wir unseren Service genauso
via JavaScript rufen und würden genauso JSON als Serialisierungsformat nutzen
können. Allerdings müssten wir den clientseitigen Aufruf dann komplett selbst
entwickeln und hätten keine Proxies zur Verfügung.
</p>
        <p>
Da wir jedoch bequem sind, lassen wir uns Proxymethoden generieren. Diese können
wir dann in unserem bestehenden Client Script Block innerhalb der Seite aufrufen.
</p>
        <p>
Wie die folgende Abbildung zeigt, erhalten wir dann sogar Intellisense und erfahren
somit, welche Argumente eine bestimmte Methode entgegen nimmt.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/05_VS.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="87" alt="05_VS" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/05_VS_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Der Rest gestaltet sich ähnlich der Page Method Implementierung. Als wichtiger
Unterschied wäre noch zu erwähnen, dass die generierten Proxies standardmäßig
in eine externe JavaScript Datei geschrieben werden und somit nicht mehr als Client
Script Block in der Seite auftauchen.
</p>
        <p>
Die Kommunikation zwischen Client und Server läuft analog der Page Method Implementierung.
</p>
        <p>
Der Client sendet in seiner Anfrage unter anderem einen Header Content-Type mit dem
Wert "application/json; charset=utf-8". Dieser ist besonders wichtig, denn
er steuert den Serialisierungsmechanismus des Servers. Hat dieser Header einen anderen
Wert, wird die Antwort XML Serialisiert. Somit ist sichergestellt, dass JavaScript
Clients JSON erhalten, wohingegen andere Clients XML erhalten.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/06_ajaxheader2.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="70" alt="06_ajaxheader2" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/06_ajaxheader2_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Die nächste Abbildung zeigt, dass auch die Post Parameter via JSON serialisiert
werden:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/07_ajaxpost2.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="85" alt="07_ajaxpost2" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/07_ajaxpost2_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Für die Antwort ist dies natürlich auch weiterhin der Fall:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/07_ajaxantwort2.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="41" alt="07_ajaxantwort2" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/07_ajaxantwort2_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h4>Fazit:
</h4>
        <p>
Dieser Teil der Serie hat gezeigt, dass sich die Menge der übertragenen Daten
während eines Ajax Requests mit der Hilfe von Page Methods, Script Services und
dem ASP.NET Ajax Framework auf ein Minimum reduzieren lassen. Außerdem wird bei
dieser Variante der ASP.NET Page Life Cycle im Gegensatz zu den vorherigen Beispielen
nicht durchlaufen.
</p>
        <p>
Beides in Kombination kann zu gewaltigen Performancevorteilen verglichen mit Client
Callbacks oder dem Updatepanel führen.
</p>
        <p>
Einziger Wermutstropfen ist die Übertragung der 85 kb großen ASP.NET Ajax
Framework Java Script Dateien während des ersten Requests. 
</p>
        <p>
Eine Abhilfe für dieses Problem werden wir uns im nächsten Teil der Serie
ansehen.
</p>
        <p>
Wie immer freue ich mich natürlich über Kommentare zu diesem Blog Beitrag.
</p>
        <p>
 
</p>
        <p>
          <em>Dieser Beitrag war hilfreich? Dann bitte nicht vergessen Ihn zu kicken!</em>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=762299a1-efea-490c-b27e-d0fa137677bf" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>ASP.NET Webforms Anwendungen und Ajax (Teil 4) Scriptservices, Page Methods und das ASP.NET AJAX Framework</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,762299a1-efea-490c-b27e-d0fa137677bf.aspx</guid>
      <link>http://blog.codemurai.de/2010/02/18/ASPNETWebformsAnwendungenUndAjaxTeil4ScriptservicesPageMethodsUndDasASPNETAJAXFramework.aspx</link>
      <pubDate>Thu, 18 Feb 2010 21:14:42 GMT</pubDate>
      <description>&lt;style type="text/css"&gt;







.cf { font-family: courier new; font-size: 10pt; color: black; background: white; border: solid 1px; }
.cl { margin: 0px; }
.cln { color: #2b91af; }
.cb1 { color: blue; }
.cb2 { color: #2b91af; }
.cb3 { color: #a31515; }
.cb4 { color: #a31515; }
.cb5 { color: red; }
.cb6 { color: #a31515; }
.cb7 { color: red; }
.cb8 { color: green; }&lt;/style&gt;
&lt;p&gt;
Nachdem ich in &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 1)" href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank"&gt;Teil
1&lt;/a&gt; der Serie den manuellen Ansatz zur AJAX Implementierung gezeigt habe und in
den Teilen &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks" href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank"&gt;2&lt;/a&gt; und &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel" href="http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx" target="_blank"&gt;3&lt;/a&gt; auf
(halb-)automatische Alternativen einging, m&amp;#246;chte ich dieses Mal einen anderen
Weg zeigen, ASP.NET Scriptservices in Verbindung mit ASP.NET AJAX.
&lt;/p&gt;
&lt;p&gt;
Rekapitulieren wir noch einmal:
&lt;/p&gt;
&lt;p&gt;
&lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 1)" href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank"&gt;Teil
1&lt;/a&gt; der Serie zeigte einen manuellen Ansatz, der haupts&amp;#228;chlich damit k&amp;#228;mpfte,
dass man innerhalb des JavaScript Codes selbst darauf achten musste, die verschiedenen
Besonderheiten der unterschiedlichen Browser zu ber&amp;#252;cksichtigen. Dies geschah
in den Teilen &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks" href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank"&gt;2&lt;/a&gt; und &lt;a title="ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel" href="http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx" target="_blank"&gt;3&lt;/a&gt; zwar
automatisch hinter den Kulissen, daf&amp;#252;r hatten wir bei diesen Alternativen jedoch
das Problem, dass bei jedem AJAX Request sowohl der komplette ViewState &amp;#252;bertragen
wurde und vor allem auf dem Server auch der komplette Page Life Cycle durchlebt wurde.
&lt;/p&gt;
&lt;h4&gt;Leichtgewichtig durch die Ajax Welt
&lt;/h4&gt;
&lt;p&gt;
Heute m&amp;#246;chte ich deshalb einen Ansatz zeigen, der die Vorteile der bisher vorgestellten
Ans&amp;#228;tze vereint, jedoch nicht &amp;#252;ber die selben Nachteile verf&amp;#252;gt.
&lt;/p&gt;
&lt;p&gt;
Konkret bedeutet dies, dass die Implementierung auf Clientseite browser&amp;#252;bergreifend
stattfinden wird, zwischen Client und Server nur die wirklich notwendigen Daten &amp;#252;bertragen
werden und der Page Life Cycle auf der Serverseite nicht durchlaufen wird.
&lt;/p&gt;
&lt;h4&gt;Page Methods
&lt;/h4&gt;
&lt;p&gt;
Der erste Schritt Richtung einer leichtgewichtigen Implementierung f&amp;#252;hrt &amp;#252;ber
die sogenannten &lt;em&gt;Page Methods&lt;/em&gt;. Page Methods sind statische Methoden einer
*.aspx Seite, die mit dem &lt;em&gt;&lt;a title="Verf&amp;#252;gbarmachen von Webdiensten f&amp;#252;r Clientskript" href="http://msdn.microsoft.com/de-de/library/bb398998.aspx" target="_blank"&gt;[WebMethod]&lt;/a&gt;&lt;/em&gt; Attribut
annotiert werden. F&amp;#252;r den Client erscheinen Page Methods wie normale Methoden
eines Web Services.
&lt;/p&gt;
&lt;p&gt;
Ausgehend vom Beispielcode der letzten drei Teile der Serie passe ich den Servercode
f&amp;#252;r die Methode, die den Inhalt einer Datei zur&amp;#252;ckliefert also wie folgt
an:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:79133c5c-df74-4b9b-b3ad-77395ad61c02" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c#"&gt;using System.IO;
using System.Web.UI;
using System.Web.Services;

public partial class Teil4 : Page
{
	[WebMethod]
    public static string ReadStaticFile()
    {

	     string fileContent;
         using (var reader =
             new StreamReader(
                 System.Web.HttpContext.Current.Server.MapPath("~/static.html")))
         {

             fileContent = reader.ReadToEnd();
         }
         return fileContent;
     }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Als einzige Neuerung im Vergleich zur vorherigen Version f&amp;#228;llt das zuvor beschriebene
Attribut &lt;em&gt;[WebMethod]&lt;/em&gt; auf.
&lt;/p&gt;
&lt;p&gt;
Um die Methode ReadStaticFile nun clientseitig &amp;#252;ber das ASP.NET Ajax Framwork
nutzen zu k&amp;#246;nnen, m&amp;#252;ssen wir innerhalb der *.aspx Seite bei unserem ScriptManager
noch die Eigenschaft &lt;em&gt;EnablePageMethods&lt;/em&gt; mit dem Wert &lt;em&gt;true&lt;/em&gt; versehen.
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:febf8d8f-146e-4477-8838-b8c3eb92e5bb" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="True"/&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Als Ergebnis rendert der Server bei einem Aufruf der Seite nun folgenden Java Script
Code inline in die Seite hinein:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:94b51a16-300f-47c9-8981-b75edc9c9d74" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js:firstline[67]"&gt; &amp;lt;script type="text/javascript"&amp;gt;
         //&amp;lt;![CDATA[
         var PageMethods = function() {

            PageMethods.initializeBase(this);
            this._timeout = 0;
            this._userContext = null;
            this._succeeded = null;
            this._failed = null;
         }
         PageMethods.prototype = {
             _get_path: function() {
                 var p = this.get_path();
                 if (p) return p;
                 else return PageMethods._staticInstance.get_path();
             },
             ReadStaticFile: function(succeededCallback, failedCallback, userContext) {
                 /// &amp;lt;param name="succeededCallback" type="Function" optional="true" mayBeNull="true"&amp;gt;&amp;lt;/param&amp;gt;
                 /// &amp;lt;param name="failedCallback" type="Function" optional="true" mayBeNull="true"&amp;gt;&amp;lt;/param&amp;gt;
                 /// &amp;lt;param name="userContext" optional="true" mayBeNull="true"&amp;gt;&amp;lt;/param&amp;gt;
                 return this._invoke(this._get_path(), 'ReadStaticFile', false, {}, succeededCallback, failedCallback, userContext);
             } 
         }
         // und vieles mehr ;-)&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Wie man sieht, wird ein JavaScript Objekt &lt;em&gt;PageMethods&lt;/em&gt; angelegt, welches &amp;#252;ber
eine Funktion &lt;em&gt;ReadStaticFile&lt;/em&gt; verf&amp;#252;gt. Die Funktion hat also genau denselben
Namen wie unsere serverseitige Funktion. Weiter nimmt Sie drei optionale Parameter
entgegen:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;succeededCallBack&lt;/strong&gt;: Funktion, die aufgerufen wird, wenn die Ajax Anfrage &lt;em&gt;erfolgreich&lt;/em&gt; beendet
wurde 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;failedCallBack&lt;/strong&gt;: Funktion, die aufgerufen wird, wenn die Ajax Anfrage &lt;em&gt;fehlerhaft&lt;/em&gt; beendet
wurde 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;userContext&lt;/strong&gt;: Der Inhalt dieser Variable wird an die Funktionen succeededCallBack
bzw. faildCallBack durchgereicht. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Der clientseitige Aufruf der Page Method gestaltet sich nun relativ einfach. Als erstes
f&amp;#252;gen wir der *.aspx Seite einen neuen ClientScriptBlock hinzu:
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2f3175ac-a7e9-4aa3-96f6-8e08f9196470" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="js"&gt;&amp;lt;script type="text/javascript"&amp;gt;       
  function getStaticFile() {
    PageMethods.ReadStaticFile(onSuccess, onError, "MeinKontext");
  }

  function onSuccess(result, userContext, methodName) {
    var contentDiv = $get('content');
    if (userContext) {
      result += "&amp;lt;p&amp;gt;Der UserContext war: &amp;lt;strong&amp;gt;" + userContext + "&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;";
    }

    result += "&amp;lt;p&amp;gt;Der Methoden Name war: &amp;lt;strong&amp;gt;" + methodName + "&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;";
    contentDiv.innerHTML = result;
  } 

  function onError(result) {
    var contentDiv = $get('content');
    contentDiv.innerHTML = result;
  }

&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
Einstiegspunkt f&amp;#252;r unseren sp&amp;#228;teren Code (Click Ereignis unseres Links)
ist die Funktion &lt;em&gt;getStaticFile&lt;/em&gt;. Sie ruft die Methode &lt;em&gt;ReadStaticFile&lt;/em&gt; des
Objekts &lt;em&gt;PageMethods&lt;/em&gt;. Als Argumente &amp;#252;bergeben wir zum einen die Funktionen
f&amp;#252;r die erfolgreiche bzw. fehlerhafte Behandlung der Ajax Anfrage sowie als drittes
die Zeichenfolge &lt;em&gt;&amp;quot;MeinKontext&amp;quot;.&lt;/em&gt; 
&lt;/p&gt;
&lt;p&gt;
Die Funktion onSuccess ist nun die Funktion, die die (erfolgreiche) Antwort des Servers
verarbeitet. Sie nimmt neben der eigentlichen Antwort des Servers, auch den zuvor
&amp;#252;bergebenen userContext entgegen. Au&amp;#223;erdem wird der Name der aufgerufenen
Servermethode im Parameter &lt;em&gt;methodName&lt;/em&gt; &amp;#252;bergeben. Da JavaScript relativ
flexibel ist, was die Anzahl der Parameter angeht und Funktionen &lt;strong&gt;einzig durch
ihren Namen&lt;/strong&gt; und nicht anhand ihrer Signatur identifiziert, k&amp;#246;nnen die
beiden letzten Parameter &amp;#252;brigens auch problemlos weg gelassen werden.
&lt;/p&gt;
&lt;p&gt;
Innerhalb der Methode onSuccess holen wir uns via &lt;em&gt;&lt;a title="Sys.UI.DomElement $get-Methode" href="http://msdn.microsoft.com/de-de/library/bb397717.aspx" target="_blank"&gt;$get&lt;/a&gt;&lt;/em&gt; zun&amp;#228;chst
eine Referenz auf das Div Element in das wir sp&amp;#228;ter unser Ergebnis schreiben
m&amp;#246;chten. &lt;em&gt;&lt;a title="Sys.UI.DomElement $get-Methode" href="http://msdn.microsoft.com/de-de/library/bb397717.aspx" target="_blank"&gt;$get&lt;/a&gt;&lt;/em&gt; ist
&amp;#252;brigens eine Funktion des &lt;a title="Clientreferenz" href="http://msdn.microsoft.com/de-de/library/bb397536.aspx" target="_blank"&gt;ASP.NET
Ajax Client Frameworks&lt;/a&gt;. Sie ist (vereinfacht gesagt) die Kurzschreibweise f&amp;#252;r
die JavaScript Funktion &lt;em&gt;document.getElementById&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
Weiter werden noch userContext (falls vorhanden) und der aufgerufene Methodenname
an das Ergebnis angehangen. Im letzten Schritt wird das komplette Ergebnis schlie&amp;#223;lich
in unser Container Div geschrieben.
&lt;/p&gt;
&lt;p&gt;
Der Aufruf&amp;#160; der Funktion &lt;em&gt;getStaticFile&lt;/em&gt; geschieht schlie&amp;#223;lich im
Event onclick eines HTML Links (a Tag).
&lt;/p&gt;
&lt;div class="cf"&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cb6"&gt;p&lt;/span&gt;&lt;span class="cb1"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cb6"&gt;a&lt;/span&gt; &lt;span class="cb7"&gt;href&lt;/span&gt;&lt;span class="cb1"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="cb7"&gt;onclick&lt;/span&gt;&lt;span class="cb1"&gt;=&amp;quot;getStaticFile()&amp;quot;&amp;gt;&lt;/span&gt;Hier
klicken zum Request einer statischen Datei
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="cb6"&gt;a&lt;/span&gt;&lt;span class="cb1"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160; // ....&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&lt;/span&gt;&lt;span class="cln"&gt;&amp;#160;&amp;#160; 27&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="cb6"&gt;p&lt;/span&gt;&lt;span class="cb1"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 28&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cb6"&gt;div&lt;/span&gt; &lt;span class="cb7"&gt;id&lt;/span&gt;&lt;span class="cb1"&gt;=&amp;quot;content&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 29&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
Bitte klicken Sie auf einen der Links, damit dieser Bereich gef&amp;#252;llt wird.
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 30&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="cb6"&gt;div&lt;/span&gt;&lt;span class="cb1"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;h4&gt;Schweres Leichtgewicht
&lt;/h4&gt;
&lt;p&gt;
Ruft man die Seite nun im Browser auf, f&amp;#228;llt auf, dass neben der eigentlichen
Seite auch drei JavaScript Dateien des Microsoft ASP.NET Ajax Client Frameworks geladen
werden.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/01_initialerRequest.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="Erster Request der Seite" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/01_initialerRequest_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Die erste Anfrage umfasst nun also 93 kb, von denen sich 85 kb auf die MS AJAX Script
Dateien verteilen.
&lt;/p&gt;
&lt;p&gt;
Seinen Vorteil spielt die Herangehensweise jedoch bei den Ajax Anfragen aus. Wie man
im folgenden Screenshot sieht, gehen hier gerade einmal 127 Byte &amp;#252;ber die Leitung.
Weiter erkannt man deutlich, dass w&amp;#228;hrend des Posts kein ViewState mehr zum Server
&amp;#252;bertragen wird.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/02_ajaxpost.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="28" alt="02_ajaxpost" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/02_ajaxpost_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Auch die Antwort ist relativ schmal und beschr&amp;#228;nkt sich auf das n&amp;#246;tigste:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/03_ajaxantwort.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="31" alt="03_ajaxantwort" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/03_ajaxantwort_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Die Antwort ist &amp;#252;brigens im &lt;a title="Einf&amp;#252;hrung in JSON" href="http://www.json.org/json-de.html" target="_blank"&gt;JSON
(Java Script Object Notation)&lt;/a&gt; Format serialisiert. H&amp;#228;tte unser Post Daten
in Form von Argumenten f&amp;#252;r unsere Page Method enthalten, w&amp;#228;ren diese auch
automatisch im JSON Format serialisiert worden. Eine etwas besser lesbare Variante
der JSON formatierten Antwort enthalt der Tab JSON des Firebugs:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/04_ajaxjson.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="28" alt="04_ajaxjson" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/04_ajaxjson_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
In unserem Beispiel ist die Antwort zwar noch recht &amp;#252;bersichtlich, so dass wir
den Tab JSON eigentlich nicht ben&amp;#246;tigen w&amp;#252;rden, sp&amp;#228;testens bei der
R&amp;#252;ckgabe komplexer Objektstrukturen lernt an den Tab jedoch schnell zu sch&amp;#228;tzen
;-)
&lt;/p&gt;
&lt;h4&gt;Es geht noch besser!
&lt;/h4&gt;
&lt;p&gt;
Obwohl die bisherige Implementierung bereits ganz gut ist, gibt es noch zwei Kritikpunkte.
Zum einen erscheint die Plazierung einer statischen Methode innerhalb der *.aspx Seite
ein wenig eigenartig. Da sie weder auf &lt;strike&gt;Instanz&lt;/strike&gt; Exemplar-Felder, noch
auf Exemplar-Methoden der Seite zugreifen kann, ist sie innerhalb der Seite eigentlich
fehl am Platz.
&lt;/p&gt;
&lt;p&gt;
Au&amp;#223;erdem st&amp;#246;rt mich der automatisch generierte JavaScript Script Block innerhalb
der Seite, der die Proxies f&amp;#252;r die PageMethod Aufrufe zur Verf&amp;#252;gung stellt.
Lieber w&amp;#228;re mir die Variante einer eingelinkten externen JavaScript Datei.
&lt;/p&gt;
&lt;p&gt;
Beide Punkte k&amp;#246;nnen wir gl&amp;#252;cklicherweise recht einfach l&amp;#246;sen, n&amp;#228;mlich
durch den Einsatz von Script Services. Script Services sind normale Web Services,
die mit dem ScriptService Attribut annotiert werden. Erstellt man einen Web Service
mit Visual Studio 2008, ist dieses Attribut sogar bereits &amp;#252;ber der Klasse enthalten.
Allerdings wird es automatisch auskommentiert.
&lt;/p&gt;
&lt;p&gt;
Um einen Web Service nun also als Script Service zur Verf&amp;#252;gung zu stellen, gen&amp;#252;gt
es den Kommentar, wie in Zeile 13 des folgenden Listings gezeigt, zu entfernen.
&lt;/p&gt;
&lt;div class="cf"&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt; [&lt;span class="cb2"&gt;WebServiceBinding&lt;/span&gt;(ConformsTo
= &lt;span class="cb2"&gt;WsiProfiles&lt;/span&gt;.BasicProfile1_1)]
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&lt;span class="cb8"&gt;// To allow this Web
Service to be called from script, using ASP.NET AJAX, uncomment the following line. &lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt; [System.Web.Script.Services.&lt;span class="cb2"&gt;ScriptService&lt;/span&gt;]
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&lt;span class="cb1"&gt;public&lt;/span&gt; &lt;span class="cb1"&gt;class&lt;/span&gt; &lt;span class="cb2"&gt;AjaxDemoService&lt;/span&gt; : &lt;span class="cb2"&gt;WebService&lt;/span&gt; {
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [&lt;span class="cb2"&gt;WebMethod&lt;/span&gt;]
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;public&lt;/span&gt; &lt;span class="cb1"&gt;string&lt;/span&gt; HelloWorld()
{
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;return&lt;/span&gt; &lt;span class="cb5"&gt;&amp;quot;Hello
World&amp;quot;&lt;/span&gt;;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [&lt;span class="cb2"&gt;WebMethod&lt;/span&gt;]
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;public&lt;/span&gt; &lt;span class="cb1"&gt;string&lt;/span&gt; Echo(&lt;span class="cb1"&gt;int&lt;/span&gt; number)
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 23&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 24&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;return&lt;/span&gt; &lt;span class="cb1"&gt;string&lt;/span&gt;.Format(&lt;span class="cb5"&gt;&amp;quot;Sie
haben {0} eingegeben.&amp;quot;&lt;/span&gt;, number);
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 25&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&amp;#160;&amp;#160; 
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 26&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Prinzipiell reicht dies aus, um den Service via Ajax anzusprechen. Um uns das Leben
jedoch ein wenig einfacher zu machen, lassen wir das ASP.NET Ajax Framework f&amp;#252;r
uns - analog zur Page Method L&amp;#246;sung - JavaScript Proxies f&amp;#252;r unsere Methoden
Aufrufe erstellen. Dazu f&amp;#252;gen wir innerhalb des ScriptManager Tags der Seite
ein Kind Element &lt;em&gt;&amp;lt;Services&amp;gt;&lt;/em&gt; ein. Diesem Element f&amp;#252;gen wir als
weiteres Kind Element eine &lt;em&gt;ServiceReference&lt;/em&gt; ein, deren Pfad auf unseren Service
verwei&amp;#223;t.
&lt;/p&gt;
&lt;div class="cf"&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cb3"&gt;asp&lt;/span&gt;&lt;span class="cb1"&gt;:&lt;/span&gt;&lt;span class="cb3"&gt;ScriptManager&lt;/span&gt; &lt;span class="cb7"&gt;ID&lt;/span&gt;&lt;span class="cb1"&gt;=&amp;quot;ScriptManager1&amp;quot;&lt;/span&gt; &lt;span class="cb7"&gt;runat&lt;/span&gt;&lt;span class="cb1"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class="cb7"&gt;EnablePageMethods&lt;/span&gt;&lt;span class="cb1"&gt;=&amp;quot;True&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cb3"&gt;Services&lt;/span&gt;&lt;span class="cb1"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cb3"&gt;asp&lt;/span&gt;&lt;span class="cb1"&gt;:&lt;/span&gt;&lt;span class="cb3"&gt;ServiceReference&lt;/span&gt; &lt;span class="cb7"&gt;Path&lt;/span&gt;&lt;span class="cb1"&gt;=&amp;quot;~/AjaxDemoService.asmx&amp;quot;&lt;/span&gt; &lt;span class="cb1"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="cb3"&gt;Services&lt;/span&gt;&lt;span class="cb1"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p class="cl"&gt;
&lt;span class="cln"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="cb1"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="cb3"&gt;asp&lt;/span&gt;&lt;span class="cb1"&gt;:&lt;/span&gt;&lt;span class="cb3"&gt;ScriptManager&lt;/span&gt;&lt;span class="cb1"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
An dieser Stelle sei noch einmal darauf hingewiesen, dass dieser Schritt reine Bequemlichkeit
und nicht zwingend erforderlich ist. Ohne ihn k&amp;#246;nnten wir unseren Service genauso
via JavaScript rufen und w&amp;#252;rden genauso JSON als Serialisierungsformat nutzen
k&amp;#246;nnen. Allerdings m&amp;#252;ssten wir den clientseitigen Aufruf dann komplett selbst
entwickeln und h&amp;#228;tten keine Proxies zur Verf&amp;#252;gung.
&lt;/p&gt;
&lt;p&gt;
Da wir jedoch bequem sind, lassen wir uns Proxymethoden generieren. Diese k&amp;#246;nnen
wir dann in unserem bestehenden Client Script Block innerhalb der Seite aufrufen.
&lt;/p&gt;
&lt;p&gt;
Wie die folgende Abbildung zeigt, erhalten wir dann sogar Intellisense und erfahren
somit, welche Argumente eine bestimmte Methode entgegen nimmt.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/05_VS.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="87" alt="05_VS" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/05_VS_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Der Rest gestaltet sich &amp;#228;hnlich der Page Method Implementierung. Als wichtiger
Unterschied w&amp;#228;re noch zu erw&amp;#228;hnen, dass die generierten Proxies standardm&amp;#228;&amp;#223;ig
in eine externe JavaScript Datei geschrieben werden und somit nicht mehr als Client
Script Block in der Seite auftauchen.
&lt;/p&gt;
&lt;p&gt;
Die Kommunikation zwischen Client und Server l&amp;#228;uft analog der Page Method Implementierung.
&lt;/p&gt;
&lt;p&gt;
Der Client sendet in seiner Anfrage unter anderem einen Header Content-Type mit dem
Wert &amp;quot;application/json; charset=utf-8&amp;quot;. Dieser ist besonders wichtig, denn
er steuert den Serialisierungsmechanismus des Servers. Hat dieser Header einen anderen
Wert, wird die Antwort XML Serialisiert. Somit ist sichergestellt, dass JavaScript
Clients JSON erhalten, wohingegen andere Clients XML erhalten.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/06_ajaxheader2.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="70" alt="06_ajaxheader2" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/06_ajaxheader2_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Die n&amp;#228;chste Abbildung zeigt, dass auch die Post Parameter via JSON serialisiert
werden:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/07_ajaxpost2.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="85" alt="07_ajaxpost2" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/07_ajaxpost2_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
F&amp;#252;r die Antwort ist dies nat&amp;#252;rlich auch weiterhin der Fall:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/07_ajaxantwort2.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="41" alt="07_ajaxantwort2" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAja.NETAJAX_7339/07_ajaxantwort2_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;Fazit:
&lt;/h4&gt;
&lt;p&gt;
Dieser Teil der Serie hat gezeigt, dass sich die Menge der &amp;#252;bertragenen Daten
w&amp;#228;hrend eines Ajax Requests mit der Hilfe von Page Methods, Script Services und
dem ASP.NET Ajax Framework auf ein Minimum reduzieren lassen. Au&amp;#223;erdem wird bei
dieser Variante der ASP.NET Page Life Cycle im Gegensatz zu den vorherigen Beispielen
nicht durchlaufen.
&lt;/p&gt;
&lt;p&gt;
Beides in Kombination kann zu gewaltigen Performancevorteilen verglichen mit Client
Callbacks oder dem Updatepanel f&amp;#252;hren.
&lt;/p&gt;
&lt;p&gt;
Einziger Wermutstropfen ist die &amp;#220;bertragung der 85 kb gro&amp;#223;en ASP.NET Ajax
Framework Java Script Dateien w&amp;#228;hrend des ersten Requests. 
&lt;/p&gt;
&lt;p&gt;
Eine Abhilfe f&amp;#252;r dieses Problem werden wir uns im n&amp;#228;chsten Teil der Serie
ansehen.
&lt;/p&gt;
&lt;p&gt;
Wie immer freue ich mich nat&amp;#252;rlich &amp;#252;ber Kommentare zu diesem Blog Beitrag.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Dieser Beitrag war hilfreich? Dann bitte nicht vergessen Ihn zu kicken!&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=762299a1-efea-490c-b27e-d0fa137677bf" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,762299a1-efea-490c-b27e-d0fa137677bf.aspx</comments>
      <category>.NET</category>
      <category>Ajax</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=b5e6a334-e5ca-4fb9-9007-456f20a71c47</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,b5e6a334-e5ca-4fb9-9007-456f20a71c47.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,b5e6a334-e5ca-4fb9-9007-456f20a71c47.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=b5e6a334-e5ca-4fb9-9007-456f20a71c47</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Zu Anfang hoch gelobt, später ausgepfiffen und verpönt. Was sich im ersten
Moment nach der typischen Geschichte deutscher Castingshow Teilnehmer anhört,
ist in Wirklichkeit das Schicksal des <a title="Dokumentation des ASP.NET Updatepanels" href="http://www.asp.net/Ajax/Documentation/Live/overview/UpdatePanelOverview.aspx" target="_blank">ASP.NET
AJAX Updatepanels</a>.
</p>
        <p>
Woll kaum ein anderes Control hat nach seiner Einführung einen solchen Hype verursacht
und ist später so tief gefallen.
</p>
        <h4>Der Reihe nach
</h4>
        <p>
Ehe wir im dritten Teil meiner ASP.NET Ajax Serie prüfen werden, ob das Updatepanel
seinen schlechten Ruf zu recht oder unrecht hat, möchte ich zunächst jedoch
kurz ein paar allgemeine Worte über das Steuerelement verlieren.
</p>
        <p>
Das Updatepanel kam mit den ASP.NET Ajax Extensions in der Version 1.0 für das
.NET Framework 2.0 auf den Markt und musste für Visual Studio 2005 noch separat
heruntergeladen und installiert werden. Ab Visual Studio 2008 ist das UpdatePanel
sofort von Hause aus in der Version 3.5 des ASP.NET Ajax Frameworks enthalten.
</p>
        <p>
Ziel des Updatepanels ist es, ASP.NET Entwicklern die Möglichkeit zu geben Ajax
zu implementieren,<strong> ohne selbst clientseitigen Code schreiben zu müssen</strong>.
Im Gegensatz zu den Client Callbacks, die ich im <a href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank">Teil
2 der Serie</a> vorgestellt habe, können ASP.NET Entwickler also in Ihrer Komfortzone
- dem Server - bleiben. 
</p>
        <h4>Der klassische Ansatz über ASP.NET Postbacks
</h4>
        <p>
Basis für den heutigen Blogpost wird wieder eine leicht modifizierte Variante
des Beispielcodes der vorherigen <a href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank">beiden</a><a href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank">Teile</a> der
Serie sein. Da das Updatepanel aus Entwicklersicht rein serverseitig arbeitet, sind
zunächst einige Veränderungen am bestehenden Quellcode notwendig.
</p>
        <p>
Zum einen sind sämtliche HTML Links (<em>a</em> Tags) durch ASP.NET LinkButtons
zu ersetzen. Außerdem habe ich den HTML Div Tag, der das Ergebnis der Click-Aktionen
anzeigte, durch ein ASP.NET Literal Control ersetzt. Den zuvor in die Seite integrierten
JavaScript Code des letzten Beispiels habe ich komplett entfernt.
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="background: #ffee62">&lt;%</span><span style="color: blue">@</span><span style="color: #a31515">Page</span><span style="color: red">Language</span><span style="color: blue">="C#"</span><span style="color: red">AutoEventWireup</span><span style="color: blue">="true"</span><span style="color: red">CodeFile</span><span style="color: blue">="Teil3.aspx.cs"</span><span style="color: red">Inherits</span><span style="color: blue">="Teil2"</span><span style="background: #ffee62">%&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span> <span style="color: blue">&lt;!</span><span style="color: #a31515">DOCTYPE</span><span style="color: red">html</span><span style="color: red">PUBLIC</span><span style="color: blue">"-//W3C//DTD
XHTML 1.0 Transitional//EN"</span><span style="color: blue">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span> <span style="color: blue">&lt;</span><span style="color: #a31515">html</span><span style="color: red">xmlns</span><span style="color: blue">="http://www.w3.org/1999/xhtml"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span> <span style="color: blue">&lt;</span><span style="color: #a31515">head</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">title</span><span style="color: blue">&gt;&lt;/</span><span style="color: #a31515">title</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span> <span style="color: blue">&lt;/</span><span style="color: #a31515">head</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span> <span style="color: blue">&lt;</span><span style="color: #a31515">body</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">form</span><span style="color: red">id</span><span style="color: blue">="form1"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">h1</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>        
ASP.NET Webforms Anwendungen und Ajax (Teil3): Das Updatepanel<span style="color: blue">&lt;/</span><span style="color: #a31515">h1</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>         <span style="color: blue">&lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   14</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: red">ID</span><span style="color: blue">="StaticLinkButton"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: red">OnClick</span><span style="color: blue">="StaticLinkButton_Click"&gt;</span>Hier
klicken zum Request einer
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   15</span>                
statischen Datei<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   16</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   17</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: red">ID</span><span style="color: blue">="HelloWorldLinkButton"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: red">OnClick</span><span style="color: blue">="HelloWorldLinkButton_Click"&gt;</span>Hier
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   18</span>                
für Hello World WebService klicken<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   19</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   20</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: red">ID</span><span style="color: blue">="EchoLinkButton"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: red">OnClick</span><span style="color: blue">="EchoLinkButton_Click"&gt;</span>Hier
für Echo WebService klicken. 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   21</span>                
Geben Sie bitte vorher eine Zahl in nebenstehendem Feld ein:<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   22</span>             <span style="color: red">&amp;nbsp;</span><span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">TextBox</span><span style="color: red">ID</span><span style="color: blue">="EchoTextBox"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: red">Width</span><span style="color: blue">="40px"&gt;</span>4711<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">TextBox</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   23</span>         <span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   24</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   25</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Literal</span><span style="color: red">ID</span><span style="color: blue">="contentLiteral"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span>Bitte
klicken Sie auf einen der Links, 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   26</span>     damit
dieser Bereich gefüllt wird.<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Literal</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   27</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">form</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   28</span> <span style="color: blue">&lt;/</span><span style="color: #a31515">body</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   29</span> <span style="color: blue">&lt;/</span><span style="color: #a31515">html</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Serverseitig hat der Code keine Überraschungen parat. Je HTML Link Button gibt
es einen Handler für das Click Event, in dem der Inhalt des Literal Controls
gesetzt wird.
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>     <span style="color: blue">protected</span><span style="color: blue">void</span> StaticLinkButton_Click(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>         <span style="color: blue">this</span>.contentLiteral.Text
= <span style="color: blue">this</span>.ReadStaticFile();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>     <span style="color: blue">protected</span><span style="color: blue">void</span> HelloWorldLinkButton_Click(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>         <span style="color: blue">this</span>.contentLiteral.Text
= <span style="color: blue">this</span>.CallHelloWorldService();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>     <span style="color: blue">protected</span><span style="color: blue">void</span> EchoLinkButton_Click(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>         <span style="color: blue">this</span>.contentLiteral.Text
= <span style="color: blue">this</span>.CallEchoService();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   14</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   15</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   16</span>     <span style="color: blue">private</span><span style="color: blue">string</span> ReadStaticFile()
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   17</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   18</span>         <span style="color: blue">string</span> fileContent;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   19</span>         <span style="color: blue">using</span> (<span style="color: blue">var</span> reader
= <span style="color: blue">new</span><span style="color: #2b91af">StreamReader</span>(Server.MapPath(<span style="color: #a31515">"~/static.html"</span>)))
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   20</span>        
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   21</span>            
fileContent = reader.ReadToEnd();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   22</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   23</span>         <span style="color: blue">return</span> fileContent;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   24</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   25</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   26</span>     <span style="color: blue">private</span><span style="color: blue">string</span> CallHelloWorldService()
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   27</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   28</span>         <span style="color: blue">return</span><span style="color: blue">new</span><span style="color: #2b91af">AjaxDemoService</span>().HelloWorld();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   29</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   30</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   31</span>     <span style="color: blue">private</span><span style="color: blue">string</span> CallEchoService()
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   32</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   33</span>         <span style="color: blue">int</span> value;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   34</span>         <span style="color: blue">int</span>.TryParse(<span style="color: blue">this</span>.EchoTextBox.Text, <span style="color: blue">out</span> value);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   35</span>         <span style="color: blue">return</span><span style="color: blue">new</span><span style="color: #2b91af">AjaxDemoService</span>().Echo(value);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   36</span>     }
</p>
        </div>
        <p>
Startet man die Seite nun, sieht man dass ein GET Request auf die Seite Teil3.aspx
abgesetzt wird. Die Antwort umfasst 2.1 kb.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/01ersterRequest.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="113" alt="01ersterRequest" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/01ersterRequest_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Klickt man nun auf einen der Link Buttons, wird ein Postback ausgeführt und die
komlette Seite neu vom Server auf den Client übertragen. Dies überrascht
auch nicht, schließlich wurde noch keinerlei Ajax Funktionalität implementiert.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/02normalerPostback.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="93" alt="02normalerPostback" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/02normalerPostback_thumb.png" width="244" border="0" />
          </a> 
</p>
        <h4>Ein erster Versuch mit dem Updatepanel
</h4>
        <p>
Um die Seite nun zu "<em>ajaxifizieren</em>", benötigen wir zwei Controls.
Das erste ist der ASP.NET Scriptmanager. Seine Hauptaufgabe ist es, Scripte zum Client
zu liefern. Er muss <strong>vor allen AJAX Controls</strong> innerhalb der Seite erscheinen.
Außerdem ist noch anzumerken, dass der Scriptmanager nach dem Highlander prinzip
arbeitet: "<em>Es kann nur einen geben</em>!" - nun ja, zumindest pro Seite.
Andernfalls würde zur Laufzeit eine <em>InvalidOperationException</em> ausgelöst
werden.
</p>
        <p>
Dies bedeutet übrigens, dass ich beim Einsatz von Masterpages keinen ScriptManager
auf einer Contentseite platzieren darf, falls  auf der Masterpage bereits ein
Scriptmanager genutzt wurde. Stattdessen müsste ich auf der Contentseite einen
ScriptmanagerProxy einsetzen. Diesen benötige ich allerdings nur, falls ich auf
der Contentseite deklarativ noch weitere Scripte hinzufügen möchte, die
auf der Masterpage nicht gebraucht werden.
</p>
        <p>
Da ich langsam etwas ausschweifend werde: <strong>Zurück zum Thema</strong>!
</p>
        <p>
Das zweite Control, das wir auf unserer Seite brauchen ist ein Updatepanel. Es dient
als Container des Bereichs, der später aktualisiert werden soll. Updatepanels
dürfen im Gegensatz zum Scriptmanager übrigens mehrfach auf einer Seite
vorkommen.
</p>
        <p>
 <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/03toolbox.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="238" alt="03toolbox" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/03toolbox_thumb.png" width="244" border="0" /></a></p>
        <p>
Nachdem ich Scriptmanager und Updatepanel auf die Seite gezogen, und die die Clientcontrols
in das Updatepanel verschoben habe, sieht das Markup meiner Seite wie folgt aus.
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">&lt;</span><span style="color: #a31515">body</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">form</span><span style="color: red">id</span><span style="color: blue">="form1"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">ScriptManager</span><span style="color: red">ID</span><span style="color: blue">="ScriptManager1"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">ScriptManager</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">h1</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>        
ASP.NET Webforms Anwendungen und Ajax (Teil3): Das Updatepanel<span style="color: blue">&lt;/</span><span style="color: #a31515">h1</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    <strong>7</strong></span>     <strong><span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">UpdatePanel</span><span style="color: red">ID</span><span style="color: blue">="UpdatePanel1"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span></strong></p>
          <p style="margin: 0px">
            <strong>
              <span style="color: #2b91af">    8</span>         <span style="color: blue">&lt;</span><span style="color: #a31515">ContentTemplate</span><span style="color: blue">&gt;</span></strong>
          </p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>                 <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: red">ID</span><span style="color: blue">="StaticLinkButton"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: red">OnClick</span><span style="color: blue">="StaticLinkButton_Click"&gt;</span>Hier
klicken zum Request einer
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>                
statischen Datei<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>                 <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>                 <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: red">ID</span><span style="color: blue">="HelloWorldLinkButton"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: red">OnClick</span><span style="color: blue">="HelloWorldLinkButton_Click"&gt;</span>Hier
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   14</span>                
für Hello World WebService klicken<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   15</span>                 <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   16</span>                 <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: red">ID</span><span style="color: blue">="EchoLinkButton"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: red">OnClick</span><span style="color: blue">="EchoLinkButton_Click"&gt;</span>Hier
für Echo WebService klicken. 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   17</span>                
Geben Sie bitte vorher eine Zahl in nebenstehendem Feld ein:<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">LinkButton</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   18</span>                 <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">TextBox</span><span style="color: red">ID</span><span style="color: blue">="EchoTextBox"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: red">Width</span><span style="color: blue">="40px"&gt;</span>4711<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">TextBox</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   19</span>             <span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   20</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Literal</span><span style="color: red">ID</span><span style="color: blue">="contentLiteral"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span>Bitte
klicken Sie auf einen der Links, 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   21</span>     damit
dieser Bereich gefüllt wird.<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Literal</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <strong>
              <span style="color: #2b91af">   22</span>         <span style="color: blue">&lt;/</span><span style="color: #a31515">ContentTemplate</span><span style="color: blue">&gt;</span></strong>
          </p>
          <p style="margin: 0px">
            <strong>
              <span style="color: #2b91af">   23</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">UpdatePanel</span><span style="color: blue">&gt;</span></strong>
          </p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   24</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">form</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   25</span> <span style="color: blue">&lt;/</span><span style="color: #a31515">body</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Da keine Anpassungen im Code Behind meiner Seite notwendig sind, kann ich die Anwendung
nun direkt starten.
</p>
        <p>
Ein Blick auf den Netzwerkverkehr zeigt, dass bei der ersten Anfrage der Seite neben
der eigentlichen Seite noch drei JavaScript Dateien übertragen wurden. Die Verweise
auf diese drei Script Dateien wurden durch den ScriptManager automatisch in die Seite
eingetragen. Allerdings werden nun statt der initialen <strong>2.1 kb</strong> knapp <strong>90
kb</strong> zum Client übertragen.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/04ersterRequestMitUpdatePanel.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="134" alt="04ersterRequestMitUpdatePanel" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/04ersterRequestMitUpdatePanel_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Den eigentlichen Vorteil sehen wir, sobald wir auf einen der Links klicken. Nicht
nur, dass die Seite nicht komplett neu geladen wird und somit das lästige flackern
beim Seitenneuaufbau entfällt, auch die Menge der übertragenen Daten hat
sich auf <strong>1,5 kb</strong> reduziert. 
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/05AsyncRequest1Post.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="155" alt="05AsyncRequest1Post" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/05AsyncRequest1Post_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Anscheinend haben wir also alles richtig gemacht. <strong>Leider aber auch nur anscheinend</strong>.
Ein näherer Blick auf die Antwort des Servers zeigt, dass neben dem aktualisierten
Inhalt auch das Markup für unsere drei Aktionslinks sowie die Textbox erneut
übertragen wurden.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/06AsyncRequest1Antwort.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="169" alt="06AsyncRequest1Antwort" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/06AsyncRequest1Antwort_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Das liegt daran, dass wir einen klassichen <em>Updatepanel Anfängerfehler</em> gemacht
haben. Wir haben den kompletten Inhalt der Seite in das Updatepanel geschoben. Somit
wird dieser auch vollkommen korrekt wieder vollständig vom Server zum Client
übertragen.
</p>
        <p>
Das ist selbstverständlich nicht das, was wir wollten. Schließlich ist unsere
Ajax Implementierung nur augenwischerei wenn im Hintergrund doch wieder (fast) alles
zum Client übertragen wird.
</p>
        <h4>Ein zweiter Anlauf
</h4>
        <p>
Was können wir also tun? Nun, da wir nur den Inhalt des Steuerelements <em>contentLiteral</em> aktualisieren
möchten, sollten wir offensichtlich auch nur diesen in das Updatepanel aufnehmen.
Dazu schieben wir einfach die drei Aktionslinks wieder über das Updatepanel.
</p>
        <p>
Wenn wir die Seite nun starten, stellen wir jedoch fest, dass ein Klick auf einen
der Aktionslinks wieder einen vollständigen Postback inklusive komplettem Rendern
der Seite auslöst.
</p>
        <p>
Die Ursache hierfür ist, dass ein Updatepanel standardmäßig nur einen
partiellen Postback verursacht und sich somit erneuert, wenn eines seiner Childcontrols
einen Postback initiert.
</p>
        <p>
Glücklicherweise lässt sich dieses Verhalten jedoch leicht ändern.
Für jedes Updatepanel können sogenannte Trigger registriert werden, die
einen partiellen Postback auslösen. Ein Trigger ist dabei nichts anderes, als
ein Event eines Servercontrols.
</p>
        <p>
Das Registrieren eines solchen Triggers kann entweder über den Designer oder
über das ASP.NET Markup geschehen. Um es über das Markup zu lösen,
müssen wir unser Beispiel wie folgt anpassen:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">UpdatePanel</span><span style="color: red">ID</span><span style="color: blue">="UpdatePanel1"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>         <span style="color: blue">&lt;</span><span style="color: #a31515">ContentTemplate</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Literal</span><span style="color: red">ID</span><span style="color: blue">="contentLiteral"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span>Bitte
klicken Sie auf einen der Links, 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     damit
dieser Bereich gefüllt wird.<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Literal</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>         <span style="color: blue">&lt;/</span><span style="color: #a31515">ContentTemplate</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>        <span style="color: blue">&lt;</span><span style="color: #a31515">Triggers</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">AsyncPostBackTrigger</span><span style="color: red">ControlID</span><span style="color: blue">="StaticLinkButton"</span><span style="color: red">EventName</span><span style="color: blue">="Click"</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">AsyncPostBackTrigger</span><span style="color: red">ControlID</span><span style="color: blue">="HelloWorldLinkButton"</span><span style="color: red">EventName</span><span style="color: blue">="Click"</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">AsyncPostBackTrigger</span><span style="color: red">ControlID</span><span style="color: blue">="EchoLinkButton"</span><span style="color: red">EventName</span><span style="color: blue">="Click"</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>         <span style="color: blue">&lt;/</span><span style="color: #a31515">Triggers</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">UpdatePanel</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Lädt man die Seite nun erneut, stellt man fest, dass die Aktionslinks wieder
partielle Postbacks auslösen. Außerdem werden auch nur die notwendigen Daten
übertragen.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/07AsyncRequest2Antwort.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="129" alt="07AsyncRequest2Antwort" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/07AsyncRequest2Antwort_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h4>Zu viel des Guten
</h4>
        <p>
Das Ergebnis sieht eigentlich schon ganz gut, so das man meinen könnte, dass
wir nun fertig wären. Leider gibt es aber noch ein kleines Problem. Um dies zu
verdeutlichen lege ich ein weiteres Updatepanel auf der Seite an. Dieses Panel erhält
ein Literal-Control, welches serverseitig mit der aktuellen Uhrzeit gefüllt wird.
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">UpdatePanel</span><span style="color: red">ID</span><span style="color: blue">="UpdatePanel2"</span><span style="color: red">runat</span><span style="color: blue">="server"</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>         <span style="color: blue">&lt;</span><span style="color: #a31515">ContentTemplate</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Literal</span><span style="color: red">ID</span><span style="color: blue">="TimeLiteral"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Literal</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>         <span style="color: blue">&lt;/</span><span style="color: #a31515">ContentTemplate</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">UpdatePanel</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
 
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>     <span style="color: blue">protected</span><span style="color: blue">void</span> Page_Load(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>         <span style="color: blue">this</span>.TimeLiteral.Text
= <span style="color: #2b91af">DateTime</span>.Now.ToLongTimeString();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     }
</p>
        </div>
        <p>
Meine Erwartungshaltung wäre, dass bei einem Klick auf einen der drei Aktionslinks
nur das ursprüngliche Updatepanel aktualisiert wird, da die Links nur hier als
Trigger registriert wurden. Das neue Updatepanel sollte nicht aktualisiert werden.
</p>
        <p>
Ein kurzer Test zeigt dass dem nicht so ist:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels1.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="116" alt="08_2UpdatePanels1" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels1_thumb.png" width="244" border="0" />
          </a>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels2.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="109" alt="08_2UpdatePanels2" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels2_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Wie die beiden Abbildungen zeigen, wurde nicht nur der Bereich des ersten Updatepanels,
sondern auch der des zweiten Updatepanels aktualisiert.
</p>
        <p>
Glücklicherweise lässt sich dieses Verhalten jedoch steuern! Das Updatepanel
verfügt über eine Eigenschaft <em>UpdateMode</em>. Diese gibt an, wann sich
das Updatepanel aktualisieren soll. Standardmässig ist diese Eigenschaft mit
dem Wert <em>Always</em> belegt. Stellt man den Wert jedoch auf <em>Contidional</em>,
wird das Updatepanel nur noch aktualisiert, wenn entweder eines seiner Childcontrols
einen Postback initiert hat, einer der registrierten Trigger ausgelöst wurde,
oder explizit die Methode <em>Update</em> serverseitig gerufen wurde.
</p>
        <p>
Die folgenden Abbildungen zeigen die Auswirkung der Änderung des UpdateModes:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels3.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="133" alt="08_2UpdatePanels3" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels3_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels4.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="170" alt="08_2UpdatePanels4" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels4_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels5.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="171" alt="08_2UpdatePanels5" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels5_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h4>Fazit
</h4>
        <p>
          <strong>Richtig eingesetzt</strong> ist das Updatepanel meiner Meinung nach besser
als sein Ruf und für <strong>einfache Szenarien</strong> durchaus geeignet. Ajax
Funktionalitäten können mit wenig Aufwand und ohne manuellen Scriptcode
implementiert werden.
</p>
        <p>
Achtet man darauf, nicht die komplette Seite in <strong>ein</strong> Updatepanel zu
integrieren und den <em>UpdateMode</em> auf <em>Conditional</em> zu setzen, kann das
Updatepanel in vielen Szenarien guten Gewissens genutzt werden. Man sollte sich allerdings
darüber im Klaren sein, dass serverseitig bei jeder Anfrage <strong>der komplette
Page-Life</strong>cycle durchlaufen wird. Zeitaufwändige Operationen im Page_Load
können - ähnlich wie bei den Client Callbacks - die Ajax Anfragen demnach
erheblich verlangsamen!
</p>
        <p>
Was man machen kann, wenn man den Pagelifecycle nicht komplett durchlaufen möchte,
werde ich übrigens im nächsten Teil dieser Serie zeigen.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=b5e6a334-e5ca-4fb9-9007-456f20a71c47" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>ASP.NET Webforms Anwendungen und Ajax (Teil 3) Das Updatepanel</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,b5e6a334-e5ca-4fb9-9007-456f20a71c47.aspx</guid>
      <link>http://blog.codemurai.de/2010/02/11/ASPNETWebformsAnwendungenUndAjaxTeil3DasUpdatepanel.aspx</link>
      <pubDate>Thu, 11 Feb 2010 23:51:55 GMT</pubDate>
      <description>&lt;p&gt;
Zu Anfang hoch gelobt, sp&amp;#228;ter ausgepfiffen und verp&amp;#246;nt. Was sich im ersten
Moment nach der typischen Geschichte deutscher Castingshow Teilnehmer anh&amp;#246;rt,
ist in Wirklichkeit das Schicksal des &lt;a title="Dokumentation des ASP.NET Updatepanels" href="http://www.asp.net/Ajax/Documentation/Live/overview/UpdatePanelOverview.aspx" target="_blank"&gt;ASP.NET
AJAX Updatepanels&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Woll kaum ein anderes Control hat nach seiner Einf&amp;#252;hrung einen solchen Hype verursacht
und ist sp&amp;#228;ter so tief gefallen.
&lt;/p&gt;
&lt;h4&gt;Der Reihe nach
&lt;/h4&gt;
&lt;p&gt;
Ehe wir im dritten Teil meiner ASP.NET Ajax Serie pr&amp;#252;fen werden, ob das Updatepanel
seinen schlechten Ruf zu recht oder unrecht hat, m&amp;#246;chte ich zun&amp;#228;chst jedoch
kurz ein paar allgemeine Worte &amp;#252;ber das Steuerelement verlieren.
&lt;/p&gt;
&lt;p&gt;
Das Updatepanel kam mit den ASP.NET Ajax Extensions in der Version 1.0 f&amp;#252;r das
.NET Framework 2.0 auf den Markt und musste f&amp;#252;r Visual Studio 2005 noch separat
heruntergeladen und installiert werden. Ab Visual Studio 2008 ist das UpdatePanel
sofort von Hause aus in der Version 3.5 des ASP.NET Ajax Frameworks enthalten.
&lt;/p&gt;
&lt;p&gt;
Ziel des Updatepanels ist es, ASP.NET Entwicklern die M&amp;#246;glichkeit zu geben Ajax
zu implementieren,&lt;strong&gt; ohne selbst clientseitigen Code schreiben zu m&amp;#252;ssen&lt;/strong&gt;.
Im Gegensatz zu den Client Callbacks, die ich im &lt;a href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank"&gt;Teil
2 der Serie&lt;/a&gt; vorgestellt habe, k&amp;#246;nnen ASP.NET Entwickler also in Ihrer Komfortzone
- dem Server - bleiben. 
&lt;/p&gt;
&lt;h4&gt;Der klassische Ansatz &amp;#252;ber ASP.NET Postbacks
&lt;/h4&gt;
&lt;p&gt;
Basis f&amp;#252;r den heutigen Blogpost wird wieder eine leicht modifizierte Variante
des Beispielcodes der vorherigen &lt;a href="http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx" target="_blank"&gt;beiden&lt;/a&gt; &lt;a href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank"&gt;Teile&lt;/a&gt; der
Serie sein. Da das Updatepanel aus Entwicklersicht rein serverseitig arbeitet, sind
zun&amp;#228;chst einige Ver&amp;#228;nderungen am bestehenden Quellcode notwendig.
&lt;/p&gt;
&lt;p&gt;
Zum einen sind s&amp;#228;mtliche HTML Links (&lt;em&gt;a&lt;/em&gt; Tags) durch ASP.NET LinkButtons
zu ersetzen. Au&amp;#223;erdem habe ich den HTML Div Tag, der das Ergebnis der Click-Aktionen
anzeigte, durch ein ASP.NET Literal Control ersetzt. Den zuvor in die Seite integrierten
JavaScript Code des letzten Beispiels habe ich komplett entfernt.
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="background: #ffee62"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue"&gt;@&lt;/span&gt; &lt;span style="color: #a31515"&gt;Page&lt;/span&gt; &lt;span style="color: red"&gt;Language&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;C#&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;AutoEventWireup&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;CodeFile&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Teil3.aspx.cs&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;Inherits&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Teil2&amp;quot;&lt;/span&gt; &lt;span style="background: #ffee62"&gt;%&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;!&lt;/span&gt;&lt;span style="color: #a31515"&gt;DOCTYPE&lt;/span&gt; &lt;span style="color: red"&gt;html&lt;/span&gt; &lt;span style="color: red"&gt;PUBLIC&lt;/span&gt; &lt;span style="color: blue"&gt;&amp;quot;-//W3C//DTD
XHTML 1.0 Transitional//EN&amp;quot;&lt;/span&gt; &lt;span style="color: blue"&gt;&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;html&lt;/span&gt; &lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;head&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;title&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;head&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;body&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;form&lt;/span&gt; &lt;span style="color: red"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;form1&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;h1&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
ASP.NET Webforms Anwendungen und Ajax (Teil3): Das Updatepanel&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;h1&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;StaticLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;OnClick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;StaticLinkButton_Click&amp;quot;&amp;gt;&lt;/span&gt;Hier
klicken zum Request einer
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
statischen Datei&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HelloWorldLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;OnClick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HelloWorldLinkButton_Click&amp;quot;&amp;gt;&lt;/span&gt;Hier
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
f&amp;#252;r Hello World WebService klicken&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;EchoLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;OnClick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;EchoLinkButton_Click&amp;quot;&amp;gt;&lt;/span&gt;Hier
f&amp;#252;r Echo WebService klicken. 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
Geben Sie bitte vorher eine Zahl in nebenstehendem Feld ein:&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: red"&gt;&amp;amp;nbsp;&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;EchoTextBox&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;40px&amp;quot;&amp;gt;&lt;/span&gt;4711&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 23&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 24&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 25&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;contentLiteral&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;Bitte
klicken Sie auf einen der Links, 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 26&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; damit
dieser Bereich gef&amp;#252;llt wird.&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 27&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;form&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 28&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;body&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 29&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;html&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Serverseitig hat der Code keine &amp;#220;berraschungen parat. Je HTML Link Button gibt
es einen Handler f&amp;#252;r das Click Event, in dem der Inhalt des Literal Controls
gesetzt wird.
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; StaticLinkButton_Click(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.contentLiteral.Text
= &lt;span style="color: blue"&gt;this&lt;/span&gt;.ReadStaticFile();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; HelloWorldLinkButton_Click(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.contentLiteral.Text
= &lt;span style="color: blue"&gt;this&lt;/span&gt;.CallHelloWorldService();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; EchoLinkButton_Click(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.contentLiteral.Text
= &lt;span style="color: blue"&gt;this&lt;/span&gt;.CallEchoService();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; ReadStaticFile()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;string&lt;/span&gt; fileContent;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: blue"&gt;var&lt;/span&gt; reader
= &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;StreamReader&lt;/span&gt;(Server.MapPath(&lt;span style="color: #a31515"&gt;&amp;quot;~/static.html&amp;quot;&lt;/span&gt;)))
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
fileContent = reader.ReadToEnd();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 23&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;return&lt;/span&gt; fileContent;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 24&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 25&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 26&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; CallHelloWorldService()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 27&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 28&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AjaxDemoService&lt;/span&gt;().HelloWorld();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 29&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 30&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 31&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; CallEchoService()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 32&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 33&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;int&lt;/span&gt; value;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 34&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;int&lt;/span&gt;.TryParse(&lt;span style="color: blue"&gt;this&lt;/span&gt;.EchoTextBox.Text, &lt;span style="color: blue"&gt;out&lt;/span&gt; value);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 35&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AjaxDemoService&lt;/span&gt;().Echo(value);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 36&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Startet man die Seite nun, sieht man dass ein GET Request auf die Seite Teil3.aspx
abgesetzt wird. Die Antwort umfasst 2.1 kb.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/01ersterRequest.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="113" alt="01ersterRequest" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/01ersterRequest_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Klickt man nun auf einen der Link Buttons, wird ein Postback ausgef&amp;#252;hrt und die
komlette Seite neu vom Server auf den Client &amp;#252;bertragen. Dies &amp;#252;berrascht
auch nicht, schlie&amp;#223;lich wurde noch keinerlei Ajax Funktionalit&amp;#228;t implementiert.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/02normalerPostback.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="93" alt="02normalerPostback" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/02normalerPostback_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;&amp;#160;
&lt;/p&gt;
&lt;h4&gt;Ein erster Versuch mit dem Updatepanel
&lt;/h4&gt;
&lt;p&gt;
Um die Seite nun zu &amp;quot;&lt;em&gt;ajaxifizieren&lt;/em&gt;&amp;quot;, ben&amp;#246;tigen wir zwei Controls.
Das erste ist der ASP.NET Scriptmanager. Seine Hauptaufgabe ist es, Scripte zum Client
zu liefern. Er muss &lt;strong&gt;vor allen AJAX Controls&lt;/strong&gt; innerhalb der Seite erscheinen.
Au&amp;#223;erdem ist noch anzumerken, dass der Scriptmanager nach dem Highlander prinzip
arbeitet: &amp;quot;&lt;em&gt;Es kann nur einen geben&lt;/em&gt;!&amp;quot; - nun ja, zumindest pro Seite.
Andernfalls w&amp;#252;rde zur Laufzeit eine &lt;em&gt;InvalidOperationException&lt;/em&gt; ausgel&amp;#246;st
werden.
&lt;/p&gt;
&lt;p&gt;
Dies bedeutet &amp;#252;brigens, dass ich beim Einsatz von Masterpages keinen ScriptManager
auf einer Contentseite platzieren darf, falls&amp;#160; auf der Masterpage bereits ein
Scriptmanager genutzt wurde. Stattdessen m&amp;#252;sste ich auf der Contentseite einen
ScriptmanagerProxy einsetzen. Diesen ben&amp;#246;tige ich allerdings nur, falls ich auf
der Contentseite deklarativ noch weitere Scripte hinzuf&amp;#252;gen m&amp;#246;chte, die
auf der Masterpage nicht gebraucht werden.
&lt;/p&gt;
&lt;p&gt;
Da ich langsam etwas ausschweifend werde: &lt;strong&gt;Zur&amp;#252;ck zum Thema&lt;/strong&gt;!
&lt;/p&gt;
&lt;p&gt;
Das zweite Control, das wir auf unserer Seite brauchen ist ein Updatepanel. Es dient
als Container des Bereichs, der sp&amp;#228;ter aktualisiert werden soll. Updatepanels
d&amp;#252;rfen im Gegensatz zum Scriptmanager &amp;#252;brigens mehrfach auf einer Seite
vorkommen.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/03toolbox.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="238" alt="03toolbox" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/03toolbox_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Nachdem ich Scriptmanager und Updatepanel auf die Seite gezogen, und die die Clientcontrols
in das Updatepanel verschoben habe, sieht das Markup meiner Seite wie folgt aus.
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;body&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;form&lt;/span&gt; &lt;span style="color: red"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;form1&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;ScriptManager&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;ScriptManager1&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;ScriptManager&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;h1&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
ASP.NET Webforms Anwendungen und Ajax (Teil3): Das Updatepanel&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;h1&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;7&lt;/strong&gt;&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;UpdatePanel&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;UpdatePanel1&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;strong&gt;&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;StaticLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;OnClick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;StaticLinkButton_Click&amp;quot;&amp;gt;&lt;/span&gt;Hier
klicken zum Request einer
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
statischen Datei&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HelloWorldLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;OnClick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HelloWorldLinkButton_Click&amp;quot;&amp;gt;&lt;/span&gt;Hier
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
f&amp;#252;r Hello World WebService klicken&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;EchoLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;OnClick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;EchoLinkButton_Click&amp;quot;&amp;gt;&lt;/span&gt;Hier
f&amp;#252;r Echo WebService klicken. 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
Geben Sie bitte vorher eine Zahl in nebenstehendem Feld ein:&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;LinkButton&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;EchoTextBox&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;40px&amp;quot;&amp;gt;&lt;/span&gt;4711&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;contentLiteral&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;Bitte
klicken Sie auf einen der Links, 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; damit
dieser Bereich gef&amp;#252;llt wird.&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;strong&gt;&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;strong&gt;&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 23&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;UpdatePanel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 24&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;form&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 25&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;body&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Da keine Anpassungen im Code Behind meiner Seite notwendig sind, kann ich die Anwendung
nun direkt starten.
&lt;/p&gt;
&lt;p&gt;
Ein Blick auf den Netzwerkverkehr zeigt, dass bei der ersten Anfrage der Seite neben
der eigentlichen Seite noch drei JavaScript Dateien &amp;#252;bertragen wurden. Die Verweise
auf diese drei Script Dateien wurden durch den ScriptManager automatisch in die Seite
eingetragen. Allerdings werden nun statt der initialen &lt;strong&gt;2.1 kb&lt;/strong&gt; knapp &lt;strong&gt;90
kb&lt;/strong&gt; zum Client &amp;#252;bertragen.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/04ersterRequestMitUpdatePanel.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="134" alt="04ersterRequestMitUpdatePanel" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/04ersterRequestMitUpdatePanel_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Den eigentlichen Vorteil sehen wir, sobald wir auf einen der Links klicken. Nicht
nur, dass die Seite nicht komplett neu geladen wird und somit das l&amp;#228;stige flackern
beim Seitenneuaufbau entf&amp;#228;llt, auch die Menge der &amp;#252;bertragenen Daten hat
sich auf &lt;strong&gt;1,5 kb&lt;/strong&gt; reduziert. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/05AsyncRequest1Post.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="155" alt="05AsyncRequest1Post" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/05AsyncRequest1Post_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Anscheinend haben wir also alles richtig gemacht. &lt;strong&gt;Leider aber auch nur anscheinend&lt;/strong&gt;.
Ein n&amp;#228;herer Blick auf die Antwort des Servers zeigt, dass neben dem aktualisierten
Inhalt auch das Markup f&amp;#252;r unsere drei Aktionslinks sowie die Textbox erneut
&amp;#252;bertragen wurden.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/06AsyncRequest1Antwort.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="169" alt="06AsyncRequest1Antwort" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/06AsyncRequest1Antwort_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Das liegt daran, dass wir einen klassichen &lt;em&gt;Updatepanel Anf&amp;#228;ngerfehler&lt;/em&gt; gemacht
haben. Wir haben den kompletten Inhalt der Seite in das Updatepanel geschoben. Somit
wird dieser auch vollkommen korrekt wieder vollst&amp;#228;ndig vom Server zum Client
&amp;#252;bertragen.
&lt;/p&gt;
&lt;p&gt;
Das ist selbstverst&amp;#228;ndlich nicht das, was wir wollten. Schlie&amp;#223;lich ist unsere
Ajax Implementierung nur augenwischerei wenn im Hintergrund doch wieder (fast) alles
zum Client &amp;#252;bertragen wird.
&lt;/p&gt;
&lt;h4&gt;Ein zweiter Anlauf
&lt;/h4&gt;
&lt;p&gt;
Was k&amp;#246;nnen wir also tun? Nun, da wir nur den Inhalt des Steuerelements &lt;em&gt;contentLiteral&lt;/em&gt; aktualisieren
m&amp;#246;chten, sollten wir offensichtlich auch nur diesen in das Updatepanel aufnehmen.
Dazu schieben wir einfach die drei Aktionslinks wieder &amp;#252;ber das Updatepanel.
&lt;/p&gt;
&lt;p&gt;
Wenn wir die Seite nun starten, stellen wir jedoch fest, dass ein Klick auf einen
der Aktionslinks wieder einen vollst&amp;#228;ndigen Postback inklusive komplettem Rendern
der Seite ausl&amp;#246;st.
&lt;/p&gt;
&lt;p&gt;
Die Ursache hierf&amp;#252;r ist, dass ein Updatepanel standardm&amp;#228;&amp;#223;ig nur einen
partiellen Postback verursacht und sich somit erneuert, wenn eines seiner Childcontrols
einen Postback initiert.
&lt;/p&gt;
&lt;p&gt;
Gl&amp;#252;cklicherweise l&amp;#228;sst sich dieses Verhalten jedoch leicht &amp;#228;ndern.
F&amp;#252;r jedes Updatepanel k&amp;#246;nnen sogenannte Trigger registriert werden, die
einen partiellen Postback ausl&amp;#246;sen. Ein Trigger ist dabei nichts anderes, als
ein Event eines Servercontrols.
&lt;/p&gt;
&lt;p&gt;
Das Registrieren eines solchen Triggers kann entweder &amp;#252;ber den Designer oder
&amp;#252;ber das ASP.NET Markup geschehen. Um es &amp;#252;ber das Markup zu l&amp;#246;sen,
m&amp;#252;ssen wir unser Beispiel wie folgt anpassen:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;UpdatePanel&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;UpdatePanel1&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;contentLiteral&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;Bitte
klicken Sie auf einen der Links, 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; damit
dieser Bereich gef&amp;#252;llt wird.&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Triggers&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;AsyncPostBackTrigger&lt;/span&gt; &lt;span style="color: red"&gt;ControlID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;StaticLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;EventName&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Click&amp;quot;&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;AsyncPostBackTrigger&lt;/span&gt; &lt;span style="color: red"&gt;ControlID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;HelloWorldLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;EventName&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Click&amp;quot;&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;AsyncPostBackTrigger&lt;/span&gt; &lt;span style="color: red"&gt;ControlID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;EchoLinkButton&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;EventName&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;Click&amp;quot;&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Triggers&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;UpdatePanel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
L&amp;#228;dt man die Seite nun erneut, stellt man fest, dass die Aktionslinks wieder
partielle Postbacks ausl&amp;#246;sen. Au&amp;#223;erdem werden auch nur die notwendigen Daten
&amp;#252;bertragen.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/07AsyncRequest2Antwort.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="129" alt="07AsyncRequest2Antwort" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/07AsyncRequest2Antwort_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;Zu viel des Guten
&lt;/h4&gt;
&lt;p&gt;
Das Ergebnis sieht eigentlich schon ganz gut, so das man meinen k&amp;#246;nnte, dass
wir nun fertig w&amp;#228;ren. Leider gibt es aber noch ein kleines Problem. Um dies zu
verdeutlichen lege ich ein weiteres Updatepanel auf der Seite an. Dieses Panel erh&amp;#228;lt
ein Literal-Control, welches serverseitig mit der aktuellen Uhrzeit gef&amp;#252;llt wird.
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;UpdatePanel&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;UpdatePanel2&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;TimeLiteral&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;UpdatePanel&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.TimeLiteral.Text
= &lt;span style="color: #2b91af"&gt;DateTime&lt;/span&gt;.Now.ToLongTimeString();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Meine Erwartungshaltung w&amp;#228;re, dass bei einem Klick auf einen der drei Aktionslinks
nur das urspr&amp;#252;ngliche Updatepanel aktualisiert wird, da die Links nur hier als
Trigger registriert wurden. Das neue Updatepanel sollte nicht aktualisiert werden.
&lt;/p&gt;
&lt;p&gt;
Ein kurzer Test zeigt dass dem nicht so ist:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels1.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="116" alt="08_2UpdatePanels1" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels1_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; &lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels2.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="109" alt="08_2UpdatePanels2" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels2_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Wie die beiden Abbildungen zeigen, wurde nicht nur der Bereich des ersten Updatepanels,
sondern auch der des zweiten Updatepanels aktualisiert.
&lt;/p&gt;
&lt;p&gt;
Gl&amp;#252;cklicherweise l&amp;#228;sst sich dieses Verhalten jedoch steuern! Das Updatepanel
verf&amp;#252;gt &amp;#252;ber eine Eigenschaft &lt;em&gt;UpdateMode&lt;/em&gt;. Diese gibt an, wann sich
das Updatepanel aktualisieren soll. Standardm&amp;#228;ssig ist diese Eigenschaft mit
dem Wert &lt;em&gt;Always&lt;/em&gt; belegt. Stellt man den Wert jedoch auf &lt;em&gt;Contidional&lt;/em&gt;,
wird das Updatepanel nur noch aktualisiert, wenn entweder eines seiner Childcontrols
einen Postback initiert hat, einer der registrierten Trigger ausgel&amp;#246;st wurde,
oder explizit die Methode &lt;em&gt;Update&lt;/em&gt; serverseitig gerufen wurde.
&lt;/p&gt;
&lt;p&gt;
Die folgenden Abbildungen zeigen die Auswirkung der &amp;#196;nderung des UpdateModes:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels3.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="133" alt="08_2UpdatePanels3" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels3_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels4.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="170" alt="08_2UpdatePanels4" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels4_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels5.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="171" alt="08_2UpdatePanels5" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil3Da_7B57/08_2UpdatePanels5_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;Fazit
&lt;/h4&gt;
&lt;p&gt;
&lt;strong&gt;Richtig eingesetzt&lt;/strong&gt; ist das Updatepanel meiner Meinung nach besser
als sein Ruf und f&amp;#252;r &lt;strong&gt;einfache Szenarien&lt;/strong&gt; durchaus geeignet. Ajax
Funktionalit&amp;#228;ten k&amp;#246;nnen mit wenig Aufwand und ohne manuellen Scriptcode
implementiert werden.
&lt;/p&gt;
&lt;p&gt;
Achtet man darauf, nicht die komplette Seite in &lt;strong&gt;ein&lt;/strong&gt; Updatepanel zu
integrieren und den &lt;em&gt;UpdateMode&lt;/em&gt; auf &lt;em&gt;Conditional&lt;/em&gt; zu setzen, kann das
Updatepanel in vielen Szenarien guten Gewissens genutzt werden. Man sollte sich allerdings
dar&amp;#252;ber im Klaren sein, dass serverseitig bei jeder Anfrage &lt;strong&gt;der komplette
Page-Life&lt;/strong&gt;cycle durchlaufen wird. Zeitaufw&amp;#228;ndige Operationen im Page_Load
k&amp;#246;nnen - &amp;#228;hnlich wie bei den Client Callbacks - die Ajax Anfragen demnach
erheblich verlangsamen!
&lt;/p&gt;
&lt;p&gt;
Was man machen kann, wenn man den Pagelifecycle nicht komplett durchlaufen m&amp;#246;chte,
werde ich &amp;#252;brigens im n&amp;#228;chsten Teil dieser Serie zeigen.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=b5e6a334-e5ca-4fb9-9007-456f20a71c47" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,b5e6a334-e5ca-4fb9-9007-456f20a71c47.aspx</comments>
      <category>.NET</category>
      <category>Ajax</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=fafe2ddd-4f3a-46d7-bf2d-ec5b76ec793a</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,fafe2ddd-4f3a-46d7-bf2d-ec5b76ec793a.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,fafe2ddd-4f3a-46d7-bf2d-ec5b76ec793a.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=fafe2ddd-4f3a-46d7-bf2d-ec5b76ec793a</wfw:commentRss>
      <slash:comments>7</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <p>
In meinem <a href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank">letzten
Blog Eintrag</a> habe ich erklärt, wie Ajax von Hand mit Hilfe des XMLHttpRequest
Objekts implementiert werden kann. 
</p>
        <p>
Eine Alternative zu dieser händischen Implementierung ist die Nutzung des ASP.NET
Client <a href="http://msdn.microsoft.com/en-us/library/ms178208.aspx" target="_blank">Callback
Frameworks</a>, welches mit der Version 2.0 von ASP.NET erschien.
</p>
        <p>
Um Client Callbacks nutzen zu können muss eine ASP.NET Seite bzw. ein ASP.NET
Control das Interface <em><a href="http://msdn.microsoft.com/en-us/library/system.web.ui.icallbackeventhandler.aspx" target="_blank">ICallbackEventHandler</a></em> implementieren.
Das Interface definiert die beiden Methoden:
</p>
        <ul>
          <li>
void <em><a href="http://msdn.microsoft.com/en-us/library/system.web.ui.icallbackeventhandler.raisecallbackevent.aspx" target="_blank">RaiseCallbackEvent</a></em>(string
eventArgument) 
</li>
          <li>
string <em><a href="http://msdn.microsoft.com/en-us/library/system.web.ui.icallbackeventhandler.getcallbackresult.aspx" target="_blank">GetCallbackResult</a></em>() 
</li>
        </ul>
        <p>
          <em>RaiseCallbackEvent</em> ist die Methode, den Aufruf des Clients entgegen nimmt. <em>GetCallbackResult</em> gibt
das Ergebnis der serverseitigen Verarbeitung an den Client zurück.
</p>
        <p>
Startet der Client eine Anfrage an eine Seite / ein Control welches <em>ICallBackEventHandler</em> implementiert,
wird eine <a href="http://edndoc.esri.com/arcobjects/9.2/NET_Server_Doc/developer/ADF/ajax_callback.htm" target="_blank">reduzierte
Variante</a> des <a href="http://msdn.microsoft.com/en-us/library/ms178472.aspx" target="_blank">ASP.NET
Page Lifecycle</a> / ASP.NET Control Lifecycle ausgeführt. Im wesentlichen entspricht
die Callback Variante der "klassichen" Postback Variante, es fehlen jedoch
die Methoden, die sich um das Rendering des Outputs kümmern. Außerdem werden
keine Postback Events ausgeführt.
</p>
        <p>
Das ganze sieht bezogen auf die Phasen also ungefähr so aus:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/04lifecycle.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="223" alt="04lifecycle" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/04lifecycle_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h4>Los gehts
</h4>
        <p>
Sehen wir uns das ganze nun einmal an einem konkreten Beispiel an. Als Ausgangsbasis
soll eine modifizierte Kopie der Seite des letzten Beispiels mit folgendem Markup
dienen:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>         <span style="color: blue">&lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span>&gt;Hier
klicken zum Request einer
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>                
statischen Datei <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: blue">&gt;</span>Hier
für Hello World WebService klicken <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: blue">&gt;</span>Hier<span style="color: #2b91af"></span>für
Echo WebService klicken. Geben Sie bitte vorher eine Zahl in nebenstehendem Feld ein: <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span><span style="color: red">&amp;nbsp;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9             </span>
            <span style="color: blue">&lt;</span>
            <span style="color: #a31515">asp</span>
            <span style="color: blue">:</span>
            <span style="color: #a31515">TextBox</span>
            <span style="color: red">ID</span>
            <span style="color: blue">="TextBox1"</span>
            <span style="color: red">runat</span>
            <span style="color: blue">="server"</span>
            <span style="color: red">Width</span>
            <span style="color: blue">="40px"&gt;</span>4711<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">TextBox</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>         <span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: red">id</span><span style="color: blue">="content"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>        
Bitte klicken Sie auf einen der Links, damit dieser Bereich gefüllt wird.
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   14</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></p>
        </div>
        <h3> 
</h3>
        <h3>Der Server
</h3>
        <p>
Auf Serverseite müssen wir nun in unserer Seite das Interface ICallbackEventHandler
implementieren. Ausgehend von unserem Markup gilt es drei Operationen zu unterstützen:
</p>
        <ul>
          <li>
Zurückgeben des Inhalts einer statischen Datei 
</li>
          <li>
Aufruf einer parameterlosen Methode eines Webservices, die "Hello World"
zurück gibt 
</li>
          <li>
Aufruf einer Methode <em>Echo</em> eines Webservices, welche einen numerischen Wert
entgegen nimmt und einen String zurück gibt. 
</li>
        </ul>
        <p>
Welche Operation auszuführen ist, unterscheiden wir anhand des einzigen Arguments
der Methode <em>RaiseCallbackEvent</em>: <em>eventArgument</em>.
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">public</span><span style="color: blue">partial</span><span style="color: blue">class</span><span style="color: #2b91af">Teil2</span> : <span style="color: #2b91af">Page</span>, <span style="color: #2b91af">ICallbackEventHandler</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">private</span><span style="color: blue">string</span> callbackResult;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>     <span style="color: blue">public</span><span style="color: blue">void</span> RaiseCallbackEvent(<span style="color: blue">string</span> eventArgument)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>         <span style="color: blue">switch</span> (eventArgument)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>        
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>             <span style="color: blue">case</span><span style="color: #a31515">"static"</span>:
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>                 <span style="color: blue">this</span>.ReadStaticFile();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>                 <span style="color: blue">break</span>;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>             <span style="color: blue">case</span><span style="color: #a31515">"HelloWorld"</span>:
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>                 <span style="color: blue">this</span>.CallHelloWorldService();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   14</span>                 <span style="color: blue">break</span>;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   15</span>             <span style="color: blue">case</span><span style="color: #a31515">"Echo"</span>:
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   16</span>                 <span style="color: blue">this</span>.CallEchoService();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   17</span>                 <span style="color: blue">break</span>;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   18</span>             <span style="color: blue">default</span>:
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   19</span>                 <span style="color: blue">this</span>.ReturnUnknownOperationError();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   20</span>                 <span style="color: blue">break</span>;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   21</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   22</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   23</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   24</span>     <span style="color: blue">public</span><span style="color: blue">string</span> GetCallbackResult()
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   25</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   26</span>         <span style="color: blue">return</span><span style="color: blue">this</span>.callbackResult;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   27</span>     }
</p>
        </div>
        <p>
Je nach Wert des Arguments eventArgument wird eine andere Methode zur weiteren Verarbeitung
aufgerufen. Jede dieser Methoden schreibt ihr Ergebnis wiederum in das Feld <em>callbackResult</em>.
Dieses wird wiederum als Ergebnis der Methode <em>GetCallbackResult</em> an den Client
zurück gegeben.
</p>
        <p>
Der Inhalt der verarbeitenden Methoden sieht wie folgt aus:
</p>
        <p>
          <strong>Auslesen der statischen Datei:</strong>
        </p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">private</span><span style="color: blue">void</span> ReadStaticFile()
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">using</span> (<span style="color: blue">var</span> reader
= <span style="color: blue">new</span><span style="color: #2b91af">StreamReader</span>(Server.MapPath(<span style="color: #a31515">"~/static.html"</span>)))
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>         <span style="color: blue">this</span>.callbackResult
= reader.ReadToEnd();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span> }
</p>
        </div>
        <p>
          <strong>Aufruf der Methode HelloWorld des Webservices:</strong>
        </p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">private</span><span style="color: blue">void</span> CallHelloWorldService()
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">this</span>.callbackResult
= <span style="color: blue">new</span><span style="color: #2b91af">AjaxDemoService</span>().HelloWorld();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span> }
</p>
        </div>
        <p>
          <strong>Aufruf der Methode Echo des Webservices:</strong>
        </p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">private</span><span style="color: blue">void</span> CallEchoService()
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">int</span> value;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     <span style="color: blue">int</span>.TryParse(<span style="color: blue">this</span>.TextBox1.Text, <span style="color: blue">out</span> value);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>     <span style="color: blue">this</span>.callbackResult
= <span style="color: blue">new</span><span style="color: #2b91af">AjaxDemoService</span>().Echo(value);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span> }
</p>
        </div>
        <p>
Wie man beim Aufruf der Webservice Methoden sieht, geschieht dieser Aufruf nun vom <strong>Server</strong> aus
und nicht vom <strong>Client</strong>. Dadurch dass im Gegensatz zum vorherigen Beispiel
der Client nun nicht mehr direkt den Service ruft, musste ich mir einen Proxy auf
Serverseite erstellen.
</p>
        <h4>Schön, aber wie komme ich nun auf den Server?
</h4>
        <p>
Bisher haben wir zwar geklärt, was auf dem Server alles geschehen muss, damit
Client Callbacks funktionieren, offen ist allerdings noch, wie man überhaupt
vom Client auf den Server kommt.
</p>
        <p>
Der Aufruf des Servers geschieht über die JavaScript Funktion <em>WebForm_DoCallback</em>.
Einen entsprechenden Aufruf der Methode kann man sich über den <em>ClientScriptManager</em> der
Seite anhand der Methode <em>GetCallbackEventReference</em> erzeugen lassen. <strong>Zeile
5</strong> des folgenden Listing demonstriert dies.
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">protected</span><span style="color: blue">void</span> Page_Load(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">var</span> clientScript
= Page.ClientScript;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     <span style="color: blue">string</span> callbackReference
=
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>        
clientScript.GetCallbackEventReference(<span style="color: blue">this</span>, <span style="color: #a31515">"argument"</span>, <span style="color: #a31515">"requestFinished"</span>, <span style="color: #a31515">"context"</span>, <span style="color: blue">true</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>     <span style="color: blue">string</span> script
= <span style="color: blue">string</span>.Format(<span style="color: #a31515">"function
sendAjaxRequest(argument, context){{\n {0}; }}"</span>, callbackReference);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>     <span style="color: blue">if</span> (!clientScript.IsClientScriptBlockRegistered(<span style="color: #a31515">"callback"</span>))
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>        
clientScript.RegisterClientScriptBlock(<span style="color: blue">this</span>.GetType(), <span style="color: #a31515">"callback"</span>,
script, <span style="color: blue">true</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span> }
</p>
        </div>
        <p>
Die Methode GetCallbackEventReference hat in der höchsten Überladung folgende
Parameter:
</p>
        <table style="border-right: black 1px solid; border-top: black 1px solid; border-left: black 1px solid; border-bottom: black 1px solid" cellspacing="0" cellpadding="2">
          <thead>
            <tr>
              <th valign="top" width="150">
 
Parameter</th>
              <th valign="top">
Bedeutung</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td valign="top" width="150">
control</td>
              <td valign="top">
Servercontrol, dass den Callback behandelt.</td>
            </tr>
            <tr>
              <td valign="top" width="150">
argument</td>
              <td valign="top">
Argument, das an die Methode RaiseCallbackEvent des behandelnden Controls geschickt
wird.</td>
            </tr>
            <tr>
              <td valign="top" width="150">
clientCallback</td>
              <td valign="top">
Name der Javascript Funktion, die die Rückgabe des Servers im Erfolgsfall behandelt.</td>
            </tr>
            <tr>
              <td valign="top" width="150">
context</td>
              <td valign="top">
Javascsript Code, der ausgeführt wird, ehe die Anfrage an den Server geschickt
wird. Achtung, hierbei handelt es sich nicht um einen JavaScript String, sondern um
einen Befehl / eine Funktion</td>
            </tr>
            <tr>
              <td valign="top" width="150">
clientErrorCallback</td>
              <td valign="top">
Name der Javascript Funktion, die die Rückgabe des Servers im Fehlerfall behandelt.
In meinem Beispiel habe ich diesen Paramter nicht gesetzt.</td>
            </tr>
            <tr>
              <td valign="top" width="150">
useAsync</td>
              <td valign="top">
Boolscher Wert, der angibt, ob die Anfrage asynchron (true) oder synchron (false)
abgesetzt werden soll.</td>
            </tr>
          </tbody>
        </table>
        <p>
Der Einfachheit halber verpackt man den generierten Aufruf der Methode <em>WebForm_DoCallback</em> in
eine eigene JavaScript Funktion, die nur noch die wirklichen variablen Parameter <em>argument</em> und <em>context</em> entgegen
nimmt, wie in <strong>Zeile 7</strong> geschehen. Anschließend registriert man
wie in <strong>Zeile 9 - 11</strong> noch einen ClientScriptBlock für diese Funktion,
der wie folgt in die Seite gerendert wird.
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">&lt;</span><span style="color: #a31515">script</span><span style="color: red">type</span><span style="color: blue">="text/javascript"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>     <span style="color: green">//&lt;![CDATA[</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">function</span> sendAjaxRequest(argument,
context) {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>        
WebForm_DoCallback(<span style="color: #a31515">'__Page'</span>, argument, requestFinished,
context, <span style="color: blue">null</span>, <span style="color: blue">true</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>     } <span style="color: green">//]]&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span> <span style="color: blue">&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Die generierte Methode <em>sendAjaxRequest</em> kann man anschließend wie folgt
aufrufen:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: red">onclick</span><span style="color: blue">="sendAjaxRequest('static',
showMessage());"&gt;</span>Hier klicken zum Request einer
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>                
statischen Datei <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: red">onclick</span><span style="color: blue">="sendAjaxRequest('HelloWorld',
'');"&gt;</span>Hier
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>                
für Hello World WebService klicken <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: red">onclick</span><span style="color: blue">="sendAjaxRequest('Echo',
null);"&gt;</span>Hier
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>                
für Echo WebService klicken. Geben Sie bitte vorher eine Zahl in 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>            
nebenstehendem Feld ein: <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Zeile 1 zeigt, wie der Parameter <em>context</em> genutzt wird. Ich übergebe
einfach die JavaScript Funktion <em>showMessage</em> als Argument. Diese wird nun
automatisch aufgerufen, ehe der Request gestartet wird. Dies ist zum Beispiel bei
länger dauernden Ajax Aufrufen sinnvoll, bei denen man dem Benutzer einen Hinweis
anzeigen möchte, wie folgendes Listing zeigt:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">&lt;</span><span style="color: #a31515">script</span><span style="color: red">type</span><span style="color: blue">="text/javascript"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>     <span style="color: blue">function</span> showMessage()
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>         <span style="color: blue">var</span> contentDiv
= document.getElementById(<span style="color: #a31515">'content'</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>        
contentDiv.innerHTML = <span style="color: #a31515">'Lade...'</span>;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span> <span style="color: blue">&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Wichtig ist, dass der Parameter <strong>keinen String</strong> entgegen nimmt (wie
leider in vielen Beispielen fälschlicherweise gezeigt), sondern eine JavaScript
Funktion!
</p>
        <p>
Eigentlich Interessant für unser Beispiel ist jedoch nicht der Parameter <em>context</em>,
sonder der Parameter <em>argument</em>. Der Inhalt dieses Parameters (und nur dieser!)
wird an die Methode <em>RaiseCallbackEvent</em> des Servers übergeben. Er steuert
somit die auszuführende Funktionalität.
</p>
        <h4>
        </h4>
        <h4>Alles beim Alten?
</h4>
        <p>
Spielt man nun ein wenig mit der vorgestellten Lösung herum, bemerkt man schnell,
dass der Aufruf der Methode Echo stets ausgibt, das man <em>4711</em> eingegeben hat
- auch wenn der Wert der Textbox zwischenzeitlich geändert wurde.
</p>
        <p>
Ursache hierfür ist, dass ASP.NET Client Callbacks für alle Formularfelder
stets die initialen Werte zurücksendet.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/01alterpost.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="161" alt="Screenshot der Beispielanwendung" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/01alterpost_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Abhilfe schafft folgender JavaScript Code:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> __theFormPostData = <span style="color: #a31515">''</span>;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> WebForm_InitCallback();
</p>
        </div>
        <p>
Diesen packt man einfach in eine JavaScript Funktion, z. B. mit dem Namen <em>repostForm</em>.
</p>
        <p>
Gibt man diese nun als context während des Aufrufs an:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: red">onclick</span><span style="color: blue">="sendAjaxRequest('Echo',
repostForm());"&gt;</span>Hier [...]
</p>
        </div>
        <p>
werden auch die geänderten Eingaben des Benutzers übertragen.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/02neuerpost.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="153" alt="Screenshot zeigt dass die geänderten Werte übertragen wurden" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/02neuerpost_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h4>Fazit
</h4>
        <p>
ASP.NET Client Callbacks sind eine schnelle und einfache Lösung um Ajax Funktionalitäten
unter ASP.NET ab der Version 2.0 zu implementieren.
</p>
        <p>
Bei aller Einfachheit sollte man jedoch beachten, dass diese Lösung auch einige
Schwächen hat:
</p>
        <ol>
          <li>
Auf dem Server wird fast der komplette Page Lifecycle ausgeführt. Daher sollten
Codebestandteile, die bei einem Callback nicht zwingend ausgeführt werden müssen
immer durch ein <em>if(!Page.IsCallback)</em> ... geklammert werden, um unnötige
Wartezeiten zu verhindern.</li>
          <li>
Bei jedem Callback wird der komplette Viewstate zum Server übertragen. Gerade
bei großem Viewstate und schlechter Internetanbindung verlangsamt dieser Umstand
die Ajax Anfrage enorm.</li>
          <li>
Es kann immer nur ein Argument an den Server übergeben werden. Möchte man
mehr als eins übergeben, muss man die Werte durch ein Trennzeichen trennen und
auf der Serverseite auseinanderpflücken</li>
          <li>
Das übergebene Argument wird nicht wieder vom Server auf den Client zurück
übertragen. Somit ist es in der verarbeitenden Javascript Funktion auf dem Client
unmöglich herauszufinden, welche Operation ursprünglich gestartet wurde.
Abhilfe schafft auch hier ein zusammengesetzter Rückgabewert, oder aber eine
eigene verarbeitende Funktion je Operation.</li>
        </ol>
        <p>
Hat man diese Schwächen jedoch im Blick, lassen sich mit ASP.NET Client Callbacks
wunderbare Ajax Applikationen implementieren.
</p>
        <p>
Unter der Haube arbeiten diese Client Callbacks übrigens genauso wie das händische
Beispiel aus dem letzten Blogpost - nämlich mit dem XMLHttpRequest Objekt:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/03unterderhaube.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="150" alt="Screenshot des JavaScript Debuggers, zeigt Zugriff auf XMLHttpRequest Objekt" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/03unterderhaube_thumb.png" width="244" border="0" />
          </a>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=fafe2ddd-4f3a-46d7-bf2d-ec5b76ec793a" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>ASP.NET Webforms Anwendungen und Ajax (Teil 2) Client Callbacks</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,fafe2ddd-4f3a-46d7-bf2d-ec5b76ec793a.aspx</guid>
      <link>http://blog.codemurai.de/2010/02/05/ASPNETWebformsAnwendungenUndAjaxTeil2ClientCallbacks.aspx</link>
      <pubDate>Fri, 05 Feb 2010 00:20:23 GMT</pubDate>
      <description>&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
In meinem &lt;a href="http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx" target="_blank"&gt;letzten
Blog Eintrag&lt;/a&gt; habe ich erkl&amp;#228;rt, wie Ajax von Hand mit Hilfe des XMLHttpRequest
Objekts implementiert werden kann. 
&lt;/p&gt;
&lt;p&gt;
Eine Alternative zu dieser h&amp;#228;ndischen Implementierung ist die Nutzung des ASP.NET
Client &lt;a href="http://msdn.microsoft.com/en-us/library/ms178208.aspx" target="_blank"&gt;Callback
Frameworks&lt;/a&gt;, welches mit der Version 2.0 von ASP.NET erschien.
&lt;/p&gt;
&lt;p&gt;
Um Client Callbacks nutzen zu k&amp;#246;nnen muss eine ASP.NET Seite bzw. ein ASP.NET
Control das Interface &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.icallbackeventhandler.aspx" target="_blank"&gt;ICallbackEventHandler&lt;/a&gt;&lt;/em&gt; implementieren.
Das Interface definiert die beiden Methoden:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
void &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.icallbackeventhandler.raisecallbackevent.aspx" target="_blank"&gt;RaiseCallbackEvent&lt;/a&gt;&lt;/em&gt;(string
eventArgument) 
&lt;/li&gt;
&lt;li&gt;
string &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.icallbackeventhandler.getcallbackresult.aspx" target="_blank"&gt;GetCallbackResult&lt;/a&gt;&lt;/em&gt;() 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;em&gt;RaiseCallbackEvent&lt;/em&gt; ist die Methode, den Aufruf des Clients entgegen nimmt. &lt;em&gt;GetCallbackResult&lt;/em&gt; gibt
das Ergebnis der serverseitigen Verarbeitung an den Client zur&amp;#252;ck.
&lt;/p&gt;
&lt;p&gt;
Startet der Client eine Anfrage an eine Seite / ein Control welches &lt;em&gt;ICallBackEventHandler&lt;/em&gt; implementiert,
wird eine &lt;a href="http://edndoc.esri.com/arcobjects/9.2/NET_Server_Doc/developer/ADF/ajax_callback.htm" target="_blank"&gt;reduzierte
Variante&lt;/a&gt; des &lt;a href="http://msdn.microsoft.com/en-us/library/ms178472.aspx" target="_blank"&gt;ASP.NET
Page Lifecycle&lt;/a&gt; / ASP.NET Control Lifecycle ausgef&amp;#252;hrt. Im wesentlichen entspricht
die Callback Variante der &amp;quot;klassichen&amp;quot; Postback Variante, es fehlen jedoch
die Methoden, die sich um das Rendering des Outputs k&amp;#252;mmern. Au&amp;#223;erdem werden
keine Postback Events ausgef&amp;#252;hrt.
&lt;/p&gt;
&lt;p&gt;
Das ganze sieht bezogen auf die Phasen also ungef&amp;#228;hr so aus:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/04lifecycle.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="223" alt="04lifecycle" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/04lifecycle_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;Los gehts
&lt;/h4&gt;
&lt;p&gt;
Sehen wir uns das ganze nun einmal an einem konkreten Beispiel an. Als Ausgangsbasis
soll eine modifizierte Kopie der Seite des letzten Beispiels mit folgendem Markup
dienen:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt;&amp;gt;Hier
klicken zum Request einer
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
statischen Datei &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Hier
f&amp;#252;r Hello World WebService klicken &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Hier&lt;span style="color: #2b91af"&gt; &lt;/span&gt;f&amp;#252;r
Echo WebService klicken. Geben Sie bitte vorher eine Zahl in nebenstehendem Feld ein: &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: red"&gt;&amp;amp;nbsp;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox&lt;/span&gt; &lt;span style="color: red"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;TextBox1&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;Width&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;40px&amp;quot;&amp;gt;&lt;/span&gt;4711&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;asp&lt;/span&gt;&lt;span style="color: blue"&gt;:&lt;/span&gt;&lt;span style="color: #a31515"&gt;TextBox&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt; &lt;span style="color: red"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;content&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
Bitte klicken Sie auf einen der Links, damit dieser Bereich gef&amp;#252;llt wird.
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;&amp;#160;
&lt;/h3&gt;
&lt;h3&gt;Der Server
&lt;/h3&gt;
&lt;p&gt;
Auf Serverseite m&amp;#252;ssen wir nun in unserer Seite das Interface ICallbackEventHandler
implementieren. Ausgehend von unserem Markup gilt es drei Operationen zu unterst&amp;#252;tzen:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Zur&amp;#252;ckgeben des Inhalts einer statischen Datei 
&lt;/li&gt;
&lt;li&gt;
Aufruf einer parameterlosen Methode eines Webservices, die &amp;quot;Hello World&amp;quot;
zur&amp;#252;ck gibt 
&lt;/li&gt;
&lt;li&gt;
Aufruf einer Methode &lt;em&gt;Echo&lt;/em&gt; eines Webservices, welche einen numerischen Wert
entgegen nimmt und einen String zur&amp;#252;ck gibt. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Welche Operation auszuf&amp;#252;hren ist, unterscheiden wir anhand des einzigen Arguments
der Methode &lt;em&gt;RaiseCallbackEvent&lt;/em&gt;: &lt;em&gt;eventArgument&lt;/em&gt;.
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;partial&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Teil2&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;Page&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;ICallbackEventHandler&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; callbackResult;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; RaiseCallbackEvent(&lt;span style="color: blue"&gt;string&lt;/span&gt; eventArgument)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;switch&lt;/span&gt; (eventArgument)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;case&lt;/span&gt; &lt;span style="color: #a31515"&gt;&amp;quot;static&amp;quot;&lt;/span&gt;:
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.ReadStaticFile();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;break&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;case&lt;/span&gt; &lt;span style="color: #a31515"&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;:
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.CallHelloWorldService();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;break&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;case&lt;/span&gt; &lt;span style="color: #a31515"&gt;&amp;quot;Echo&amp;quot;&lt;/span&gt;:
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.CallEchoService();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;break&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;default&lt;/span&gt;:
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.ReturnUnknownOperationError();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;break&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 23&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 24&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; GetCallbackResult()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 25&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 26&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;this&lt;/span&gt;.callbackResult;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 27&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Je nach Wert des Arguments eventArgument wird eine andere Methode zur weiteren Verarbeitung
aufgerufen. Jede dieser Methoden schreibt ihr Ergebnis wiederum in das Feld &lt;em&gt;callbackResult&lt;/em&gt;.
Dieses wird wiederum als Ergebnis der Methode &lt;em&gt;GetCallbackResult&lt;/em&gt; an den Client
zur&amp;#252;ck gegeben.
&lt;/p&gt;
&lt;p&gt;
Der Inhalt der verarbeitenden Methoden sieht wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Auslesen der statischen Datei:&lt;/strong&gt;
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; ReadStaticFile()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;using&lt;/span&gt; (&lt;span style="color: blue"&gt;var&lt;/span&gt; reader
= &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;StreamReader&lt;/span&gt;(Server.MapPath(&lt;span style="color: #a31515"&gt;&amp;quot;~/static.html&amp;quot;&lt;/span&gt;)))
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.callbackResult
= reader.ReadToEnd();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;strong&gt;Aufruf der Methode HelloWorld des Webservices:&lt;/strong&gt;
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; CallHelloWorldService()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.callbackResult
= &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AjaxDemoService&lt;/span&gt;().HelloWorld();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;strong&gt;Aufruf der Methode Echo des Webservices:&lt;/strong&gt;
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; CallEchoService()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;int&lt;/span&gt; value;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;int&lt;/span&gt;.TryParse(&lt;span style="color: blue"&gt;this&lt;/span&gt;.TextBox1.Text, &lt;span style="color: blue"&gt;out&lt;/span&gt; value);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.callbackResult
= &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AjaxDemoService&lt;/span&gt;().Echo(value);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Wie man beim Aufruf der Webservice Methoden sieht, geschieht dieser Aufruf nun vom &lt;strong&gt;Server&lt;/strong&gt; aus
und nicht vom &lt;strong&gt;Client&lt;/strong&gt;. Dadurch dass im Gegensatz zum vorherigen Beispiel
der Client nun nicht mehr direkt den Service ruft, musste ich mir einen Proxy auf
Serverseite erstellen.
&lt;/p&gt;
&lt;h4&gt;Sch&amp;#246;n, aber wie komme ich nun auf den Server?
&lt;/h4&gt;
&lt;p&gt;
Bisher haben wir zwar gekl&amp;#228;rt, was auf dem Server alles geschehen muss, damit
Client Callbacks funktionieren, offen ist allerdings noch, wie man &amp;#252;berhaupt
vom Client auf den Server kommt.
&lt;/p&gt;
&lt;p&gt;
Der Aufruf des Servers geschieht &amp;#252;ber die JavaScript Funktion &lt;em&gt;WebForm_DoCallback&lt;/em&gt;.
Einen entsprechenden Aufruf der Methode kann man sich &amp;#252;ber den &lt;em&gt;ClientScriptManager&lt;/em&gt; der
Seite anhand der Methode &lt;em&gt;GetCallbackEventReference&lt;/em&gt; erzeugen lassen. &lt;strong&gt;Zeile
5&lt;/strong&gt; des folgenden Listing demonstriert dies.
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;var&lt;/span&gt; clientScript
= Page.ClientScript;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;string&lt;/span&gt; callbackReference
=
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
clientScript.GetCallbackEventReference(&lt;span style="color: blue"&gt;this&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;argument&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;requestFinished&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;context&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;true&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;string&lt;/span&gt; script
= &lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;function
sendAjaxRequest(argument, context){{\n {0}; }}&amp;quot;&lt;/span&gt;, callbackReference);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (!clientScript.IsClientScriptBlockRegistered(&lt;span style="color: #a31515"&gt;&amp;quot;callback&amp;quot;&lt;/span&gt;))
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
clientScript.RegisterClientScriptBlock(&lt;span style="color: blue"&gt;this&lt;/span&gt;.GetType(), &lt;span style="color: #a31515"&gt;&amp;quot;callback&amp;quot;&lt;/span&gt;,
script, &lt;span style="color: blue"&gt;true&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Die Methode GetCallbackEventReference hat in der h&amp;#246;chsten &amp;#220;berladung folgende
Parameter:
&lt;/p&gt;
&lt;table style="border-right: black 1px solid; border-top: black 1px solid; border-left: black 1px solid; border-bottom: black 1px solid" cellspacing="0" cellpadding="2"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th valign="top" width="150"&gt;
&amp;#160;&gt;
Parameter&lt;/th&gt;
&lt;th valign="top"&gt;
Bedeutung&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="150"&gt;
control&lt;/td&gt;
&lt;td valign="top"&gt;
Servercontrol, dass den Callback behandelt.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="150"&gt;
argument&lt;/td&gt;
&lt;td valign="top"&gt;
Argument, das an die Methode RaiseCallbackEvent des behandelnden Controls geschickt
wird.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="150"&gt;
clientCallback&lt;/td&gt;
&lt;td valign="top"&gt;
Name der Javascript Funktion, die die R&amp;#252;ckgabe des Servers im Erfolgsfall behandelt.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="150"&gt;
context&lt;/td&gt;
&lt;td valign="top"&gt;
Javascsript Code, der ausgef&amp;#252;hrt wird, ehe die Anfrage an den Server geschickt
wird. Achtung, hierbei handelt es sich nicht um einen JavaScript String, sondern um
einen Befehl / eine Funktion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="150"&gt;
clientErrorCallback&lt;/td&gt;
&lt;td valign="top"&gt;
Name der Javascript Funktion, die die R&amp;#252;ckgabe des Servers im Fehlerfall behandelt.
In meinem Beispiel habe ich diesen Paramter nicht gesetzt.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="150"&gt;
useAsync&lt;/td&gt;
&lt;td valign="top"&gt;
Boolscher Wert, der angibt, ob die Anfrage asynchron (true) oder synchron (false)
abgesetzt werden soll.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Der Einfachheit halber verpackt man den generierten Aufruf der Methode &lt;em&gt;WebForm_DoCallback&lt;/em&gt; in
eine eigene JavaScript Funktion, die nur noch die wirklichen variablen Parameter &lt;em&gt;argument&lt;/em&gt; und &lt;em&gt;context&lt;/em&gt; entgegen
nimmt, wie in &lt;strong&gt;Zeile 7&lt;/strong&gt; geschehen. Anschlie&amp;#223;end registriert man
wie in &lt;strong&gt;Zeile 9 - 11&lt;/strong&gt; noch einen ClientScriptBlock f&amp;#252;r diese Funktion,
der wie folgt in die Seite gerendert wird.
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;script&lt;/span&gt; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: green"&gt;//&amp;lt;![CDATA[&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;function&lt;/span&gt; sendAjaxRequest(argument,
context) {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
WebForm_DoCallback(&lt;span style="color: #a31515"&gt;'__Page'&lt;/span&gt;, argument, requestFinished,
context, &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: blue"&gt;true&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;span style="color: green"&gt;//]]&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;script&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Die generierte Methode &lt;em&gt;sendAjaxRequest&lt;/em&gt; kann man anschlie&amp;#223;end wie folgt
aufrufen:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;onclick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;sendAjaxRequest('static',
showMessage());&amp;quot;&amp;gt;&lt;/span&gt;Hier klicken zum Request einer
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
statischen Datei &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;onclick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;sendAjaxRequest('HelloWorld',
'');&amp;quot;&amp;gt;&lt;/span&gt;Hier
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
f&amp;#252;r Hello World WebService klicken &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;onclick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;sendAjaxRequest('Echo',
null);&amp;quot;&amp;gt;&lt;/span&gt;Hier
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
f&amp;#252;r Echo WebService klicken. Geben Sie bitte vorher eine Zahl in 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
nebenstehendem Feld ein: &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Zeile 1 zeigt, wie der Parameter &lt;em&gt;context&lt;/em&gt; genutzt wird. Ich &amp;#252;bergebe
einfach die JavaScript Funktion &lt;em&gt;showMessage&lt;/em&gt; als Argument. Diese wird nun
automatisch aufgerufen, ehe der Request gestartet wird. Dies ist zum Beispiel bei
l&amp;#228;nger dauernden Ajax Aufrufen sinnvoll, bei denen man dem Benutzer einen Hinweis
anzeigen m&amp;#246;chte, wie folgendes Listing zeigt:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;script&lt;/span&gt; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;function&lt;/span&gt; showMessage()
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;var&lt;/span&gt; contentDiv
= document.getElementById(&lt;span style="color: #a31515"&gt;'content'&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
contentDiv.innerHTML = &lt;span style="color: #a31515"&gt;'Lade...'&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;script&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Wichtig ist, dass der Parameter &lt;strong&gt;keinen String&lt;/strong&gt; entgegen nimmt (wie
leider in vielen Beispielen f&amp;#228;lschlicherweise gezeigt), sondern eine JavaScript
Funktion!
&lt;/p&gt;
&lt;p&gt;
Eigentlich Interessant f&amp;#252;r unser Beispiel ist jedoch nicht der Parameter &lt;em&gt;context&lt;/em&gt;,
sonder der Parameter &lt;em&gt;argument&lt;/em&gt;. Der Inhalt dieses Parameters (und nur dieser!)
wird an die Methode &lt;em&gt;RaiseCallbackEvent&lt;/em&gt; des Servers &amp;#252;bergeben. Er steuert
somit die auszuf&amp;#252;hrende Funktionalit&amp;#228;t.
&lt;/p&gt;
&lt;h4&gt;
&lt;/h4&gt;
&lt;h4&gt;Alles beim Alten?
&lt;/h4&gt;
&lt;p&gt;
Spielt man nun ein wenig mit der vorgestellten L&amp;#246;sung herum, bemerkt man schnell,
dass der Aufruf der Methode Echo stets ausgibt, das man &lt;em&gt;4711&lt;/em&gt; eingegeben hat
- auch wenn der Wert der Textbox zwischenzeitlich ge&amp;#228;ndert wurde.
&lt;/p&gt;
&lt;p&gt;
Ursache hierf&amp;#252;r ist, dass ASP.NET Client Callbacks f&amp;#252;r alle Formularfelder
stets die initialen Werte zur&amp;#252;cksendet.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/01alterpost.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="161" alt="Screenshot der Beispielanwendung" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/01alterpost_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Abhilfe schafft folgender JavaScript Code:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt; __theFormPostData = &lt;span style="color: #a31515"&gt;''&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; WebForm_InitCallback();
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Diesen packt man einfach in eine JavaScript Funktion, z. B. mit dem Namen &lt;em&gt;repostForm&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
Gibt man diese nun als context w&amp;#228;hrend des Aufrufs an:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;onclick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;sendAjaxRequest('Echo',
repostForm());&amp;quot;&amp;gt;&lt;/span&gt;Hier [...]
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
werden auch die ge&amp;#228;nderten Eingaben des Benutzers &amp;#252;bertragen.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/02neuerpost.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="153" alt="Screenshot zeigt dass die ge&amp;#228;nderten Werte &amp;#252;bertragen wurden" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/02neuerpost_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;Fazit
&lt;/h4&gt;
&lt;p&gt;
ASP.NET Client Callbacks sind eine schnelle und einfache L&amp;#246;sung um Ajax Funktionalit&amp;#228;ten
unter ASP.NET ab der Version 2.0 zu implementieren.
&lt;/p&gt;
&lt;p&gt;
Bei aller Einfachheit sollte man jedoch beachten, dass diese L&amp;#246;sung auch einige
Schw&amp;#228;chen hat:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Auf dem Server wird fast der komplette Page Lifecycle ausgef&amp;#252;hrt. Daher sollten
Codebestandteile, die bei einem Callback nicht zwingend ausgef&amp;#252;hrt werden m&amp;#252;ssen
immer durch ein &lt;em&gt;if(!Page.IsCallback)&lt;/em&gt; ... geklammert werden, um unn&amp;#246;tige
Wartezeiten zu verhindern.&lt;/li&gt;
&lt;li&gt;
Bei jedem Callback wird der komplette Viewstate zum Server &amp;#252;bertragen. Gerade
bei gro&amp;#223;em Viewstate und schlechter Internetanbindung verlangsamt dieser Umstand
die Ajax Anfrage enorm.&lt;/li&gt;
&lt;li&gt;
Es kann immer nur ein Argument an den Server &amp;#252;bergeben werden. M&amp;#246;chte man
mehr als eins &amp;#252;bergeben, muss man die Werte durch ein Trennzeichen trennen und
auf der Serverseite auseinanderpfl&amp;#252;cken&lt;/li&gt;
&lt;li&gt;
Das &amp;#252;bergebene Argument wird nicht wieder vom Server auf den Client zur&amp;#252;ck
&amp;#252;bertragen. Somit ist es in der verarbeitenden Javascript Funktion auf dem Client
unm&amp;#246;glich herauszufinden, welche Operation urspr&amp;#252;nglich gestartet wurde.
Abhilfe schafft auch hier ein zusammengesetzter R&amp;#252;ckgabewert, oder aber eine
eigene verarbeitende Funktion je Operation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Hat man diese Schw&amp;#228;chen jedoch im Blick, lassen sich mit ASP.NET Client Callbacks
wunderbare Ajax Applikationen implementieren.
&lt;/p&gt;
&lt;p&gt;
Unter der Haube arbeiten diese Client Callbacks &amp;#252;brigens genauso wie das h&amp;#228;ndische
Beispiel aus dem letzten Blogpost - n&amp;#228;mlich mit dem XMLHttpRequest Objekt:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/03unterderhaube.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="150" alt="Screenshot des JavaScript Debuggers, zeigt Zugriff auf XMLHttpRequest Objekt" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil2Cl_68C4/03unterderhaube_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=fafe2ddd-4f3a-46d7-bf2d-ec5b76ec793a" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,fafe2ddd-4f3a-46d7-bf2d-ec5b76ec793a.aspx</comments>
      <category>.NET</category>
      <category>Ajax</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=c1d68af1-23ac-4bf3-8053-c388408472b3</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,c1d68af1-23ac-4bf3-8053-c388408472b3.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,c1d68af1-23ac-4bf3-8053-c388408472b3.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=c1d68af1-23ac-4bf3-8053-c388408472b3</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Das man mit statischen, oder auch dyanamischen Seiten, die bei jeder Anfrage die komplette
Seite neu aufbauen, heute keinen Blumentopf mehr gewinnt, dürfte jedem klar sein.
Verwöhnt durch Webanwendungen wie zum Beispiel Google-Maps oder Outlook Web Access
erwarten Endanwender Webanwendungen, die einen ähnlichen Bedienkomfort wie Desktop
Anwendungen aufweisen.
</p>
        <p>
Als Entwickler solcher Webanwendungen bringt uns dies in die Situation, dass wir unsere
Entwicklungstätigkeiten nun nicht mehr rein auf den Server beschränken können,
sondern auch auf dem Client aktiv werden müssen, um die hohen Erwartungen unserer
Anwender zu erfüllen.
</p>
        <p>
Was <em>"auf dem Client aktiv werden"</em> konkret bedeutet möchte
ich in einer kleinen Artikelreihe in meinem Blog beantworten.
</p>
        <h4>Der Client - das unbekannte Wesen
</h4>
        <p>
Heutzutage sind eine Reihe <em>Ajax Frameworks</em> verfügbar, die uns die <em>"schmutzige"</em> Arbeit
auf dem Weg zur dynamischen Webseite abnehmen wollen. Da es meiner Meinung nach aber
nie schaden kann, wenn man weiss was diese magischen Toolsets und Frameworks unter
der Haube machen, werden wir heute die Ärmel hoch krempeln und die <em>"Drecksarbeit"</em> auf
dem Client selbst erledigen. 
</p>
        <p>
Ehe wir los legen, sollten wir zuvor jedoch einen Blick auf die notwendigen Zutaten
werfen und kurz klären, worum es sich dabei im einzelnen handelt.
</p>
        <ol>
          <li>
            <strong>JavaScript</strong>
            <p>
              <em>Das <strong>J</strong> in A<strong>J</strong>AX. Eine von vielen Entwicklern zu
unrecht gefürchtete und/oder belächelte Client Script Sprache ;-) Der Scriptcode
wird entweder direkt in eine Seite eingebettet, oder aber in eine externe Datei ausgelagert.
JavaScript wird zur Manipulation des DOM genutzt</em>
            </p>
          </li>
          <li>
das <strong>Document Object Model (DOM)</strong> des Browsers  
<p><em>Das DOM des Browsers ist eine Schnittstelle, die den Zugriff auf das zugrundeliegende
(X)HTML Dokument bereitstellt. Über das DOM habe ich die Möglichkeit, Aussehen
und Struktur der einer Webseite zu verändern.</em></p></li>
          <li>
das <strong>XMLHttpRequest</strong> Objekt 
<p><em>Eines der Objekte des window Objekts des Browsers(zumindest in modernen Browsern.
Andernfalls ein ActiveX Objekt). Es ermöglicht einem Script das Absetzen einer
(asynchronen) Anfrage an einen Webserver.</em> 
</p></li>
        </ol>
        <p>
Im Überblick sieht das Zusammenspiel der drei Komponenten ungefähr so aus:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/ueberblick.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="116" alt="Zusammenspiel zwischen JavaScript, DOM und XMLHttpRequest" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/ueberblick_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h4>
        </h4>
        <h4>Los gehts!
</h4>
        <p>
Wir wissen zwar jetzt, was wir alles brauchen, allerdings fehlt immer noch die Antwort,
wie die Komponenten nun genutzt werden müssen, um AJAX in die eigene Webseite
zu bekommen.
</p>
        <p>
Starten wir dazu mit einem kleinen und sehr einfachen Beispiel. 
</p>
        <p>
Wir erstellen eine einfache ASPX Seite, die aus einem Link und einem Platzhalter Bereich
bestehen soll. Sobald der Anwender auf den Link klickt, soll dieser Platzhalter mit
dem Inhalt einer statischen Datei, welche auf dem Server liegt, gefüllt werden.
</p>
        <p>
Der zugehörige HTML Code der ASPX Seite sieht wie folgt aus:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">form</span><span style="color: red">id</span><span style="color: blue">="form1"</span><span style="color: red">runat</span><span style="color: blue">="server"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>         <span style="color: blue">&lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: blue">&gt;</span>Hier
klicken zum Request einer
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>                
statischen Datei <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>         <span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: red">id</span><span style="color: blue">="content"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>        
Bitte klicken Sie den Link, damit dieser Bereich gefüllt wird.
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>     <span style="color: blue">&lt;/</span><span style="color: #a31515">form</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Der Link, welcher später die Ajax Aktion initiieren soll, wird in den Zeilen
5 und 6 definiert. Der Bereich welcher später ersetzt werden soll, ist der Inhalt
des DIV Tags aus Zeile 9.
</p>
        <p>
Noch ist das ganze jedoch nicht sonderlich dynamisch. Dazu benötigen wir noch
etwas JavaScript:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>     <span style="color: blue">&lt;</span><span style="color: #a31515">script</span><span style="color: red">type</span><span style="color: blue">="text/javascript"&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>         <span style="color: blue">var</span> xmlHttp;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>        
window.onload = <span style="color: blue">function</span>() {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>            
initializeXmlHttp();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>         <span style="color: blue">function</span> initializeXmlHttp()
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>             <span style="color: blue">if</span> (window.XMLHttpRequest)
{ <span style="color: green">// IE7, IE8, Mozilla, Safari, Opera</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>                
xmlHttp = <span style="color: blue">new</span> XMLHttpRequest();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>            
} <span style="color: blue">else</span><span style="color: blue">if</span> (window.ActiveXObject)
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>                 <span style="color: blue">try</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>                    
xmlHttp = <span style="color: blue">new</span> ActiveXObject(<span style="color: #a31515">"Microsoft.XMLHTTP"</span>); <span style="color: green">//IE
5.x, 6</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>                
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   14</span>                 <span style="color: blue">catch</span> (e)
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   15</span>                    
alert(<span style="color: #a31515">'Ajax Zugriffe sind aufgrund der aktuellen Sicherheitseinstellungen
leider nicht möglich'</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   16</span>                
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   17</span>            
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   18</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   19</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   20</span>         <span style="color: blue">function</span> sendAjaxRequest(url)
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   21</span>             <span style="color: blue">if</span> (xmlHttp)
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   22</span>                
xmlHttp.open(<span style="color: #a31515">"GET"</span>, url, <span style="color: blue">true</span>); 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   23</span>                
xmlHttp.onreadystatechange = requestFinished;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   24</span>                
xmlHttp.send(<span style="color: blue">null</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   25</span>            
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   26</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   27</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   28</span>         <span style="color: blue">function</span> requestFinished()
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   </span>
            <span style="color: #2b91af">29</span>             <span style="color: blue">if</span> (xmlHttp.readyState==4)
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   </span>
            <span style="color: #2b91af">30</span>               <span style="color: blue">if</span> (xmlHttp.status==200)
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   31</span>                 <span style="color: blue">var</span> contentDiv
= document.getElementById(<span style="color: #a31515">'content'</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   32</span>                
contentDiv.innerHTML = xmlHttp.responseText;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   33</span>              
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   34</span>            
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   35</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   36</span>    <span style="color: blue">&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
        </p>
        <p>
Das Script deklariert zunächst in <strong>Zeile 2</strong> eine Variable, die
einen Verweis auf das <em>XMLHhtpRequest</em> Objekt hält. Wie zuvor beschrieben
ermöglicht dieses das Absetzen einer asynchronen Abfrage an den Server.
</p>
        <p>
Die Funktion <em>initializeXmlHttp</em> ab <strong>Zeile 7</strong> füllt dieses
Objekt nun mit Leben. Der Code sollte recht selbsterklärend sein. Zeile 8 prüft,
ob das XMLHttpRequest Objekt am window Objekt hängt. Falls ja, kann ein neues
XMLHttpRequest Objekt erstellt werden. Ist dies nicht der Fall, muss es als ActiveX
Objekt erstellt werden.
</p>
        <p>
Die Funktion <em>sendAjaxRequest</em> ab <strong>Zeile 20</strong> setzt die eigentliche
Abfrage ab. Dazu prüft Sie in Zeile 21 zuerst, ob die Variable xmlHttp initialisiert
werden konnte. Wäre dies nicht der Fall, könnte keine Abfrage abgesandt
werden. Anschließend wird in <strong>Zeile 22</strong> eine asynchrone Verbindung
geöffnet mit der Methode <em>open </em>geöffnet. Diese Methode erhält
als Parameter die Methode ("GET" oder "POST"), die URL, sowie
ein Flag, ob die Anfrage asynchron abgesetzt werden soll.
</p>
        <p>
          <strong>Zeile 23</strong> gibt eine CallBack-Funktion an (in unserem Fall requestFinished),
die aufgerufen werden soll, sobald eine Antwort auf die Anfrage zurück gekommen
ist.
</p>
        <p>
          <strong>Zeile 24</strong> sendet die Anfrage nun schließlich ab.
</p>
        <p>
Die Funktion <em>requestFinished</em> ab <strong>Zeile 28</strong> verarbeitet die
Antwort des Webservers. Da eine Anfrage verschiedene Phasen durchlebt, prüft
die Funktion in <strong>Zeile 29</strong> anhand der Eigenschaft <em>readyState</em> ab,
ob die Anfrage tatsächlich komplett beendet wurde.
</p>
        <p>
Da zu Ende nicht immer "hat auch geklappt" heißen muss, wird in der
nächsten Zeile geprüft, ob die Anfrage auch erfolgreich beendet wurde (HTTP
Statuscode 200).
</p>
        <p>
Die eigentliche Verarbeitung findet nun in den <strong>Zeilen 31 und 32</strong> statt. <strong>Zeile
31</strong> holt sich eine Referenz auf den zu ersetzenden Bereich (unser Div mit
der ID Content). <strong>Zeile 32</strong> überschreibt diesen Inhalt schlussendlich
mit der Antwort des Servers.
</p>
        <p>
Damit das ganze auch funktioniert muss die Funktion <em>sendAjaxRequest</em> aus <strong>Zeile
20</strong> noch aus unserem HTML Code heraus aufgerufen werden. Dazu erweitern wir
unseren Link aus den <strong>Zeilen 5/6</strong> einfach um das Attribut <em>onclick</em>. 
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: red">onclick</span><span style="color: blue">="sendAjaxRequest('static.html');"&gt;</span>Hier 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>                
klicken zum Request einer statischen Datei <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Ausgeführt sieht das ganze dann wie folgt aus:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/1_erster_Start.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="117" alt="Erster Aufruf der Seite" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/1_erster_Start_thumb.png" width="244" border="0" />
          </a>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/2_aufruf_statisch.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="106" alt="Nach Aufruf des Links" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/2_aufruf_statisch_thumb.png" width="244" border="0" />
          </a>
        </p>
        <h4>Ganz nett ...
</h4>
        <blockquote>
          <p>
            <em>wir wissen nun also, wie wir statische Dateien nachladen können, aber steht
das <strong>X</strong> in AJA<strong>X</strong> nicht für XML Webservices?</em>
          </p>
        </blockquote>
        <p>
Genau! Deshalb habe ich das Demoprojekt auch um einen kleinen Webservice mit zwei
sinnlosen Methoden erweitert:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">public</span><span style="color: blue">class</span><span style="color: #2b91af">AjaxDemoService</span> :
System.Web.Services.<span style="color: #2b91af">WebService</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     [<span style="color: #2b91af">WebMethod</span>]
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     <span style="color: blue">public</span><span style="color: blue">string</span> HelloWorld()
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>         <span style="color: blue">return</span><span style="color: #a31515">"Hello
World"</span>;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>     [<span style="color: #2b91af">WebMethod</span>]
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>     <span style="color: blue">public</span><span style="color: blue">string</span> Echo(<span style="color: blue">int</span> number)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>         <span style="color: blue">return</span><span style="color: blue">string</span>.Format(<span style="color: #a31515">"Sie
haben {0} eingegeben."</span>, number);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>     }   
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span> }
</p>
        </div>
        <p>
Wie rufen wir einen solchen Service nun aber per JavaScript auf?
</p>
        <p>
Die Antwort findet sich relativ schnell, wenn man die URL des Webservices im Browser
eingibt. In der nun erscheinenden Seite werden sämtliche Methoden des Webservices
aufgelistet. Ein Klick auf eine dieser Methoden verrät schlussendlich, wie die
Methode aufgerufen werden muss. Im Beispiel der Methode HelloWorld sieht die Ausgabe
für eine HTTP Post Anfrage zum Beispiel wie folgt aus:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/3_hello_world_http_post.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="128" alt="Beschreibung des POST Aufrufs der Webservice Methode" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/3_hello_world_http_post_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Für die Methode Echo wird folgende Ausgabe produziert:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/4_echo_http_post.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="156" alt="4_echo_http_post" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/4_echo_http_post_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Im Vergleich zu unserer bisherigen Vorgehensweise beim dynamischen Nachladen der statischen
Datei fällt auf, dass die Methode, über die die Anfrage gestartet wird,
nun nicht mehr <strong>GET</strong> ein kann, sondern <strong>POST</strong> sein muss.
</p>
        <p>
Außerdem wird nun auch ein bestimmter Content-Type, nämlich <em>application/x-www-form-urlencoded</em> benötigt.
Speziell bei der Methode Echo fällt auf, dass außerdem nun auch Daten mit
an den Server gesendet werden müssen.
</p>
        <p>
Um die veränderten Anforderungen abdecken zu können, erweitere ich das bestehende
JavaScript um eine neue Funktion:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>         <span style="color: blue">function</span> postAjaxRequest(url,
data) {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>             <span style="color: blue">if</span> (xmlHttp)
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>                
xmlHttp.open(<span style="color: #a31515">"POST"</span>, url, <span style="color: blue">true</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>                
xmlHttp.onreadystatechange = requestFinished;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>                
xmlHttp.setRequestHeader(<span style="color: #a31515">'Content-type'</span>, <span style="color: #a31515">'application/x-www-form-urlencoded'</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>                
xmlHttp.send(data);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>            
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af"> </span>
          </p>
        </div>
        <p>
Die neuen Funktion, <em>postAjaxRequest</em> ähnelt der vorherigen Funktion <em>sendAjaxRequest</em>.
Die veränderten Anforderungen ließen sich relativ einfach integrieren. In <strong>Zeile
3</strong> wurde aus einem <em>GET</em> ein <em>POST</em>. In <strong>Zeile 5</strong> wird
der zusätzlich benötigte Content-Type gesetzt. In <strong>Zeile 6</strong> wird
der Methode <em>send</em> nun nicht mehr fix <em>null</em> als Datenparameter übergeben.
Stattdessen wird das neue Argument <em>data</em> weiter gereicht.
</p>
        <p>
Der HTML Code musste auch nur unwesentlich erweitert werden. Er erhält zwei neue
Links zum Aufruf der beiden Webmethoden:
</p>
        <div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: red">onclick</span><span style="color: blue">="postAjaxRequest('AjaxDemoService.asmx/HelloWorld',
null);"&gt;</span>Hier
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>                
für Hello World WebService klicken <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">br</span><span style="color: blue">/&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>             <span style="color: blue">&lt;</span><span style="color: #a31515">a</span><span style="color: red">href</span><span style="color: blue">="#"</span><span style="color: red">onclick</span><span style="color: blue">="postAjaxRequest('AjaxDemoService.asmx/Echo',
'number=1');"&gt;</span>Hier
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>                
für Echo WebService klicken <span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></p>
        </div>
        <p>
Das Ergebnis sieht anschließend wie folgt aus:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/5_hello_world.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="115" alt="Abbildung zeigt den Rückgabewert des Hello World Webservices" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/5_hello_world_thumb.png" width="244" border="0" />
          </a> <a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/6_echo.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="156" alt="Abbildung zeigt die Rückgabe des Echo Web Services" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/6_echo_thumb.png" width="244" border="0" /></a></p>
        <h4>Fazit
</h4>
        <p>
Ajax in eine Webanwendung zu integrieren ist aus technischer Sicht nicht sonderlich
schwierig. Der vorliegende Blog Post hat gezeigt, dass sich selbst ohne "<em>magische</em>"
Frameworks mit wenigen Zeilen JavaScript Ajax Funktionalitäten integrieren lassen.
Natürlich ist die gezeigte Implementierung nur sehr rudimentär. So wurde
das zurückgegeben XML des Webservices zum Beispiel noch nicht geparsed und es
fand außerdem so gut wie keine Fehlerbehandlung statt. Dieses in das Beispiel
zu integrieren hätte den Rahmen eines Blogposts jedoch vollständig gesprengt.
Außerdem gibt es genau aus diesen Gründen auch bereits fertige Frameworks,
wie ASP.NET AJAX oder jQuery, die einem genau diese Detailarbeit abnehmen.
</p>
        <p>
Ehe man ein solches Framework einsetzt, sollte man jedoch die Grundlagen dessen kennen,
was hinter den Kulissen geschieht. Und genau diese Grundlagen haben wir in diesem
Blog Post geschaffen.
</p>
        <p>
Das vollständige Beispiel werde ich übrigens am Wochenende zum Download
bereit stellen.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=c1d68af1-23ac-4bf3-8053-c388408472b3" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>ASP.NET Webforms Anwendungen und Ajax (Teil 1)</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,c1d68af1-23ac-4bf3-8053-c388408472b3.aspx</guid>
      <link>http://blog.codemurai.de/2010/01/28/ASPNETWebformsAnwendungenUndAjaxTeil1.aspx</link>
      <pubDate>Thu, 28 Jan 2010 23:51:35 GMT</pubDate>
      <description>&lt;p&gt;
Das man mit statischen, oder auch dyanamischen Seiten, die bei jeder Anfrage die komplette
Seite neu aufbauen, heute keinen Blumentopf mehr gewinnt, d&amp;#252;rfte jedem klar sein.
Verw&amp;#246;hnt durch Webanwendungen wie zum Beispiel Google-Maps oder Outlook Web Access
erwarten Endanwender Webanwendungen, die einen &amp;#228;hnlichen Bedienkomfort wie Desktop
Anwendungen aufweisen.
&lt;/p&gt;
&lt;p&gt;
Als Entwickler solcher Webanwendungen bringt uns dies in die Situation, dass wir unsere
Entwicklungst&amp;#228;tigkeiten nun nicht mehr rein auf den Server beschr&amp;#228;nken k&amp;#246;nnen,
sondern auch auf dem Client aktiv werden m&amp;#252;ssen, um die hohen Erwartungen unserer
Anwender zu erf&amp;#252;llen.
&lt;/p&gt;
&lt;p&gt;
Was &lt;em&gt;&amp;quot;auf dem Client aktiv werden&amp;quot;&lt;/em&gt; konkret bedeutet m&amp;#246;chte
ich in einer kleinen Artikelreihe in meinem Blog beantworten.
&lt;/p&gt;
&lt;h4&gt;Der Client - das unbekannte Wesen
&lt;/h4&gt;
&lt;p&gt;
Heutzutage sind eine Reihe &lt;em&gt;Ajax Frameworks&lt;/em&gt; verf&amp;#252;gbar, die uns die &lt;em&gt;&amp;quot;schmutzige&amp;quot;&lt;/em&gt; Arbeit
auf dem Weg zur dynamischen Webseite abnehmen wollen. Da es meiner Meinung nach aber
nie schaden kann, wenn man weiss was diese magischen Toolsets und Frameworks unter
der Haube machen, werden wir heute die &amp;#196;rmel hoch krempeln und die &lt;em&gt;&amp;quot;Drecksarbeit&amp;quot;&lt;/em&gt; auf
dem Client selbst erledigen. 
&lt;/p&gt;
&lt;p&gt;
Ehe wir los legen, sollten wir zuvor jedoch einen Blick auf die notwendigen Zutaten
werfen und kurz kl&amp;#228;ren, worum es sich dabei im einzelnen handelt.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript&lt;/strong&gt; 
&lt;p&gt;
&lt;em&gt;Das &lt;strong&gt;J&lt;/strong&gt; in A&lt;strong&gt;J&lt;/strong&gt;AX. Eine von vielen Entwicklern zu
unrecht gef&amp;#252;rchtete und/oder bel&amp;#228;chelte Client Script Sprache ;-) Der Scriptcode
wird entweder direkt in eine Seite eingebettet, oder aber in eine externe Datei ausgelagert.
JavaScript wird zur Manipulation des DOM genutzt&lt;/em&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
das &lt;strong&gt;Document Object Model (DOM)&lt;/strong&gt; des Browsers&amp;#160; 
&lt;p&gt;
&lt;em&gt;Das DOM des Browsers ist eine Schnittstelle, die den Zugriff auf das zugrundeliegende
(X)HTML Dokument bereitstellt. &amp;#220;ber das DOM habe ich die M&amp;#246;glichkeit, Aussehen
und Struktur der einer Webseite zu ver&amp;#228;ndern.&lt;/em&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
das &lt;strong&gt;XMLHttpRequest&lt;/strong&gt; Objekt 
&lt;p&gt;
&lt;em&gt;Eines der Objekte des window Objekts des Browsers(zumindest in modernen Browsern.
Andernfalls ein ActiveX Objekt). Es erm&amp;#246;glicht einem Script das Absetzen einer
(asynchronen) Anfrage an einen Webserver.&lt;/em&gt;&amp;#160;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Im &amp;#220;berblick sieht das Zusammenspiel der drei Komponenten ungef&amp;#228;hr so aus:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/ueberblick.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="116" alt="Zusammenspiel zwischen JavaScript, DOM und XMLHttpRequest" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/ueberblick_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;
&lt;/h4&gt;
&lt;h4&gt;Los gehts!
&lt;/h4&gt;
&lt;p&gt;
Wir wissen zwar jetzt, was wir alles brauchen, allerdings fehlt immer noch die Antwort,
wie die Komponenten nun genutzt werden m&amp;#252;ssen, um AJAX in die eigene Webseite
zu bekommen.
&lt;/p&gt;
&lt;p&gt;
Starten wir dazu mit einem kleinen und sehr einfachen Beispiel. 
&lt;/p&gt;
&lt;p&gt;
Wir erstellen eine einfache ASPX Seite, die aus einem Link und einem Platzhalter Bereich
bestehen soll. Sobald der Anwender auf den Link klickt, soll dieser Platzhalter mit
dem Inhalt einer statischen Datei, welche auf dem Server liegt, gef&amp;#252;llt werden.
&lt;/p&gt;
&lt;p&gt;
Der zugeh&amp;#246;rige HTML Code der ASPX Seite sieht wie folgt aus:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;form&lt;/span&gt; &lt;span style="color: red"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;form1&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;runat&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;server&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Hier
klicken zum Request einer
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
statischen Datei &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;p&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt; &lt;span style="color: red"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;content&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
Bitte klicken Sie den Link, damit dieser Bereich gef&amp;#252;llt wird.
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;div&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;form&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Der Link, welcher sp&amp;#228;ter die Ajax Aktion initiieren soll, wird in den Zeilen
5 und 6 definiert. Der Bereich welcher sp&amp;#228;ter ersetzt werden soll, ist der Inhalt
des DIV Tags aus Zeile 9.
&lt;/p&gt;
&lt;p&gt;
Noch ist das ganze jedoch nicht sonderlich dynamisch. Dazu ben&amp;#246;tigen wir noch
etwas JavaScript:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;script&lt;/span&gt; &lt;span style="color: red"&gt;type&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;var&lt;/span&gt; xmlHttp;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
window.onload = &lt;span style="color: blue"&gt;function&lt;/span&gt;() {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
initializeXmlHttp();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;function&lt;/span&gt; initializeXmlHttp()
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (window.XMLHttpRequest)
{ &lt;span style="color: green"&gt;// IE7, IE8, Mozilla, Safari, Opera&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp = &lt;span style="color: blue"&gt;new&lt;/span&gt; XMLHttpRequest();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
} &lt;span style="color: blue"&gt;else&lt;/span&gt; &lt;span style="color: blue"&gt;if&lt;/span&gt; (window.ActiveXObject)
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;try&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp = &lt;span style="color: blue"&gt;new&lt;/span&gt; ActiveXObject(&lt;span style="color: #a31515"&gt;&amp;quot;Microsoft.XMLHTTP&amp;quot;&lt;/span&gt;); &lt;span style="color: green"&gt;//IE
5.x, 6&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;catch&lt;/span&gt; (e)
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
alert(&lt;span style="color: #a31515"&gt;'Ajax Zugriffe sind aufgrund der aktuellen Sicherheitseinstellungen
leider nicht m&amp;#246;glich'&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;function&lt;/span&gt; sendAjaxRequest(url)
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (xmlHttp)
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp.open(&lt;span style="color: #a31515"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;, url, &lt;span style="color: blue"&gt;true&lt;/span&gt;); 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 23&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp.onreadystatechange = requestFinished;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 24&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp.send(&lt;span style="color: blue"&gt;null&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 25&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 26&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 27&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 28&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;function&lt;/span&gt; requestFinished()
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;29&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (xmlHttp.readyState==4)
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;30&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (xmlHttp.status==200)
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 31&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;var&lt;/span&gt; contentDiv
= document.getElementById(&lt;span style="color: #a31515"&gt;'content'&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 32&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
contentDiv.innerHTML = xmlHttp.responseText;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 33&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 34&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 35&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 36&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;script&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Das Script deklariert zun&amp;#228;chst in &lt;strong&gt;Zeile 2&lt;/strong&gt; eine Variable, die
einen Verweis auf das &lt;em&gt;XMLHhtpRequest&lt;/em&gt; Objekt h&amp;#228;lt. Wie zuvor beschrieben
erm&amp;#246;glicht dieses das Absetzen einer asynchronen Abfrage an den Server.
&lt;/p&gt;
&lt;p&gt;
Die Funktion &lt;em&gt;initializeXmlHttp&lt;/em&gt; ab &lt;strong&gt;Zeile 7&lt;/strong&gt; f&amp;#252;llt dieses
Objekt nun mit Leben. Der Code sollte recht selbsterkl&amp;#228;rend sein. Zeile 8 pr&amp;#252;ft,
ob das XMLHttpRequest Objekt am window Objekt h&amp;#228;ngt. Falls ja, kann ein neues
XMLHttpRequest Objekt erstellt werden. Ist dies nicht der Fall, muss es als ActiveX
Objekt erstellt werden.
&lt;/p&gt;
&lt;p&gt;
Die Funktion &lt;em&gt;sendAjaxRequest&lt;/em&gt; ab &lt;strong&gt;Zeile 20&lt;/strong&gt; setzt die eigentliche
Abfrage ab. Dazu pr&amp;#252;ft Sie in Zeile 21 zuerst, ob die Variable xmlHttp initialisiert
werden konnte. W&amp;#228;re dies nicht der Fall, k&amp;#246;nnte keine Abfrage abgesandt
werden. Anschlie&amp;#223;end wird in &lt;strong&gt;Zeile 22&lt;/strong&gt; eine asynchrone Verbindung
ge&amp;#246;ffnet mit der Methode &lt;em&gt;open &lt;/em&gt;ge&amp;#246;ffnet. Diese Methode erh&amp;#228;lt
als Parameter die Methode (&amp;quot;GET&amp;quot; oder &amp;quot;POST&amp;quot;), die URL, sowie
ein Flag, ob die Anfrage asynchron abgesetzt werden soll.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Zeile 23&lt;/strong&gt; gibt eine CallBack-Funktion an (in unserem Fall requestFinished),
die aufgerufen werden soll, sobald eine Antwort auf die Anfrage zur&amp;#252;ck gekommen
ist.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Zeile 24&lt;/strong&gt; sendet die Anfrage nun schlie&amp;#223;lich ab.
&lt;/p&gt;
&lt;p&gt;
Die Funktion &lt;em&gt;requestFinished&lt;/em&gt; ab &lt;strong&gt;Zeile 28&lt;/strong&gt; verarbeitet die
Antwort des Webservers. Da eine Anfrage verschiedene Phasen durchlebt, pr&amp;#252;ft
die Funktion in &lt;strong&gt;Zeile 29&lt;/strong&gt; anhand der Eigenschaft &lt;em&gt;readyState&lt;/em&gt; ab,
ob die Anfrage tats&amp;#228;chlich komplett beendet wurde.
&lt;/p&gt;
&lt;p&gt;
Da zu Ende nicht immer &amp;quot;hat auch geklappt&amp;quot; hei&amp;#223;en muss, wird in der
n&amp;#228;chsten Zeile gepr&amp;#252;ft, ob die Anfrage auch erfolgreich beendet wurde (HTTP
Statuscode 200).
&lt;/p&gt;
&lt;p&gt;
Die eigentliche Verarbeitung findet nun in den &lt;strong&gt;Zeilen 31 und 32&lt;/strong&gt; statt. &lt;strong&gt;Zeile
31&lt;/strong&gt; holt sich eine Referenz auf den zu ersetzenden Bereich (unser Div mit
der ID Content). &lt;strong&gt;Zeile 32&lt;/strong&gt; &amp;#252;berschreibt diesen Inhalt schlussendlich
mit der Antwort des Servers.
&lt;/p&gt;
&lt;p&gt;
Damit das ganze auch funktioniert muss die Funktion &lt;em&gt;sendAjaxRequest&lt;/em&gt; aus &lt;strong&gt;Zeile
20&lt;/strong&gt; noch aus unserem HTML Code heraus aufgerufen werden. Dazu erweitern wir
unseren Link aus den &lt;strong&gt;Zeilen 5/6&lt;/strong&gt; einfach um das Attribut &lt;em&gt;onclick&lt;/em&gt;. 
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;onclick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;sendAjaxRequest('static.html');&amp;quot;&amp;gt;&lt;/span&gt;Hier 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
klicken zum Request einer statischen Datei &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Ausgef&amp;#252;hrt sieht das ganze dann wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/1_erster_Start.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="117" alt="Erster Aufruf der Seite" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/1_erster_Start_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; &lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/2_aufruf_statisch.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="106" alt="Nach Aufruf des Links" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/2_aufruf_statisch_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;Ganz nett ...
&lt;/h4&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;wir wissen nun also, wie wir statische Dateien nachladen k&amp;#246;nnen, aber steht
das &lt;strong&gt;X&lt;/strong&gt; in AJA&lt;strong&gt;X&lt;/strong&gt; nicht f&amp;#252;r XML Webservices?&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Genau! Deshalb habe ich das Demoprojekt auch um einen kleinen Webservice mit zwei
sinnlosen Methoden erweitert:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AjaxDemoService&lt;/span&gt; :
System.Web.Services.&lt;span style="color: #2b91af"&gt;WebService&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [&lt;span style="color: #2b91af"&gt;WebMethod&lt;/span&gt;]
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; HelloWorld()
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: #a31515"&gt;&amp;quot;Hello
World&amp;quot;&lt;/span&gt;;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [&lt;span style="color: #2b91af"&gt;WebMethod&lt;/span&gt;]
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; Echo(&lt;span style="color: blue"&gt;int&lt;/span&gt; number)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Sie
haben {0} eingegeben.&amp;quot;&lt;/span&gt;, number);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&amp;#160;&amp;#160; 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Wie rufen wir einen solchen Service nun aber per JavaScript auf?
&lt;/p&gt;
&lt;p&gt;
Die Antwort findet sich relativ schnell, wenn man die URL des Webservices im Browser
eingibt. In der nun erscheinenden Seite werden s&amp;#228;mtliche Methoden des Webservices
aufgelistet. Ein Klick auf eine dieser Methoden verr&amp;#228;t schlussendlich, wie die
Methode aufgerufen werden muss. Im Beispiel der Methode HelloWorld sieht die Ausgabe
f&amp;#252;r eine HTTP Post Anfrage zum Beispiel wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/3_hello_world_http_post.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="128" alt="Beschreibung des POST Aufrufs der Webservice Methode" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/3_hello_world_http_post_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
F&amp;#252;r die Methode Echo wird folgende Ausgabe produziert:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/4_echo_http_post.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="156" alt="4_echo_http_post" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/4_echo_http_post_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Im Vergleich zu unserer bisherigen Vorgehensweise beim dynamischen Nachladen der statischen
Datei f&amp;#228;llt auf, dass die Methode, &amp;#252;ber die die Anfrage gestartet wird,
nun nicht mehr &lt;strong&gt;GET&lt;/strong&gt; ein kann, sondern &lt;strong&gt;POST&lt;/strong&gt; sein muss.
&lt;/p&gt;
&lt;p&gt;
Au&amp;#223;erdem wird nun auch ein bestimmter Content-Type, n&amp;#228;mlich &lt;em&gt;application/x-www-form-urlencoded&lt;/em&gt; ben&amp;#246;tigt.
Speziell bei der Methode Echo f&amp;#228;llt auf, dass au&amp;#223;erdem nun auch Daten mit
an den Server gesendet werden m&amp;#252;ssen.
&lt;/p&gt;
&lt;p&gt;
Um die ver&amp;#228;nderten Anforderungen abdecken zu k&amp;#246;nnen, erweitere ich das bestehende
JavaScript um eine neue Funktion:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;function&lt;/span&gt; postAjaxRequest(url,
data) {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (xmlHttp)
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp.open(&lt;span style="color: #a31515"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;, url, &lt;span style="color: blue"&gt;true&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp.onreadystatechange = requestFinished;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp.setRequestHeader(&lt;span style="color: #a31515"&gt;'Content-type'&lt;/span&gt;, &lt;span style="color: #a31515"&gt;'application/x-www-form-urlencoded'&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
xmlHttp.send(data);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Die neuen Funktion, &lt;em&gt;postAjaxRequest&lt;/em&gt; &amp;#228;hnelt der vorherigen Funktion &lt;em&gt;sendAjaxRequest&lt;/em&gt;.
Die ver&amp;#228;nderten Anforderungen lie&amp;#223;en sich relativ einfach integrieren. In &lt;strong&gt;Zeile
3&lt;/strong&gt; wurde aus einem &lt;em&gt;GET&lt;/em&gt; ein &lt;em&gt;POST&lt;/em&gt;. In &lt;strong&gt;Zeile 5&lt;/strong&gt; wird
der zus&amp;#228;tzlich ben&amp;#246;tigte Content-Type gesetzt. In &lt;strong&gt;Zeile 6&lt;/strong&gt; wird
der Methode &lt;em&gt;send&lt;/em&gt; nun nicht mehr fix &lt;em&gt;null&lt;/em&gt; als Datenparameter &amp;#252;bergeben.
Stattdessen wird das neue Argument &lt;em&gt;data&lt;/em&gt; weiter gereicht.
&lt;/p&gt;
&lt;p&gt;
Der HTML Code musste auch nur unwesentlich erweitert werden. Er erh&amp;#228;lt zwei neue
Links zum Aufruf der beiden Webmethoden:
&lt;/p&gt;
&lt;div style="border-right: 1px solid; border-top: 1px solid; font-size: 10pt; background: white; border-left: 1px solid; color: black; border-bottom: 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;onclick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;postAjaxRequest('AjaxDemoService.asmx/HelloWorld',
null);&amp;quot;&amp;gt;&lt;/span&gt;Hier
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
f&amp;#252;r Hello World WebService klicken &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;br&lt;/span&gt; &lt;span style="color: blue"&gt;/&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt; &lt;span style="color: red"&gt;href&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span style="color: red"&gt;onclick&lt;/span&gt;&lt;span style="color: blue"&gt;=&amp;quot;postAjaxRequest('AjaxDemoService.asmx/Echo',
'number=1');&amp;quot;&amp;gt;&lt;/span&gt;Hier
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
f&amp;#252;r Echo WebService klicken &lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;a&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Das Ergebnis sieht anschlie&amp;#223;end wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/5_hello_world.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="115" alt="Abbildung zeigt den R&amp;#252;ckgabewert des Hello World Webservices" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/5_hello_world_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;a href="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/6_echo.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="156" alt="Abbildung zeigt die R&amp;#252;ckgabe des Echo Web Services" src="http://blog.codemurai.de/images/ASP.NETWebformsAnwendungenundAjaxTeil1_7DDD/6_echo_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;h4&gt;Fazit
&lt;/h4&gt;
&lt;p&gt;
Ajax in eine Webanwendung zu integrieren ist aus technischer Sicht nicht sonderlich
schwierig. Der vorliegende Blog Post hat gezeigt, dass sich selbst ohne &amp;quot;&lt;em&gt;magische&lt;/em&gt;&amp;quot;
Frameworks mit wenigen Zeilen JavaScript Ajax Funktionalit&amp;#228;ten integrieren lassen.
Nat&amp;#252;rlich ist die gezeigte Implementierung nur sehr rudiment&amp;#228;r. So wurde
das zur&amp;#252;ckgegeben XML des Webservices zum Beispiel noch nicht geparsed und es
fand au&amp;#223;erdem so gut wie keine Fehlerbehandlung statt. Dieses in das Beispiel
zu integrieren h&amp;#228;tte den Rahmen eines Blogposts jedoch vollst&amp;#228;ndig gesprengt.
Au&amp;#223;erdem gibt es genau aus diesen Gr&amp;#252;nden auch bereits fertige Frameworks,
wie ASP.NET AJAX oder jQuery, die einem genau diese Detailarbeit abnehmen.
&lt;/p&gt;
&lt;p&gt;
Ehe man ein solches Framework einsetzt, sollte man jedoch die Grundlagen dessen kennen,
was hinter den Kulissen geschieht. Und genau diese Grundlagen haben wir in diesem
Blog Post geschaffen.
&lt;/p&gt;
&lt;p&gt;
Das vollst&amp;#228;ndige Beispiel werde ich &amp;#252;brigens am Wochenende zum Download
bereit stellen.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=c1d68af1-23ac-4bf3-8053-c388408472b3" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,c1d68af1-23ac-4bf3-8053-c388408472b3.aspx</comments>
      <category>.NET</category>
      <category>Ajax</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=a799cf40-3e18-4f1b-91d1-ab4b45dbe5df</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,a799cf40-3e18-4f1b-91d1-ab4b45dbe5df.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,a799cf40-3e18-4f1b-91d1-ab4b45dbe5df.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=a799cf40-3e18-4f1b-91d1-ab4b45dbe5df</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
vielen Missverständnissen. Eines dieser Missverständnisse ist die häufig
anzutreffende Meinung, dass der ASP.NET ViewState für DropDownList Controls nicht
abgeschaltet werden darf. Andernfalls würde die DropDownList den vom Anwender
gewählten Wert beim Postback "verlieren".
</p>
        <h3>Ein kleines Beispiel
</h3>
        <p>
Sehen wir uns zur Verdeutlichung ein kleines Beispiel an. Ein Entwickler - nennen
wir ihn Herrn Brause -  hat die Aufgabe eine Webseite zu schreiben, auf der ein
Anwender in einer DropDownListe auswählen kann, wie viele Zeilen Quellcode er
heute schreiben kann. Nach der Bestätigung der Auswahl soll der entsprechende
Wert auf der Webseite angezeigt werden.
</p>
        <p>
Herr Brause macht sich schnell ans Werk und erstellt folgende Seite:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/ViewStateWebForm.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="199" alt="Screenshot der erstellen Webseite, bestehend aus Text und DropDownList" src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/ViewStateWebForm_thumb.png" width="244" border="0" />
          </a> 
</p>
        <p>
Die DropDownListe füllt er mit folgendem Code.
</p>
        <div style="border-right: #333333 1px solid; border-top: #333333 1px solid; font-size: 10pt; background: white; border-left: #333333 1px solid; color: black; border-bottom: #333333 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">using</span> System;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> <span style="color: blue">using</span> System.Web.UI.WebControls;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span> <span style="color: blue">public</span><span style="color: blue">partial</span><span style="color: blue">class</span> _Default
: System.Web.UI.Page
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>     <span style="color: blue">protected</span><span style="color: blue">void</span> Page_Load(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>         <span style="color: blue">if</span> (!IsPostBack)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>        
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>            
linesOfCodeDropDown.DataSource = GetLinesOfCodeListItems();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>            
linesOfCodeDropDown.DataBind();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   14</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   15</span>     <span style="color: blue">static</span> ListItemCollection
GetLinesOfCodeListItems()
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   16</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   17</span>        
var items = <span style="color: blue">new</span> ListItemCollection();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   18</span>         <span style="color: blue">for</span> (<span style="color: blue">int</span> i
= 0; i &lt; 1000; i++)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   19</span>        
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   20</span>            
items.Add(<span style="color: blue">new</span> ListItem(<span style="color: blue">string</span>.Format(<span style="color: #a31515">"{0}
Codezeilen"</span>, i), i.ToString()));
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   21</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   22</span>         <span style="color: blue">return</span> items;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   23</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   24</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   25</span>     <span style="color: blue">protected</span><span style="color: blue">void</span> sendButton_Click(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   26</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   27</span>        
linesOfCodeLiteral.Text = linesOfCodeDropDown.SelectedItem.Text;
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   28</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   29</span> }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   30</span> 
</p>
        </div>
        <p>
Ein erster kleiner Test auf Herrn Brauses Rechner ergibt, dass die Webseite zufriedenstellend
läuft. Stolz übergibt er sein Arbeitsergebnis an seinen Chef.
</p>
        <h3>Nicht so schnell!
</h3>
        <p>
Kurz nach der Veröffentlichung der Seite mehren sich die Beschwerden von Anwendern,
die an Standorten mit schlechten Internetverbindungen arbeiten. Sie klagen über
extrem lange Ladezeiten.
</p>
        <p>
Herr Brause nimmt sich dem Problem an und findet schnell heraus, dass sich mehr als
ein Drittel der übertragenen Daten aus dem ViewState der Seite zusammen setzt.
Von den insgesamt knapp 107 kB der Seite verteilen sich 40 kB auf den ViewState.
</p>
        <p>
          <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="28" alt="Bild der Seiten- und Viewstategröße." src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/vorher_yslow_viewstate.png" width="221" border="0" />
        </p>
        <p>
Diese 40 kB werden übrigens nicht nur zum Client heruntergeladen, sondern bei
jedem PostBack auch wieder zurück zum Server geschickt. Sie belasten die Seite
also doppelt!
</p>
        <h3>Was war noch mal der ViewState?
</h3>
        <p>
Ehe wir den ViewState gleich eliminieren werden, möchte ich zuvor schnell erklären,
was genau wir überhaupt versuchen los zu werden.
</p>
        <p>
Der ViewState speichert Werte von ASP.NET Controls anhand ihres Namens. Er ist vergleichbar
mit einer Hashtable. Diese Name/Wert Paare serialisiert er in ein verstecktes Formularfeld
mit dem Namen __VIEWSTATE. Nach einem Postback wird das __VIEWSTATE Feld deserialisiert
und der Viewstate somit wieder hergestellt.
</p>
        <p>
In unserem Beispiel sieht das __VIEWSTATE Feld so aus:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/viewstate.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="153" alt="Bild des Seitenquelltexts mit Viewstate." src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/viewstate_thumb.png" width="244" border="0" />
          </a> 
</p>
        <p>
Der tatsächliche Viewstate der Seite ist um einiges größer! Die Abbildung
zeigt nur einen Ausschnitt.
</p>
        <p>
Der ViewState dient übrigens als Datenspeicher für die meisten Controleigenschaften.
Die Eigenschaft "DataSource" der DropDownList könnte daher zum Beispiel
wie folgt implementiert sein:
</p>
        <div style="border-right: #333333 1px solid; border-top: #333333 1px solid; font-size: 10pt; background: white; border-left: #333333 1px solid; color: black; border-bottom: #333333 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">public</span><span style="color: #2b91af">IEnumerable</span> DataSource
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     <span style="color: blue">get</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>         <span style="color: blue">return</span> ViewState[<span style="color: #a31515">"DataSource"</span>] <span style="color: blue">as</span><span style="color: #2b91af">IEnumerable</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>     <span style="color: blue">set</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>     { 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>        
ViewState[<span style="color: #a31515">"DataSource"</span>] = <span style="color: blue">value</span>; 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>     }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span> }
</p>
        </div>
        <h3> 
</h3>
        <h3>Also weg damit!
</h3>
        <p>
Um die übertragene Datenmenge seiner Seite zu reduzieren, schaltet Herr Brause
also den ViewState der DropDownList ab. Da die DataSource der Liste nach einem PostBack
nun nicht mehr automatisch gefüllt wird, entfernt er außerdem die Prüfung
auf einen PostBack ehe er die DataSource der Liste füllt:
</p>
        <div style="border-right: #333333 1px solid; border-top: #333333 1px solid; font-size: 10pt; background: white; border-left: #333333 1px solid; color: black; border-bottom: #333333 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">protected</span><span style="color: blue">void</span> Page_Load(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     linesOfCodeDropDown.DataSource
= GetLinesOfCodeListItems();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     linesOfCodeDropDown.DataBind();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span> }
</p>
        </div>
        <p>
Die anschließende Prüfung ergibt, dass der ViewState nun nur noch 0,05 kB
beträgt und die komplette Seite nun über 40 kB kleiner geworden ist.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/nachher_yslow_viewstate.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="28" alt="Der ViewState beträgt nun nur noch 0.05 kB" src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/nachher_yslow_viewstate_thumb.png" width="208" border="0" />
          </a>
        </p>
        <p>
Leider ergibt der zweite Test, dass die Seite nun nicht mehr funktioniert. Egal was
der Anwender auswählt, die Seite gibt immer "0 Codezeilen" aus. Dies
liegt daran, dass der "SelectedIndex" der Liste innerhalb des Button Click
Events immer 0 ist.
</p>
        <p>
Im folgenden Screenshot wurde zum Beispiel "5 Codezeilen" ausgewählt
und anschließend auf Absenden geklickt.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/WebFormOhneViewState.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="57" alt="Obwohl der Anwender den Wert 5 auswählte, wird nur eine 0 dargestellt." src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/WebFormOhneViewState_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Ist der ViewState also dafür zuständig, die Auswahl des Anwenders in das
Servercontrol zu schreiben?
</p>
        <p>
          <strong>Nein!</strong>
        </p>
        <p>
Auch wenn diese Vermutung zunächst nahe liegt, ist sie vollkommen falsch. Um
das Rätsel zu lösen, muss man sich kurz den <a title="Verweis auf die Dokumentation des ASP.NET Page Life Cycle in der MSDN" href="http://msdn.microsoft.com/en-us/library/ms178472.aspx" target="_blank">ASP.NET
Page Life Cycle</a> vor Augen halten.
</p>
        <p>
Dieser teilt sich in folgende Phasen auf:
</p>
        <ol>
          <li>
Page Request 
</li>
          <li>
Start 
</li>
          <li>
            <strong>Page Initialization </strong>
          </li>
          <li>
            <strong>Load</strong>
          </li>
          <li>
Validation 
</li>
          <li>
Postback event handling 
</li>
          <li>
Rendering 
</li>
          <li>
Unload 
</li>
        </ol>
        <p>
Interessant für unsere Situation sind die Phasen <strong>PageInitialization</strong> und <strong>Load</strong>.
</p>
        <p>
In der Phase <strong>PageInitialization</strong> werden die folgenden Methoden durchlaufen:
</p>
        <h5>OnInit
</h5>
        <p>
Alle Controls der Seite sind bereits erstellt worden. Deklarativ in der ASPX Seite
festgelegte Werte wurden zugewiesen. <strong>ViewState</strong> und durch den Anwender <strong>gepostete
Werte</strong><strong>wurden noch nicht</strong> in die Controleigenschaften geschrieben
</p>
        <h5>OnInitComplete
</h5>
        <p>
Wird aufgerufen, nachdem das die Methode OnInit durchgelaufen ist.
</p>
        <h5>OnPreLoad
</h5>
        <p>
Wird aufgerufen, ehe die Phase <strong>Load</strong> begonnen wird.
</p>
        <p>
In der Phase <strong>Load</strong> werden<strong> unter anderem</strong> die folgenden
Methoden durchlaufen
</p>
        <h5>LoadViewState
</h5>
        <p>
In dieser Methode wird der <strong>ViewState</strong> zurück in die Seite und
die Controls geschrieben. In unserem ursprünglichen Beispiel würde hier
also die DataSource Eigenschaft der DropDownList gefüllt werden.
</p>
        <h5>ProcessPostData
</h5>
        <p>
Diese Methode schreibt die durch den <strong>Benutzer geposteten</strong> Werte in
die Controls. In unserem Beispiel wird hier also der selektierte Wert der DropDownList
gesetzt.
</p>
        <h5>PageLoad
</h5>
        <p>
Wenn diese Methode ausgeführt wird, ist die Seite vollständig initialisiert.
In unserem Ursprünglichen Beispiel haben wir hier die DataSource der DropDownList
gesetzt.
</p>
        <p>
Die Events der einzelnen Controls, also zum Beispiel das Event Click unseres Buttons
werden übrigens in einer späteren Phase, nämlich der Phase <strong>PostBack
Event Handling</strong> ausgelöst.
</p>
        <h3>
        </h3>
        <h3>Interessant, aber was hat es mit unserem Problem zu tun?
</h3>
        <p>
Auch wenn der kleine Exkurs in Richtung Page Life Cycle sicherlich (vielleicht ;-))
sehr interessant war, stellt sich die Frage, wo der Zusammenhang zu unserem Problem
der fehlenden geposteten Daten besteht.
</p>
        <p>
Nun, dies ist eigentlich ganz einfach. Ursprünglich lief unsere Seite wie folgt:
</p>
        <p>
          <strong>Erster Request:</strong>
        </p>
        <p>
Setzen der DataSource Eigenschaft in der Methode <strong>Page_Load</strong>.
</p>
        <p>
          <strong>PostBack</strong>
        </p>
        <p>
Automatisches Wiederherstellen der DataSource Eigenschaft in der Methode <strong>LoadViewState</strong>,
anschließend automatisches Zuweisen des durch den Anwender ausgewählten
Werts in <strong>ProcessPostData</strong>.
</p>
        <p>
Durch unsere Änderungen, nämlich das Deaktivieren des ViewStates und der
Entfernung der Prüfung auf einen PostBack in Page_Load haben wir nun folgendes
Bewirkt:
</p>
        <p>
          <strong>Erster Request:</strong>
        </p>
        <p>
Setzen der <strong>DataSource</strong> Eigenschaft in der Methode <strong>Page_Load</strong>.
</p>
        <p>
          <strong>PostBack</strong>
        </p>
        <p>
Automatisches Zuweisen des durch den Anwender ausgewählten Werts in <strong>ProcessPostData</strong>.
Da die DropDownListe jedoch noch keine DataSource hat, kann dies hier noch nicht funktionieren.
Die DataSource wird erst anschließend in Page_Load gesetzt.
</p>
        <h3>Und das bedeutet?
</h3>
        <p>
Das bedeutet, dass die "fehlenden" geposteten Werte eigentlich gar nichts
mit dem deaktivierten ViewState zu tun hatten. Die Ursache ist einfach die Tatsache,
dass wir die DataSource setzen, <strong>nachdem</strong> die Daten des Anwenders in
das Control geschrieben wurden.
</p>
        <h4>Und die Lösung?
</h4>
        <p>
Die Lösung ist recht einfach. Der Code, der die DataSource der DropDownList setzt
muss einfach ausgeführt werden, ehe <strong>ProcessPostData</strong> durchlaufen
wird. Typischerweise nimmt man dazu die Methode <strong>OnInit</strong>.
</p>
        <div style="border-right: #333333 1px solid; border-top: #333333 1px solid; font-size: 10pt; background: white; border-left: #333333 1px solid; color: black; border-bottom: #333333 1px solid; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span> <span style="color: blue">protected</span><span style="color: blue">override</span><span style="color: blue">void</span> OnInit(EventArgs
e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>     linesOfCodeDropDown.DataSource
= GetLinesOfCodeListItems();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>     linesOfCodeDropDown.DataBind();
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span> }
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span> <span style="color: blue">protected</span><span style="color: blue">void</span> Page_Load(<span style="color: blue">object</span> sender,
EventArgs e)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span> {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span> }
</p>
        </div>
        <h4>Fazit
</h4>
        <p>
Der ViewState einer DropDownList darf sehr wohl deaktiviert werden. Um das Problem
der "fehlenden" geposteten Werte in den Griff zu bekommen, muss lediglich
die Zuweisung der DataSource an einen früheren Zeitpunkt innerhalb des Page Life
Cycle verschoben werden.
</p>
        <p>
Wer mehr zu dem Thema wissen möchte, sollte sich übrigens in jedem Fall
Dave Reeds Artikel <a title="Die wohl beste Erklärung zum ViewState, die im Web zu finden ist" href="http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx" target="_blank">Truly
Understanding ViewState</a> durchlesen. Eine umfangreichere und vor allem bessere
Behandlung des Themas habe ich bisher an keiner anderen Stelle im Web gefunden.
</p>
        <p>
Wer mehr über den ASP.NET Page Life Cycle wissen möchte, dem kann ich den
Artikel <a title="Sehr detaillierte Beschreibung des ASP.NET Page Life Cycle" href="http://www.visual-eye.de/visualeye/index.php?option=com_content&amp;view=article&amp;id=55:asp-page-lifecycle&amp;catid=49:aspnet&amp;Itemid=64Externer" target="_blank">Der
Lebenszyklus einer ASP.NET 2.0 Seite</a> empfehlen.
</p>
        <p>
Tja und wer gar nichts mehr mit ViewState oder Page Life Cycle zu tun haben möchte,
der sollte zum <a href="http://www.asp.net/mvc" target="_blank">ASP.NET MVC Framework</a> greifen;-)
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=a799cf40-3e18-4f1b-91d1-ab4b45dbe5df" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Die Geschichte des ViewStates ist eine Geschichte mit ...</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,a799cf40-3e18-4f1b-91d1-ab4b45dbe5df.aspx</guid>
      <link>http://blog.codemurai.de/2010/01/22/DieGeschichteDesViewStatesIstEineGeschichteMit.aspx</link>
      <pubDate>Fri, 22 Jan 2010 08:43:51 GMT</pubDate>
      <description>&lt;p&gt;
vielen Missverst&amp;#228;ndnissen. Eines dieser Missverst&amp;#228;ndnisse ist die h&amp;#228;ufig
anzutreffende Meinung, dass der ASP.NET ViewState f&amp;#252;r DropDownList Controls nicht
abgeschaltet werden darf. Andernfalls w&amp;#252;rde die DropDownList den vom Anwender
gew&amp;#228;hlten Wert beim Postback &amp;quot;verlieren&amp;quot;.
&lt;/p&gt;
&lt;h3&gt;Ein kleines Beispiel
&lt;/h3&gt;
&lt;p&gt;
Sehen wir uns zur Verdeutlichung ein kleines Beispiel an. Ein Entwickler - nennen
wir ihn Herrn Brause -&amp;#160; hat die Aufgabe eine Webseite zu schreiben, auf der ein
Anwender in einer DropDownListe ausw&amp;#228;hlen kann, wie viele Zeilen Quellcode er
heute schreiben kann. Nach der Best&amp;#228;tigung der Auswahl soll der entsprechende
Wert auf der Webseite angezeigt werden.
&lt;/p&gt;
&lt;p&gt;
Herr Brause macht sich schnell ans Werk und erstellt folgende Seite:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/ViewStateWebForm.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="199" alt="Screenshot der erstellen Webseite, bestehend aus Text und DropDownList" src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/ViewStateWebForm_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;&amp;#160;
&lt;/p&gt;
&lt;p&gt;
Die DropDownListe f&amp;#252;llt er mit folgendem Code.
&lt;/p&gt;
&lt;div style="border-right: #333333 1px solid; border-top: #333333 1px solid; font-size: 10pt; background: white; border-left: #333333 1px solid; color: black; border-bottom: #333333 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;using&lt;/span&gt; System;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;using&lt;/span&gt; System.Web.UI.WebControls;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;partial&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; _Default
: System.Web.UI.Page
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (!IsPostBack)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
linesOfCodeDropDown.DataSource = GetLinesOfCodeListItems();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
linesOfCodeDropDown.DataBind();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;static&lt;/span&gt; ListItemCollection
GetLinesOfCodeListItems()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
var items = &lt;span style="color: blue"&gt;new&lt;/span&gt; ListItemCollection();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;for&lt;/span&gt; (&lt;span style="color: blue"&gt;int&lt;/span&gt; i
= 0; i &amp;lt; 1000; i++)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
items.Add(&lt;span style="color: blue"&gt;new&lt;/span&gt; ListItem(&lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;{0}
Codezeilen&amp;quot;&lt;/span&gt;, i), i.ToString()));
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;return&lt;/span&gt; items;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 23&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 24&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 25&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; sendButton_Click(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 26&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 27&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
linesOfCodeLiteral.Text = linesOfCodeDropDown.SelectedItem.Text;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 28&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 29&lt;/span&gt; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 30&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Ein erster kleiner Test auf Herrn Brauses Rechner ergibt, dass die Webseite zufriedenstellend
l&amp;#228;uft. Stolz &amp;#252;bergibt er sein Arbeitsergebnis an seinen Chef.
&lt;/p&gt;
&lt;h3&gt;Nicht so schnell!
&lt;/h3&gt;
&lt;p&gt;
Kurz nach der Ver&amp;#246;ffentlichung der Seite mehren sich die Beschwerden von Anwendern,
die an Standorten mit schlechten Internetverbindungen arbeiten. Sie klagen &amp;#252;ber
extrem lange Ladezeiten.
&lt;/p&gt;
&lt;p&gt;
Herr Brause nimmt sich dem Problem an und findet schnell heraus, dass sich mehr als
ein Drittel der &amp;#252;bertragenen Daten aus dem ViewState der Seite zusammen setzt.
Von den insgesamt knapp 107 kB der Seite verteilen sich 40 kB auf den ViewState.
&lt;/p&gt;
&lt;p&gt;
&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="28" alt="Bild der Seiten- und Viewstategr&amp;#246;&amp;#223;e." src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/vorher_yslow_viewstate.png" width="221" border="0" /&gt; 
&lt;/p&gt;
&lt;p&gt;
Diese 40 kB werden &amp;#252;brigens nicht nur zum Client heruntergeladen, sondern bei
jedem PostBack auch wieder zur&amp;#252;ck zum Server geschickt. Sie belasten die Seite
also doppelt!
&lt;/p&gt;
&lt;h3&gt;Was war noch mal der ViewState?
&lt;/h3&gt;
&lt;p&gt;
Ehe wir den ViewState gleich eliminieren werden, m&amp;#246;chte ich zuvor schnell erkl&amp;#228;ren,
was genau wir &amp;#252;berhaupt versuchen los zu werden.
&lt;/p&gt;
&lt;p&gt;
Der ViewState speichert Werte von ASP.NET Controls anhand ihres Namens. Er ist vergleichbar
mit einer Hashtable. Diese Name/Wert Paare serialisiert er in ein verstecktes Formularfeld
mit dem Namen __VIEWSTATE. Nach einem Postback wird das __VIEWSTATE Feld deserialisiert
und der Viewstate somit wieder hergestellt.
&lt;/p&gt;
&lt;p&gt;
In unserem Beispiel sieht das __VIEWSTATE Feld so aus:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/viewstate.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="153" alt="Bild des Seitenquelltexts mit Viewstate." src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/viewstate_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;&amp;#160;
&lt;/p&gt;
&lt;p&gt;
Der tats&amp;#228;chliche Viewstate der Seite ist um einiges gr&amp;#246;&amp;#223;er! Die Abbildung
zeigt nur einen Ausschnitt.
&lt;/p&gt;
&lt;p&gt;
Der ViewState dient &amp;#252;brigens als Datenspeicher f&amp;#252;r die meisten Controleigenschaften.
Die Eigenschaft &amp;quot;DataSource&amp;quot; der DropDownList k&amp;#246;nnte daher zum Beispiel
wie folgt implementiert sein:
&lt;/p&gt;
&lt;div style="border-right: #333333 1px solid; border-top: #333333 1px solid; font-size: 10pt; background: white; border-left: #333333 1px solid; color: black; border-bottom: #333333 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt; DataSource
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;get&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;return&lt;/span&gt; ViewState[&lt;span style="color: #a31515"&gt;&amp;quot;DataSource&amp;quot;&lt;/span&gt;] &lt;span style="color: blue"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IEnumerable&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;set&lt;/span&gt; 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
ViewState[&lt;span style="color: #a31515"&gt;&amp;quot;DataSource&amp;quot;&lt;/span&gt;] = &lt;span style="color: blue"&gt;value&lt;/span&gt;; 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;&amp;#160;
&lt;/h3&gt;
&lt;h3&gt;Also weg damit!
&lt;/h3&gt;
&lt;p&gt;
Um die &amp;#252;bertragene Datenmenge seiner Seite zu reduzieren, schaltet Herr Brause
also den ViewState der DropDownList ab. Da die DataSource der Liste nach einem PostBack
nun nicht mehr automatisch gef&amp;#252;llt wird, entfernt er au&amp;#223;erdem die Pr&amp;#252;fung
auf einen PostBack ehe er die DataSource der Liste f&amp;#252;llt:
&lt;/p&gt;
&lt;div style="border-right: #333333 1px solid; border-top: #333333 1px solid; font-size: 10pt; background: white; border-left: #333333 1px solid; color: black; border-bottom: #333333 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; linesOfCodeDropDown.DataSource
= GetLinesOfCodeListItems();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; linesOfCodeDropDown.DataBind();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Die anschlie&amp;#223;ende Pr&amp;#252;fung ergibt, dass der ViewState nun nur noch 0,05 kB
betr&amp;#228;gt und die komplette Seite nun &amp;#252;ber 40 kB kleiner geworden ist.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/nachher_yslow_viewstate.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="28" alt="Der ViewState betr&amp;#228;gt nun nur noch 0.05 kB" src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/nachher_yslow_viewstate_thumb.png" width="208" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Leider ergibt der zweite Test, dass die Seite nun nicht mehr funktioniert. Egal was
der Anwender ausw&amp;#228;hlt, die Seite gibt immer &amp;quot;0 Codezeilen&amp;quot; aus. Dies
liegt daran, dass der &amp;quot;SelectedIndex&amp;quot; der Liste innerhalb des Button Click
Events immer 0 ist.
&lt;/p&gt;
&lt;p&gt;
Im folgenden Screenshot wurde zum Beispiel &amp;quot;5 Codezeilen&amp;quot; ausgew&amp;#228;hlt
und anschlie&amp;#223;end auf Absenden geklickt.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/WebFormOhneViewState.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="57" alt="Obwohl der Anwender den Wert 5 ausw&amp;#228;hlte, wird nur eine 0 dargestellt." src="http://blog.codemurai.de/images/DieGeschichtedesViewStatesisteineGeschi_72D9/WebFormOhneViewState_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Ist der ViewState also daf&amp;#252;r zust&amp;#228;ndig, die Auswahl des Anwenders in das
Servercontrol zu schreiben?
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Nein!&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Auch wenn diese Vermutung zun&amp;#228;chst nahe liegt, ist sie vollkommen falsch. Um
das R&amp;#228;tsel zu l&amp;#246;sen, muss man sich kurz den &lt;a title="Verweis auf die Dokumentation des ASP.NET Page Life Cycle in der MSDN" href="http://msdn.microsoft.com/en-us/library/ms178472.aspx" target="_blank"&gt;ASP.NET
Page Life Cycle&lt;/a&gt; vor Augen halten.
&lt;/p&gt;
&lt;p&gt;
Dieser teilt sich in folgende Phasen auf:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Page Request 
&lt;/li&gt;
&lt;li&gt;
Start 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Page Initialization &lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load&lt;/strong&gt; 
&lt;/li&gt;
&lt;li&gt;
Validation 
&lt;/li&gt;
&lt;li&gt;
Postback event handling 
&lt;/li&gt;
&lt;li&gt;
Rendering 
&lt;/li&gt;
&lt;li&gt;
Unload 
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Interessant f&amp;#252;r unsere Situation sind die Phasen &lt;strong&gt;PageInitialization&lt;/strong&gt; und &lt;strong&gt;Load&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
In der Phase &lt;strong&gt;PageInitialization&lt;/strong&gt; werden die folgenden Methoden durchlaufen:
&lt;/p&gt;
&lt;h5&gt;OnInit
&lt;/h5&gt;
&lt;p&gt;
Alle Controls der Seite sind bereits erstellt worden. Deklarativ in der ASPX Seite
festgelegte Werte wurden zugewiesen. &lt;strong&gt;ViewState&lt;/strong&gt; und durch den Anwender &lt;strong&gt;gepostete
Werte&lt;/strong&gt; &lt;strong&gt;wurden noch nicht&lt;/strong&gt; in die Controleigenschaften geschrieben
&lt;/p&gt;
&lt;h5&gt;OnInitComplete
&lt;/h5&gt;
&lt;p&gt;
Wird aufgerufen, nachdem das die Methode OnInit durchgelaufen ist.
&lt;/p&gt;
&lt;h5&gt;OnPreLoad
&lt;/h5&gt;
&lt;p&gt;
Wird aufgerufen, ehe die Phase &lt;strong&gt;Load&lt;/strong&gt; begonnen wird.
&lt;/p&gt;
&lt;p&gt;
In der Phase &lt;strong&gt;Load&lt;/strong&gt; werden&lt;strong&gt; unter anderem&lt;/strong&gt; die folgenden
Methoden durchlaufen
&lt;/p&gt;
&lt;h5&gt;LoadViewState
&lt;/h5&gt;
&lt;p&gt;
In dieser Methode wird der &lt;strong&gt;ViewState&lt;/strong&gt; zur&amp;#252;ck in die Seite und
die Controls geschrieben. In unserem urspr&amp;#252;nglichen Beispiel w&amp;#252;rde hier
also die DataSource Eigenschaft der DropDownList gef&amp;#252;llt werden.
&lt;/p&gt;
&lt;h5&gt;ProcessPostData
&lt;/h5&gt;
&lt;p&gt;
Diese Methode schreibt die durch den &lt;strong&gt;Benutzer geposteten&lt;/strong&gt; Werte in
die Controls. In unserem Beispiel wird hier also der selektierte Wert der DropDownList
gesetzt.
&lt;/p&gt;
&lt;h5&gt;PageLoad
&lt;/h5&gt;
&lt;p&gt;
Wenn diese Methode ausgef&amp;#252;hrt wird, ist die Seite vollst&amp;#228;ndig initialisiert.
In unserem Urspr&amp;#252;nglichen Beispiel haben wir hier die DataSource der DropDownList
gesetzt.
&lt;/p&gt;
&lt;p&gt;
Die Events der einzelnen Controls, also zum Beispiel das Event Click unseres Buttons
werden &amp;#252;brigens in einer sp&amp;#228;teren Phase, n&amp;#228;mlich der Phase &lt;strong&gt;PostBack
Event Handling&lt;/strong&gt; ausgel&amp;#246;st.
&lt;/p&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;Interessant, aber was hat es mit unserem Problem zu tun?
&lt;/h3&gt;
&lt;p&gt;
Auch wenn der kleine Exkurs in Richtung Page Life Cycle sicherlich (vielleicht ;-))
sehr interessant war, stellt sich die Frage, wo der Zusammenhang zu unserem Problem
der fehlenden geposteten Daten besteht.
&lt;/p&gt;
&lt;p&gt;
Nun, dies ist eigentlich ganz einfach. Urspr&amp;#252;nglich lief unsere Seite wie folgt:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Erster Request:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Setzen der DataSource Eigenschaft in der Methode &lt;strong&gt;Page_Load&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;PostBack&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Automatisches Wiederherstellen der DataSource Eigenschaft in der Methode &lt;strong&gt;LoadViewState&lt;/strong&gt;,
anschlie&amp;#223;end automatisches Zuweisen des durch den Anwender ausgew&amp;#228;hlten
Werts in &lt;strong&gt;ProcessPostData&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
Durch unsere &amp;#196;nderungen, n&amp;#228;mlich das Deaktivieren des ViewStates und der
Entfernung der Pr&amp;#252;fung auf einen PostBack in Page_Load haben wir nun folgendes
Bewirkt:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Erster Request:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Setzen der &lt;strong&gt;DataSource&lt;/strong&gt; Eigenschaft in der Methode &lt;strong&gt;Page_Load&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;PostBack&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Automatisches Zuweisen des durch den Anwender ausgew&amp;#228;hlten Werts in &lt;strong&gt;ProcessPostData&lt;/strong&gt;.
Da die DropDownListe jedoch noch keine DataSource hat, kann dies hier noch nicht funktionieren.
Die DataSource wird erst anschlie&amp;#223;end in Page_Load gesetzt.
&lt;/p&gt;
&lt;h3&gt;Und das bedeutet?
&lt;/h3&gt;
&lt;p&gt;
Das bedeutet, dass die &amp;quot;fehlenden&amp;quot; geposteten Werte eigentlich gar nichts
mit dem deaktivierten ViewState zu tun hatten. Die Ursache ist einfach die Tatsache,
dass wir die DataSource setzen, &lt;strong&gt;nachdem&lt;/strong&gt; die Daten des Anwenders in
das Control geschrieben wurden.
&lt;/p&gt;
&lt;h4&gt;Und die L&amp;#246;sung?
&lt;/h4&gt;
&lt;p&gt;
Die L&amp;#246;sung ist recht einfach. Der Code, der die DataSource der DropDownList setzt
muss einfach ausgef&amp;#252;hrt werden, ehe &lt;strong&gt;ProcessPostData&lt;/strong&gt; durchlaufen
wird. Typischerweise nimmt man dazu die Methode &lt;strong&gt;OnInit&lt;/strong&gt;.
&lt;/p&gt;
&lt;div style="border-right: #333333 1px solid; border-top: #333333 1px solid; font-size: 10pt; background: white; border-left: #333333 1px solid; color: black; border-bottom: #333333 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; OnInit(EventArgs
e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; linesOfCodeDropDown.DataSource
= GetLinesOfCodeListItems();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; linesOfCodeDropDown.DataBind();
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt; }
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Page_Load(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender,
EventArgs e)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt; }
&lt;/p&gt;
&lt;/div&gt;
&lt;h4&gt;Fazit
&lt;/h4&gt;
&lt;p&gt;
Der ViewState einer DropDownList darf sehr wohl deaktiviert werden. Um das Problem
der &amp;quot;fehlenden&amp;quot; geposteten Werte in den Griff zu bekommen, muss lediglich
die Zuweisung der DataSource an einen fr&amp;#252;heren Zeitpunkt innerhalb des Page Life
Cycle verschoben werden.
&lt;/p&gt;
&lt;p&gt;
Wer mehr zu dem Thema wissen m&amp;#246;chte, sollte sich &amp;#252;brigens in jedem Fall
Dave Reeds Artikel &lt;a title="Die wohl beste Erkl&amp;#228;rung zum ViewState, die im Web zu finden ist" href="http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx" target="_blank"&gt;Truly
Understanding ViewState&lt;/a&gt; durchlesen. Eine umfangreichere und vor allem bessere
Behandlung des Themas habe ich bisher an keiner anderen Stelle im Web gefunden.
&lt;/p&gt;
&lt;p&gt;
Wer mehr &amp;#252;ber den ASP.NET Page Life Cycle wissen m&amp;#246;chte, dem kann ich den
Artikel &lt;a title="Sehr detaillierte Beschreibung des ASP.NET Page Life Cycle" href="http://www.visual-eye.de/visualeye/index.php?option=com_content&amp;amp;view=article&amp;amp;id=55:asp-page-lifecycle&amp;amp;catid=49:aspnet&amp;amp;Itemid=64Externer" target="_blank"&gt;Der
Lebenszyklus einer ASP.NET 2.0 Seite&lt;/a&gt; empfehlen.
&lt;/p&gt;
&lt;p&gt;
Tja und wer gar nichts mehr mit ViewState oder Page Life Cycle zu tun haben m&amp;#246;chte,
der sollte zum &lt;a href="http://www.asp.net/mvc" target="_blank"&gt;ASP.NET MVC Framework&lt;/a&gt; greifen;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=a799cf40-3e18-4f1b-91d1-ab4b45dbe5df" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,a799cf40-3e18-4f1b-91d1-ab4b45dbe5df.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=34c0df4d-6b8d-48bc-bb29-c986bdc4c998</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,34c0df4d-6b8d-48bc-bb29-c986bdc4c998.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,34c0df4d-6b8d-48bc-bb29-c986bdc4c998.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=34c0df4d-6b8d-48bc-bb29-c986bdc4c998</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Jeder der in einer ASP.NET Webforms Anwendung ein oder mehrere "Ajax-Enabled"
Controls eines Komponentenherstellers nutzt kennt das Problem: Die Anzahl der zum
Client übertragenen Scripte steigt explosionsartig an.
</p>
        <p>
Dies liegt daran, dass die meisten Komponentenhersteller <strong>je Control ein eigenes
Script</strong> zum Client senden. Generell ist das auch durchaus sinnvoll, denn nur
so kann gewährleistet werden, dass der Browser nur die minimal benötigte
Anzahl an Scriptcode vom Server herunterladen muss.
</p>
        <p>
Wie der folgende Screenshot zeigt, wird dieser Segen jedoch auch schnell zum Fluch.
Die Abbildung zeigt einen Mitschnitt des Netzwerktraffics beim Besuch einer Seite
eines aktuellen Projekts. Inhalt der Seite sind ein Scriptmanager, zwei <a title="Link zur Infragistics NetAdvantage for ASP.Net Produktseite" href="http://www.infragistics.com/dotnet/netadvantage/aspnet.aspx" target="_blank">Infragistics
Controls</a>, einige <a title="Link auf die Esri Web ADF Vorstellung" href="http://resources.esri.com/arcgisserver/adf/dotnet/" target="_blank">ESRI
WebADF Controls</a> sowie ein paar eigene Servercontrols, die auch eigene Scripts
rendern.
</p>
        <h1>
          <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/1_Vorher.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="1_Vorher" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/1_Vorher_thumb.png" width="244" border="0" />
          </a>
        </h1>
        <p>
Die Anzahl zu übertragenden Scripts beträgt laut Screenshot also 37 Stück.
</p>
        <h3>Interessant, aber wo liegt nun das Problem?
</h3>
        <p>
Wir wissen zwar nun, dass wir 37 Scripte zum Client übertragen müssen, aber
was ist daran so schlimm und warum sollte es uns überhaupt interessieren?
</p>
        <p>
Um das Problem an der Situation zu erkennen, sollten wir uns kurz vor Auge führen,
dass die Scripte nicht gemeinsam innerhalb des selben HTTP Requests wie die eigentliche
Website übertragen werden. Stattdessen wird je Script (und auch Bild, CSS Stylesheet,
etc.) eine eigene Anfrage an den Webserver gestellt.
</p>
        <p>
Jede dieser Anfragen hat eine gewisse "Rüstzeit" oder auch Latenz.
Damit ist die Zeitspanne gemeint, die zwischen dem Absetzen des Befehls, eine Anfrage
zu starten und dem tatsächlichen Start der Anfrage vergeht. Je nach Entfernung
zwischen Client und Server sowie der Qualität der Internetanbindung der beiden
variiert der tatsächliche Wert dieser Reaktionszeit.
</p>
        <h3>Und was bedeutet dies nun konkret?
</h3>
        <p>
Schauen wir uns zur Verdeutlichung ein kleines Beispiel an. Gehen wir von jemandem
mit einer extrem schlechten Anbindung und einer Latenz von 500 ms aus (<em>zugegeben,
der Wert ist recht hoch, lässt sich aber schön einfach rechnen</em> ;-))
</p>
        <p>
Um unsere 37 Scriptdateien herunterzuladen, hätten wir nun also
</p>
        <p>
37 Anfragen * 500 ms Latenz + 37 Antworten * 500 ms Latenz = 37 Sekunden.
</p>
        <p>
Diese 37 Sekunden sind reine Wartezeit und kommen zur eigentlichen Übertragungszeit
der Scripte hinzu. Nun ist es natürlich nicht so, dass sämtliche Anfragen
sequentiell abgearbeitet werden. Allerdings sieht die Standardkonfiguration vieler
Browser eine Beschränkung von zwei gleichzeitigen Verbindungen zu einem Hostnamen
vor. Diese Anzahl resultiert aus einer Empfehlung der HTTP 1.1 Spezifikation. Heisst,
wir müssen unsere 37 Sekunden noch durch zwei Teilen, da zwei gleichzeitige Verbindungen
möglich sind. Bleiben immer noch 18,5 Sekunden übrig.
</p>
        <h3>Was können wir dagegen tun?
</h3>
        <p>
Um dieses Problem, was tückischerweise während der Entwicklung nur selten
auffällt, da die Latenz zwischen lokalem Webserver und lokalem Webbrowser nicht
sonderlich hoch sein dürfte ;-), in den Griff zu bekommen, bietet ASP.NET ab
der Version 3.51 das Element <em><a title="Link zur MSDN Dokumentation des CompositeScript Elements" href="http://msdn.microsoft.com/de-de/library/cc488552.aspx" target="_blank">CompositeScript</a></em> als
Kindelement des <em>Scriptmanagers</em> an.
</p>
        <p>
Dieses Element erlaubt es, einzelne Scripts anzugeben, welche anschließend automatisch
zu einem Script zusammengefasst werden.
</p>
        <p>
Das Ganze sieht ungefähr so aus:
</p>
        <p>
&lt;asp:ScriptManager runat="server" ID="sm1"&gt; 
<br />
    &lt;CompositeScript&gt; 
<br />
        &lt;Scripts&gt; 
<br />
            &lt;asp:ScriptReference
Name="/Scripts/MeinScript1.js" /&gt; 
<br />
            &lt;asp:ScriptReference
Name="/Scripts/MeinScript2.js" /&gt; 
<br />
            &lt;asp:ScriptReference
Name="/Scrips/MeinScript3.js" /&gt; 
<br />
        &lt;/Scripts&gt; 
<br />
    &lt;/CompositeScript&gt; 
<br />
&lt;/asp:ScriptManager&gt;
</p>
        <p>
Problematisch ist nur, dass man die URL der notwendigen Scripts nur für Dateibasierte
Scripts kennt. Sobald ein Script aber als eingebettete Ressource über die <em>Webresource.axd</em> nach
aussen gerendert wird, ist die URL unbekannt.
</p>
        <p>
Um dieses Problem zu lösen, kann das auf Codeplex erhältliche Control <a href="http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=13356">ScriptReferenceProfiler</a> genutzt
werden. Wird es auf einer Seite eingesetzt, rendert es eine Liste aller genutzten
Scripte heraus. Diese Liste kann 1:1 kopiert und in das <em>Scripts</em> Element des <em>CompositeScript</em> Elements
eingefügt werden.
</p>
        <h1>
          <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/4_ScriptProfilerOutput.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="181" alt="4_ScriptProfilerOutput" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/4_ScriptProfilerOutput_thumb.png" width="244" border="0" />
          </a>
        </h1>
        <p>
Die eingefügten Scripts werden anschließend serverseitig zu einem großen
Script hinzugefügt und innerhalb einer einzigen Anfrage herunter geladen.
</p>
        <h3>
        </h3>
        <h3>Nicht so schnell!
</h3>
        <p>
Der Versuch, alle 37 Scripte der zuvor genannten Seite in einem <em>CompositeScript</em> Element
zusammen zu führen resultiert in folgendem Fehler:
</p>
        <h1>
          <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/5_ASP_Error.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="209" alt="5_ASP_Error" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/5_ASP_Error_thumb.png" width="244" border="0" />
          </a>
        </h1>
        <p>
Die Ursache für diesen Fehler ist, dass der Scriptmanager jedes benötigte
Script mit einem kryptischen Bezeichner an die URL anhängt. Dies sprengt schnell
die maximale Begrenzung einer URL auf 1024 Zeichen.
</p>
        <h3>Die Lösung
</h3>
        <p>
Um dieses Problem zu umgehen platziert man einfach mehrere <em>CompositeScript</em> Elemente
auf der Seite und verteilt die Scripte auf diese. Da jedes <em>CompositeScript</em> Element
einen eigenen Scriptmanager benötigt, nutzt man ab dem zweiten CompositeScript
Element statt zusätzlichen Scriptmanagern, von denen es immer nur einen pro Seite
geben darf einfach ScriptmanagerProxy Controls.
</p>
        <p>
Die optimale Verteilung der Scripte auf die einzelnen <em>CompositeScript</em> Elemente
ist schnell im Trial-and-Error-Verfahren gefunden. In meinem Beispiel sah sie übrigens
wie folgt aus:
</p>
        <p>
&lt;asp:ScriptManagerProxy ID="ScriptManagerProxyAjax" runat="server"&gt; 
<br />
    &lt;CompositeScript&gt; 
<br />
        &lt;Scripts&gt; 
<br />
            &lt;asp:ScriptReference
Name="MicrosoftAjax.js" /&gt; 
<br />
            &lt;asp:ScriptReference
Name="MicrosoftAjaxWebForms.js" /&gt; 
<br />
            &lt;asp:ScriptReference
Name="AjaxControlToolkit.Common.Common.js" Assembly="AjaxControlToolkit,
Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" /&gt; 
<br />
            &lt;asp:ScriptReference
Name="AjaxControlToolkit.Compat.Timer.Timer.js" Assembly="AjaxControlToolkit,
Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" /&gt; 
<br />
            &lt;asp:ScriptReference
Name="AjaxControlToolkit.Compat.DragDrop.DragDropScripts.js"                
Assembly="AjaxControlToolkit, Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"
/&gt; 
<br />
            &lt;asp:ScriptReference
Name="AjaxControlToolkit.Animation.Animations.js" Assembly="AjaxControlToolkit,
Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" /&gt; 
<br />
        &lt;/Scripts&gt; 
<br />
    &lt;/CompositeScript&gt; 
<br />
&lt;/asp:ScriptManagerProxy&gt;
</p>
        <p>
&lt;asp:ScriptManagerProxy ID="ScriptManagerProxyInfragisticsCommon" runat="server"&gt; 
<br />
    &lt;CompositeScript&gt; 
<br />
        &lt;Scripts&gt;
</p>
        <p>
... 
<br />
        &lt;/Scripts&gt; 
<br />
    &lt;/CompositeScript&gt; 
<br />
&lt;/asp:ScriptManagerProxy&gt;
</p>
        <p>
...
</p>
        <p>
Gerade wenn man sich mit einem Element nahe an der 1024 Zeichen Grenze befindet, sollte
man jedoch im Hinterkopf halten, dass die tatsächliche Url der Seite später
meist nicht mehr <a href="http://localhost">http://localhost</a> ist, sondern eher <a href="http://meinesubdomain.meinedomain.de">http://meinesubdomain.meinedomain.de</a>.
Durch die Änderung des Hostnamens während der Produktivsetzung ändert
sich also eventuell noch einmal die Länge der URL. Daher im Zweifelsfall lieber
ein Script weniger als in der Entwicklungsumgebung möglich in die <em>CompositeScript</em> Tags
einfügen.
</p>
        <p>
Es müssen übrigens nicht alle Scripts in <em>CompositeScript</em> Tags gepackt
werden. Solche, die nicht verpackt wurden, werden wie gehabt ganz normal weiter als
einzelner Script Tag zum Browser herausgerendert.
</p>
        <h3>Und was bringts nun?
</h3>
        <p>
Tja, was bringt der ganze Aufwand nun? Da Bilder bekanntlich mehr als Worte sagen,
hier ein paar Vorher/Nachher Screenshots der zuvor vorgestellten Seite:
</p>
        <p>
Initial hat die Seite 37 Scripts heruntergeladen.
</p>
        <p>
 <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/1_Vorher_3.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="1_Vorher" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/1_Vorher_thumb_3.png" width="244" border="0" /></a></p>
        <p>
Yahoo's YSlow gab der Seite eine Gesamtnote von E.
</p>
        <p>
 <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/2_Vorher_YSlowGrade.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="92" alt="2_Vorher_YSlowGrade" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/2_Vorher_YSlowGrade_thumb.png" width="244" border="0" /></a></p>
        <p>
Die Ladezeit betrug knapp 15 s, die Gesamtgröße 734 kb.
</p>
        <p>
 <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/3_Vorher_YSlowSize.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="28" alt="3_Vorher_YSlowSize" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/3_Vorher_YSlowSize_thumb.png" width="145" border="0" /></a></p>
        <p>
Nach den Änderungen wurden nur noch 9 Scripte referenziert.
</p>
        <p>
 <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/6_Firebug_Nachher.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="68" alt="6_Firebug_Nachher" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/6_Firebug_Nachher_thumb.png" width="244" border="0" /></a></p>
        <p>
Die YSlow Benotung stieg immerhin von E auf D.
</p>
        <p>
 <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/7_Nachher_YSlowGrade.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="99" alt="7_Nachher_YSlowGrade" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/7_Nachher_YSlowGrade_thumb.png" width="244" border="0" /></a></p>
        <p>
Die Ladezeit reduzierte sich auf knapp 5 s, die Gesamtgröße auf 655 kb.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/8_Nachher_YSlowSize.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="29" alt="8_Nachher_YSlowSize" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/8_Nachher_YSlowSize_thumb.png" width="140" border="0" />
          </a>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=34c0df4d-6b8d-48bc-bb29-c986bdc4c998" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Client Scripte mit ASP.NET 3.51 zusammenfassen</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,34c0df4d-6b8d-48bc-bb29-c986bdc4c998.aspx</guid>
      <link>http://blog.codemurai.de/2010/01/14/ClientScripteMitASPNET351Zusammenfassen.aspx</link>
      <pubDate>Thu, 14 Jan 2010 09:16:22 GMT</pubDate>
      <description>&lt;p&gt;
Jeder der in einer ASP.NET Webforms Anwendung ein oder mehrere &amp;quot;Ajax-Enabled&amp;quot;
Controls eines Komponentenherstellers nutzt kennt das Problem: Die Anzahl der zum
Client &amp;#252;bertragenen Scripte steigt explosionsartig an.
&lt;/p&gt;
&lt;p&gt;
Dies liegt daran, dass die meisten Komponentenhersteller &lt;strong&gt;je Control ein eigenes
Script&lt;/strong&gt; zum Client senden. Generell ist das auch durchaus sinnvoll, denn nur
so kann gew&amp;#228;hrleistet werden, dass der Browser nur die minimal ben&amp;#246;tigte
Anzahl an Scriptcode vom Server herunterladen muss.
&lt;/p&gt;
&lt;p&gt;
Wie der folgende Screenshot zeigt, wird dieser Segen jedoch auch schnell zum Fluch.
Die Abbildung zeigt einen Mitschnitt des Netzwerktraffics beim Besuch einer Seite
eines aktuellen Projekts. Inhalt der Seite sind ein Scriptmanager, zwei &lt;a title="Link zur Infragistics NetAdvantage for ASP.Net Produktseite" href="http://www.infragistics.com/dotnet/netadvantage/aspnet.aspx" target="_blank"&gt;Infragistics
Controls&lt;/a&gt;, einige &lt;a title="Link auf die Esri Web ADF Vorstellung" href="http://resources.esri.com/arcgisserver/adf/dotnet/" target="_blank"&gt;ESRI
WebADF Controls&lt;/a&gt; sowie ein paar eigene Servercontrols, die auch eigene Scripts
rendern.
&lt;/p&gt;
&lt;h1&gt;&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/1_Vorher.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="1_Vorher" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/1_Vorher_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/h1&gt;
&lt;p&gt;
Die Anzahl zu &amp;#252;bertragenden Scripts betr&amp;#228;gt laut Screenshot also 37 St&amp;#252;ck.
&lt;/p&gt;
&lt;h3&gt;Interessant, aber wo liegt nun das Problem?
&lt;/h3&gt;
&lt;p&gt;
Wir wissen zwar nun, dass wir 37 Scripte zum Client &amp;#252;bertragen m&amp;#252;ssen, aber
was ist daran so schlimm und warum sollte es uns &amp;#252;berhaupt interessieren?
&lt;/p&gt;
&lt;p&gt;
Um das Problem an der Situation zu erkennen, sollten wir uns kurz vor Auge f&amp;#252;hren,
dass die Scripte nicht gemeinsam innerhalb des selben HTTP Requests wie die eigentliche
Website &amp;#252;bertragen werden. Stattdessen wird je Script (und auch Bild, CSS Stylesheet,
etc.) eine eigene Anfrage an den Webserver gestellt.
&lt;/p&gt;
&lt;p&gt;
Jede dieser Anfragen hat eine gewisse &amp;quot;R&amp;#252;stzeit&amp;quot; oder auch Latenz.
Damit ist die Zeitspanne gemeint, die zwischen dem Absetzen des Befehls, eine Anfrage
zu starten und dem tats&amp;#228;chlichen Start der Anfrage vergeht. Je nach Entfernung
zwischen Client und Server sowie der Qualit&amp;#228;t der Internetanbindung der beiden
variiert der tats&amp;#228;chliche Wert dieser Reaktionszeit.
&lt;/p&gt;
&lt;h3&gt;Und was bedeutet dies nun konkret?
&lt;/h3&gt;
&lt;p&gt;
Schauen wir uns zur Verdeutlichung ein kleines Beispiel an. Gehen wir von jemandem
mit einer extrem schlechten Anbindung und einer Latenz von 500 ms aus (&lt;em&gt;zugegeben,
der Wert ist recht hoch, l&amp;#228;sst sich aber sch&amp;#246;n einfach rechnen&lt;/em&gt; ;-))
&lt;/p&gt;
&lt;p&gt;
Um unsere 37 Scriptdateien herunterzuladen, h&amp;#228;tten wir nun also
&lt;/p&gt;
&lt;p&gt;
37 Anfragen * 500 ms Latenz + 37 Antworten * 500 ms Latenz = 37 Sekunden.
&lt;/p&gt;
&lt;p&gt;
Diese 37 Sekunden sind reine Wartezeit und kommen zur eigentlichen &amp;#220;bertragungszeit
der Scripte hinzu. Nun ist es nat&amp;#252;rlich nicht so, dass s&amp;#228;mtliche Anfragen
sequentiell abgearbeitet werden. Allerdings sieht die Standardkonfiguration vieler
Browser eine Beschr&amp;#228;nkung von zwei gleichzeitigen Verbindungen zu einem Hostnamen
vor. Diese Anzahl resultiert aus einer Empfehlung der HTTP 1.1 Spezifikation. Heisst,
wir m&amp;#252;ssen unsere 37 Sekunden noch durch zwei Teilen, da zwei gleichzeitige Verbindungen
m&amp;#246;glich sind. Bleiben immer noch 18,5 Sekunden &amp;#252;brig.
&lt;/p&gt;
&lt;h3&gt;Was k&amp;#246;nnen wir dagegen tun?
&lt;/h3&gt;
&lt;p&gt;
Um dieses Problem, was t&amp;#252;ckischerweise w&amp;#228;hrend der Entwicklung nur selten
auff&amp;#228;llt, da die Latenz zwischen lokalem Webserver und lokalem Webbrowser nicht
sonderlich hoch sein d&amp;#252;rfte ;-), in den Griff zu bekommen, bietet ASP.NET ab
der Version 3.51 das Element &lt;em&gt;&lt;a title="Link zur MSDN Dokumentation des CompositeScript Elements" href="http://msdn.microsoft.com/de-de/library/cc488552.aspx" target="_blank"&gt;CompositeScript&lt;/a&gt;&lt;/em&gt; als
Kindelement des &lt;em&gt;Scriptmanagers&lt;/em&gt; an.
&lt;/p&gt;
&lt;p&gt;
Dieses Element erlaubt es, einzelne Scripts anzugeben, welche anschlie&amp;#223;end automatisch
zu einem Script zusammengefasst werden.
&lt;/p&gt;
&lt;p&gt;
Das Ganze sieht ungef&amp;#228;hr so aus:
&lt;/p&gt;
&lt;p&gt;
&amp;lt;asp:ScriptManager runat=&amp;quot;server&amp;quot; ID=&amp;quot;sm1&amp;quot;&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;CompositeScript&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Scripts&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;/Scripts/MeinScript1.js&amp;quot; /&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;/Scripts/MeinScript2.js&amp;quot; /&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;/Scrips/MeinScript3.js&amp;quot; /&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Scripts&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;/CompositeScript&amp;gt; 
&lt;br /&gt;
&amp;lt;/asp:ScriptManager&amp;gt;
&lt;/p&gt;
&lt;p&gt;
Problematisch ist nur, dass man die URL der notwendigen Scripts nur f&amp;#252;r Dateibasierte
Scripts kennt. Sobald ein Script aber als eingebettete Ressource &amp;#252;ber die &lt;em&gt;Webresource.axd&lt;/em&gt; nach
aussen gerendert wird, ist die URL unbekannt.
&lt;/p&gt;
&lt;p&gt;
Um dieses Problem zu l&amp;#246;sen, kann das auf Codeplex erh&amp;#228;ltliche Control &lt;a href="http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=13356"&gt;ScriptReferenceProfiler&lt;/a&gt; genutzt
werden. Wird es auf einer Seite eingesetzt, rendert es eine Liste aller genutzten
Scripte heraus. Diese Liste kann 1:1 kopiert und in das &lt;em&gt;Scripts&lt;/em&gt; Element des &lt;em&gt;CompositeScript&lt;/em&gt; Elements
eingef&amp;#252;gt werden.
&lt;/p&gt;
&lt;h1&gt;&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/4_ScriptProfilerOutput.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="181" alt="4_ScriptProfilerOutput" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/4_ScriptProfilerOutput_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/h1&gt;
&lt;p&gt;
Die eingef&amp;#252;gten Scripts werden anschlie&amp;#223;end serverseitig zu einem gro&amp;#223;en
Script hinzugef&amp;#252;gt und innerhalb einer einzigen Anfrage herunter geladen.
&lt;/p&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;Nicht so schnell!
&lt;/h3&gt;
&lt;p&gt;
Der Versuch, alle 37 Scripte der zuvor genannten Seite in einem &lt;em&gt;CompositeScript&lt;/em&gt; Element
zusammen zu f&amp;#252;hren resultiert in folgendem Fehler:
&lt;/p&gt;
&lt;h1&gt;&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/5_ASP_Error.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="209" alt="5_ASP_Error" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/5_ASP_Error_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/h1&gt;
&lt;p&gt;
Die Ursache f&amp;#252;r diesen Fehler ist, dass der Scriptmanager jedes ben&amp;#246;tigte
Script mit einem kryptischen Bezeichner an die URL anh&amp;#228;ngt. Dies sprengt schnell
die maximale Begrenzung einer URL auf 1024 Zeichen.
&lt;/p&gt;
&lt;h3&gt;Die L&amp;#246;sung
&lt;/h3&gt;
&lt;p&gt;
Um dieses Problem zu umgehen platziert man einfach mehrere &lt;em&gt;CompositeScript&lt;/em&gt; Elemente
auf der Seite und verteilt die Scripte auf diese. Da jedes &lt;em&gt;CompositeScript&lt;/em&gt; Element
einen eigenen Scriptmanager ben&amp;#246;tigt, nutzt man ab dem zweiten CompositeScript
Element statt zus&amp;#228;tzlichen Scriptmanagern, von denen es immer nur einen pro Seite
geben darf einfach ScriptmanagerProxy Controls.
&lt;/p&gt;
&lt;p&gt;
Die optimale Verteilung der Scripte auf die einzelnen &lt;em&gt;CompositeScript&lt;/em&gt; Elemente
ist schnell im Trial-and-Error-Verfahren gefunden. In meinem Beispiel sah sie &amp;#252;brigens
wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&amp;lt;asp:ScriptManagerProxy ID=&amp;quot;ScriptManagerProxyAjax&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;CompositeScript&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Scripts&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;MicrosoftAjax.js&amp;quot; /&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;MicrosoftAjaxWebForms.js&amp;quot; /&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;AjaxControlToolkit.Common.Common.js&amp;quot; Assembly=&amp;quot;AjaxControlToolkit,
Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e&amp;quot; /&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;AjaxControlToolkit.Compat.Timer.Timer.js&amp;quot; Assembly=&amp;quot;AjaxControlToolkit,
Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e&amp;quot; /&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;AjaxControlToolkit.Compat.DragDrop.DragDropScripts.js&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
Assembly=&amp;quot;AjaxControlToolkit, Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e&amp;quot;
/&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:ScriptReference
Name=&amp;quot;AjaxControlToolkit.Animation.Animations.js&amp;quot; Assembly=&amp;quot;AjaxControlToolkit,
Version=3.0.30512.20315, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e&amp;quot; /&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Scripts&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;/CompositeScript&amp;gt; 
&lt;br /&gt;
&amp;lt;/asp:ScriptManagerProxy&amp;gt;
&lt;/p&gt;
&lt;p&gt;
&amp;lt;asp:ScriptManagerProxy ID=&amp;quot;ScriptManagerProxyInfragisticsCommon&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;CompositeScript&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Scripts&amp;gt;
&lt;/p&gt;
&lt;p&gt;
... 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Scripts&amp;gt; 
&lt;br /&gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;/CompositeScript&amp;gt; 
&lt;br /&gt;
&amp;lt;/asp:ScriptManagerProxy&amp;gt;
&lt;/p&gt;
&lt;p&gt;
...
&lt;/p&gt;
&lt;p&gt;
Gerade wenn man sich mit einem Element nahe an der 1024 Zeichen Grenze befindet, sollte
man jedoch im Hinterkopf halten, dass die tats&amp;#228;chliche Url der Seite sp&amp;#228;ter
meist nicht mehr &lt;a href="http://localhost"&gt;http://localhost&lt;/a&gt; ist, sondern eher &lt;a href="http://meinesubdomain.meinedomain.de"&gt;http://meinesubdomain.meinedomain.de&lt;/a&gt;.
Durch die &amp;#196;nderung des Hostnamens w&amp;#228;hrend der Produktivsetzung &amp;#228;ndert
sich also eventuell noch einmal die L&amp;#228;nge der URL. Daher im Zweifelsfall lieber
ein Script weniger als in der Entwicklungsumgebung m&amp;#246;glich in die &lt;em&gt;CompositeScript&lt;/em&gt; Tags
einf&amp;#252;gen.
&lt;/p&gt;
&lt;p&gt;
Es m&amp;#252;ssen &amp;#252;brigens nicht alle Scripts in &lt;em&gt;CompositeScript&lt;/em&gt; Tags gepackt
werden. Solche, die nicht verpackt wurden, werden wie gehabt ganz normal weiter als
einzelner Script Tag zum Browser herausgerendert.
&lt;/p&gt;
&lt;h3&gt;Und was bringts nun?
&lt;/h3&gt;
&lt;p&gt;
Tja, was bringt der ganze Aufwand nun? Da Bilder bekanntlich mehr als Worte sagen,
hier ein paar Vorher/Nachher Screenshots der zuvor vorgestellten Seite:
&lt;/p&gt;
&lt;p&gt;
Initial hat die Seite 37 Scripts heruntergeladen.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/1_Vorher_3.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="1_Vorher" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/1_Vorher_thumb_3.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Yahoo's YSlow gab der Seite eine Gesamtnote von E.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/2_Vorher_YSlowGrade.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="92" alt="2_Vorher_YSlowGrade" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/2_Vorher_YSlowGrade_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Die Ladezeit betrug knapp 15 s, die Gesamtgr&amp;#246;&amp;#223;e 734 kb.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/3_Vorher_YSlowSize.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="28" alt="3_Vorher_YSlowSize" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/3_Vorher_YSlowSize_thumb.png" width="145" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Nach den &amp;#196;nderungen wurden nur noch 9 Scripte referenziert.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/6_Firebug_Nachher.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="68" alt="6_Firebug_Nachher" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/6_Firebug_Nachher_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Die YSlow Benotung stieg immerhin von E auf D.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/7_Nachher_YSlowGrade.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="99" alt="7_Nachher_YSlowGrade" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/7_Nachher_YSlowGrade_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Die Ladezeit reduzierte sich auf knapp 5 s, die Gesamtgr&amp;#246;&amp;#223;e auf 655 kb.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/8_Nachher_YSlowSize.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="29" alt="8_Nachher_YSlowSize" src="http://blog.codemurai.de/images/ClientScriptemitASP.NETzusammenfassen_80D2/8_Nachher_YSlowSize_thumb.png" width="140" border="0" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=34c0df4d-6b8d-48bc-bb29-c986bdc4c998" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,34c0df4d-6b8d-48bc-bb29-c986bdc4c998.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Tips und Tricks</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=489651aa-54e0-4c3c-9041-3912ec7fd7df</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,489651aa-54e0-4c3c-9041-3912ec7fd7df.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,489651aa-54e0-4c3c-9041-3912ec7fd7df.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=489651aa-54e0-4c3c-9041-3912ec7fd7df</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Als Consultant lebe ich davon, mich und mein Wissen an den Mann zu bringen. Neben
stark ausgeprägten Soft Skills, sind tiefgehende technische Fertigkeiten somit unabdingbar.
Da sich die IT Welt schneller zu drehen scheint als der Rest der Welt, stellt die
Aufrechterhaltung des persönlichen technischen Know Hows eine nicht zu unterschätzende
Herausforderung dar.
</p>
        <p>
Diese Herausforderung kann man entweder ignorieren, unkoordiniert und zufällig oder
aber geplant angehen. Für 2010 habe ich mich entschieden, die Sache geplant anzugehen.
</p>
        <p>
Dabei bin ich zu folgender Strategie gekommen, die ich an allen Arbeitstagen durchhalten <strike>möchte</strike> werde.
Als Zeitlimit werde ich ein bis zwei Stunden am Tag ansetzen.
</p>
        <h4>Montags: Eine Code Kata durchführen
</h4>
        <p>
Jeder der eine Kampfkunst ausübt weiß, dass eine (annähernde) Perfektion nur durch
stetige Wiederholung erreicht werden kann. Jede Bewegung wird tausendfach wiederholt
und bis ins kleinste Detail perfektioniert.
</p>
        <p>
Nun ist die Softwareentwicklung sicherlich keine Kampfkunst. Zumindest habe ich während
der Ausübung meines Berufs bisher weder geblutet, geschweige denn irgendwelche schlimmeren
Verletzungen davon getragen. Auch geschwitzt habe ich nur, wenn im Sommer die Klimaanlage
abgeschaltet war.
</p>
        <p>
Trotz allem ist auch in der Softwareentwicklung ständiges Üben hilfreich, um den Geist
zu schärfen und die eigenen Fertigkeiten zu verbessern (danke an <a href="http://coding.roecher.de" target="_blank">Mario</a>,
der mich meine Einstellung zu diesem Thema überdenken lies).
</p>
        <p>
Deshalb ist Montag ab sofort Code Kata Tag. Diese Woche habe ich mich an der <a href="http://osherove.com/tdd-kata-1/" target="_blank">Calculator
Kata</a> versucht. Eine sehr interessante Erfahrung.
</p>
        <h4>Dienstags: Eine <a href="http://www.tekpub.com" target="_blank">Tekpub</a> Episode
ansehen
</h4>
        <p>
Was <a href="http://blog.wekeroad.com/" target="_blank">Rob</a> und <a href="http://averyblog.com/" target="_blank">James</a> hier
auf die Beine gestellt haben ist einfach nur großartig. Es gibt wohl keinen effektiveren
Weg, sich in ein Thema einzuarbeiten, als sich die Screencasts der beiden anzusehen.
</p>
        <p>
Wer die Seite noch nicht kennt, sollte sofort <a href="http://www.tekpub.com" target="_blank">dort
hin gehen</a> und sich die <a href="http://www.tekpub.com/view/coder/1" target="_blank">beiden</a><a href="http://www.tekpub.com/view/concepts/1" target="_blank">freien</a> Serien
sowie die Previews der kostenpflichtigen Inhalte ansehen.
</p>
        <p>
Für 2010 habe ich mir eine Jahresmitgliedschaft für die <a href="http://www.tekpub.com" target="_blank">Tekpub</a> Website
gekauft. Seitdem ist Dienstags Tekpub Tag. 
</p>
        <h4>Mittwochs: Einen Blog Eintrag schreiben
</h4>
        <p>
Bloggen ist aus meiner Sicht aus mehreren Gründen äußerst sinnvoll:
</p>
        <ol>
          <li>
Man teilt sein Wissen mit der Community, wodurch es sich unweigerlich vermehrt</li>
          <li>
Während man (oder zumindest ich) einen Blog Eintrag schreibt, reflektiert man selbst
noch einmal über das Thema, recherchiert vielleicht auch noch ein wenig und lernt
dadurch auch selbst dazu.</li>
          <li>
Man trainiert die Fähigkeit komplizierte Sachverhalte aufzubereiten und einfach darzustellen.</li>
        </ol>
        <p>
Da ich in der Vergangenheit viel zu unregelmässig gebloggt habe, wird ab sofort jeden
Mittwoch gebloggt!
</p>
        <h4>Donnerstags: An einem privaten Übungsprojekten arbeiten
</h4>
        <p>
Code Katas und Trainingsvideos sind zwar sehr sinnvoll, einige Sachen lernt man allerdings
nur, wenn man versucht, ein Ergebnis zu erzielen. Aus meiner Erfahrung geht dies besonders
gut im privaten Umfeld. Generell bin ich bei diesen Projekten viel experimentierfreudiger,
als bei einem Kundenprojekt.
</p>
        <h4>Freitags: lesen
</h4>
        <p>
Bekanntermaßen bildet lesen. Deshalb sollte lesen auch in dieser Auflistung nicht
fehlen. Freitags ist somit Lesetag. Der Lesestoff kann entweder ganz klassisch ein
Buch, oder auch ein Fachmagazin sein. Alternativ kann ich mir natürlich auch vorstellen,
Online Artikel zu lesen, oder einfach den Code erfolgreicher Open Source Projekte
durchzuarbeiten, um daraus zu lernen.
</p>
        <h4>Ist das alles überhaupt machbar?
</h4>
        <p>
Auf den ersten Blick sieht es nach einer Menge Arbeit aus. Natürlich stellt sich die
Frage, ob neben Familie, Haus, Beruf, der eigenen User Group und nicht zuletzt auch
Freizeitaktivitäten überhaupt genug Zeit bleibt, um all dies Woche für Woche zu erledigen.
</p>
        <p>
Ich denke, dass es wahrscheinlich nicht jeden Tag funktionieren wird. Gerade wenn
es im Projekt etwas heikler zugeht, werde ich solche Aktivitäten wohl zuerst gegen
Überstunden eintauschen. Glücklicherweise bin ich jedoch in der Situation, dass Überstunden
Ausnahmen darstellen. Daher bin ich guter Dinge, dass ich mein Vorhaben durchführen
kann. Ob dem so ist, kann der aufmerksame Leser jeden Mittwoch Abend beziehungsweise
Donnerstag Morgen selbst herausfinden ;-)
</p>
        <h4>Und ihr?
</h4>
Ich glaube nicht, dass ich der einzige bin, der seine Skills auf der Höhe der Zeit
halten möchte. Daher interessiert mich natürlich brennend, wie ihr die Sache angeht.
Lasst es mich einfach über die Kommentarfunktion meines Blogs wissen! <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=489651aa-54e0-4c3c-9041-3912ec7fd7df" /><br /><hr /><a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Skills 2010</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,489651aa-54e0-4c3c-9041-3912ec7fd7df.aspx</guid>
      <link>http://blog.codemurai.de/2010/01/06/Skills2010.aspx</link>
      <pubDate>Wed, 06 Jan 2010 21:10:40 GMT</pubDate>
      <description>&lt;p&gt;
Als Consultant lebe ich davon, mich und mein Wissen an den Mann zu bringen. Neben
stark ausgeprägten Soft Skills, sind tiefgehende technische Fertigkeiten somit unabdingbar.
Da sich die IT Welt schneller zu drehen scheint als der Rest der Welt, stellt die
Aufrechterhaltung des persönlichen technischen Know Hows eine nicht zu unterschätzende
Herausforderung dar.
&lt;/p&gt;
&lt;p&gt;
Diese Herausforderung kann man entweder ignorieren, unkoordiniert und zufällig oder
aber geplant angehen. Für 2010 habe ich mich entschieden, die Sache geplant anzugehen.
&lt;/p&gt;
&lt;p&gt;
Dabei bin ich zu folgender Strategie gekommen, die ich an allen Arbeitstagen durchhalten &lt;strike&gt;möchte&lt;/strike&gt; werde.
Als Zeitlimit werde ich ein bis zwei Stunden am Tag ansetzen.
&lt;/p&gt;
&lt;h4&gt;Montags: Eine Code Kata durchführen
&lt;/h4&gt;
&lt;p&gt;
Jeder der eine Kampfkunst ausübt weiß, dass eine (annähernde) Perfektion nur durch
stetige Wiederholung erreicht werden kann. Jede Bewegung wird tausendfach wiederholt
und bis ins kleinste Detail perfektioniert.
&lt;/p&gt;
&lt;p&gt;
Nun ist die Softwareentwicklung sicherlich keine Kampfkunst. Zumindest habe ich während
der Ausübung meines Berufs bisher weder geblutet, geschweige denn irgendwelche schlimmeren
Verletzungen davon getragen. Auch geschwitzt habe ich nur, wenn im Sommer die Klimaanlage
abgeschaltet war.
&lt;/p&gt;
&lt;p&gt;
Trotz allem ist auch in der Softwareentwicklung ständiges Üben hilfreich, um den Geist
zu schärfen und die eigenen Fertigkeiten zu verbessern (danke an &lt;a href="http://coding.roecher.de" target="_blank"&gt;Mario&lt;/a&gt;,
der mich meine Einstellung zu diesem Thema überdenken lies).
&lt;/p&gt;
&lt;p&gt;
Deshalb ist Montag ab sofort Code Kata Tag. Diese Woche habe ich mich an der &lt;a href="http://osherove.com/tdd-kata-1/" target="_blank"&gt;Calculator
Kata&lt;/a&gt; versucht. Eine sehr interessante Erfahrung.
&lt;/p&gt;
&lt;h4&gt;Dienstags: Eine &lt;a href="http://www.tekpub.com" target="_blank"&gt;Tekpub&lt;/a&gt; Episode
ansehen
&lt;/h4&gt;
&lt;p&gt;
Was &lt;a href="http://blog.wekeroad.com/" target="_blank"&gt;Rob&lt;/a&gt; und &lt;a href="http://averyblog.com/" target="_blank"&gt;James&lt;/a&gt; hier
auf die Beine gestellt haben ist einfach nur großartig. Es gibt wohl keinen effektiveren
Weg, sich in ein Thema einzuarbeiten, als sich die Screencasts der beiden anzusehen.
&lt;/p&gt;
&lt;p&gt;
Wer die Seite noch nicht kennt, sollte sofort &lt;a href="http://www.tekpub.com" target="_blank"&gt;dort
hin gehen&lt;/a&gt; und sich die &lt;a href="http://www.tekpub.com/view/coder/1" target="_blank"&gt;beiden&lt;/a&gt; &lt;a href="http://www.tekpub.com/view/concepts/1" target="_blank"&gt;freien&lt;/a&gt; Serien
sowie die Previews der kostenpflichtigen Inhalte ansehen.
&lt;/p&gt;
&lt;p&gt;
Für 2010 habe ich mir eine Jahresmitgliedschaft für die &lt;a href="http://www.tekpub.com" target="_blank"&gt;Tekpub&lt;/a&gt; Website
gekauft. Seitdem ist Dienstags Tekpub Tag. 
&lt;/p&gt;
&lt;h4&gt;Mittwochs: Einen Blog Eintrag schreiben
&lt;/h4&gt;
&lt;p&gt;
Bloggen ist aus meiner Sicht aus mehreren Gründen äußerst sinnvoll:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Man teilt sein Wissen mit der Community, wodurch es sich unweigerlich vermehrt&lt;/li&gt;
&lt;li&gt;
Während man (oder zumindest ich) einen Blog Eintrag schreibt, reflektiert man selbst
noch einmal über das Thema, recherchiert vielleicht auch noch ein wenig und lernt
dadurch auch selbst dazu.&lt;/li&gt;
&lt;li&gt;
Man trainiert die Fähigkeit komplizierte Sachverhalte aufzubereiten und einfach darzustellen.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Da ich in der Vergangenheit viel zu unregelmässig gebloggt habe, wird ab sofort jeden
Mittwoch gebloggt!
&lt;/p&gt;
&lt;h4&gt;Donnerstags: An einem privaten Übungsprojekten arbeiten
&lt;/h4&gt;
&lt;p&gt;
Code Katas und Trainingsvideos sind zwar sehr sinnvoll, einige Sachen lernt man allerdings
nur, wenn man versucht, ein Ergebnis zu erzielen. Aus meiner Erfahrung geht dies besonders
gut im privaten Umfeld. Generell bin ich bei diesen Projekten viel experimentierfreudiger,
als bei einem Kundenprojekt.
&lt;/p&gt;
&lt;h4&gt;Freitags: lesen
&lt;/h4&gt;
&lt;p&gt;
Bekanntermaßen bildet lesen. Deshalb sollte lesen auch in dieser Auflistung nicht
fehlen. Freitags ist somit Lesetag. Der Lesestoff kann entweder ganz klassisch ein
Buch, oder auch ein Fachmagazin sein. Alternativ kann ich mir natürlich auch vorstellen,
Online Artikel zu lesen, oder einfach den Code erfolgreicher Open Source Projekte
durchzuarbeiten, um daraus zu lernen.
&lt;/p&gt;
&lt;h4&gt;Ist das alles überhaupt machbar?
&lt;/h4&gt;
&lt;p&gt;
Auf den ersten Blick sieht es nach einer Menge Arbeit aus. Natürlich stellt sich die
Frage, ob neben Familie, Haus, Beruf, der eigenen User Group und nicht zuletzt auch
Freizeitaktivitäten überhaupt genug Zeit bleibt, um all dies Woche für Woche zu erledigen.
&lt;/p&gt;
&lt;p&gt;
Ich denke, dass es wahrscheinlich nicht jeden Tag funktionieren wird. Gerade wenn
es im Projekt etwas heikler zugeht, werde ich solche Aktivitäten wohl zuerst gegen
Überstunden eintauschen. Glücklicherweise bin ich jedoch in der Situation, dass Überstunden
Ausnahmen darstellen. Daher bin ich guter Dinge, dass ich mein Vorhaben durchführen
kann. Ob dem so ist, kann der aufmerksame Leser jeden Mittwoch Abend beziehungsweise
Donnerstag Morgen selbst herausfinden ;-)
&lt;/p&gt;
&lt;h4&gt;Und ihr?
&lt;/h4&gt;
Ich glaube nicht, dass ich der einzige bin, der seine Skills auf der Höhe der Zeit
halten möchte. Daher interessiert mich natürlich brennend, wie ihr die Sache angeht.
Lasst es mich einfach über die Kommentarfunktion meines Blogs wissen! &lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=489651aa-54e0-4c3c-9041-3912ec7fd7df" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,489651aa-54e0-4c3c-9041-3912ec7fd7df.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Vorsätze</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=a31f05ff-967e-458f-aa27-9fce9760abb2</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,a31f05ff-967e-458f-aa27-9fce9760abb2.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,a31f05ff-967e-458f-aa27-9fce9760abb2.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=a31f05ff-967e-458f-aa27-9fce9760abb2</wfw:commentRss>
      <slash:comments>17</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Bis vor kurzem hätte ich die Frage, ob Klassen, Methoden, Eigenschaften und Variablen
innerhalb eines Quellcodes Deutsch oder Englisch benannt werden sollen ohne zu zögern
mit "Natürlich Englisch" beantwortet.
</p>
        <p>
Mittlerweile bin ich mir dessen nicht mehr so sicher. Seit einiger Zeit befasse ich
mich nun mit Domain-Driven-Design und damit verwandten Themen. In der meist englischen
Literatur bzw. Blog Beiträgen wird stets darauf hingewiesen, dass man im DDD komplett
in die Domäne des Kundens eintauchen und dessen Sprache sprechen sollte. 
</p>
        <p>
So schreibt Gojko Adzic zum Beispiel in seinem Buch <a href="http://www.amazon.de/Bridging-Communication-Gap-Specification-Acceptance/" target="_blank">Bridging
the Communication Gap</a>, dass man als Entwickler nicht mit technischen Bezeichnungen
arbeiten und diese für den Kunden übersetzen, sondern durch das ganze Projekt hindurch
die (Geschäfts-)sprache des Kundens nutzen soll. 
</p>
        <p>
Gerade im englischsprachigen Raum kann ich mir dies auch problemlos vorstellen. Wenn
bei meinen Kunden ein Artikel in einer Bestellung zum Beispiel Order<em>Item</em> genannt
wird, hätte ich auch kein Problem damit, eine Klasse Order<em>Item</em> in meinem
Code anzulegen. Auch Methoden wie <em>GetOrderItemById</em>, oder <em>GetOrderItemByName</em> würde
ich ohne zu zögern in einem Repository unterbringen.
</p>
        <p>
Was aber, wenn wir im deutschsprachigen Raum arbeiten? Der domänenspezifische Begriff
des Kundens wäre zum Beispiel Bestellposition.
</p>
        <p>
Heißt dies nun, dass ich eine Klasse <em>Bestellposition</em> anlegen sollte? und
ein <em>BestellpositionenRepository</em>? Mit den Methoden <em>GetBestellpositionById</em> und <em>GetBestellpositionByName</em>?
</p>
        <p>
Für mich persönlich klingt dies unheimlich grausam. Natürlich könnte ich die Methoden
auch <em>HoleBestellPositionAnhandDerId</em> oder <em>HoleBestellPositionAnhandDesNamens</em> nennen.
So würde die vermischte Schreibweise zumindest entfallen. Trotzdem würde ein solcher
Code, der englische Schlüsselwörter mit deutschen Klassen und Membern vermischt, eigenartig
und fremd auf mich wirken.
</p>
        <p>
Auf der anderen Seite habe ich auch schon genug Situationen erlebt, in denen man das
korrekte englische Wort zum Domänenbegriff des Kundens einfach nicht kannte. Also
ging man schnell zu <a href="http://dict.leo.org" target="_blank">leo</a>, um dort
eine Übersetzung nachzuschlagen. Ergebnis war dann häufig, man entweder eine unpassende
und eher komische Übersetzung benutzte, oder aber andere Entwickler gar nicht wussten,
was dieser eigenartige englische Begriff bedeuten könnte. Im schlimmsten Fall ging
ein anderer Entwickler also auch zu <a href="http://dict.leo.org" target="_blank">leo</a> und
suchte sich dort eine andere Übersetzung heraus. So habe ich zum Beispiel mehrere
Jahre in einem Projekt gearbeitet, in dem für den Deutschen Begriff <em>Artikel</em> die
englischen Begriffe <em>Article</em>, <em>Part</em> und <em>Material</em> genutzt
wurden. Wie man sich vorstellen kann, trug das nicht gerade zur Lesbarkeit des Codes
bei.
</p>
        <p>
Von daher meine Frage an die Community: Wie geht ihr in deutschen Projekten vor? Deutsche
Namen? Englische Namen? Beides wild gemischt?
</p>
        <p>
Über zahlreiche Kommentare oder auch Blogantworten würde ich mich sehr freuen!
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=a31f05ff-967e-458f-aa27-9fce9760abb2" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Umfrage: Zieht DDD eine deutsche Benennung für Klassen und deren Member nach sich?</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,a31f05ff-967e-458f-aa27-9fce9760abb2.aspx</guid>
      <link>http://blog.codemurai.de/2009/11/27/UmfrageZiehtDDDEineDeutscheBenennungF%c3%bcrKlassenUndDerenMemberNachSich.aspx</link>
      <pubDate>Fri, 27 Nov 2009 18:35:16 GMT</pubDate>
      <description>&lt;p&gt;
Bis vor kurzem hätte ich die Frage, ob Klassen, Methoden, Eigenschaften und Variablen
innerhalb eines Quellcodes Deutsch oder Englisch benannt werden sollen ohne zu zögern
mit "Natürlich Englisch" beantwortet.
&lt;/p&gt;
&lt;p&gt;
Mittlerweile bin ich mir dessen nicht mehr so sicher. Seit einiger Zeit befasse ich
mich nun mit Domain-Driven-Design und damit verwandten Themen. In der meist englischen
Literatur bzw. Blog Beiträgen wird stets darauf hingewiesen, dass man im DDD komplett
in die Domäne des Kundens eintauchen und dessen Sprache sprechen sollte. 
&lt;/p&gt;
&lt;p&gt;
So schreibt Gojko Adzic zum Beispiel in seinem Buch &lt;a href="http://www.amazon.de/Bridging-Communication-Gap-Specification-Acceptance/" target="_blank"&gt;Bridging
the Communication Gap&lt;/a&gt;, dass man als Entwickler nicht mit technischen Bezeichnungen
arbeiten und diese für den Kunden übersetzen, sondern durch das ganze Projekt hindurch
die (Geschäfts-)sprache des Kundens nutzen soll. 
&lt;/p&gt;
&lt;p&gt;
Gerade im englischsprachigen Raum kann ich mir dies auch problemlos vorstellen. Wenn
bei meinen Kunden ein Artikel in einer Bestellung zum Beispiel Order&lt;em&gt;Item&lt;/em&gt; genannt
wird, hätte ich auch kein Problem damit, eine Klasse Order&lt;em&gt;Item&lt;/em&gt; in meinem
Code anzulegen. Auch Methoden wie &lt;em&gt;GetOrderItemById&lt;/em&gt;, oder &lt;em&gt;GetOrderItemByName&lt;/em&gt; würde
ich ohne zu zögern in einem Repository unterbringen.
&lt;/p&gt;
&lt;p&gt;
Was aber, wenn wir im deutschsprachigen Raum arbeiten? Der domänenspezifische Begriff
des Kundens wäre zum Beispiel Bestellposition.
&lt;/p&gt;
&lt;p&gt;
Heißt dies nun, dass ich eine Klasse &lt;em&gt;Bestellposition&lt;/em&gt; anlegen sollte? und
ein &lt;em&gt;BestellpositionenRepository&lt;/em&gt;? Mit den Methoden &lt;em&gt;GetBestellpositionById&lt;/em&gt; und &lt;em&gt;GetBestellpositionByName&lt;/em&gt;?
&lt;/p&gt;
&lt;p&gt;
Für mich persönlich klingt dies unheimlich grausam. Natürlich könnte ich die Methoden
auch &lt;em&gt;HoleBestellPositionAnhandDerId&lt;/em&gt; oder &lt;em&gt;HoleBestellPositionAnhandDesNamens&lt;/em&gt; nennen.
So würde die vermischte Schreibweise zumindest entfallen. Trotzdem würde ein solcher
Code, der englische Schlüsselwörter mit deutschen Klassen und Membern vermischt, eigenartig
und fremd auf mich wirken.
&lt;/p&gt;
&lt;p&gt;
Auf der anderen Seite habe ich auch schon genug Situationen erlebt, in denen man das
korrekte englische Wort zum Domänenbegriff des Kundens einfach nicht kannte. Also
ging man schnell zu &lt;a href="http://dict.leo.org" target="_blank"&gt;leo&lt;/a&gt;, um dort
eine Übersetzung nachzuschlagen. Ergebnis war dann häufig, man entweder eine unpassende
und eher komische Übersetzung benutzte, oder aber andere Entwickler gar nicht wussten,
was dieser eigenartige englische Begriff bedeuten könnte. Im schlimmsten Fall ging
ein anderer Entwickler also auch zu &lt;a href="http://dict.leo.org" target="_blank"&gt;leo&lt;/a&gt; und
suchte sich dort eine andere Übersetzung heraus. So habe ich zum Beispiel mehrere
Jahre in einem Projekt gearbeitet, in dem für den Deutschen Begriff &lt;em&gt;Artikel&lt;/em&gt; die
englischen Begriffe &lt;em&gt;Article&lt;/em&gt;, &lt;em&gt;Part&lt;/em&gt; und &lt;em&gt;Material&lt;/em&gt; genutzt
wurden. Wie man sich vorstellen kann, trug das nicht gerade zur Lesbarkeit des Codes
bei.
&lt;/p&gt;
&lt;p&gt;
Von daher meine Frage an die Community: Wie geht ihr in deutschen Projekten vor? Deutsche
Namen? Englische Namen? Beides wild gemischt?
&lt;/p&gt;
&lt;p&gt;
Über zahlreiche Kommentare oder auch Blogantworten würde ich mich sehr freuen!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=a31f05ff-967e-458f-aa27-9fce9760abb2" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,a31f05ff-967e-458f-aa27-9fce9760abb2.aspx</comments>
      <category>.NET</category>
      <category>DDD</category>
      <category>DotNetGerman Bloggers</category>
      <category>Feedback erwünscht</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=8950c601-a2ca-48b0-9bb7-b8d837d5fa6f</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,8950c601-a2ca-48b0-9bb7-b8d837d5fa6f.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,8950c601-a2ca-48b0-9bb7-b8d837d5fa6f.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=8950c601-a2ca-48b0-9bb7-b8d837d5fa6f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
"<b>Dieser Webpart kann nicht angezeigt werden</b>. Öffnen Sie diese Webseite in einem
Windows SharePoint Services-kompatiblen HTML-Editor, wie beispielsweise Microsoft
Office SharePoint Designer, um dieses Problem zu behandeln. Falls das Problem weiterhin
besteht, wenden Sie sich an Ihren Webserveradministrator."
</p>
        <p>
Dies ist mit großem Abstand meine Sharepoint Lieblingsfehlermeldung. Dahinter kann
sich so ziemlich alles verbergen. Kürzlich erhielt ich diese Meldung, nachdem ich
einige Änderungen an einem Dataview Webpart (DVWP) bei einem meiner Kunden vorgenommen
hatte.
</p>
        <p>
Typischerweise kommt diese Meldung, wenn man ein DVWP in einer Sharepoint Umgebung
exportiert und in eine andere Importiert. Ursache ist in solchen Fällen die fehlerhafte
Liste GUID, die innerhalb der XSL Transformation sowie als Parameter in den Webpart
Eigenschaften gespeichert wurde.
</p>
        <p>
In meinem Fall konnte ich diese Ursache allerdings ausschließen. Interessanterweise
wurde der Fehler nämlich nur anonymen Nutzern der Seite angezeigt. Als angemeldeter
Nutzer (mit Admin-Rechten) wurde der Webpart fehlerfrei angezeigt.
</p>
        <p>
Nach einer Stunde relativer Ratlosigkeit und sprichwörtlicher Suche der Nadel im Heuhaufen
fand ich glücklicherweise die Quelle des Fehlers.
</p>
        <p>
Während der Entwicklung hatte ich die XSL Transformation des Wepart nicht direkt innerhalb
des Webparts gespeichert. Stattdessen hatte ich sie in die Style Library ausgelagert.
Was ich allerdings vergessen hatte: Die XSL Datei war zwar wunderbar ausgelagert,
jedoch <strong>nicht veröffentlicht</strong>. Somit hatte ich als authentifizierter
Benutzer zwar keine Probleme den Webpart anzuzeigen, anonyme Anwender konnten das
Herzstück des Webparts - nämlich die Transformation - jedoch nicht zugreifen und erhielten
somit (zurecht) die oben genannte Fehlermeldung.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=8950c601-a2ca-48b0-9bb7-b8d837d5fa6f" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Dieser Webpart kann nicht angezeigt werden</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,8950c601-a2ca-48b0-9bb7-b8d837d5fa6f.aspx</guid>
      <link>http://blog.codemurai.de/2009/11/16/DieserWebpartKannNichtAngezeigtWerden.aspx</link>
      <pubDate>Mon, 16 Nov 2009 15:01:20 GMT</pubDate>
      <description>&lt;p&gt;
"&lt;b&gt;Dieser Webpart kann nicht angezeigt werden&lt;/b&gt;. Öffnen Sie diese Webseite in einem
Windows SharePoint Services-kompatiblen HTML-Editor, wie beispielsweise Microsoft
Office SharePoint Designer, um dieses Problem zu behandeln. Falls das Problem weiterhin
besteht, wenden Sie sich an Ihren Webserveradministrator."
&lt;/p&gt;
&lt;p&gt;
Dies ist mit großem Abstand meine Sharepoint Lieblingsfehlermeldung. Dahinter kann
sich so ziemlich alles verbergen. Kürzlich erhielt ich diese Meldung, nachdem ich
einige Änderungen an einem Dataview Webpart (DVWP) bei einem meiner Kunden vorgenommen
hatte.
&lt;/p&gt;
&lt;p&gt;
Typischerweise kommt diese Meldung, wenn man ein DVWP in einer Sharepoint Umgebung
exportiert und in eine andere Importiert. Ursache ist in solchen Fällen die fehlerhafte
Liste GUID, die innerhalb der XSL Transformation sowie als Parameter in den Webpart
Eigenschaften gespeichert wurde.
&lt;/p&gt;
&lt;p&gt;
In meinem Fall konnte ich diese Ursache allerdings ausschließen. Interessanterweise
wurde der Fehler nämlich nur anonymen Nutzern der Seite angezeigt. Als angemeldeter
Nutzer (mit Admin-Rechten) wurde der Webpart fehlerfrei angezeigt.
&lt;/p&gt;
&lt;p&gt;
Nach einer Stunde relativer Ratlosigkeit und sprichwörtlicher Suche der Nadel im Heuhaufen
fand ich glücklicherweise die Quelle des Fehlers.
&lt;/p&gt;
&lt;p&gt;
Während der Entwicklung hatte ich die XSL Transformation des Wepart nicht direkt innerhalb
des Webparts gespeichert. Stattdessen hatte ich sie in die Style Library ausgelagert.
Was ich allerdings vergessen hatte: Die XSL Datei war zwar wunderbar ausgelagert,
jedoch &lt;strong&gt;nicht veröffentlicht&lt;/strong&gt;. Somit hatte ich als authentifizierter
Benutzer zwar keine Probleme den Webpart anzuzeigen, anonyme Anwender konnten das
Herzstück des Webparts - nämlich die Transformation - jedoch nicht zugreifen und erhielten
somit (zurecht) die oben genannte Fehlermeldung.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=8950c601-a2ca-48b0-9bb7-b8d837d5fa6f" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,8950c601-a2ca-48b0-9bb7-b8d837d5fa6f.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Sharepoint</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=ddd41245-e18a-4d20-81fc-0eb1b052e108</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,ddd41245-e18a-4d20-81fc-0eb1b052e108.aspx</pingback:target>
      <dc:creator>Admin</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,ddd41245-e18a-4d20-81fc-0eb1b052e108.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=ddd41245-e18a-4d20-81fc-0eb1b052e108</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">Während der Webpart Entwicklung kann es
nützlich sein, zu wissen ob man sich gerade im Webpart Design Modus befindet. Folgender
Codeausschnitt zeigt, wie man an diese Information kommt:<br /><pre><span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">protected</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">bool</span> IsDesignMode()
{ <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">bool</span> designMode <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">true</span>; <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">if</span> (<span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">this</span>.Page
!<span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">null</span>)
{ WebPartManager wp <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span> WebPartManager.GetCurrentWebPartManager(<span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">this</span>.Page); <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">if</span> (wp
!<span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span><span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">null</span>)
{ designMode <span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span> (wp.DisplayMode
!<span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;">=</span> WebPartManager.BrowseDisplayMode);
} } <span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;">return</span> designMode;
}</span></pre>Hilfreich ist dies zum Beispiel, um Validatoren während des Design Modus
abzuschalten.<br /><p></p><img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=ddd41245-e18a-4d20-81fc-0eb1b052e108" /><br /><hr /><a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Prüfen, ob sich ein Webpart im Design Modus befindet</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,ddd41245-e18a-4d20-81fc-0eb1b052e108.aspx</guid>
      <link>http://blog.codemurai.de/2009/09/17/Pr%c3%bcfenObSichEinWebpartImDesignModusBefindet.aspx</link>
      <pubDate>Thu, 17 Sep 2009 07:29:23 GMT</pubDate>
      <description>Während der Webpart Entwicklung kann es nützlich sein, zu wissen ob man sich gerade im Webpart Design Modus befindet. Folgender Codeausschnitt zeigt, wie man an diese Information kommt:&lt;br&gt;
&lt;pre&gt;&lt;span style="color: Black; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;protected&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;bool&lt;/span&gt; IsDesignMode()
{ &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;bool&lt;/span&gt; designMode &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;true&lt;/span&gt;; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt; (&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;.Page
!&lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;null&lt;/span&gt;)
{ WebPartManager wp &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; WebPartManager.GetCurrentWebPartManager(&lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;this&lt;/span&gt;.Page); &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;if&lt;/span&gt; (wp
!&lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;null&lt;/span&gt;)
{ designMode &lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; (wp.DisplayMode
!&lt;span style="color: Red; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;=&lt;/span&gt; WebPartManager.BrowseDisplayMode);
} } &lt;span style="color: Blue; background-color: Transparent; font-family: Courier New; font-size: 11px;"&gt;return&lt;/span&gt; designMode;
}&lt;/span&gt;&lt;/pre&gt;Hilfreich ist dies zum Beispiel, um Validatoren während des Design Modus
abzuschalten.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=ddd41245-e18a-4d20-81fc-0eb1b052e108" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,ddd41245-e18a-4d20-81fc-0eb1b052e108.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Sharepoint</category>
      <category>Tips und Tricks</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=a388c50c-7e98-4e84-b435-0381cb4056bc</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,a388c50c-7e98-4e84-b435-0381cb4056bc.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,a388c50c-7e98-4e84-b435-0381cb4056bc.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=a388c50c-7e98-4e84-b435-0381cb4056bc</wfw:commentRss>
      <slash:comments>8</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In meinem <a title="Meine Top Drei Entwicklertools" href="http://blog.codemurai.de/2009/06/04/MeineDreiTopEntwicklertools.aspx" target="_blank">Beitrag</a> zur <a title="MSDN Blogparade" href="http://blogs.msdn.com/softwarehersteller/archive/2009/05/06/msdn-blog-parade-was-sind-ihre-lieblings-entwickler-tools-mitmachen-und-gewinnen.aspx" target="_blank">MSDN
Blogparade</a> zum Thema Entwicklungstools zählte ich <a href="http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx" target="_blank">WinDbg</a> als
einen meiner Favoriten auf. In einem Nebensatz erwähnte ich, dass ich bei Interesse
gerne ein kleines Tutorial zu diesem Werkzeug schreiben könnte. Die Anzahl der Rückmeldungen
auf diesen Beitrag führten zu zwei Schlussfolgerungen:
</p>
        <ol>
          <li>
Mein Blog lesen mehr Leute als ich dachte, und nicht wie vorher vermutet nur meine
Frau und meine Mutter. 
</li>
          <li>
Das Interesse an einem Tutorial ist definitiv vorhanden. Also werde ich mein Versprechen
einhalten und ein kleines Tutorial schreiben.</li>
        </ol>
        <p>
Sicherlich stellt sich nun die Frage, warum überhaupt so lange gedauert hat, das Tutorial
zu verfassen!
</p>
        <p>
Nun, das liegt zum einen daran, dass ich zur Zeit nicht in Köln, sondern in Bonn arbeite.
Somit verbringe ich viel weniger Zeit im Zug und habe somit auch viel weniger Zeit
zum bloggen. Zum anderen liegt es daran, dass ich die knappe Zeit im Zug nicht zum
schreiben, sondern zum Ansehen von <a href="http://blog.wekeroad.com/mvc-storefront/" target="_blank">Rob
Conneries StoreFront</a> Webcasts genutzt habe. An dieser Stelle möchte ich mich als
absoluter Fan der Serie bekennen. Wer sich die Webcasts noch nicht angesehen hat,
sollte dies unbedingt nachholen! Dann kam auch noch der Urlaub hinzu, so dass dieser
Eintrag einfach ein wenig warten musste.
</p>
        <p>
Jetzt aber zurück zum eigentlichen Thema!
</p>
        <h3>WinDbg - Was ist das überhaupt?
</h3>
        <p>
Wie in meinem vorherigen Blog Post geschrieben, ist WinDbg ein unmanaged (native)
Debugger mit grafischer Benutzeroberfläche. Dank der SOS Erweiterung kann man ihn
jedoch wunderbar dazu verwenden, auch managed Code zu debuggen. WinDbg benötigt <em>eigentlich</em> keinerlei
Installation auf dem zu debuggenden System und kann somit wunderbar als Geheimwaffe
auf einem <strike>Schweizer Taschenmesser</strike> USB Stick mitgeführt werden.
</p>
        <h3>Wo bekommt man ihn her und was muss bei der Installation beachtet werden?
</h3>
        <p>
Herunterladen kann man WinDbg in Form eines MSI Paketes auf der <a title="WinDBG Download Seite" href="http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx" target="_blank">Download
Seite</a> der Microsoft Debugging Tools for Windows. Die Installation an sich verläuft
recht geradlinig (Next -&gt; Next -&gt; I Agree -&gt; Next -&gt; Finish ;-)). Sind
die Debugging Tools installiert, kann der komplette Inhalt des Verzeichnisses wie
bereits erwähnt auf einen Stick kopiert werden und wäre auch von dort aus lauffähig.
</p>
        <p>
Bevor WinDbg nun wirklich genutzt werden kann, ist jedoch noch eine kleine Vorarbeit
- nämlich die Definition des Symbol-Pfads - notwendig. Andernfalls meldet WinDbg während
der Debugging Aktivitäten stets, dass er keine Symbole (PDB-Dateien) findet, was die
Übersichtlichkeit ein wenig leiden lässt.
</p>
        <p>
Zur Angabe des Symbol Pfads legt man nun zunächst ein Verzeichnis auf seiner Festplatte/Stick
an, zum Beispiel <font face="Courier New">c:\symbols</font>. Anschließend startet
man WinDbg und wählt im Menü <font face="Courier New">File</font> den Eintrag <font face="Courier New">Symbol
File Path ...</font> aus. Im sich anschließend öffnenden Dialog gibt man über folgenden
Befehl an, dass man die Symbole gerne von Microsoft herunter laden und auf der Festplatte
im Verzeichnis <font face="Courier New">c:\symbols</font>  speichern würde:
</p>
        <p>
          <font face="Courier New">SRV*c:\symbols*</font>
          <a href="http://msdl.microsoft.com/download/symbols">
            <font face="Courier New">http://msdl.microsoft.com/download/symbols</font>
          </a>
        </p>
        <h3> 
</h3>
        <h3>Genug der Vorarbeit. Los gehts!
</h3>
        <p>
Jetzt, nachdem WinDbg korrekt installiert und konfiguriert ist, möchte ich anhand
eines kleinen Beispiels die Funktionsweise zeigen. Source Code sowie die kompilierte
Version gibt es übrigens bald auf meiner Hompage zum Download. 
</p>
        <p>
Die Applikation um die es sich handelt ist eine kleine Windows Anwendung, die nur
aus einem Login Dialog besteht. Gibt der Anwender die korrekten Zugangsdaten ein,
erhält er Bestätigungsmeldung: 
</p>
        <p>
          <a href="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg1.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="182" alt="windbg1" src="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg1_thumb.png" width="244" border="0" />
          </a>   
</p>
        <p>
Sind die Benutzerdaten falsch, kommt eine Fehlermeldung: 
</p>
        <p>
          <a href="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg2.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="189" alt="windbg2" src="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg2_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Das ganze läuft seit einer ganzen Weile recht gut beim Kunden im produktiven Einsatz.
Seit kurzem ist jedoch kein Login mehr möglich. Der Kunde meldet, dass trotz 100%ig
richtiger Zugangsdaten stets die Meldung "Ungültige Benutzername / Passwort Kombination"
Meldung kommt. Eine Log Datei wird leider nicht erstellt, so dass die Ursache des
Fehlers derzeit vollkommen offen ist. Ein Blick auf den Quellocde zeigt folgende Zeilen
innerhalb des Login-Formulars 
</p>
        <p>
          <font face="Courier New" size="2">private void LoginButton_Click(object sender, EventArgs
e)<br />
{<br />
    UserService service = new UserService();<br />
    try 
<br />
    {<br />
        service.ValidateUser(UserNameTextBox.Text,
PasswordTextBox.Text);<br />
        MessageBox.Show("Login erfolgreich");<br />
    }<br />
    catch<br />
    {<br />
        MessageBox.Show("Ungültige Benutzername
/ Passwort Kombination");<br />
    }<br />
}</font>
        </p>
        <p>
Wie man sieht, wird hier Logik über Exceptions gesteuert. Nicht schön, aber vorerst
leider nicht zu ändern. Da der Code im Falle <strong>irgendeiner</strong> Exception
die Meldung "<em>Ungültige Benutzername / Passwort Kombination</em>" bringt, liegt
die Vermutung nahe, dass irgendein Fehler innerhalb der Methode ValidateUser auftritt,
der zu einer Exception führt. Die Frage ist nur: Welche Exception und warum tritt
diese überhaupt auf? 
</p>
        <p>
Die Ursache des Problems wäre mit einer kleinen Quellcodeänderung schnell gefunden.
Eine schnelle Lösung ist zwar genau das, was unser Kunde braucht, jedoch möchte er
uns weder zum Debuggen in sein Netzwerk, noch auf Gut Glück neue Versionsstände mit
erweiterten Log Nachrichten einspielen lassen. Allerdings willigt er ein, dass wir
mit einem USB Stick bewaffnet an einen der betroffenen PCs dürfen. Voraussetzung jedoch
ist, dass wir keine Software installieren. 
</p>
        <h3>Showtime
</h3>
        <p>
Die beschriebene Situation ist ein typisches Einsatzszenario für WinDbg.
</p>
        <p>
Wir starten also WinDbg von unserem USB Stick und wählen das Menü <em>File</em>-&gt;<em>Attach
to a process.</em> Anschließend wählen wir unsere fehlerhafte Applikation aus der
Prozessliste aus und drücken OK. WinDbg sollte nun ungefähr so aussehen:
</p>
        <p>
          <a href="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg3.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="windbg3" src="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg3_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Als nächstes geben wir folgende Kommandos in die Eingabezeile ein:
</p>
        <p>
          <font face="Courier New">sxe clr</font>
        </p>
        <p>
          <font face="Courier New">.loadby sos mscorwks</font>
        </p>
        <p>
Falls nun keine Fehlermeldung kommt, haben wir alles richtig gemacht ;-)
</p>
        <p>
sxe clr sagt dem Debugger, dass er bei jeder CLR Exception anhalten soll. Der Befehl
".loadby sos mscorwks" dient dazu, die SOS Extension zu laden. Diese DLL ermöglicht
die Untersuchung von Managed Code innerhalb von WinDbg, der ja eigentlich ein Debugger
für unmanaged Code ist. Für jede Version der CLR gibt es eine eigene SOS.DLL. Um nun
die zum Framework der fehlerhaften Anwendung passende SOS.DLL zu laden, kann man entweder
den vollständigen Pfad angeben, oder man lädt die Extension einfach aus dem Pfad,
aus dem auch die mscorwks geladen wurden. Die Datei mscorwks gehört zum .NET Framework.
</p>
        <p>
Derzeit befindet sich das Programm immer noch im Haltemodus. Über die Eingabe von
g (für Go) bzw. drücken von F5 können wir die Ausführung fortführen. 
</p>
        <p>
Als nächstes Klicken wir in unserer fehlerhaften Applikation erneut auf den Button
Login, um den Fehler zu provozieren. Ein Wechsel zu WinDbg zeigt, dass die Ausführung
aufgrund der Exception angehalten wurde. Außerdem werden folgende Zeilen ausgegeben:
</p>
        <p>
          <font face="Courier New">(1144.1380): CLR exception - code e0434f4d (first chance)<br />
First chance exceptions are reported before any exception handling.<br />
This exception may be expected and handled.<br />
eax=0012ecf0 ebx=e0434f4d ecx=00000000 edx=00000028 esi=0012ed7c edi=0015b718<br />
eip=7c812a6b esp=0012ecec ebp=0012ed40 iopl=0        
nv up ei pl nz na po nc<br />
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000            
efl=00000202<br />
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\KERNEL32.dll
- 
<br />
KERNEL32!RaiseException+0x52:<br />
7c812a6b 5e             
pop     esi</font>
        </p>
        <p>
Wir sehen also, dass eine CLR Exception aufgetreten ist. Leider sagt die aktuelle
Ausgabe noch relativ wenig über die Ursache aus. Wie kommen wir also an die Details?
</p>
        <p>
Dazu gibt es prinzipiell zwei Möglichkeiten.
</p>
        <p>
Variante 1 ist, über den Befehl
</p>
        <p>
          <font face="courier ">!DumpStackObjects</font> (oder kurz <font face="courier ">!dso</font>)
eine Liste aller Objekte, die aktuell auf dem Stack verwiesen werden, abzurufen.
</p>
        <p>
Das Ergebnis sieht in meinem Beispiel wie folgt aus:
</p>
        <p>
          <font face="Courier New">0:000&gt; <strong>!dso<br /></strong>*** ERROR: Symbol file could not be found.  Defaulted to export symbols
for c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll - 
<br />
PDB symbol for mscorwks.dll not loaded<br />
OS Thread Id: 0x1380 (0)<br />
ESP/REG  Object   Name<br />
0012ed5c <strong><font color="#ff0000">014c8974 System.Data.SqlServerCe.SqlCeException<br /></font></strong>0012eda8 014c8974 System.Data.SqlServerCe.SqlCeException<br />
0012edec 014c8974 System.Data.SqlServerCe.SqlCeException<br />
0012edf8 014c8974 System.Data.SqlServerCe.SqlCeException<br />
0012ee20 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ee24 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ee50 014c8974 System.Data.SqlServerCe.SqlCeException<br />
0012ee7c 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ef00 014bf388 System.Windows.Forms.MouseEventArgs<br />
0012ef04 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService<br />
0012ef08 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ef14 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ef18 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ef2c 014b075c System.Object[]    (System.Object[])<br />
0012ef30 014bf388 System.Windows.Forms.MouseEventArgs<br />
0012ef34 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService<br />
0012ef50 014c048c System.Text.StringBuilder<br />
0012ef5c 014c04a0 System.String    test<br />
0012ef60 014a6e80 System.String    Data Source=CodemuraiDb2.sdf<br />
0012ef64 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ef68 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ef6c 014a6b78 System.Configuration.ConnectionStringSettings<br />
0012ef70 014a5f8c System.Configuration.ConnectionStringSettingsCollection<br />
0012ef80 014c04d8 System.Data.SqlServerCe.SqlCeConnection<br />
0012ef84 014a6b78 System.Configuration.ConnectionStringSettings<br />
0012ef88 014a5f8c System.Configuration.ConnectionStringSettingsCollection<br />
0012ef8c 014c045c System.String    wilhelm<br />
0012ef98 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService<br />
0012efb0 014bf388 System.Windows.Forms.MouseEventArgs<br />
0012efb4 013c8b28 System.EventHandler<br />
0012efb8 013c6a04 System.Windows.Forms.Button<br />
0012efc4 014c04a0 System.String    test<br />
0012efc8 014c04a0 System.String    test<br />
0012efcc 014c045c System.String    wilhelm<br />
0012efd0 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService<br />
0012efd4 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService<br />
0012efd8 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService</font>
        </p>
        <p>
          <font face="Courier New">...</font>
        </p>
        <p>
Wir sehen, dass ganz oben auf dem Stack eine SqlCeException liegt. Diese ist unter
der Adresse <strong>014c8974 </strong>auf dem Heap abgelegt. Details eines Objekts
kann man sich über <font face="Courier New">!DumpObj</font> bzw. <font face="Courier New">!do</font> ansehen. 
</p>
        <p>
          <font face="Courier New">0:000&gt; <strong>!do 014c8974</strong><br />
Name: System.Data.SqlServerCe.SqlCeException<br />
MethodTable: 07d8255c<br />
EEClass: 07d04f14<br />
Size: 76(0x4c) bytes<br />
(C:\WINDOWS\assembly\GAC_MSIL\System.Data.SqlServerCe\3.5.1.0__89845dcd8080cc91\System.Data.SqlServerCe.dll)<br />
Fields:<br />
      MT    Field   Offset                
Type VT     Attr    Value Name<br />
79330a00  40000b5        4       
System.String  0 instance 00000000 _className<br />
7932fe74  40000b6        8 ...ection.MethodBase 
0 instance 00000000 _exceptionMethod<br />
79330a00  40000b7        c       
System.String  0 instance 00000000 _exceptionMethodString<br />
79330a00  40000b8       10       
System.String  0 <strong><font color="#ff0000">instance 014c8e0c _message</font></strong><br />
7932a35c  40000b9       14 ...tions.IDictionary 
0 instance 00000000 _data<br />
79330b94  40000ba       18    
System.Exception  0 instance 00000000 _innerException<br />
79330a00  40000bb       1c       
System.String  0 instance 00000000 _helpURL<br />
7933061c  40000bc       20       
System.Object  0 instance 00000000 _stackTrace<br />
79330a00  40000bd       24       
System.String  0 instance 00000000 _stackTraceString<br />
79330a00  40000be       28       
System.String  0 instance 00000000 _remoteStackTraceString<br />
79332c4c  40000bf       34        
System.Int32  1 instance        0 _remoteStackIndex<br />
7933061c  40000c0       2c       
System.Object  0 instance 00000000 _dynamicMethods<br />
79332c4c  40000c1       38        
System.Int32  1 instance -2146233087 _HResult<br />
79330a00  40000c2       30       
System.String  0 instance 00000000 _source<br />
793332c8  40000c3       3c       
System.IntPtr  1 instance        0 _xptrs<br />
79332c4c  40000c4       40        
System.Int32  1 instance -532459699 _xcode<br />
07d82660  400032a       44 ...CeErrorCollection 
0 instance 014c8784 errors</font>
        </p>
        <p>
In den Informationen über unser Exception Objekt sehen wir nun, dass es ein Feld _message
gibt, dessen Inhalt sich an der Adresse 014c8e0c befindet. An die Details des Felds
_message kommen wir wieder über den Befehl <font face="Courier New">!do</font>. 
</p>
        <p>
          <font face="Courier New">0:000&gt; <strong>!do 014c8e0c</strong><br />
Name: System.String<br />
MethodTable: 79330a00<br />
EEClass: 790ed64c<br />
Size: 282(0x11a) bytes<br />
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)<br /><strong><font color="#ff0000">String: The database file cannot be found. Check the
path to the database. [ Data Source = CodemuraiDb2.sdf ]<br /></font></strong>Fields:<br />
      MT    Field   Offset                
Type VT     Attr    Value Name<br />
79332c4c  4000096        4        
System.Int32  1 instance      133 m_arrayLength<br />
79332c4c  4000097        8        
System.Int32  1 instance      101 m_stringLength<br />
793316e0  4000098        c         
System.Char  1 instance       54 m_firstChar<br />
79330a00  4000099       10       
System.String  0   shared   static Empty<br />
    &gt;&gt; Domain:Value  00163700:013a1198 &lt;&lt;<br />
79331630  400009a       14       
System.Char[]  0   shared   static WhitespaceChars<br />
    &gt;&gt; Domain:Value  00163700:013a18ec &lt;&lt;</font>
        </p>
        <p>
          <font face="trech">Prima, diese Aussage hat doch gleich eine ganz andere Qualität.
Benutzername/Passwort waren wirklich nicht falsch. Einzig die geschluckte Exception
sorgte für den Eindruck. Statt dessen konnte die DB nicht gefunden werden. Ein kurzer
Blick die App.Config zeigt folgenden Eintrag:</font>
        </p>
        <p>
&lt;connectionStrings&gt;<br />
    &lt;add name="CodemuraiDb" connectionString="Data Source=<strong>CodemuraiDb2.sdf</strong>"<br />
        providerName="Microsoft.SqlServerCe.Client.3.5"
/&gt; 
</p>
        <p>
 
</p>
        <p>
Die DB selbst heißt im Dateisystem jedoch: CodemuraiDb.sdf.
</p>
        <p>
Einen kurzen Eintrag in der Datei Codemurai.Tutorial.WinDbg.ExceptionHunting.exe.config
später läuft das Programm wieder wie gewünscht.
</p>
        <h3>
          <font face="trech">Geht das auch schneller?</font>
        </h3>
        <p>
          <font face="trech">Selbstverständlich. Sobald unser Code wegen einer Exception steht
hätten wir statt !dso und mindestens Zwei mal !do auch einfach !<strong>PrintException</strong>,
oder kurz <strong>!pe</strong> eingeben können.</font>
        </p>
        <p>
          <font face="Courier New">0:000&gt; <strong>!pe</strong><br /><strong>Exception object: 014c8974</strong><br />
Exception type: System.Data.SqlServerCe.SqlCeException<br />
Message: The database file cannot be found. Check the path to the database. [ Data
Source = CodemuraiDb2.sdf ]<br />
InnerException: &lt;none&gt;<br />
StackTrace (generated):<br />
&lt;none&gt;<br />
StackTraceString: &lt;none&gt;<br />
HResult: 80131501</font>
        </p>
        <p>
Aber das kann ja jeder ;-) Außerdem haben wir über den anderen Weg direkt noch ein
paar Debugging Tipps gelernt.
</p>
        <h3>Zusammenfassung
</h3>
        <p>
In diesem Eintrag wurden folgende Befehle besprochen.
</p>
        <table cellspacing="0" cellpadding="2" width="90%" border="1">
          <thead>
            <tr>
              <th>
Befehl</th>
              <th>
Bedeutung</th>
            </tr>
            <thead>
              <tbody>
                <tr>
                  <td valign="top" width="200">
sxe clr</td>
                  <td valign="top">
Bei jeder CLR Exception anhalten</td>
                </tr>
                <tr>
                  <td valign="top" width="200">
                    <font face="Courier New">.loadby sos mscorwks</font>
                  </td>
                  <td valign="top">
SOS Extension passend zur .NET Framework Version laden</td>
                </tr>
                <tr>
                  <td valign="top" width="200">
g</td>
                  <td valign="top">
Ausführung fortführen</td>
                </tr>
                <tr>
                  <td valign="top" width="200">
                    <font face="courier ">!DumpStackObjects</font> / !dso</td>
                  <td valign="top">
Auflistung aller Objekte, die auf dem Stack verwiesen werden</td>
                </tr>
                <tr>
                  <td valign="top" width="200">
                    <font face="Courier New">!DumpObj</font> /<font face="Courier New">!do &lt;Adresse&gt;</font> </td>
                  <td valign="top">
Details zu einem Objekt ansehen</td>
                </tr>
                <tr>
                  <td valign="top" width="200">
                    <font face="Courier New">!PrintException / !pe</font> </td>
                  <td valign="top">
Details zur aktuellen Exception ansehen</td>
                </tr>
              </tbody>
            </thead>
          </thead>
        </table>
        <br />
        <h3>Wie gehts weiter?
</h3>
        <p>
Ziel dieses kleinen Beispiels war es, den Einstieg in WinDbg zu erleichtern. Natürlich
gibt es noch weitaus mehr, was mit WinDbg angestellt werden kann. So ist der Debugger
sehr hilfreich, um Speicherlecks, oder (vermeintliche) Deadlocks zu finden. Auch die
Option, einen zuvor durch den Kunden generierten MemoryDump zu analysieren ist sehr
interessant.
</p>
        <p>
Sollte also Interesse an einer Fortsetzung bestehen, reicht es einen kurzen Kommentar
zu diesem Beitrag zu hinterlassen. Kommen genug Kommentare zusammen, schreibe ich
gerne weitere Teile - dieses Mal auch mit weniger Wartezeit ;-)
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=a388c50c-7e98-4e84-b435-0381cb4056bc" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>WinDbg Tutorial: Fehlerursachen finden (Teil 1 einer Serie???)</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,a388c50c-7e98-4e84-b435-0381cb4056bc.aspx</guid>
      <link>http://blog.codemurai.de/2009/09/04/WinDbgTutorialFehlerursachenFindenTeil1EinerSerie.aspx</link>
      <pubDate>Fri, 04 Sep 2009 14:43:28 GMT</pubDate>
      <description>&lt;p&gt;
In meinem &lt;a title="Meine Top Drei Entwicklertools" href="http://blog.codemurai.de/2009/06/04/MeineDreiTopEntwicklertools.aspx" target="_blank"&gt;Beitrag&lt;/a&gt; zur &lt;a title="MSDN Blogparade" href="http://blogs.msdn.com/softwarehersteller/archive/2009/05/06/msdn-blog-parade-was-sind-ihre-lieblings-entwickler-tools-mitmachen-und-gewinnen.aspx" target="_blank"&gt;MSDN
Blogparade&lt;/a&gt; zum Thema Entwicklungstools zählte ich &lt;a href="http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx" target="_blank"&gt;WinDbg&lt;/a&gt; als
einen meiner Favoriten auf. In einem Nebensatz erwähnte ich, dass ich bei Interesse
gerne ein kleines Tutorial zu diesem Werkzeug schreiben könnte. Die Anzahl der Rückmeldungen
auf diesen Beitrag führten zu zwei Schlussfolgerungen:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Mein Blog lesen mehr Leute als ich dachte, und nicht wie vorher vermutet nur meine
Frau und meine Mutter. 
&lt;li&gt;
Das Interesse an einem Tutorial ist definitiv vorhanden. Also werde ich mein Versprechen
einhalten und ein kleines Tutorial schreiben.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Sicherlich stellt sich nun die Frage, warum überhaupt so lange gedauert hat, das Tutorial
zu verfassen!
&lt;/p&gt;
&lt;p&gt;
Nun, das liegt zum einen daran, dass ich zur Zeit nicht in Köln, sondern in Bonn arbeite.
Somit verbringe ich viel weniger Zeit im Zug und habe somit auch viel weniger Zeit
zum bloggen. Zum anderen liegt es daran, dass ich die knappe Zeit im Zug nicht zum
schreiben, sondern zum Ansehen von &lt;a href="http://blog.wekeroad.com/mvc-storefront/" target="_blank"&gt;Rob
Conneries StoreFront&lt;/a&gt; Webcasts genutzt habe. An dieser Stelle möchte ich mich als
absoluter Fan der Serie bekennen. Wer sich die Webcasts noch nicht angesehen hat,
sollte dies unbedingt nachholen! Dann kam auch noch der Urlaub hinzu, so dass dieser
Eintrag einfach ein wenig warten musste.
&lt;/p&gt;
&lt;p&gt;
Jetzt aber zurück zum eigentlichen Thema!
&lt;/p&gt;
&lt;h3&gt;WinDbg - Was ist das überhaupt?
&lt;/h3&gt;
&lt;p&gt;
Wie in meinem vorherigen Blog Post geschrieben, ist WinDbg ein unmanaged (native)
Debugger mit grafischer Benutzeroberfläche. Dank der SOS Erweiterung kann man ihn
jedoch wunderbar dazu verwenden, auch managed Code zu debuggen. WinDbg benötigt &lt;em&gt;eigentlich&lt;/em&gt; keinerlei
Installation auf dem zu debuggenden System und kann somit wunderbar als Geheimwaffe
auf einem &lt;strike&gt;Schweizer Taschenmesser&lt;/strike&gt; USB Stick mitgeführt werden.
&lt;/p&gt;
&lt;h3&gt;Wo bekommt man ihn her und was muss bei der Installation beachtet werden?
&lt;/h3&gt;
&lt;p&gt;
Herunterladen kann man WinDbg in Form eines MSI Paketes auf der &lt;a title="WinDBG Download Seite" href="http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx" target="_blank"&gt;Download
Seite&lt;/a&gt; der Microsoft Debugging Tools for Windows. Die Installation an sich verläuft
recht geradlinig (Next -&amp;gt; Next -&amp;gt; I Agree -&amp;gt; Next -&amp;gt; Finish ;-)). Sind
die Debugging Tools installiert, kann der komplette Inhalt des Verzeichnisses wie
bereits erwähnt auf einen Stick kopiert werden und wäre auch von dort aus lauffähig.
&lt;/p&gt;
&lt;p&gt;
Bevor WinDbg nun wirklich genutzt werden kann, ist jedoch noch eine kleine Vorarbeit
- nämlich die Definition des Symbol-Pfads - notwendig. Andernfalls meldet WinDbg während
der Debugging Aktivitäten stets, dass er keine Symbole (PDB-Dateien) findet, was die
Übersichtlichkeit ein wenig leiden lässt.
&lt;/p&gt;
&lt;p&gt;
Zur Angabe des Symbol Pfads legt man nun zunächst ein Verzeichnis auf seiner Festplatte/Stick
an, zum Beispiel &lt;font face="Courier New"&gt;c:\symbols&lt;/font&gt;. Anschließend startet
man WinDbg und wählt im Menü &lt;font face="Courier New"&gt;File&lt;/font&gt; den Eintrag &lt;font face="Courier New"&gt;Symbol
File Path ...&lt;/font&gt; aus. Im sich anschließend öffnenden Dialog gibt man über folgenden
Befehl an, dass man die Symbole gerne von Microsoft herunter laden und auf der Festplatte
im Verzeichnis &lt;font face="Courier New"&gt;c:\symbols&lt;/font&gt;&amp;nbsp; speichern würde:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;SRV*c:\symbols*&lt;/font&gt;&lt;a href="http://msdl.microsoft.com/download/symbols"&gt;&lt;font face="Courier New"&gt;http://msdl.microsoft.com/download/symbols&lt;/font&gt;&lt;/a&gt; 
&lt;h3&gt;&amp;nbsp;
&lt;/h3&gt;
&lt;h3&gt;Genug der Vorarbeit. Los gehts!
&lt;/h3&gt;
&lt;p&gt;
Jetzt, nachdem WinDbg korrekt installiert und konfiguriert ist, möchte ich anhand
eines kleinen Beispiels die Funktionsweise zeigen. Source Code sowie die kompilierte
Version gibt es übrigens bald auf meiner Hompage zum Download. 
&lt;p&gt;
Die Applikation um die es sich handelt ist eine kleine Windows Anwendung, die nur
aus einem Login Dialog besteht. Gibt der Anwender die korrekten Zugangsdaten ein,
erhält er Bestätigungsmeldung: 
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg1.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="182" alt="windbg1" src="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg1_thumb.png" width="244" border="0"&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp; 
&lt;p&gt;
Sind die Benutzerdaten falsch, kommt eine Fehlermeldung: 
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg2.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="189" alt="windbg2" src="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg2_thumb.png" width="244" border="0"&gt;&lt;/a&gt; 
&lt;p&gt;
Das ganze läuft seit einer ganzen Weile recht gut beim Kunden im produktiven Einsatz.
Seit kurzem ist jedoch kein Login mehr möglich. Der Kunde meldet, dass trotz 100%ig
richtiger Zugangsdaten stets die Meldung "Ungültige Benutzername / Passwort Kombination"
Meldung kommt. Eine Log Datei wird leider nicht erstellt, so dass die Ursache des
Fehlers derzeit vollkommen offen ist. Ein Blick auf den Quellocde zeigt folgende Zeilen
innerhalb des Login-Formulars 
&lt;p&gt;
&lt;font face="Courier New" size="2"&gt;private void LoginButton_Click(object sender, EventArgs
e)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; UserService service = new UserService();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; try 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; service.ValidateUser(UserNameTextBox.Text,
PasswordTextBox.Text);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageBox.Show("Login erfolgreich");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; catch&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageBox.Show("Ungültige Benutzername
/ Passwort Kombination");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
}&lt;/font&gt; 
&lt;p&gt;
Wie man sieht, wird hier Logik über Exceptions gesteuert. Nicht schön, aber vorerst
leider nicht zu ändern. Da der Code im Falle &lt;strong&gt;irgendeiner&lt;/strong&gt; Exception
die Meldung "&lt;em&gt;Ungültige Benutzername / Passwort Kombination&lt;/em&gt;" bringt, liegt
die Vermutung nahe, dass irgendein Fehler innerhalb der Methode ValidateUser auftritt,
der zu einer Exception führt. Die Frage ist nur: Welche Exception und warum tritt
diese überhaupt auf? 
&lt;p&gt;
Die Ursache des Problems wäre mit einer kleinen Quellcodeänderung schnell gefunden.
Eine schnelle Lösung ist zwar genau das, was unser Kunde braucht, jedoch möchte er
uns weder zum Debuggen in sein Netzwerk, noch auf Gut Glück neue Versionsstände mit
erweiterten Log Nachrichten einspielen lassen. Allerdings willigt er ein, dass wir
mit einem USB Stick bewaffnet an einen der betroffenen PCs dürfen. Voraussetzung jedoch
ist, dass wir keine Software installieren. 
&lt;h3&gt;Showtime
&lt;/h3&gt;
&lt;p&gt;
Die beschriebene Situation ist ein typisches Einsatzszenario für WinDbg.
&lt;/p&gt;
&lt;p&gt;
Wir starten also WinDbg von unserem USB Stick und wählen das Menü &lt;em&gt;File&lt;/em&gt;-&amp;gt;&lt;em&gt;Attach
to a process.&lt;/em&gt; Anschließend wählen wir unsere fehlerhafte Applikation aus der
Prozessliste aus und drücken OK. WinDbg sollte nun ungefähr so aussehen:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg3.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="windbg3" src="http://blog.codemurai.de/images/WinDbgTutorialFehlerursachenfindenTeil1e_EACB/windbg3_thumb.png" width="244" border="0"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Als nächstes geben wir folgende Kommandos in die Eingabezeile ein:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;sxe clr&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;.loadby sos mscorwks&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Falls nun keine Fehlermeldung kommt, haben wir alles richtig gemacht ;-)
&lt;/p&gt;
&lt;p&gt;
sxe clr sagt dem Debugger, dass er bei jeder CLR Exception anhalten soll. Der Befehl
".loadby sos mscorwks" dient dazu, die SOS Extension zu laden. Diese DLL ermöglicht
die Untersuchung von Managed Code innerhalb von WinDbg, der ja eigentlich ein Debugger
für unmanaged Code ist. Für jede Version der CLR gibt es eine eigene SOS.DLL. Um nun
die zum Framework der fehlerhaften Anwendung passende SOS.DLL zu laden, kann man entweder
den vollständigen Pfad angeben, oder man lädt die Extension einfach aus dem Pfad,
aus dem auch die mscorwks geladen wurden. Die Datei mscorwks gehört zum .NET Framework.
&lt;/p&gt;
&lt;p&gt;
Derzeit befindet sich das Programm immer noch im Haltemodus. Über die Eingabe von
g (für Go) bzw. drücken von F5 können wir die Ausführung fortführen. 
&lt;/p&gt;
&lt;p&gt;
Als nächstes Klicken wir in unserer fehlerhaften Applikation erneut auf den Button
Login, um den Fehler zu provozieren. Ein Wechsel zu WinDbg zeigt, dass die Ausführung
aufgrund der Exception angehalten wurde. Außerdem werden folgende Zeilen ausgegeben:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;(1144.1380): CLR exception - code e0434f4d (first chance)&lt;br&gt;
First chance exceptions are reported before any exception handling.&lt;br&gt;
This exception may be expected and handled.&lt;br&gt;
eax=0012ecf0 ebx=e0434f4d ecx=00000000 edx=00000028 esi=0012ed7c edi=0015b718&lt;br&gt;
eip=7c812a6b esp=0012ecec ebp=0012ed40 iopl=0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
nv up ei pl nz na po nc&lt;br&gt;
cs=001b&amp;nbsp; ss=0023&amp;nbsp; ds=0023&amp;nbsp; es=0023&amp;nbsp; fs=003b&amp;nbsp; gs=0000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
efl=00000202&lt;br&gt;
*** ERROR: Symbol file could not be found.&amp;nbsp; Defaulted to export symbols for C:\WINDOWS\system32\KERNEL32.dll
- 
&lt;br&gt;
KERNEL32!RaiseException+0x52:&lt;br&gt;
7c812a6b 5e&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
pop&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; esi&lt;/font&gt; 
&lt;p&gt;
Wir sehen also, dass eine CLR Exception aufgetreten ist. Leider sagt die aktuelle
Ausgabe noch relativ wenig über die Ursache aus. Wie kommen wir also an die Details?
&lt;/p&gt;
&lt;p&gt;
Dazu gibt es prinzipiell zwei Möglichkeiten.
&lt;/p&gt;
&lt;p&gt;
Variante 1 ist, über den Befehl
&lt;/p&gt;
&lt;p&gt;
&lt;font face="courier "&gt;!DumpStackObjects&lt;/font&gt; (oder kurz &lt;font face="courier "&gt;!dso&lt;/font&gt;)
eine Liste aller Objekte, die aktuell auf dem Stack verwiesen werden, abzurufen.
&lt;/p&gt;
&lt;p&gt;
Das Ergebnis sieht in meinem Beispiel wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;0:000&amp;gt; &lt;strong&gt;!dso&lt;br&gt;
&lt;/strong&gt;*** ERROR: Symbol file could not be found.&amp;nbsp; Defaulted to export symbols
for c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll - 
&lt;br&gt;
PDB symbol for mscorwks.dll not loaded&lt;br&gt;
OS Thread Id: 0x1380 (0)&lt;br&gt;
ESP/REG&amp;nbsp; Object&amp;nbsp;&amp;nbsp; Name&lt;br&gt;
0012ed5c &lt;strong&gt;&lt;font color="#ff0000"&gt;014c8974 System.Data.SqlServerCe.SqlCeException&lt;br&gt;
&lt;/font&gt;&lt;/strong&gt;0012eda8 014c8974 System.Data.SqlServerCe.SqlCeException&lt;br&gt;
0012edec 014c8974 System.Data.SqlServerCe.SqlCeException&lt;br&gt;
0012edf8 014c8974 System.Data.SqlServerCe.SqlCeException&lt;br&gt;
0012ee20 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ee24 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ee50 014c8974 System.Data.SqlServerCe.SqlCeException&lt;br&gt;
0012ee7c 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ef00 014bf388 System.Windows.Forms.MouseEventArgs&lt;br&gt;
0012ef04 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService&lt;br&gt;
0012ef08 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ef14 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ef18 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ef2c 014b075c System.Object[]&amp;nbsp;&amp;nbsp;&amp;nbsp; (System.Object[])&lt;br&gt;
0012ef30 014bf388 System.Windows.Forms.MouseEventArgs&lt;br&gt;
0012ef34 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService&lt;br&gt;
0012ef50 014c048c System.Text.StringBuilder&lt;br&gt;
0012ef5c 014c04a0 System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; test&lt;br&gt;
0012ef60 014a6e80 System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; Data Source=CodemuraiDb2.sdf&lt;br&gt;
0012ef64 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ef68 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ef6c 014a6b78 System.Configuration.ConnectionStringSettings&lt;br&gt;
0012ef70 014a5f8c System.Configuration.ConnectionStringSettingsCollection&lt;br&gt;
0012ef80 014c04d8 System.Data.SqlServerCe.SqlCeConnection&lt;br&gt;
0012ef84 014a6b78 System.Configuration.ConnectionStringSettings&lt;br&gt;
0012ef88 014a5f8c System.Configuration.ConnectionStringSettingsCollection&lt;br&gt;
0012ef8c 014c045c System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; wilhelm&lt;br&gt;
0012ef98 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService&lt;br&gt;
0012efb0 014bf388 System.Windows.Forms.MouseEventArgs&lt;br&gt;
0012efb4 013c8b28 System.EventHandler&lt;br&gt;
0012efb8 013c6a04 System.Windows.Forms.Button&lt;br&gt;
0012efc4 014c04a0 System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; test&lt;br&gt;
0012efc8 014c04a0 System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; test&lt;br&gt;
0012efcc 014c045c System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; wilhelm&lt;br&gt;
0012efd0 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService&lt;br&gt;
0012efd4 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService&lt;br&gt;
0012efd8 014c0430 Codemurai.Tutorial.WinDbg.ExceptionHunting.UserService&lt;/font&gt; 
&lt;p&gt;
&lt;font face="Courier New"&gt;...&lt;/font&gt; 
&lt;p&gt;
Wir sehen, dass ganz oben auf dem Stack eine SqlCeException liegt. Diese ist unter
der Adresse &lt;strong&gt;014c8974 &lt;/strong&gt;auf dem Heap abgelegt. Details eines Objekts
kann man sich über &lt;font face="Courier New"&gt;!DumpObj&lt;/font&gt; bzw. &lt;font face="Courier New"&gt;!do&lt;/font&gt; ansehen. 
&lt;p&gt;
&lt;font face="Courier New"&gt;0:000&amp;gt; &lt;strong&gt;!do 014c8974&lt;/strong&gt; 
&lt;br&gt;
Name: System.Data.SqlServerCe.SqlCeException&lt;br&gt;
MethodTable: 07d8255c&lt;br&gt;
EEClass: 07d04f14&lt;br&gt;
Size: 76(0x4c) bytes&lt;br&gt;
(C:\WINDOWS\assembly\GAC_MSIL\System.Data.SqlServerCe\3.5.1.0__89845dcd8080cc91\System.Data.SqlServerCe.dll)&lt;br&gt;
Fields:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MT&amp;nbsp;&amp;nbsp;&amp;nbsp; Field&amp;nbsp;&amp;nbsp; Offset&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Type VT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Attr&amp;nbsp;&amp;nbsp;&amp;nbsp; Value Name&lt;br&gt;
79330a00&amp;nbsp; 40000b5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp; 0 instance 00000000 _className&lt;br&gt;
7932fe74&amp;nbsp; 40000b6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8 ...ection.MethodBase&amp;nbsp;
0 instance 00000000 _exceptionMethod&lt;br&gt;
79330a00&amp;nbsp; 40000b7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp; 0 instance 00000000 _exceptionMethodString&lt;br&gt;
79330a00&amp;nbsp; 40000b8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp; 0 &lt;strong&gt;&lt;font color="#ff0000"&gt;instance 014c8e0c _message&lt;/font&gt;&lt;/strong&gt;
&lt;br&gt;
7932a35c&amp;nbsp; 40000b9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 14 ...tions.IDictionary&amp;nbsp;
0 instance 00000000 _data&lt;br&gt;
79330b94&amp;nbsp; 40000ba&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 18&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Exception&amp;nbsp; 0 instance 00000000 _innerException&lt;br&gt;
79330a00&amp;nbsp; 40000bb&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1c&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp; 0 instance 00000000 _helpURL&lt;br&gt;
7933061c&amp;nbsp; 40000bc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 20&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Object&amp;nbsp; 0 instance 00000000 _stackTrace&lt;br&gt;
79330a00&amp;nbsp; 40000bd&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 24&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp; 0 instance 00000000 _stackTraceString&lt;br&gt;
79330a00&amp;nbsp; 40000be&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 28&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp; 0 instance 00000000 _remoteStackTraceString&lt;br&gt;
79332c4c&amp;nbsp; 40000bf&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 34&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Int32&amp;nbsp; 1 instance&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 _remoteStackIndex&lt;br&gt;
7933061c&amp;nbsp; 40000c0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2c&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Object&amp;nbsp; 0 instance 00000000 _dynamicMethods&lt;br&gt;
79332c4c&amp;nbsp; 40000c1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 38&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Int32&amp;nbsp; 1 instance -2146233087 _HResult&lt;br&gt;
79330a00&amp;nbsp; 40000c2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 30&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp; 0 instance 00000000 _source&lt;br&gt;
793332c8&amp;nbsp; 40000c3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3c&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.IntPtr&amp;nbsp; 1 instance&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0 _xptrs&lt;br&gt;
79332c4c&amp;nbsp; 40000c4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 40&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Int32&amp;nbsp; 1 instance -532459699 _xcode&lt;br&gt;
07d82660&amp;nbsp; 400032a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 44 ...CeErrorCollection&amp;nbsp;
0 instance 014c8784 errors&lt;/font&gt; 
&lt;p&gt;
In den Informationen über unser Exception Objekt sehen wir nun, dass es ein Feld _message
gibt, dessen Inhalt sich an der Adresse 014c8e0c befindet. An die Details des Felds
_message kommen wir wieder über den Befehl &lt;font face="Courier New"&gt;!do&lt;/font&gt;. 
&lt;p&gt;
&lt;font face="Courier New"&gt;0:000&amp;gt; &lt;strong&gt;!do 014c8e0c&lt;/strong&gt; 
&lt;br&gt;
Name: System.String&lt;br&gt;
MethodTable: 79330a00&lt;br&gt;
EEClass: 790ed64c&lt;br&gt;
Size: 282(0x11a) bytes&lt;br&gt;
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)&lt;br&gt;
&lt;strong&gt;&lt;font color="#ff0000"&gt;String: The database file cannot be found. Check the
path to the database. [ Data Source = CodemuraiDb2.sdf ]&lt;br&gt;
&lt;/font&gt;&lt;/strong&gt;Fields:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MT&amp;nbsp;&amp;nbsp;&amp;nbsp; Field&amp;nbsp;&amp;nbsp; Offset&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Type VT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Attr&amp;nbsp;&amp;nbsp;&amp;nbsp; Value Name&lt;br&gt;
79332c4c&amp;nbsp; 4000096&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Int32&amp;nbsp; 1 instance&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 133 m_arrayLength&lt;br&gt;
79332c4c&amp;nbsp; 4000097&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Int32&amp;nbsp; 1 instance&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 101 m_stringLength&lt;br&gt;
793316e0&amp;nbsp; 4000098&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Char&amp;nbsp; 1 instance&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 54 m_firstChar&lt;br&gt;
79330a00&amp;nbsp; 4000099&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp; 0&amp;nbsp;&amp;nbsp; shared&amp;nbsp;&amp;nbsp; static Empty&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;gt;&amp;gt; Domain:Value&amp;nbsp; 00163700:013a1198 &amp;lt;&amp;lt;&lt;br&gt;
79331630&amp;nbsp; 400009a&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 14&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Char[]&amp;nbsp; 0&amp;nbsp;&amp;nbsp; shared&amp;nbsp;&amp;nbsp; static WhitespaceChars&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;gt;&amp;gt; Domain:Value&amp;nbsp; 00163700:013a18ec &amp;lt;&amp;lt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="trech"&gt;Prima, diese Aussage hat doch gleich eine ganz andere Qualität.
Benutzername/Passwort waren wirklich nicht falsch. Einzig die geschluckte Exception
sorgte für den Eindruck. Statt dessen konnte die DB nicht gefunden werden. Ein kurzer
Blick die App.Config zeigt folgenden Eintrag:&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;lt;connectionStrings&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="CodemuraiDb" connectionString="Data Source=&lt;strong&gt;CodemuraiDb2.sdf&lt;/strong&gt;"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; providerName="Microsoft.SqlServerCe.Client.3.5"
/&amp;gt; 
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Die DB selbst heißt im Dateisystem jedoch: CodemuraiDb.sdf.
&lt;/p&gt;
&lt;p&gt;
Einen kurzen Eintrag in der Datei Codemurai.Tutorial.WinDbg.ExceptionHunting.exe.config
später läuft das Programm wieder wie gewünscht.
&lt;/p&gt;
&lt;h3&gt;&lt;font face="trech"&gt;Geht das auch schneller?&lt;/font&gt;
&lt;/h3&gt;
&lt;p&gt;
&lt;font face="trech"&gt;Selbstverständlich. Sobald unser Code wegen einer Exception steht
hätten wir statt !dso und mindestens Zwei mal !do auch einfach !&lt;strong&gt;PrintException&lt;/strong&gt;,
oder kurz &lt;strong&gt;!pe&lt;/strong&gt; eingeben können.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;0:000&amp;gt; &lt;strong&gt;!pe&lt;/strong&gt;
&lt;br&gt;
&lt;strong&gt;Exception object: 014c8974&lt;/strong&gt;
&lt;br&gt;
Exception type: System.Data.SqlServerCe.SqlCeException&lt;br&gt;
Message: The database file cannot be found. Check the path to the database. [ Data
Source = CodemuraiDb2.sdf ]&lt;br&gt;
InnerException: &amp;lt;none&amp;gt;&lt;br&gt;
StackTrace (generated):&lt;br&gt;
&amp;lt;none&amp;gt;&lt;br&gt;
StackTraceString: &amp;lt;none&amp;gt;&lt;br&gt;
HResult: 80131501&lt;/font&gt; 
&lt;p&gt;
Aber das kann ja jeder ;-) Außerdem haben wir über den anderen Weg direkt noch ein
paar Debugging Tipps gelernt.
&lt;/p&gt;
&lt;h3&gt;Zusammenfassung
&lt;/h3&gt;
&lt;p&gt;
In diesem Eintrag wurden folgende Befehle besprochen.
&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="2" width="90%" border="1"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
Befehl&lt;/th&gt;
&lt;th&gt;
Bedeutung&lt;/th&gt;
&lt;/tr&gt;
&lt;thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
sxe clr&lt;/td&gt;
&lt;td valign="top"&gt;
Bei jeder CLR Exception anhalten&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
&lt;font face="Courier New"&gt;.loadby sos mscorwks&lt;/font&gt;&lt;/td&gt;
&lt;td valign="top"&gt;
SOS Extension passend zur .NET Framework Version laden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
g&lt;/td&gt;
&lt;td valign="top"&gt;
Ausführung fortführen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
&lt;font face="courier "&gt;!DumpStackObjects&lt;/font&gt; / !dso&lt;/td&gt;
&lt;td valign="top"&gt;
Auflistung aller Objekte, die auf dem Stack verwiesen werden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
&lt;font face="Courier New"&gt;!DumpObj&lt;/font&gt; /&lt;font face="Courier New"&gt;!do &amp;lt;Adresse&amp;gt;&lt;/font&gt;&amp;nbsp;&lt;/td&gt;
&lt;td valign="top"&gt;
Details zu einem Objekt ansehen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
&lt;font face="Courier New"&gt;!PrintException / !pe&lt;/font&gt;&amp;nbsp;&lt;/td&gt;
&lt;td valign="top"&gt;
Details zur aktuellen Exception ansehen&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;h3&gt;Wie gehts weiter?
&lt;/h3&gt;
&lt;p&gt;
Ziel dieses kleinen Beispiels war es, den Einstieg in WinDbg zu erleichtern. Natürlich
gibt es noch weitaus mehr, was mit WinDbg angestellt werden kann. So ist der Debugger
sehr hilfreich, um Speicherlecks, oder (vermeintliche) Deadlocks zu finden. Auch die
Option, einen zuvor durch den Kunden generierten MemoryDump zu analysieren ist sehr
interessant.
&lt;/p&gt;
&lt;p&gt;
Sollte also Interesse an einer Fortsetzung bestehen, reicht es einen kurzen Kommentar
zu diesem Beitrag zu hinterlassen. Kommen genug Kommentare zusammen, schreibe ich
gerne weitere Teile - dieses Mal auch mit weniger Wartezeit ;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=a388c50c-7e98-4e84-b435-0381cb4056bc" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,a388c50c-7e98-4e84-b435-0381cb4056bc.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Tutorials</category>
      <category>WinDbg</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=845df5b3-488b-431c-a44c-64eb2df389e9</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,845df5b3-488b-431c-a44c-64eb2df389e9.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,845df5b3-488b-431c-a44c-64eb2df389e9.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=845df5b3-488b-431c-a44c-64eb2df389e9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Wer in den letzten Jahren auch nur am Rande etwas mit der Entwicklung von Webapplikationen
zu tun hatte, sollte wissen, dass der Einsatz von Tabellen zur Gestaltung des Layouts
nicht mehr wirklich State-Of-The-Art sind. Schön und gut, aber wie sieht es mit Dateneingabefomularen
aus? Diese sind häufig zweispaltig und mehrzeilig aufgebaut, so dass der Einsatz von
Tabellen nicht komplett abwegig wäre und zumindest noch halbwegs sinnvoll erscheint.
</p>
        <p>
Doch leider weit gefehlt. Jeder, der sich ein solches Eingabeformular von einem Screenreader
vorlesen lässt, merkt schnell, dass auch hier Tabellen nicht das Mittel der Wahl sein
sollten. Wie sieht nun aber die Alternative aus? In der Praxis stolpert man häufig
über wüst zusammen geschusterte DIV Tags mit fixen Positionierungen, deren einziger
Zweck in der Emulation von Tabellenzellen besteht. Dies mag zwar bereits ein Schritt
in die richtige Richtung sein, aber wenn man ehrlich ist, wurde das Problem nur verlagert.
</p>
        <p>
Weitaus interessanter finde ich <a href="http://www.themaninblue.com" target="_blank">Cameron
Adams</a><a href="http://www.themaninblue.com/experiment/InForm/margin.htm" target="_blank">Ansatz</a>,
den ich seit einiger Zeit auch erfolgreich in einigen Projekten zum Einsatz gebracht
habe. Wer also Eingabeformulare fürs Web erstellen muss, und keine Lust auf Tabellen
hat, sollte sich auf jeden Fall diesen <a href="http://www.themaninblue.com/writing/perspective/2004/03/24/" target="_blank">Link</a> inklusive
der verschiedenen <a href="http://www.themaninblue.com/experiment/InForm/columnar.htm" target="_blank">Beispiele</a> und
der Quellcodes ansehen.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=845df5b3-488b-431c-a44c-64eb2df389e9" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Tabellenlose Dateneingabeformulare im Web</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,845df5b3-488b-431c-a44c-64eb2df389e9.aspx</guid>
      <link>http://blog.codemurai.de/2009/06/19/TabellenloseDateneingabeformulareImWeb.aspx</link>
      <pubDate>Fri, 19 Jun 2009 12:19:36 GMT</pubDate>
      <description>&lt;p&gt;
Wer in den letzten Jahren auch nur am Rande etwas mit der Entwicklung von Webapplikationen
zu tun hatte, sollte wissen, dass der Einsatz von Tabellen zur Gestaltung des Layouts
nicht mehr wirklich State-Of-The-Art sind. Schön und gut, aber wie sieht es mit Dateneingabefomularen
aus? Diese sind häufig zweispaltig und mehrzeilig aufgebaut, so dass der Einsatz von
Tabellen nicht komplett abwegig wäre und zumindest noch halbwegs sinnvoll erscheint.
&lt;/p&gt;
&lt;p&gt;
Doch leider weit gefehlt. Jeder, der sich ein solches Eingabeformular von einem Screenreader
vorlesen lässt, merkt schnell, dass auch hier Tabellen nicht das Mittel der Wahl sein
sollten. Wie sieht nun aber die Alternative aus? In der Praxis stolpert man häufig
über wüst zusammen geschusterte DIV Tags mit fixen Positionierungen, deren einziger
Zweck in der Emulation von Tabellenzellen besteht. Dies mag zwar bereits ein Schritt
in die richtige Richtung sein, aber wenn man ehrlich ist, wurde das Problem nur verlagert.
&lt;/p&gt;
&lt;p&gt;
Weitaus interessanter finde ich &lt;a href="http://www.themaninblue.com" target="_blank"&gt;Cameron
Adams&lt;/a&gt; &lt;a href="http://www.themaninblue.com/experiment/InForm/margin.htm" target="_blank"&gt;Ansatz&lt;/a&gt;,
den ich seit einiger Zeit auch erfolgreich in einigen Projekten zum Einsatz gebracht
habe. Wer also Eingabeformulare fürs Web erstellen muss, und keine Lust auf Tabellen
hat, sollte sich auf jeden Fall diesen &lt;a href="http://www.themaninblue.com/writing/perspective/2004/03/24/" target="_blank"&gt;Link&lt;/a&gt; inklusive
der verschiedenen &lt;a href="http://www.themaninblue.com/experiment/InForm/columnar.htm" target="_blank"&gt;Beispiele&lt;/a&gt; und
der Quellcodes ansehen.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=845df5b3-488b-431c-a44c-64eb2df389e9" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,845df5b3-488b-431c-a44c-64eb2df389e9.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=f0264df7-1665-48ba-9e80-440d8e6a6a7b</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,f0264df7-1665-48ba-9e80-440d8e6a6a7b.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,f0264df7-1665-48ba-9e80-440d8e6a6a7b.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=f0264df7-1665-48ba-9e80-440d8e6a6a7b</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Von heute an veranstaltet die Universität Koblenz sieben Tage lang eine „Sommer-Uni“
mit Themen, die etwas außerhalb des <strong>normalen Lehrplans</strong> angesiedelt
sind. Mit dabei ist die <a href="http://www.dnug-koblenz.de/">.NET User Group Koblenz</a>,
die am 24. Juni zwei Vorträge aus dem .NET-Umfeld beisteuert: „<a href="http://www.uni-koblenz.de/~sommeruni/2009/index.php?page=wsdetails&amp;col=bilder_blau&amp;id=59">Moderne
Anwendungsarchitekturen mit .NET</a> “ und „<a href="http://www.uni-koblenz.de/~sommeruni/2009/index.php?page=wsdetails&amp;col=bilder_blau&amp;id=60">User
Interface Design mit der WPF</a>“. 
</p>
        <p>
Was ich mich dabei nur frage: Wieso liegt .NET außerhalb des normalen Lehrplans ;-)
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=f0264df7-1665-48ba-9e80-440d8e6a6a7b" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>.NET User Group Koblenz zu Gast an der Uni Koblenz</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,f0264df7-1665-48ba-9e80-440d8e6a6a7b.aspx</guid>
      <link>http://blog.codemurai.de/2009/06/19/NETUserGroupKoblenzZuGastAnDerUniKoblenz.aspx</link>
      <pubDate>Fri, 19 Jun 2009 11:45:16 GMT</pubDate>
      <description>&lt;p&gt;
Von heute an veranstaltet die Universität Koblenz sieben Tage lang eine „Sommer-Uni“
mit Themen, die etwas außerhalb des &lt;strong&gt;normalen Lehrplans&lt;/strong&gt; angesiedelt
sind. Mit dabei ist die &lt;a href="http://www.dnug-koblenz.de/"&gt;.NET User Group Koblenz&lt;/a&gt;,
die am 24. Juni zwei Vorträge aus dem .NET-Umfeld beisteuert: „&lt;a href="http://www.uni-koblenz.de/~sommeruni/2009/index.php?page=wsdetails&amp;amp;col=bilder_blau&amp;amp;id=59"&gt;Moderne
Anwendungsarchitekturen mit .NET&lt;/a&gt; “ und „&lt;a href="http://www.uni-koblenz.de/~sommeruni/2009/index.php?page=wsdetails&amp;amp;col=bilder_blau&amp;amp;id=60"&gt;User
Interface Design mit der WPF&lt;/a&gt;“. 
&lt;/p&gt;
&lt;p&gt;
Was ich mich dabei nur frage: Wieso liegt .NET außerhalb des normalen Lehrplans ;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=f0264df7-1665-48ba-9e80-440d8e6a6a7b" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,f0264df7-1665-48ba-9e80-440d8e6a6a7b.aspx</comments>
      <category>.NET</category>
      <category>Community</category>
      <category>DNUG Koblenz</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=382783fd-0514-436e-b104-47fc54018d59</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,382783fd-0514-436e-b104-47fc54018d59.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,382783fd-0514-436e-b104-47fc54018d59.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=382783fd-0514-436e-b104-47fc54018d59</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Wer kennt solche Unterhaltungen nicht:
</p>
        <p>
Ich: <em>Der Build-Vorgang schlägt fehl. Wer hat als letztes eingecheckt?</em></p>
        <p>
Er: <em>Ich wars</em></p>
        <p>
Ich: <em>Herzlichen Glückwunsch! Du hast den Build kaputt gemacht.</em></p>
        <p>
Er:<em> Bei mir läufts!</em></p>
        <p>
 
</p>
        <p>
Was ist die Moral der Geschichte? Ob es auf dem eigenen Rechner kompiliert ist egal.
Der Build Server (und nur der) ist wirklich wichtig!
</p>
        <p>
 
</p>
        <p>
Daher möchte ich aus gegebenem Anlass an dieser Stelle an folgende Zertifizierung
erinnern:
</p>
        <p>
          <a href="http://jcooney.net/archive/2007/02/01/42999.aspx">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="64" alt="worksonmymachine_logo_small" src="http://blog.codemurai.de/images/InteressanteZertifizierung_13806/worksonmymachine_logo_small.png" width="140" border="0" />
          </a>  
</p>
        <p>
Alternativ kann das Ganze übrigens auch in Form eines Awards vergeben werden:
</p>
        <p>
          <a href="http://www.codinghorror.com/blog/archives/000818.html">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="193" alt="works-on-my-machine-starburst" src="http://blog.codemurai.de/images/InteressanteZertifizierung_13806/worksonmymachinestarburst.png" width="200" border="0" />
          </a>
        </p>
        <p>
Happy coding ;-)
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=382783fd-0514-436e-b104-47fc54018d59" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Interessante Zertifizierung</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,382783fd-0514-436e-b104-47fc54018d59.aspx</guid>
      <link>http://blog.codemurai.de/2009/06/04/InteressanteZertifizierung.aspx</link>
      <pubDate>Thu, 04 Jun 2009 20:11:14 GMT</pubDate>
      <description>&lt;p&gt;
Wer kennt solche Unterhaltungen nicht:
&lt;/p&gt;
&lt;p&gt;
Ich: &lt;em&gt;Der Build-Vorgang schlägt fehl. Wer hat als letztes eingecheckt?&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Er: &lt;em&gt;Ich wars&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Ich: &lt;em&gt;Herzlichen Glückwunsch! Du hast den Build kaputt gemacht.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Er:&lt;em&gt; Bei mir läufts!&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Was ist die Moral der Geschichte? Ob es auf dem eigenen Rechner kompiliert ist egal.
Der Build Server (und nur der) ist wirklich wichtig!
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Daher möchte ich aus gegebenem Anlass an dieser Stelle an folgende Zertifizierung
erinnern:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://jcooney.net/archive/2007/02/01/42999.aspx"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="64" alt="worksonmymachine_logo_small" src="http://blog.codemurai.de/images/InteressanteZertifizierung_13806/worksonmymachine_logo_small.png" width="140" border="0"&gt;&lt;/a&gt;&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Alternativ kann das Ganze übrigens auch in Form eines Awards vergeben werden:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.codinghorror.com/blog/archives/000818.html"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="193" alt="works-on-my-machine-starburst" src="http://blog.codemurai.de/images/InteressanteZertifizierung_13806/worksonmymachinestarburst.png" width="200" border="0"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Happy coding ;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=382783fd-0514-436e-b104-47fc54018d59" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,382783fd-0514-436e-b104-47fc54018d59.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Fun</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=84e2a56f-8935-475a-ae8b-002852500beb</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,84e2a56f-8935-475a-ae8b-002852500beb.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,84e2a56f-8935-475a-ae8b-002852500beb.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=84e2a56f-8935-475a-ae8b-002852500beb</wfw:commentRss>
      <slash:comments>7</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Ich weiß, ich bin spät, aber zum Glück noch nicht zu spät. <a href="http://blogs.msdn.com/softwarehersteller/archive/2009/05/06/msdn-blog-parade-was-sind-ihre-lieblings-entwickler-tools-mitmachen-und-gewinnen.aspx" target="_blank">MSDN
Deutschland</a> hat zur Blog-Parade aufgerufen und fragt nach den drei Lieblings-Entwickler-Tools.
</p>
        <p>
          <a href="http://blogs.msdn.com/softwarehersteller/archive/2009/05/06/msdn-blog-parade-was-sind-ihre-lieblings-entwickler-tools-mitmachen-und-gewinnen.aspx" target="_blank">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="32" alt="150x32_BlogParade_anim_thumb" src="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/150x32_BlogParade_anim_thumb.gif" width="150" border="0" />
          </a>
        </p>
        <p>
Nachdem <a href="http://coding.roecher.de/2009/05/26/meine-top-3-entwicklertools/" target="_blank">Mario</a>, <a href="http://www.vb-magazin.de/forums/blogs/alexbierhaus/archive/2009/05/15/top-3-entwicklertools.aspx" target="_blank">Alex</a>, <a href="http://blog.jan-welker.de/2009/05/16/MeineTop3EntwicklerTools.aspx" target="_blank">Jan</a> und
viele andere auch schon mit gemacht haben, möchte ich meinen Senf selbstverständlich
auch zum Besten geben.
</p>
        <p>
Das Visual Studio zur Grundausstattung eines Entwicklers gehört setze ich mal voraus
und lasse es daher außen vor. Nun aber zu meinen Top 3.
</p>
        <ol>
          <li>
            <h1>
              <a href="http://microsoft.com/whdc/devtools/debugging/" target="_blank">Microsoft
WinDbg</a>
            </h1>
            <a href="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/windbg.png">
              <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="157" alt="windbg" src="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/windbg_thumb.png" width="244" border="0" />
            </a>
            <br />
            <br />
Ich kann gar nicht aufzählen, wie oft mir dieses Tool schon in unangenehmen Situationen
geholfen hat. 
<br />
Wer kennt die Situation nicht: 
<br /><ul><li>
Man entwickelt eine Applikation 
</li><li>
Auf dem Entwicklungs- und Testsystemen läuft Sie großartig 
</li><li>
Beim Kunden stürzt sie ab 
</li><li>
Man hat weder eine vernünftige Fehlermeldung, noch einen aussagekräftigen Eintrag
in der Log-Datei 
</li><li>
Der Fehler ist bei uns nicht nachvollziehbar 
</li><li>
Wir dürfen mit unserem PC nicht ins Kundennetz und Visual Studio oder CoreDbg dürfen
wir dort auch nicht installieren 
</li><li>
„Pech gehabt, lieber Kunde“ oder wirres Code-Ändern ist keine valide Option ;-) 
</li></ul><p>
Wenn es so weit ist, hilft nur noch ein ganz tiefer Griff in die Werkzeugkiste, nämlich
der zu <a href="http://microsoft.com/whdc/devtools/debugging/" target="_blank">WinDbg</a>.
Für diejenigen, die ihn nicht kennen: WinDbg ist ein unmanaged (native) Debugger mit
grafischer Benutzeroberfläche. Dank der SOS Erweiterung kann man ihn jedoch wunderbar
dazu verwenden, auch managed Code zu debuggen. Zugegeben, der Komfort liegt etwas
hinter dem des in Visual Studio integrierten Debuggers, aber in der Not nimmt man
schließlich, was man bekommen kann. Das tolle an diesem Debugger ist nämlich, dass
er nicht installiert werden muss, sondern direkt vom Stick gestartet werden kann.
Außerdem "sieht" er etwas mehr als der in VS integrierte Debugger, denn schließlich
ist er ja eigentlich ein unmanaged Debugger. Bei Interesse könnte ich mich übrigens
dazu verleiten lassen, mal ein WinDbg Einsteiger Tutorial zu schreiben, oder zumindest
mein "Cheat-Sheet" hier aufs Blog zu packen. Also einfach die <strong>Kommentarfunktion</strong> dieses
Eintrags nutzen!
</p></li>
          <li>
            <h1>
              <a href="http://www.infragistics.com" target="_blank">Infragistics NetAdvantage</a>
            </h1>
            <a href="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/infragistics.png">
              <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="infragistics" src="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/infragistics_thumb.png" width="244" border="0" />
            </a> <br /><br />
»Für den ersten Eindruck gibt es keine zweite Chance« lautet ein geflügeltes Wort.
Dass Menschen einander innerhalb weniger Augenblicke beurteilen, ist allgemein bekannt.
Da diese Beurteilung vor allem anhand optischer Gesichtspunkte statt findet, achten
viele Menschen heutzutage in besonderem Maße auf ihr Äußeres. Nur so lassen sich wichtige
erste Begegnungen, wie zum Beispiel ein Vorstellungsgespräch, erfolgreich meistern. 
<p>
Ähnlich wie das menschliche Äußere bei einem Vorstellungsgespräch, kann auch das Äußere
einer Softwareapplikation – also die Benutzeroberfläche – im Zweifelsfall über Sieg
oder Niederlage (kaufen oder nicht kaufen!) entscheiden. Der Grund dafür ist, dass
viele Benutzer, vor allem solche, die technisch nicht sonderlich versiert sind, <strong>vom
Eindruck der Benutzeroberfläche auf die Gesamtqualität der Software schließen</strong>.
Komplexe, überladene Bildschirmmasken, deren Design an ein typisches Look and Feel
von vor zehn Jahren erinnern, mindern potentiell also den kommerziellen Erfolg einer
Anwendung. Dies gilt besonders dann, wenn die Konkurrenz ihre Hausaufgaben gemacht
hat! 
</p><p>
Reichte es vor 15 Jahren noch vollkommen aus, einfach nur die Bedienung der Applikation
mit der Maus zu unterstützen, erwarten Anwender heute doch einiges mehr. Angeregt
von innovativen Oberflächenelementen in Applikationen großer Hersteller, wie zum Beispiel
Apples Coverflow, das Ribbon in Microsoft Office 2007 oder interaktiv gruppierbarer
Tabellen wie in Microsoft Outlook, erwarten Endanwender solche Features auch in anderen,
also <strong>unseren</strong> Applikationen. 
</p><p>
Leider kommt man mit den Bordmitteln, die Microsoft Visual Studio bis zur Version
2008 an dieser Stelle liefert nicht immer ans Ziel. So sind zum Beispiel weder Ribbons,
noch interaktiv gruppierbare Tabellen oder Excel ähnliche Diagramme „out-of-the-box“
möglich. 
</p><p>
Möchte man die Anforderungen an eine konkurrenzfähige Oberfläche also erfüllen, kommt
man (wirtschaftlich gesehen) kaum um den Einsatz einer 3rd Party UI Komponentensuite
herum. 
</p><p>
Die Suite meiner Wahl ist <a href="http://www.infragistics.com" target="_blank">Infragistics
NetAdvantage</a>. Die Komponenten sehen nicht nur top aus, sondern bieten auch alle
Features, die das Entwicklerherz begehrt. 
</p></li>
          <li>
            <h1>
              <a href="http://code.msdn.microsoft.com/sourceanalysis" target="_blank">StyleCop</a>
            </h1>
Konsistente Quellcode Formatierungen in einem Projekt mit mehreren Entwicklern. müssen
dank <a href="http://code.msdn.microsoft.com/sourceanalysis" target="_blank">StyleCop</a> kein
Wunschtraum mehr bleiben. Jedem, der im Team entwickelt kann ich dieses Tool nur wärmstens
ans Herz legen!<br /></li>
        </ol>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=84e2a56f-8935-475a-ae8b-002852500beb" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Meine drei Top Entwicklertools</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,84e2a56f-8935-475a-ae8b-002852500beb.aspx</guid>
      <link>http://blog.codemurai.de/2009/06/04/MeineDreiTopEntwicklertools.aspx</link>
      <pubDate>Thu, 04 Jun 2009 19:51:15 GMT</pubDate>
      <description>&lt;p&gt;
Ich weiß, ich bin spät, aber zum Glück noch nicht zu spät. &lt;a href="http://blogs.msdn.com/softwarehersteller/archive/2009/05/06/msdn-blog-parade-was-sind-ihre-lieblings-entwickler-tools-mitmachen-und-gewinnen.aspx" target="_blank"&gt;MSDN
Deutschland&lt;/a&gt; hat zur Blog-Parade aufgerufen und fragt nach den drei Lieblings-Entwickler-Tools.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blogs.msdn.com/softwarehersteller/archive/2009/05/06/msdn-blog-parade-was-sind-ihre-lieblings-entwickler-tools-mitmachen-und-gewinnen.aspx" target="_blank"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="32" alt="150x32_BlogParade_anim_thumb" src="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/150x32_BlogParade_anim_thumb.gif" width="150" border="0"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Nachdem &lt;a href="http://coding.roecher.de/2009/05/26/meine-top-3-entwicklertools/" target="_blank"&gt;Mario&lt;/a&gt;, &lt;a href="http://www.vb-magazin.de/forums/blogs/alexbierhaus/archive/2009/05/15/top-3-entwicklertools.aspx" target="_blank"&gt;Alex&lt;/a&gt;, &lt;a href="http://blog.jan-welker.de/2009/05/16/MeineTop3EntwicklerTools.aspx" target="_blank"&gt;Jan&lt;/a&gt; und
viele andere auch schon mit gemacht haben, möchte ich meinen Senf selbstverständlich
auch zum Besten geben.
&lt;/p&gt;
&lt;p&gt;
Das Visual Studio zur Grundausstattung eines Entwicklers gehört setze ich mal voraus
und lasse es daher außen vor. Nun aber zu meinen Top 3.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;h1&gt;&lt;a href="http://microsoft.com/whdc/devtools/debugging/" target="_blank"&gt;Microsoft
WinDbg&lt;/a&gt;
&lt;/h1&gt;
&lt;a href="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/windbg.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="157" alt="windbg" src="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/windbg_thumb.png" width="244" border="0"&gt;&lt;/a&gt; 
&lt;br&gt;
&lt;br&gt;
Ich kann gar nicht aufzählen, wie oft mir dieses Tool schon in unangenehmen Situationen
geholfen hat. 
&lt;br&gt;
Wer kennt die Situation nicht: 
&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;
Man entwickelt eine Applikation 
&lt;li&gt;
Auf dem Entwicklungs- und Testsystemen läuft Sie großartig 
&lt;li&gt;
Beim Kunden stürzt sie ab 
&lt;li&gt;
Man hat weder eine vernünftige Fehlermeldung, noch einen aussagekräftigen Eintrag
in der Log-Datei 
&lt;li&gt;
Der Fehler ist bei uns nicht nachvollziehbar 
&lt;li&gt;
Wir dürfen mit unserem PC nicht ins Kundennetz und Visual Studio oder CoreDbg dürfen
wir dort auch nicht installieren 
&lt;li&gt;
„Pech gehabt, lieber Kunde“ oder wirres Code-Ändern ist keine valide Option ;-) 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Wenn es so weit ist, hilft nur noch ein ganz tiefer Griff in die Werkzeugkiste, nämlich
der zu &lt;a href="http://microsoft.com/whdc/devtools/debugging/" target="_blank"&gt;WinDbg&lt;/a&gt;.
Für diejenigen, die ihn nicht kennen: WinDbg ist ein unmanaged (native) Debugger mit
grafischer Benutzeroberfläche. Dank der SOS Erweiterung kann man ihn jedoch wunderbar
dazu verwenden, auch managed Code zu debuggen. Zugegeben, der Komfort liegt etwas
hinter dem des in Visual Studio integrierten Debuggers, aber in der Not nimmt man
schließlich, was man bekommen kann. Das tolle an diesem Debugger ist nämlich, dass
er nicht installiert werden muss, sondern direkt vom Stick gestartet werden kann.
Außerdem "sieht" er etwas mehr als der in VS integrierte Debugger, denn schließlich
ist er ja eigentlich ein unmanaged Debugger. Bei Interesse könnte ich mich übrigens
dazu verleiten lassen, mal ein WinDbg Einsteiger Tutorial zu schreiben, oder zumindest
mein "Cheat-Sheet" hier aufs Blog zu packen. Also einfach die &lt;strong&gt;Kommentarfunktion&lt;/strong&gt; dieses
Eintrags nutzen!
&lt;/p&gt;
&lt;li&gt;
&lt;h1&gt;&lt;a href="http://www.infragistics.com" target="_blank"&gt;Infragistics NetAdvantage&lt;/a&gt;
&lt;/h1&gt;
&lt;a href="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/infragistics.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="infragistics" src="http://blog.codemurai.de/images/MeinedreiTopEntwicklertools_EEAD/infragistics_thumb.png" width="244" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;br&gt;
&lt;br&gt;
»Für den ersten Eindruck gibt es keine zweite Chance« lautet ein geflügeltes Wort.
Dass Menschen einander innerhalb weniger Augenblicke beurteilen, ist allgemein bekannt.
Da diese Beurteilung vor allem anhand optischer Gesichtspunkte statt findet, achten
viele Menschen heutzutage in besonderem Maße auf ihr Äußeres. Nur so lassen sich wichtige
erste Begegnungen, wie zum Beispiel ein Vorstellungsgespräch, erfolgreich meistern. 
&lt;p&gt;
Ähnlich wie das menschliche Äußere bei einem Vorstellungsgespräch, kann auch das Äußere
einer Softwareapplikation – also die Benutzeroberfläche – im Zweifelsfall über Sieg
oder Niederlage (kaufen oder nicht kaufen!) entscheiden. Der Grund dafür ist, dass
viele Benutzer, vor allem solche, die technisch nicht sonderlich versiert sind, &lt;strong&gt;vom
Eindruck der Benutzeroberfläche auf die Gesamtqualität der Software schließen&lt;/strong&gt;.
Komplexe, überladene Bildschirmmasken, deren Design an ein typisches Look and Feel
von vor zehn Jahren erinnern, mindern potentiell also den kommerziellen Erfolg einer
Anwendung. Dies gilt besonders dann, wenn die Konkurrenz ihre Hausaufgaben gemacht
hat! 
&lt;p&gt;
Reichte es vor 15 Jahren noch vollkommen aus, einfach nur die Bedienung der Applikation
mit der Maus zu unterstützen, erwarten Anwender heute doch einiges mehr. Angeregt
von innovativen Oberflächenelementen in Applikationen großer Hersteller, wie zum Beispiel
Apples Coverflow, das Ribbon in Microsoft Office 2007 oder interaktiv gruppierbarer
Tabellen wie in Microsoft Outlook, erwarten Endanwender solche Features auch in anderen,
also &lt;strong&gt;unseren&lt;/strong&gt; Applikationen. 
&lt;p&gt;
Leider kommt man mit den Bordmitteln, die Microsoft Visual Studio bis zur Version
2008 an dieser Stelle liefert nicht immer ans Ziel. So sind zum Beispiel weder Ribbons,
noch interaktiv gruppierbare Tabellen oder Excel ähnliche Diagramme „out-of-the-box“
möglich. 
&lt;p&gt;
Möchte man die Anforderungen an eine konkurrenzfähige Oberfläche also erfüllen, kommt
man (wirtschaftlich gesehen) kaum um den Einsatz einer 3rd Party UI Komponentensuite
herum. 
&lt;p&gt;
Die Suite meiner Wahl ist &lt;a href="http://www.infragistics.com" target="_blank"&gt;Infragistics
NetAdvantage&lt;/a&gt;. Die Komponenten sehen nicht nur top aus, sondern bieten auch alle
Features, die das Entwicklerherz begehrt. 
&lt;/p&gt;
&lt;li&gt;
&lt;h1&gt;&lt;a href="http://code.msdn.microsoft.com/sourceanalysis" target="_blank"&gt;StyleCop&lt;/a&gt;
&lt;/h1&gt;
Konsistente Quellcode Formatierungen in einem Projekt mit mehreren Entwicklern. müssen
dank &lt;a href="http://code.msdn.microsoft.com/sourceanalysis" target="_blank"&gt;StyleCop&lt;/a&gt; kein
Wunschtraum mehr bleiben. Jedem, der im Team entwickelt kann ich dieses Tool nur wärmstens
ans Herz legen!&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=84e2a56f-8935-475a-ae8b-002852500beb" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,84e2a56f-8935-475a-ae8b-002852500beb.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>Tips und Tricks</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=0a6665cc-4300-432b-9193-55183ddf4aaa</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,0a6665cc-4300-432b-9193-55183ddf4aaa.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,0a6665cc-4300-432b-9193-55183ddf4aaa.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=0a6665cc-4300-432b-9193-55183ddf4aaa</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Wer den RSS Feed seines Blogs via Feedburner publiziert, kann mit Hilfe eines <a href="http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;answer=78966" target="_blank">FeedFlares</a> sehr
einfach einen dynamischen Dotnet-kicks.de Link unter jeden Eintrag setzen.
</p>
        <p>
Dazu ist wie folgt vorzugehen:
</p>
        <ol>
          <li>
Einloggen bei <a href="http://feedburner.google.com" target="_blank">feedburner</a></li>
          <li>
Feed zur Verwaltung auswählen</li>
          <li>
            <a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image.png">
              <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="141" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb.png" width="244" border="0" />
            </a>
          </li>
          <li>
Registrierkarte Optimize anklicken.</li>
          <li>
Links im Menü den Punkt FeedFlare wählen<br /><a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_3.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb_3.png" width="147" border="0" /></a></li>
          <li>
Neuen Flare hinzufügen<br /><a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_4.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="182" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb_4.png" width="244" border="0" /></a><br />
Eine passende Flare Datei, die von jedem Benutzt werden darf, befindet sich auf meiner
Homepage unter <a title="http://www.codemurai.de/downloads/kick_it-deflare.xml" href="http://www.codemurai.de/downloads/kick_it-deflare.xml">http://www.codemurai.de/downloads/kick_it-deflare.xml</a></li>
          <li>
Speichern und Aktivieren<br /><a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_5.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="150" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb_5.png" width="244" border="0" /></a></li>
          <li>
Das Ergebnis genießen ;-)<br /><a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_6.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="66" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb_6.png" width="244" border="0" /></a></li>
        </ol>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=0a6665cc-4300-432b-9193-55183ddf4aaa" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Dotnet-kicks.de Link in Feedburner RSS Footer einbinden</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,0a6665cc-4300-432b-9193-55183ddf4aaa.aspx</guid>
      <link>http://blog.codemurai.de/2009/05/18/DotnetkicksdeLinkInFeedburnerRSSFooterEinbinden.aspx</link>
      <pubDate>Mon, 18 May 2009 20:25:55 GMT</pubDate>
      <description>&lt;p&gt;
Wer den RSS Feed seines Blogs via Feedburner publiziert, kann mit Hilfe eines &lt;a href="http://www.google.com/support/feedburner/bin/answer.py?hl=en&amp;amp;answer=78966" target="_blank"&gt;FeedFlares&lt;/a&gt; sehr
einfach einen dynamischen Dotnet-kicks.de Link unter jeden Eintrag setzen.
&lt;/p&gt;
&lt;p&gt;
Dazu ist wie folgt vorzugehen:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Einloggen bei &lt;a href="http://feedburner.google.com" target="_blank"&gt;feedburner&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Feed zur Verwaltung auswählen&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="141" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb.png" width="244" border="0"&gt;&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
Registrierkarte Optimize anklicken.&lt;/li&gt;
&lt;li&gt;
Links im Menü den Punkt FeedFlare wählen&lt;br&gt;
&lt;a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_3.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb_3.png" width="147" border="0"&gt;&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
Neuen Flare hinzufügen&lt;br&gt;
&lt;a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_4.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="182" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb_4.png" width="244" border="0"&gt;&lt;/a&gt; 
&lt;br&gt;
Eine passende Flare Datei, die von jedem Benutzt werden darf, befindet sich auf meiner
Homepage unter &lt;a title="http://www.codemurai.de/downloads/kick_it-deflare.xml" href="http://www.codemurai.de/downloads/kick_it-deflare.xml"&gt;http://www.codemurai.de/downloads/kick_it-deflare.xml&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Speichern und Aktivieren&lt;br&gt;
&lt;a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_5.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="150" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb_5.png" width="244" border="0"&gt;&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
Das Ergebnis genießen ;-)&lt;br&gt;
&lt;a href="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_6.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="66" alt="image" src="http://blog.codemurai.de/images/Dot.deLinkinFeedburnerRSSFootereinbinden_1397A/image_thumb_6.png" width="244" border="0"&gt;&lt;/a&gt; 
&lt;/li&gt;
&lt;/ol&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=0a6665cc-4300-432b-9193-55183ddf4aaa" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,0a6665cc-4300-432b-9193-55183ddf4aaa.aspx</comments>
      <category>.NET</category>
      <category>Community</category>
      <category>DotNetGerman Bloggers</category>
      <category>Tips und Tricks</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=33a43d8c-76fc-4ded-a1b0-2a9ebe55b1ba</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,33a43d8c-76fc-4ded-a1b0-2a9ebe55b1ba.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,33a43d8c-76fc-4ded-a1b0-2a9ebe55b1ba.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=33a43d8c-76fc-4ded-a1b0-2a9ebe55b1ba</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Seit über drei Jahren ist ASP.NET 2.0 nun schon in der Final Version auf dem Markt
und bis Mitte letzter Woche habe ich sie übersehen: Die Eigenschaft <strong>AssociatedControlID</strong> des
ASP.NET Label Controls. Bisher habe ich auf den Einsatz dieses Controls möglichst
verzichtet, da es in meinen Augen "nur" einen unnötigen Span-Tag um meinen Text setzt.
</p>
        <p>
Habe ich in meiner aspx Seite also folgenden Code:
</p>
        <p>
&lt;asp:Label ID="Label1" runat="server" Text="Ich bin ein Label"&gt;&lt;/asp:Label&gt;<br />
&lt;asp:TextBox ID="TextBox1" runat="server"&gt;Ich bin eine Textbox&lt;/asp:TextBox&gt;&lt;br
/&gt; 
</p>
        <p>
wird dies zu folgendem Markup: 
</p>
        <p>
          <strong>&lt;span id="Label1"&gt;</strong>Ich bin ein Label<strong>&lt;/span&gt;<br /></strong>&lt;input name="TextBox1" type="text" value="Ich bin eine Textbox" id="TextBox1"
/&gt;&lt;br /&gt; 
</p>
        <p>
Alles in allem ist dies wenig spektakulär. 
</p>
        <p>
Erweitere ich meinen Code nun jedoch um die Eigenschaft AssociatedControlID 
</p>
        <p>
&lt;asp:Label ID="Label2" runat="server" <strong>AssociatedControlID="TextBox2"</strong> Text="Ich
bin auch ein Label"&gt;&lt;/asp:Label&gt;<br />
&lt;asp:TextBox ID="TextBox2" runat="server"&gt;Ich bin auch eine Textbox&lt;/asp:TextBox&gt;&lt;/div&gt; 
</p>
        <p>
wird das ASP.NET Label nicht mehr als Span-Tag, sondern als HTML Label-Tag gerendert: 
</p>
        <p>
&lt;<strong>label for="TextBox2" id="Label2"&gt;</strong>Ich bin auch ein Label<strong>&lt;/label&gt;<br /></strong>&lt;input name="<strong>TextBox2</strong>" type="text" value="Ich bin auch
eine Textbox" id="TextBox2" /&gt; 
</p>
        <p>
Schön und gut, aber wo liegt der Vorteil? 
</p>
        <p>
Zum einen schafft der HTML Code durch den Zusatz "for=&lt;anderes Control&gt;" eine
logische Verknüpfung zwischen Eingabefeld und Beschriftung. Dies kann von Screenreadern
ausgelesen werden und verbessert somit die Barrierefreiheit. 
</p>
        <p>
Dies ist jedoch nicht alles. Für den Standardbenutzer ergibt sich der Vorteil, dass
er nun innerhalb des Browsers mit der Maus einfach auf das Label klicken kann und
anschließend automatisch das assozierte Steuerlement den Fokus erhält. 
</p>
        <p>
Mein Fazit: ein tolles Feature, was sowohl Usability, als auch Barrierefreiheit mit
sehr wenig Aufwand erhöht. 
</p>
        <p>
Näheres findet sich übrigens auch bei <a href="http://de.selfhtml.org/html/formulare/strukturieren.htm#label" target="_blank">selfhtml</a>. 
</p>
        <p>
Die Frage ist nur: Warum habe ich es so lange übersehen? Vielleicht liegt es daran,
dass es unter ASP.NET 1.0 noch nicht existierte und die anderen Neuerungen einfach
so viel aufregender waren?
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=33a43d8c-76fc-4ded-a1b0-2a9ebe55b1ba" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Übersehenes Feature in ASP.NET 2.0</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,33a43d8c-76fc-4ded-a1b0-2a9ebe55b1ba.aspx</guid>
      <link>http://blog.codemurai.de/2009/04/30/%c3%9cbersehenesFeatureInASPNET20.aspx</link>
      <pubDate>Thu, 30 Apr 2009 06:58:43 GMT</pubDate>
      <description>&lt;p&gt;
Seit über drei Jahren ist ASP.NET 2.0 nun schon in der Final Version auf dem Markt
und bis Mitte letzter Woche habe ich sie übersehen: Die Eigenschaft &lt;strong&gt;AssociatedControlID&lt;/strong&gt; des
ASP.NET Label Controls. Bisher habe ich auf den Einsatz dieses Controls möglichst
verzichtet, da es in meinen Augen "nur" einen unnötigen Span-Tag um meinen Text setzt.
&lt;/p&gt;
&lt;p&gt;
Habe ich in meiner aspx Seite also folgenden Code:
&lt;/p&gt;
&lt;p&gt;
&amp;lt;asp:Label ID="Label1" runat="server" Text="Ich bin ein Label"&amp;gt;&amp;lt;/asp:Label&amp;gt;&lt;br&gt;
&amp;lt;asp:TextBox ID="TextBox1" runat="server"&amp;gt;Ich bin eine Textbox&amp;lt;/asp:TextBox&amp;gt;&amp;lt;br
/&amp;gt; 
&lt;p&gt;
wird dies zu folgendem Markup: 
&lt;p&gt;
&lt;strong&gt;&amp;lt;span id="Label1"&amp;gt;&lt;/strong&gt;Ich bin ein Label&lt;strong&gt;&amp;lt;/span&amp;gt;&lt;br&gt;
&lt;/strong&gt;&amp;lt;input name="TextBox1" type="text" value="Ich bin eine Textbox" id="TextBox1"
/&amp;gt;&amp;lt;br /&amp;gt; 
&lt;p&gt;
Alles in allem ist dies wenig spektakulär. 
&lt;p&gt;
Erweitere ich meinen Code nun jedoch um die Eigenschaft AssociatedControlID 
&lt;p&gt;
&amp;lt;asp:Label ID="Label2" runat="server" &lt;strong&gt;AssociatedControlID="TextBox2"&lt;/strong&gt; Text="Ich
bin auch ein Label"&amp;gt;&amp;lt;/asp:Label&amp;gt;&lt;br&gt;
&amp;lt;asp:TextBox ID="TextBox2" runat="server"&amp;gt;Ich bin auch eine Textbox&amp;lt;/asp:TextBox&amp;gt;&amp;lt;/div&amp;gt; 
&lt;p&gt;
wird das ASP.NET Label nicht mehr als Span-Tag, sondern als HTML Label-Tag gerendert: 
&lt;p&gt;
&amp;lt;&lt;strong&gt;label for="TextBox2" id="Label2"&amp;gt;&lt;/strong&gt;Ich bin auch ein Label&lt;strong&gt;&amp;lt;/label&amp;gt;&lt;br&gt;
&lt;/strong&gt;&amp;lt;input name="&lt;strong&gt;TextBox2&lt;/strong&gt;" type="text" value="Ich bin auch
eine Textbox" id="TextBox2" /&amp;gt; 
&lt;p&gt;
Schön und gut, aber wo liegt der Vorteil? 
&lt;p&gt;
Zum einen schafft der HTML Code durch den Zusatz "for=&amp;lt;anderes Control&amp;gt;" eine
logische Verknüpfung zwischen Eingabefeld und Beschriftung. Dies kann von Screenreadern
ausgelesen werden und verbessert somit die Barrierefreiheit. 
&lt;p&gt;
Dies ist jedoch nicht alles. Für den Standardbenutzer ergibt sich der Vorteil, dass
er nun innerhalb des Browsers mit der Maus einfach auf das Label klicken kann und
anschließend automatisch das assozierte Steuerlement den Fokus erhält. 
&lt;p&gt;
Mein Fazit: ein tolles Feature, was sowohl Usability, als auch Barrierefreiheit mit
sehr wenig Aufwand erhöht. 
&lt;p&gt;
Näheres findet sich übrigens auch bei &lt;a href="http://de.selfhtml.org/html/formulare/strukturieren.htm#label" target="_blank"&gt;selfhtml&lt;/a&gt;. 
&lt;p&gt;
Die Frage ist nur: Warum habe ich es so lange übersehen? Vielleicht liegt es daran,
dass es unter ASP.NET 1.0 noch nicht existierte und die anderen Neuerungen einfach
so viel aufregender waren?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=33a43d8c-76fc-4ded-a1b0-2a9ebe55b1ba" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,33a43d8c-76fc-4ded-a1b0-2a9ebe55b1ba.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=c0ed1938-3fa2-4ea4-bb2c-797d21dbdb0c</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,c0ed1938-3fa2-4ea4-bb2c-797d21dbdb0c.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,c0ed1938-3fa2-4ea4-bb2c-797d21dbdb0c.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=c0ed1938-3fa2-4ea4-bb2c-797d21dbdb0c</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Dienstag Abend fand ich folgende E-Mail in meinem Postfach: 
</p>
        <blockquote>
          <p>
            <em>Dear Andre,<br />
Congratulations! We are pleased to present you with the 2008 Infragistics MVP Award!
Your actions in the community have not only promoted the spirit of community but have
also helped other professionals in the industry to be more successful each and every
day. This award is our way of thanking you for your contributions.</em>
          </p>
          <p>
            <em>[...]</em>
          </p>
          <p>
            <em>Thank you again,<br />
Tony Lombardo<br />
Anthony Lombardo<br />
Lead Technical Evangelist<br />
Infragistics, Inc. 
<br />
Worldwide Evangelism Group</em>
          </p>
        </blockquote>
        <p>
Bis zu diesem Augenblick wusste ich noch nicht einmal, dass Infragistics MVPs auszeichnet.
Des Rätsels Lösung: Die Auszeichnung gibt es - laut <a href="http://blogs.infragistics.com/blogs/tony_lombardo/archive/2009/03/31/announcing-the-infragistics-mvp-program.aspx" target="_blank">Tonys
Blog</a> - erst seit letztem Dienstag. Demnach bin ich einer der ersten Infragistics
MVPs.
</p>
        <p>
Die Auszeichnung kam sehr überraschen für mich und selbstverständlich habe ich mich
sehr gefreut und bin extrem stolz. Sie ist in meinen Augen ein toller Weg, um Community
Engagement zu wertschätzen. 
</p>
        <p>
Mein Dank gilt neben dem Infragistics Team vor allem Nic Goetz!
</p>
        <p>
          <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="266" alt="IgMvpLogoRotatedReflected_43836EBF" src="http://blog.codemurai.de/images/CongratulationsYouhavereceivedtheInfragi_E9D1/IgMvpLogoRotatedReflected_43836EBF.png" width="173" border="0" />
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=c0ed1938-3fa2-4ea4-bb2c-797d21dbdb0c" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Congratulations, You have received the Infragistics MVP Award</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,c0ed1938-3fa2-4ea4-bb2c-797d21dbdb0c.aspx</guid>
      <link>http://blog.codemurai.de/2009/04/03/CongratulationsYouHaveReceivedTheInfragisticsMVPAward.aspx</link>
      <pubDate>Fri, 03 Apr 2009 13:03:34 GMT</pubDate>
      <description>&lt;p&gt;
Dienstag Abend fand ich folgende E-Mail in meinem Postfach: &lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Dear Andre,&lt;br&gt;
Congratulations! We are pleased to present you with the 2008 Infragistics MVP Award!
Your actions in the community have not only promoted the spirit of community but have
also helped other professionals in the industry to be more successful each and every
day. This award is our way of thanking you for your contributions.&lt;/em&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;[...]&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Thank you again,&lt;br&gt;
Tony Lombardo&lt;br&gt;
Anthony Lombardo&lt;br&gt;
Lead Technical Evangelist&lt;br&gt;
Infragistics, Inc. 
&lt;br&gt;
Worldwide Evangelism Group&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Bis zu diesem Augenblick wusste ich noch nicht einmal, dass Infragistics MVPs auszeichnet.
Des Rätsels Lösung: Die Auszeichnung gibt es - laut &lt;a href="http://blogs.infragistics.com/blogs/tony_lombardo/archive/2009/03/31/announcing-the-infragistics-mvp-program.aspx" target="_blank"&gt;Tonys
Blog&lt;/a&gt; - erst seit letztem Dienstag. Demnach bin ich einer der ersten Infragistics
MVPs.
&lt;/p&gt;
&lt;p&gt;
Die Auszeichnung kam sehr überraschen für mich und selbstverständlich habe ich mich
sehr gefreut und bin extrem stolz. Sie ist in meinen Augen ein toller Weg, um Community
Engagement zu wertschätzen. 
&lt;/p&gt;
&lt;p&gt;
Mein Dank gilt neben dem Infragistics Team vor allem Nic Goetz!
&lt;/p&gt;
&lt;p&gt;
&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="266" alt="IgMvpLogoRotatedReflected_43836EBF" src="http://blog.codemurai.de/images/CongratulationsYouhavereceivedtheInfragi_E9D1/IgMvpLogoRotatedReflected_43836EBF.png" width="173" border="0"&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=c0ed1938-3fa2-4ea4-bb2c-797d21dbdb0c" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,c0ed1938-3fa2-4ea4-bb2c-797d21dbdb0c.aspx</comments>
      <category>.NET</category>
      <category>Community</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=5322fedd-3010-40de-a316-cc380aab6648</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,5322fedd-3010-40de-a316-cc380aab6648.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,5322fedd-3010-40de-a316-cc380aab6648.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=5322fedd-3010-40de-a316-cc380aab6648</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Genau ein Jahr und einen Monat ist es nun her, dass Eric Berres, Markus Renning, Thomas
Naunheim und ich die <a href="http://www.dnug-koblenz.de" target="_blank">.NET User
Group Koblenz</a> ins Leben riefen. Ein Jahr und <strong>einen Monat</strong>? Ist
das nicht ein wenig <strong>spät</strong> für eine Gratulation? Normalerweise schon,
aber aufgrund meiner anderen Aktivitäten (Familie, Job, Hausbau, Basta Vortrag, ...)
lag mein Blog in den letzten Wochen ein wenig brach, so dass ich erst jetzt dazu komme,
der <a href="http://www.dnug-koblenz.de" target="_blank">DNUG Koblenz</a> zu gratulieren.
</p>
        <p>
Im Januar 2008, als Eric, Markus, Thomas und ich zum ersten Mal (außerhalb eines Fast-Food-Restaurants
;-)) zur Vorbesprechung zusammen saßen, waren wir uns sehr unsicher, ob das ganze
überhaupt funktionieren würde. Wir waren uns vollkommen im unklaren darüber, wie viele
Teilnehmer wohl zu den treffen kommen würden. Unsere schlimmste Befürchtung war, dass
wir nur zu viert sein könnten und sich alles relativ schnell wieder im Sande verlieren
würde. Auch waren wir unsicher, ob wir die Organisation überhaupt geregelt bekommen,
da niemand von uns zuvor auf einem Treffen einer anderen DNUG waren. So richtig wusste
also keiner von uns, was wir auf unseren Treffen also wirklich machen müssen. Auch
hatten wir keine Idee, wie wir an andere Sprecher, intern oder extern, abgesehen von
uns selbst, heran kommen könnten.
</p>
        <p>
Glücklicherweise waren unsere Bedenken weitestgehend unnötig. Im Schnitt haben wir
ca. 20 Teilnehmer pro Treffen. Sicherlich sind es auch mal <em>nur</em> 10, oder auch
mal über 30, normalerweise sollten es jedoch um die 20 sein.
</p>
        <p>
Auch die Sprecher gingen uns nie aus. So konnten wir neben einigen Referenten aus
den eigenen Reihen auch - INETA Germany und einiger Community Kontakte sei dank -
bekannte Sprecher aus der Community für einen Vortrag bei uns gewinnen. Eines der
absoluten Highlights in diesem Zusammenhang war sicherlich der Vortrag von <a href="http://blogs.infragistics.com/tonyl" target="_blank">Tony
Lombardo</a>,  ASP.NET MVP und Worldwide Lead Evangelist der Firma Infragistics,
der während seines Europa Aufenthalts zur TechEd Europe einen Zwischenstopp in Koblenz
machte, um uns etwas zum Thema Silverlight zu erzählen.
</p>
        <p>
An dieser Stelle möchte jedoch nicht nur Tony hervorheben, sondern mich auch bei allen
anderen Sprechern für ihre tollen Vorträge bedanken.
</p>
        <p>
Im einzelnen wären da zu nennen:
</p>
        <ul>
          <li>
Eric Berres: Einführung in DNN, Einführung in die WCF 
</li>
          <li>
Jan Meinecken: Einführung in die Windows Sharepoint Services 
</li>
          <li>
            <a href="http://blog.lars-keller.net/" target="_blank">Lars Keller</a>: VSTO 
</li>
          <li>
Markus Kissling: Oracle &amp; .NET   
</li>
          <li>
David Kortmann: Eigener Membershipprovider in 12 1/2 Minuten 
</li>
          <li>
            <a href="http://blog.codemurai.de" target="_blank">André Krämer</a>: Jetzt lerne ich
C#3.0 in 12 1/2 Minuten, SOS nicht nur für Schiffbrüchige, Schätzen statt raten, Design
By Contract  
</li>
          <li>
Thomas Naunheim: TFS 2008 
</li>
          <li>
Frank Pommering: Reflection 
</li>
          <li>
Markus Rennings: Neuerungen in Visual Studio 2008 für ASP.NET, Einführung in das ADO.NET
Entity Framework, .NET Framework Debugging, Custom Images für VS Commands  
</li>
          <li>
Alexander Rippert: Unit Testing 
</li>
          <li>
Mario Röcher: Das Decorator Pattern 
</li>
          <li>
            <a href="http://blogs.msdn.com/jenss" target="_blank">Jens K. Süßmeyer</a>: Einführung
in den SQL Server 2008 
</li>
          <li>
            <a href="http://www.torstenweber.de" target="_blank">Torsten Weber</a>: Einführung
in das Mobile Computing, Keine Zeit für Herzrasen 
</li>
          <li>
            <a href="http://www.bonn-to-code.net" target="_blank">Roland Weigelt</a>: GUI Design
für nicht Designer 
</li>
        </ul>
        <p>
Außerdem gilt natürlich unseren Sponsoren ein herzlicher Dank!
</p>
        <ul>
          <li>
            <a href="http://www.artiso.de" target="_blank">Artiso</a>: Softwarelizenzen 
</li>
          <li>
            <a href="http://www.devexpress.com" target="_blank">DevExpress</a>: Softwarelizenzen 
</li>
          <li>
            <a href="http://www.dotnetpro.de" target="_blank">dotnetpro</a>: Einige freie Exemplare
der dotnetpro 
</li>
          <li>
            <a href="http://www.entwickler-press.de" target="_blank">entwickler.press</a>: Bücher 
</li>
          <li>
            <a href="http://www.ineta.org" target="_blank">INETA Germany</a>: Sprecher 
</li>
          <li>
            <a href="http://www.infragistics.com" target="_blank">Infragistics</a>: Sprecher und
Softwarelizenzen 
</li>
          <li>
            <a href="http://www.jetbrains.com" target="_blank">Jetbrains</a>: Sofwarelizenzen 
</li>
          <li>
            <a href="http://www.konzeptum.de" target="_blank">Konzeptum GmbH</a>: Raum, Technik,
Getränke 
</li>
          <li>
MS Press: Buchgutscheine 
</li>
        </ul>
        <p>
Außerdem vielen Dank an:
</p>
        <ul>
          <li>
            <a href="http://www.bonn-to-code.net" target="_blank">Roland Weigelt</a>: Für die
tolle "Anleitung" zur Gründung einer User Group 
</li>
          <li>
            <a href="http://www.torstenweber.de" target="_blank">Torsten Weber</a>: Für die hilfreichen
Tips zur Gründung einer User Group</li>
        </ul>
        <p>
Wow, die vielen Danksagungen erinnern schon fast an die Oscar Verleihung. Den haben
wir zwar (noch :-)) nicht erhalten, dafür hat Microsoft uns jedoch ein tolles Geschenk
gemacht. Am Abend des Geburtstagstreffens erhielten wir nämlich die Nachricht, dass
wir ins Microsoft CLIP Programm aufgenommen wurden! Vielen Dank (:-))
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=5322fedd-3010-40de-a316-cc380aab6648" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Happy Birthday DNUG Koblenz</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,5322fedd-3010-40de-a316-cc380aab6648.aspx</guid>
      <link>http://blog.codemurai.de/2009/03/18/HappyBirthdayDNUGKoblenz.aspx</link>
      <pubDate>Wed, 18 Mar 2009 22:25:01 GMT</pubDate>
      <description>&lt;p&gt;
Genau ein Jahr und einen Monat ist es nun her, dass Eric Berres, Markus Renning, Thomas
Naunheim und ich die &lt;a href="http://www.dnug-koblenz.de" target="_blank"&gt;.NET User
Group Koblenz&lt;/a&gt; ins Leben riefen. Ein Jahr und &lt;strong&gt;einen Monat&lt;/strong&gt;? Ist
das nicht ein wenig &lt;strong&gt;spät&lt;/strong&gt; für eine Gratulation? Normalerweise schon,
aber aufgrund meiner anderen Aktivitäten (Familie, Job, Hausbau, Basta Vortrag, ...)
lag mein Blog in den letzten Wochen ein wenig brach, so dass ich erst jetzt dazu komme,
der &lt;a href="http://www.dnug-koblenz.de" target="_blank"&gt;DNUG Koblenz&lt;/a&gt; zu gratulieren.
&lt;/p&gt;
&lt;p&gt;
Im Januar 2008, als Eric, Markus, Thomas und ich zum ersten Mal (außerhalb eines Fast-Food-Restaurants
;-)) zur Vorbesprechung zusammen saßen, waren wir uns sehr unsicher, ob das ganze
überhaupt funktionieren würde. Wir waren uns vollkommen im unklaren darüber, wie viele
Teilnehmer wohl zu den treffen kommen würden. Unsere schlimmste Befürchtung war, dass
wir nur zu viert sein könnten und sich alles relativ schnell wieder im Sande verlieren
würde. Auch waren wir unsicher, ob wir die Organisation überhaupt geregelt bekommen,
da niemand von uns zuvor auf einem Treffen einer anderen DNUG waren. So richtig wusste
also keiner von uns, was wir auf unseren Treffen also wirklich machen müssen. Auch
hatten wir keine Idee, wie wir an andere Sprecher, intern oder extern, abgesehen von
uns selbst, heran kommen könnten.
&lt;/p&gt;
&lt;p&gt;
Glücklicherweise waren unsere Bedenken weitestgehend unnötig. Im Schnitt haben wir
ca. 20 Teilnehmer pro Treffen. Sicherlich sind es auch mal &lt;em&gt;nur&lt;/em&gt; 10, oder auch
mal über 30, normalerweise sollten es jedoch um die 20 sein.
&lt;/p&gt;
&lt;p&gt;
Auch die Sprecher gingen uns nie aus. So konnten wir neben einigen Referenten aus
den eigenen Reihen auch - INETA Germany und einiger Community Kontakte sei dank -
bekannte Sprecher aus der Community für einen Vortrag bei uns gewinnen. Eines der
absoluten Highlights in diesem Zusammenhang war sicherlich der Vortrag von &lt;a href="http://blogs.infragistics.com/tonyl" target="_blank"&gt;Tony
Lombardo&lt;/a&gt;,&amp;nbsp; ASP.NET MVP und Worldwide Lead Evangelist der Firma Infragistics,
der während seines Europa Aufenthalts zur TechEd Europe einen Zwischenstopp in Koblenz
machte, um uns etwas zum Thema Silverlight zu erzählen.
&lt;/p&gt;
&lt;p&gt;
An dieser Stelle möchte jedoch nicht nur Tony hervorheben, sondern mich auch bei allen
anderen Sprechern für ihre tollen Vorträge bedanken.
&lt;/p&gt;
&lt;p&gt;
Im einzelnen wären da zu nennen:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Eric Berres: Einführung in DNN, Einführung in die WCF 
&lt;li&gt;
Jan Meinecken: Einführung in die Windows Sharepoint Services 
&lt;li&gt;
&lt;a href="http://blog.lars-keller.net/" target="_blank"&gt;Lars Keller&lt;/a&gt;: VSTO 
&lt;li&gt;
Markus Kissling: Oracle &amp;amp; .NET&amp;nbsp;&amp;nbsp; 
&lt;li&gt;
David Kortmann: Eigener Membershipprovider in 12 1/2 Minuten 
&lt;li&gt;
&lt;a href="http://blog.codemurai.de" target="_blank"&gt;André Krämer&lt;/a&gt;: Jetzt lerne ich
C#3.0 in 12 1/2 Minuten, SOS nicht nur für Schiffbrüchige, Schätzen statt raten, Design
By Contract&amp;nbsp; 
&lt;li&gt;
Thomas Naunheim: TFS 2008 
&lt;li&gt;
Frank Pommering: Reflection 
&lt;li&gt;
Markus Rennings: Neuerungen in Visual Studio 2008 für ASP.NET, Einführung in das ADO.NET
Entity Framework, .NET Framework Debugging, Custom Images für VS Commands&amp;nbsp; 
&lt;li&gt;
Alexander Rippert: Unit Testing 
&lt;li&gt;
Mario Röcher: Das Decorator Pattern 
&lt;li&gt;
&lt;a href="http://blogs.msdn.com/jenss" target="_blank"&gt;Jens K. Süßmeyer&lt;/a&gt;: Einführung
in den SQL Server 2008 
&lt;li&gt;
&lt;a href="http://www.torstenweber.de" target="_blank"&gt;Torsten Weber&lt;/a&gt;: Einführung
in das Mobile Computing, Keine Zeit für Herzrasen 
&lt;li&gt;
&lt;a href="http://www.bonn-to-code.net" target="_blank"&gt;Roland Weigelt&lt;/a&gt;: GUI Design
für nicht Designer 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Außerdem gilt natürlich unseren Sponsoren ein herzlicher Dank!
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.artiso.de" target="_blank"&gt;Artiso&lt;/a&gt;: Softwarelizenzen 
&lt;li&gt;
&lt;a href="http://www.devexpress.com" target="_blank"&gt;DevExpress&lt;/a&gt;: Softwarelizenzen 
&lt;li&gt;
&lt;a href="http://www.dotnetpro.de" target="_blank"&gt;dotnetpro&lt;/a&gt;: Einige freie Exemplare
der dotnetpro 
&lt;li&gt;
&lt;a href="http://www.entwickler-press.de" target="_blank"&gt;entwickler.press&lt;/a&gt;: Bücher 
&lt;li&gt;
&lt;a href="http://www.ineta.org" target="_blank"&gt;INETA Germany&lt;/a&gt;: Sprecher 
&lt;li&gt;
&lt;a href="http://www.infragistics.com" target="_blank"&gt;Infragistics&lt;/a&gt;: Sprecher und
Softwarelizenzen 
&lt;li&gt;
&lt;a href="http://www.jetbrains.com" target="_blank"&gt;Jetbrains&lt;/a&gt;: Sofwarelizenzen 
&lt;li&gt;
&lt;a href="http://www.konzeptum.de" target="_blank"&gt;Konzeptum GmbH&lt;/a&gt;: Raum, Technik,
Getränke 
&lt;li&gt;
MS Press: Buchgutscheine 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Außerdem vielen Dank an:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.bonn-to-code.net" target="_blank"&gt;Roland Weigelt&lt;/a&gt;: Für die
tolle "Anleitung" zur Gründung einer User Group 
&lt;li&gt;
&lt;a href="http://www.torstenweber.de" target="_blank"&gt;Torsten Weber&lt;/a&gt;: Für die hilfreichen
Tips zur Gründung einer User Group&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Wow, die vielen Danksagungen erinnern schon fast an die Oscar Verleihung. Den haben
wir zwar (noch :-)) nicht erhalten, dafür hat Microsoft uns jedoch ein tolles Geschenk
gemacht. Am Abend des Geburtstagstreffens erhielten wir nämlich die Nachricht, dass
wir ins Microsoft CLIP Programm aufgenommen wurden! Vielen Dank (:-))
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=5322fedd-3010-40de-a316-cc380aab6648" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,5322fedd-3010-40de-a316-cc380aab6648.aspx</comments>
      <category>.NET</category>
      <category>DNUG Koblenz</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=ebf80230-7fbc-4029-854a-2192460a650a</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,ebf80230-7fbc-4029-854a-2192460a650a.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,ebf80230-7fbc-4029-854a-2192460a650a.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=ebf80230-7fbc-4029-854a-2192460a650a</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
(English version below)<br />
30 begeisterte Fans des manged Codes fanden gestern Abend Ihren Weg nach Koblenz,
um bei unserer <a href="http://www.dnug-koblenz.de/" target="_blank">.NET User Group</a> Tony <strike><a href="http://www.jivetalkin.de/2007/03/hasselhoff-dos-and-donts.html" target="_blank">Hasselhoff</a></strike> <a href="http://blogs.infragistics.com/blogs/tony_lombardo" target="_blank">Lombardo</a>,
ASP.NET MVP und Lead-Evangelist bei <a href="http://www.infragistics.com/" target="_blank">Infragistics</a>,
zu hören. 
</p>
        <p>
          <a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/Tony.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="Tony" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/Tony_thumb.png" width="244" border="0" />
          </a>
          <a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/teilnehmer.jpg">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="teilnehmer" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/teilnehmer_thumb.jpg" width="244" border="0" />
          </a>
        </p>
        <p>
Tony erzählte in einem sehr spannenden Vortrag, was mit Microsoft Silverlight 2.0
fernab von sinnfreien animierten Buttons und TextBoxen machen können. Ganz Konkret
ging es um Geschäftsapplikationen, mit denen unsere Kunden sogar arbeiten können ;-)
</p>
        <p>
Unter anderem Sprach Tony über:
</p>
        <ul>
          <li>
Authentifizierung und Authorisierung</li>
          <li>
Das Speichern von Benutzereinstellungen</li>
          <li>
Datenzugriff und -bindung</li>
          <li>
sowie das MVVM Pattern.</li>
        </ul>
        <p>
          <a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/presentation.jpg">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="presentation" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/presentation_thumb.jpg" width="244" border="0" />
          </a>
        </p>
        <p>
Entgegen meiner ersten Befürchtung war die Gruppe trotz des ersten fremdsprachlichen
Vortrages recht aktiv und stellte viele Fragen. Außerdem freute ich mich sehr darüber,
so viele neue Gesichter zu sehen. Hoffentlich findet der ein oder andere zu zukünftigen
Treffen seinen Weg zu uns.
</p>
        <p>
Als User Group freuen wir uns natürlich sehr darüber, dass wir Tony als einzige Gruppe
in Europa exklusiv zu Gast haben durften. Vielen Dank an dieser Stelle noch mal an
Ihn und das ganze restliche Team von Infragistics, die diesen Vortrag möglich machten!
</p>
        <p>
Als kleines Bonbon sponsorte Infragistics zum Abschluss des Vortrags sogar noch eine
MSDN Premium Subscription sowie eine vollständige NetAdvantage Suite, die wir innerhalb
der Gruppe verlosen durften. 
</p>
        <p>
          <a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/ziehung.jpg">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="158" alt="ziehung" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/ziehung_thumb.jpg" width="244" border="0" />
          </a>
        </p>
        <p>
Als Fazit nehme ich mit:
</p>
        <ul>
          <li>
Silverlight eröffnet eine Reihe neuer Möglichkeiten im Web</li>
          <li>
5 Erwachsene passen in einen Peugeot 106, bequem ist es aber nur für den Fahrer</li>
          <li>
Man sollte auch grauen Text lesen</li>
          <li>
Jemand der kein deutsches Bier gewohnt ist, verwechselt leicht den "Kleiner als" Operator
"&lt;" mit einem öffnenden Generic</li>
        </ul>
        <p>
          <strong>English version:</strong>
        </p>
        <p>
Yesterday evening, 30 excited fans of managed code found their way to Koblenz in order
to listen  to Tony <s><a href="http://www.jivetalkin.de/2007/03/hasselhoff-dos-and-donts.html" target="_blank">Hasselhoff</a></s><a href="http://blogs.infragistics.com/blogs/tony_lombardo"><b>Lombardo</b></a>,
ASP.NET MVP and <a href="http://www.infragistics.com/"><b>Infragistics</b></a> lead
evangangelist, at our local <a href="http://www.dnug-koblenz.de/"><b>.NET user group</b></a>. 
</p>
        <p>
          <a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/Tony_3.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="Tony" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/Tony_thumb_3.png" width="244" border="0" />
          </a>
          <a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/teilnehmer_3.jpg">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="teilnehmer" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/teilnehmer_thumb_3.jpg" width="244" border="0" />
          </a>
        </p>
        <p>
Tony did a great talk on the possibilities of Microsoft Silverlight 2.0 beyond rotating
buttons or text boxes. Actually the whole thing was about Line of Business Applications,
which our customers could eventually use to get their job done ;-) 
</p>
        <p>
During his talk Tony covered: 
</p>
        <ul>
          <li>
Authentication and authorization</li>
          <li>
Preserving user settings</li>
          <li>
data access and binding</li>
          <li>
as well as the MVVM pattern</li>
        </ul>
        <p>
          <a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/presentation_3.jpg">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="presentation" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/presentation_thumb_3.jpg" width="244" border="0" />
          </a>
        </p>
        <p>
Despite my initial worries, the group was very active and asked a lot of question.
So nobody seemed to be shy at our first talk in a foreign language. In addition, I've
been very happy to see so many new faces during the meeting. Hopefully some of them
will find their way to future meetings, too. 
</p>
        <p>
As a user group we were of course very happy to be the only group to present Tony
in Europe. Many thanks again to him and the whole Infragisitcs team for making this
talk possible. 
</p>
        <p>
As a small bonbon, Infragistics sponsored our meeting by raffling a MSDN Premium Subscription
as well as a full NetAdvantage Suite. 
</p>
        <p>
          <a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/ziehung_3.jpg">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="158" alt="ziehung" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/ziehung_thumb_3.jpg" width="244" border="0" />
          </a>
        </p>
        <p>
My resume of the meeting is: 
</p>
        <ul>
          <li>
Silverlight gives you a whole set of new possibilities for web applications</li>
          <li>
5 persons do fit into a Peugeot 106, but it's only comfortable for the driver</li>
          <li>
You should read the grey text, too</li>
          <li>
Somebody who's not used to German beer may easily mix up a "lower then"-operator (&lt;)
with an opening generic</li>
        </ul>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=ebf80230-7fbc-4029-854a-2192460a650a" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>He's huge, he's huge in Germany! :-)</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,ebf80230-7fbc-4029-854a-2192460a650a.aspx</guid>
      <link>http://blog.codemurai.de/2008/11/07/HesHugeHesHugeInGermany.aspx</link>
      <pubDate>Fri, 07 Nov 2008 20:04:08 GMT</pubDate>
      <description>&lt;p&gt;
(English version below)&lt;br&gt;
30 begeisterte Fans des manged Codes fanden gestern Abend Ihren Weg nach Koblenz,
um bei unserer &lt;a href="http://www.dnug-koblenz.de/" target="_blank"&gt;.NET User Group&lt;/a&gt; Tony &lt;strike&gt;&lt;a href="http://www.jivetalkin.de/2007/03/hasselhoff-dos-and-donts.html" target="_blank"&gt;Hasselhoff&lt;/a&gt;&lt;/strike&gt;&amp;nbsp;&lt;a href="http://blogs.infragistics.com/blogs/tony_lombardo" target="_blank"&gt;Lombardo&lt;/a&gt;,
ASP.NET MVP und Lead-Evangelist bei &lt;a href="http://www.infragistics.com/" target="_blank"&gt;Infragistics&lt;/a&gt;,
zu hören. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/Tony.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="Tony" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/Tony_thumb.png" width="244" border="0"&gt;&lt;/a&gt; &lt;a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/teilnehmer.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="teilnehmer" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/teilnehmer_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Tony erzählte in einem sehr spannenden Vortrag, was mit Microsoft Silverlight 2.0
fernab von sinnfreien animierten Buttons und TextBoxen machen können. Ganz Konkret
ging es um Geschäftsapplikationen, mit denen unsere Kunden sogar arbeiten können ;-)
&lt;/p&gt;
&lt;p&gt;
Unter anderem Sprach Tony über:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Authentifizierung und Authorisierung&lt;/li&gt;
&lt;li&gt;
Das Speichern von Benutzereinstellungen&lt;/li&gt;
&lt;li&gt;
Datenzugriff und -bindung&lt;/li&gt;
&lt;li&gt;
sowie das MVVM Pattern.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/presentation.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="presentation" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/presentation_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Entgegen meiner ersten Befürchtung war die Gruppe trotz des ersten fremdsprachlichen
Vortrages recht aktiv und stellte viele Fragen. Außerdem freute ich mich sehr darüber,
so viele neue Gesichter zu sehen. Hoffentlich findet der ein oder andere zu zukünftigen
Treffen seinen Weg zu uns.
&lt;/p&gt;
&lt;p&gt;
Als User Group freuen wir uns natürlich sehr darüber, dass wir Tony als einzige Gruppe
in Europa exklusiv zu Gast haben durften. Vielen Dank an dieser Stelle noch mal an
Ihn und das ganze restliche Team von Infragistics, die diesen Vortrag möglich machten!
&lt;/p&gt;
&lt;p&gt;
Als kleines Bonbon sponsorte Infragistics zum Abschluss des Vortrags sogar noch eine
MSDN Premium Subscription sowie eine vollständige NetAdvantage Suite, die wir innerhalb
der Gruppe verlosen durften. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/ziehung.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="158" alt="ziehung" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/ziehung_thumb.jpg" width="244" border="0"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Als Fazit nehme ich mit:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Silverlight eröffnet eine Reihe neuer Möglichkeiten im Web&lt;/li&gt;
&lt;li&gt;
5 Erwachsene passen in einen Peugeot 106, bequem ist es aber nur für den Fahrer&lt;/li&gt;
&lt;li&gt;
Man sollte auch grauen Text lesen&lt;/li&gt;
&lt;li&gt;
Jemand der kein deutsches Bier gewohnt ist, verwechselt leicht den "Kleiner als" Operator
"&amp;lt;" mit einem öffnenden Generic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;strong&gt;English version:&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Yesterday evening, 30 excited fans of managed code found their way to Koblenz in order
to listen&amp;nbsp; to Tony &lt;s&gt;&lt;a href="http://www.jivetalkin.de/2007/03/hasselhoff-dos-and-donts.html" target="_blank"&gt;Hasselhoff&lt;/a&gt;&lt;/s&gt; &lt;a href="http://blogs.infragistics.com/blogs/tony_lombardo"&gt;&lt;b&gt;Lombardo&lt;/b&gt;&lt;/a&gt;,
ASP.NET MVP and &lt;a href="http://www.infragistics.com/"&gt;&lt;b&gt;Infragistics&lt;/b&gt;&lt;/a&gt; lead
evangangelist, at our local &lt;a href="http://www.dnug-koblenz.de/"&gt;&lt;b&gt;.NET user group&lt;/b&gt;&lt;/a&gt;. 
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/Tony_3.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="Tony" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/Tony_thumb_3.png" width="244" border="0"&gt;&lt;/a&gt; &lt;a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/teilnehmer_3.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="teilnehmer" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/teilnehmer_thumb_3.jpg" width="244" border="0"&gt;&lt;/a&gt; 
&lt;p&gt;
Tony did a great talk on the possibilities of Microsoft Silverlight 2.0 beyond rotating
buttons or text boxes. Actually the whole thing was about Line of Business Applications,
which our customers could eventually use to get their job done ;-) 
&lt;p&gt;
During his talk Tony covered: 
&lt;ul&gt;
&lt;li&gt;
Authentication and authorization&lt;/li&gt;
&lt;li&gt;
Preserving user settings&lt;/li&gt;
&lt;li&gt;
data access and binding&lt;/li&gt;
&lt;li&gt;
as well as the MVVM pattern&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/presentation_3.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="184" alt="presentation" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/presentation_thumb_3.jpg" width="244" border="0"&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Despite my initial worries, the group was very active and asked a lot of question.
So nobody seemed to be shy at our first talk in a foreign language. In addition, I've
been very happy to see so many new faces during the meeting. Hopefully some of them
will find their way to future meetings, too. 
&lt;p&gt;
As a user group we were of course very happy to be the only group to present Tony
in Europe. Many thanks again to him and the whole Infragisitcs team for making this
talk possible. 
&lt;p&gt;
As a small bonbon, Infragistics sponsored our meeting by raffling a MSDN Premium Subscription
as well as a full NetAdvantage Suite. 
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/ziehung_3.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="158" alt="ziehung" src="http://blog.codemurai.de/images/HeshugeheshugeinGermany_6629/ziehung_thumb_3.jpg" width="244" border="0"&gt;&lt;/a&gt; 
&lt;p&gt;
My resume of the meeting is: 
&lt;ul&gt;
&lt;li&gt;
Silverlight gives you a whole set of new possibilities for web applications&lt;/li&gt;
&lt;li&gt;
5 persons do fit into a Peugeot 106, but it's only comfortable for the driver&lt;/li&gt;
&lt;li&gt;
You should read the grey text, too&lt;/li&gt;
&lt;li&gt;
Somebody who's not used to German beer may easily mix up a "lower then"-operator (&amp;lt;)
with an opening generic&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=ebf80230-7fbc-4029-854a-2192460a650a" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,ebf80230-7fbc-4029-854a-2192460a650a.aspx</comments>
      <category>.NET</category>
      <category>DNUG Koblenz</category>
      <category>DotNetGerman Bloggers</category>
      <category>english posts</category>
      <category>Infragistics</category>
      <category>Silverlight</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=e6389cb6-6a14-416f-b581-cf95c177669d</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,e6389cb6-6a14-416f-b581-cf95c177669d.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,e6389cb6-6a14-416f-b581-cf95c177669d.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=e6389cb6-6a14-416f-b581-cf95c177669d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Er ist ASP.NET MVP, er ist Co-Leader der Central-Jersey .NET User Group, für Microsoft
hält Web-Casts direkt aus Redmond. Außerdem ist er der Leiter von Infragistics weltweiter
Evangelism Gruppe. Er kommt direkt aus den <strong>USA</strong> und im November ist
er bei uns!
</p>
        <p>
Die .NET User Group Koblenz ist stolz, Anfang November mit Tony Lombardo, Lead Evangelist
von Infragistics aus den USA, den ersten internationalen Sprecher zu Gast zu haben. 
<br />
Tony wird über Line of Business Applications mit Silverlight 2.0 sprechen. Während
des Vortrags wird er unter anderem auf alltägliche Aufgabenstellungen wie Datenbindung,
Authentifizierung oder der Speicherung von Benutzereinstellungen zu sprechen kommen. 
</p>
        <h5>
          <strong>Über den Sprecher:</strong>
        </h5>
        <p>
          <strong>
          </strong>Tony Lombardo ist der leitende Evangelist von Infragistics Welt-Weiter
Evangelisten Gruppe. Sein Spezialgebiet ist ASP.NET. Sein tiefer technischer ASP.NET
Hintergrund sowie sein Community Engagement verschafften ihm die Auszeichnung zum
Microsoft MVP für ASP.NET. 
<br />
Tony ist Co-Leader der Central-Jersey .NET User Group. Zusätzlich schreibt er regelmäßig
für online und print Medien wie zum Beispiel ASP.NET Pro, Dr. Dobb’s Journal, .NET
Developers Journal und die Redmond Developer News. 
<br />
Tony arbeitet seit fast einem Jahrzehnt für Infragistics. Diese Zeit startete er zunächst
als Entwickler für ASP.NET, wurde anschließend Produkt Manager für die Infragistics
ASP.NET Komponenten ehe er seine aktuelle Rolle als Lead-Evangelist einnahm. Bedingt
durch seinen Werdegang verfügt er über "real-world" ASP.NET Erfahrung, die er stets
mit freue teilt. 
<br />
Der Vortrag wird ausnahmsweise in englischer Sprache abgehalten werden. 
<br /></p>
        <p>
Anmeldung unter: 
<br /><a href="https://www.xing.com/app/events?op=detail;id=267741">https://www.xing.com/app/events?op=detail;id=267741</a></p>
        <h5>
        </h5>
        <h4>English Version:
</h4>
        <h5>LOB 2.0 with Silverlight 2
</h5>
        <p>
This talk will cover building a next generation web application using Silverlight
2. In this talk we will discuss how to do some common tasks including databinding,
authentication, and persistence of user defined settings. 
</p>
        <h5>Speaker: Tony Lombardo 
</h5>
        <p>
In November we have Tony Lombardo visiting Europe from the USA. Tony is the lead Technical
Evangelist in Infragistics' Worldwide Evangelism Group at Infragistics. 
<br />
Tony has a deep technical background in ASP.NET and his community participation has
earned him the ASP.NET MVP Award from Microsoft. Tony co-runs the Central Jersey .NET
Users Group, and often writes for both online and printed publications, including
ASP.NET Pro, Dr. Dobb’s Journal, .NET Developers Journal and Redmond Developer News. 
<br />
In addition, Tony has been working for Infragistics for almost a decade, and in that
time he spent his days working as a Developer on our ASP.NET product before becoming
a Product Manager and eventually moving the role he has today. As such, Tony has first-hand
experience in “real-world” issues and he will be very pleased to advise in a technical
capacity on use of Infragistics controls.<br /></p>
        <p>
Register at: 
<br /><a href="https://www.xing.com/app/events?op=detail;id=267741">https://www.xing.com/app/events?op=detail;id=267741</a></p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=e6389cb6-6a14-416f-b581-cf95c177669d" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>DNUG Koblenz Spezial: LOB Silverlight 2.0 mit Tony Lombardo aus Jersey, USA (6.11.08 ab 19:00 Uhr in Koblenz)</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,e6389cb6-6a14-416f-b581-cf95c177669d.aspx</guid>
      <link>http://blog.codemurai.de/2008/10/27/DNUGKoblenzSpezialLOBSilverlight20MitTonyLombardoAusJerseyUSA61108Ab1900UhrInKoblenz.aspx</link>
      <pubDate>Mon, 27 Oct 2008 20:17:59 GMT</pubDate>
      <description>&lt;p&gt;
Er ist ASP.NET MVP, er ist Co-Leader der Central-Jersey .NET User Group, für Microsoft
hält Web-Casts direkt aus Redmond. Außerdem ist er der Leiter von Infragistics weltweiter
Evangelism Gruppe. Er kommt direkt aus den &lt;strong&gt;USA&lt;/strong&gt; und im November ist
er bei uns!
&lt;/p&gt;
&lt;p&gt;
Die .NET User Group Koblenz ist stolz, Anfang November mit Tony Lombardo, Lead Evangelist
von Infragistics aus den USA, den ersten internationalen Sprecher zu Gast zu haben. 
&lt;br&gt;
Tony wird über Line of Business Applications mit Silverlight 2.0 sprechen. Während
des Vortrags wird er unter anderem auf alltägliche Aufgabenstellungen wie Datenbindung,
Authentifizierung oder der Speicherung von Benutzereinstellungen zu sprechen kommen. 
&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;Über den Sprecher:&lt;/strong&gt; 
&lt;/h5&gt;
&lt;p&gt;
&lt;strong&gt;&lt;/strong&gt;Tony Lombardo ist der leitende Evangelist von Infragistics Welt-Weiter
Evangelisten Gruppe. Sein Spezialgebiet ist ASP.NET. Sein tiefer technischer ASP.NET
Hintergrund sowie sein Community Engagement verschafften ihm die Auszeichnung zum
Microsoft MVP für ASP.NET. 
&lt;br&gt;
Tony ist Co-Leader der Central-Jersey .NET User Group. Zusätzlich schreibt er regelmäßig
für online und print Medien wie zum Beispiel ASP.NET Pro, Dr. Dobb’s Journal, .NET
Developers Journal und die Redmond Developer News. 
&lt;br&gt;
Tony arbeitet seit fast einem Jahrzehnt für Infragistics. Diese Zeit startete er zunächst
als Entwickler für ASP.NET, wurde anschließend Produkt Manager für die Infragistics
ASP.NET Komponenten ehe er seine aktuelle Rolle als Lead-Evangelist einnahm. Bedingt
durch seinen Werdegang verfügt er über "real-world" ASP.NET Erfahrung, die er stets
mit freue teilt. 
&lt;br&gt;
Der Vortrag wird ausnahmsweise in englischer Sprache abgehalten werden. 
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
Anmeldung unter: 
&lt;br&gt;
&lt;a href="https://www.xing.com/app/events?op=detail;id=267741"&gt;https://www.xing.com/app/events?op=detail;id=267741&lt;/a&gt;
&lt;/p&gt;
&lt;h5&gt;
&lt;/h5&gt;
&lt;h4&gt;English Version:
&lt;/h4&gt;
&lt;h5&gt;LOB 2.0 with Silverlight 2
&lt;/h5&gt;
&lt;p&gt;
This talk will cover building a next generation web application using Silverlight
2. In this talk we will discuss how to do some common tasks including databinding,
authentication, and persistence of user defined settings. 
&lt;/p&gt;
&lt;h5&gt;Speaker: Tony Lombardo 
&lt;/h5&gt;
&lt;p&gt;
In November we have Tony Lombardo visiting Europe from the USA. Tony is the lead Technical
Evangelist in Infragistics' Worldwide Evangelism Group at Infragistics. 
&lt;br&gt;
Tony has a deep technical background in ASP.NET and his community participation has
earned him the ASP.NET MVP Award from Microsoft. Tony co-runs the Central Jersey .NET
Users Group, and often writes for both online and printed publications, including
ASP.NET Pro, Dr. Dobb’s Journal, .NET Developers Journal and Redmond Developer News. 
&lt;br&gt;
In addition, Tony has been working for Infragistics for almost a decade, and in that
time he spent his days working as a Developer on our ASP.NET product before becoming
a Product Manager and eventually moving the role he has today. As such, Tony has first-hand
experience in “real-world” issues and he will be very pleased to advise in a technical
capacity on use of Infragistics controls.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
Register at: 
&lt;br&gt;
&lt;a href="https://www.xing.com/app/events?op=detail;id=267741"&gt;https://www.xing.com/app/events?op=detail;id=267741&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=e6389cb6-6a14-416f-b581-cf95c177669d" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,e6389cb6-6a14-416f-b581-cf95c177669d.aspx</comments>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>DNUG Koblenz</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>Silverlight</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=aa926621-fa63-4785-b45f-5e63ad2395ba</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,aa926621-fa63-4785-b45f-5e63ad2395ba.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,aa926621-fa63-4785-b45f-5e63ad2395ba.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=aa926621-fa63-4785-b45f-5e63ad2395ba</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Abgesehen von "Können Sie mir hier bitte einen Stempel drauf machen?"
oder "Darf ich so einen Kuli haben?" war  die dritthäufigste Frage
an unserem <a href="http://www.Infragistics.com" target="_blank">Infragistics</a>-Stand
während der diesjährigen <a href="http://www.basta.net" target="_blank">Herbst-Basta</a> sicherlich
"Wann kommen die <a href="http://www.infragistics.com/hot/silverlight.aspx" target="_blank">Infragistics
Silverlight 2.0</a> Controls raus?"
</p>
        <p>
Nun, während der Messe lautete unsere Antwort stets: "So lange Microsoft
selbst nicht weiss, wann Silverlight 2.0 heraus kommt, können wir hier leider
keine Antwort geben" ;-) 
</p>
        <p>
Tja, wie heute in diversen Blogs zu lesen war ([<a href="http://silverlight.net/blogs/jesseliberty/archive/2008/10/13/silverlight-2-releases-tomorrow.aspx" target="_blank">1</a>],
[<a href="http://www.nathanbrouwer.nl/default.aspx?e=275" target="_blank">2</a>],
[<a href="http://blog.silverlight-city.de/post/2008/10/13/Silverlight-RTE-eclipse4SL-eclipse-OpenSource.aspx" target="_blank">3</a>])
hat Microsoft die Katze aus dem Sack gelassen und das Silverlight 2.0 RTW für
morgen angekündigt.
</p>
        <p>
Infragistics war allerdings ein wenig schneller - zumindest was die Ankündigungen
angeht -  und gabin <a href="http://blogs.infragistics.com/blogs/tony_lombardo/archive/2008/10/08/netadvantage-silverlight-roadmap-it-s-here.aspx" target="_blank">Tony's
Blog</a> letzten Mittwoch die <a href="http://www.infragistics.com/dotnet/netadvantage/silverlight.aspx" target="_blank">Infragistics
NetAdvantage Silverlight Controls for Line of Business (LOB) Applications Roadmap</a> bekannt.
</p>
        <p>
Zusammengefasst sieht diese wie folgt aus:
</p>
        <table cellspacing="0" cellpadding="2" width="400" border="0">
          <thead>
            <tr>
              <th>
Meilenstein 
</th>
              <th>
Datum 
</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td valign="top" width="200">
Roadmap angekündigt</td>
              <td valign="top" width="200">
Oktober 2008</td>
            </tr>
            <tr>
              <td valign="top" width="200">
Erstes CTP</td>
              <td valign="top" width="200">
Ende 2008</td>
            </tr>
            <tr>
              <td valign="top" width="200">
Zweites CTP</td>
              <td valign="top" width="200">
März 2009</td>
            </tr>
            <tr>
              <td valign="top" width="200">
2009 Vol 1 Release (inkl. Silverlight LOB Controls)</td>
              <td valign="top" width="200">
Quartal 2 2009</td>
            </tr>
          </tbody>
        </table>
        <p>
Die ersten Screenshots sehen schon recht vielversprechend aus
</p>
        <p>
          <a href="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/xamWebChart.jpg">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="210" alt="xamWebChart" src="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/xamWebChart_thumb.jpg" width="244" border="0" />
          </a>
          <a href="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/xamOutlookbar.jpg">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="xamOutlookbar" src="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/xamOutlookbar_thumb.jpg" width="155" border="0" />
          </a>
        </p>
        <p>
bleibt nun also abzuwarten, was tatsächlich daraus wird.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/PIC0031.jpg">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="184" alt="PIC-0031" src="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/PIC0031_thumb.jpg" width="244" border="0" />
          </a>
        </p>
        <p>
          <font size="0">Eine Aussage zum NetAdvantage Silverlight Release Datum konnten wir
während der Basta leider nicht treffen. Spaß auf dem "Bastoberfest"
hatten wir aber trotzdem ;-)</font>
        </p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=aa926621-fa63-4785-b45f-5e63ad2395ba" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Infragistics gibt NetAdvantage Silverlight Roadmap bekannt</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,aa926621-fa63-4785-b45f-5e63ad2395ba.aspx</guid>
      <link>http://blog.codemurai.de/2008/10/13/InfragisticsGibtNetAdvantageSilverlightRoadmapBekannt.aspx</link>
      <pubDate>Mon, 13 Oct 2008 21:01:48 GMT</pubDate>
      <description>&lt;p&gt;
Abgesehen von &amp;quot;K&amp;#246;nnen Sie mir hier bitte einen Stempel drauf machen?&amp;quot;
oder &amp;quot;Darf ich so einen Kuli haben?&amp;quot; war&amp;#160; die dritth&amp;#228;ufigste Frage
an unserem &lt;a href="http://www.Infragistics.com" target="_blank"&gt;Infragistics&lt;/a&gt;-Stand
w&amp;#228;hrend der diesj&amp;#228;hrigen &lt;a href="http://www.basta.net" target="_blank"&gt;Herbst-Basta&lt;/a&gt; sicherlich
&amp;quot;Wann kommen die &lt;a href="http://www.infragistics.com/hot/silverlight.aspx" target="_blank"&gt;Infragistics
Silverlight 2.0&lt;/a&gt; Controls raus?&amp;quot;
&lt;/p&gt;
&lt;p&gt;
Nun, w&amp;#228;hrend der Messe lautete unsere Antwort stets: &amp;quot;So lange Microsoft
selbst nicht weiss, wann Silverlight 2.0 heraus kommt, k&amp;#246;nnen wir hier leider
keine Antwort geben&amp;quot; ;-) 
&lt;/p&gt;
&lt;p&gt;
Tja, wie heute in diversen Blogs zu lesen war ([&lt;a href="http://silverlight.net/blogs/jesseliberty/archive/2008/10/13/silverlight-2-releases-tomorrow.aspx" target="_blank"&gt;1&lt;/a&gt;],
[&lt;a href="http://www.nathanbrouwer.nl/default.aspx?e=275" target="_blank"&gt;2&lt;/a&gt;],
[&lt;a href="http://blog.silverlight-city.de/post/2008/10/13/Silverlight-RTE-eclipse4SL-eclipse-OpenSource.aspx" target="_blank"&gt;3&lt;/a&gt;])
hat Microsoft die Katze aus dem Sack gelassen und das Silverlight 2.0 RTW f&amp;#252;r
morgen angek&amp;#252;ndigt.
&lt;/p&gt;
&lt;p&gt;
Infragistics war allerdings ein wenig schneller - zumindest was die Ank&amp;#252;ndigungen
angeht -&amp;#160; und gabin &lt;a href="http://blogs.infragistics.com/blogs/tony_lombardo/archive/2008/10/08/netadvantage-silverlight-roadmap-it-s-here.aspx" target="_blank"&gt;Tony's
Blog&lt;/a&gt; letzten Mittwoch die &lt;a href="http://www.infragistics.com/dotnet/netadvantage/silverlight.aspx" target="_blank"&gt;Infragistics
NetAdvantage Silverlight Controls for Line of Business (LOB) Applications Roadmap&lt;/a&gt; bekannt.
&lt;/p&gt;
&lt;p&gt;
Zusammengefasst sieht diese wie folgt aus:
&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
Meilenstein 
&lt;/th&gt;
&lt;th&gt;
Datum 
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
Roadmap angek&amp;#252;ndigt&lt;/td&gt;
&lt;td valign="top" width="200"&gt;
Oktober 2008&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
Erstes CTP&lt;/td&gt;
&lt;td valign="top" width="200"&gt;
Ende 2008&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
Zweites CTP&lt;/td&gt;
&lt;td valign="top" width="200"&gt;
M&amp;#228;rz 2009&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;
2009 Vol 1 Release (inkl. Silverlight LOB Controls)&lt;/td&gt;
&lt;td valign="top" width="200"&gt;
Quartal 2 2009&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Die ersten Screenshots sehen schon recht vielversprechend aus
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/xamWebChart.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="210" alt="xamWebChart" src="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/xamWebChart_thumb.jpg" width="244" border="0" /&gt;&lt;/a&gt; &lt;a href="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/xamOutlookbar.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="xamOutlookbar" src="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/xamOutlookbar_thumb.jpg" width="155" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
bleibt nun also abzuwarten, was tats&amp;#228;chlich daraus wird.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/PIC0031.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="184" alt="PIC-0031" src="http://blog.codemurai.de/images/InfragisticsgibtNetAdvantageSilverlightR_143B9/PIC0031_thumb.jpg" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;font size="0"&gt;Eine Aussage zum NetAdvantage Silverlight Release Datum konnten wir
w&amp;#228;hrend der Basta leider nicht treffen. Spa&amp;#223; auf dem &amp;quot;Bastoberfest&amp;quot;
hatten wir aber trotzdem ;-)&lt;/font&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=aa926621-fa63-4785-b45f-5e63ad2395ba" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,aa926621-fa63-4785-b45f-5e63ad2395ba.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>Silverlight</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=00a2b888-daf3-408b-8deb-a560cd44f3c5</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,00a2b888-daf3-408b-8deb-a560cd44f3c5.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,00a2b888-daf3-408b-8deb-a560cd44f3c5.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=00a2b888-daf3-408b-8deb-a560cd44f3c5</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Die .NET User Group Koblenz freut sich, am 23. Oktober, mit Torsten Weber einen weiteren
Top Speaker zu Gast zu haben. Torsten ist Microsoft MVP, Buchautor, Basta-Speaker
und Leiter der .NET User Group Leipzig. 
<br /></p>
        <h4>Inhalt des Vortrags: 
</h4>
        <p>
Mobile Computing ist schwer, denn dazu benötigt man einerseits komplexes Fachwissen
und andererseits mindestens ein mobiles Gerät. Falsch; Mobile Computing ist nicht
so schwer, wie man vielleicht denkt. Viel schwerer ist es, die Angst davor zu verlieren.
Genau das bietet Torsten Weber in seinem „Wo und wie beginne ich"-Vortrag.
Da die Begriffe AJAX und Web Irgendetwas.Null derzeit auf Entwickler viel magische
Anziehungskraft besitzen und manche Entwickler lieber bei den "guten alten"
Webanwendungen bleiben als bei Windows Forms, gibt es für alle Schmackes oben
drauf: Die Unterstützung vom Internet Explorer Mobile als auch von Windows Forms
für AJAX &amp; Co. Abgerundet wird alles mit Best Practices bei mobilen Anwendungen. 
</p>
        <h4>Über den Sprecher: 
</h4>
        <p>
Torsten Weber hat sich seit seinem ersten mobilen Gerät vor über einem Jahrzehnt
in die Mobilität verliebt und schwört mit Beginn der ersten Version des
.NET Compact Frameworks auf genau diese Plattform. Als Wirtschaftsinformatiker, gelernter
Bankkaufmann, Technologieberater und Querdenker hat er langjährige Berufserfahrung
in der Softwareentwicklung, insbesondere wenn es um betriebswirtschaftliche Gesamtzusammenhänge
geht. Ob bei seiner Tätigkeit bei Microsoft als Project Manager, ob als Buchautor
oder in seinem Engagement in der Leipziger .NET User Group mit Alexander Groß
bis hin zu seinem MVP für Device Application Development – es geht ihm
immer ein wenig um "so wird das Ganze dann mobil!". 
</p>
        <p>
Anmeldungen werden unter: <a title="https://www.xing.com/app/events?op=detail;id=259135;" href="https://www.xing.com/app/events?op=detail;id=259135;">https://www.xing.com/app/events?op=detail;id=259135;</a> angenommen.
Näheres zur .NET Developer Group Koblenz kann unter <a href="http://www.dnug-koblenz.de" target="_blank">http://www.dnug-koblenz.de</a> nachgelesen
werden.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=00a2b888-daf3-408b-8deb-a560cd44f3c5" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Torsten Weber im Oktober zu Gast bei der .NET Developer Group Koblenz</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,00a2b888-daf3-408b-8deb-a560cd44f3c5.aspx</guid>
      <link>http://blog.codemurai.de/2008/10/07/TorstenWeberImOktoberZuGastBeiDerNETDeveloperGroupKoblenz.aspx</link>
      <pubDate>Tue, 07 Oct 2008 20:22:39 GMT</pubDate>
      <description>&lt;p&gt;
Die .NET User Group Koblenz freut sich, am 23. Oktober, mit Torsten Weber einen weiteren
Top Speaker zu Gast zu haben. Torsten ist Microsoft MVP, Buchautor, Basta-Speaker
und Leiter der .NET User Group Leipzig. 
&lt;br /&gt;
&lt;/p&gt;
&lt;h4&gt;Inhalt des Vortrags: 
&lt;/h4&gt;
&lt;p&gt;
Mobile Computing ist schwer, denn dazu ben&amp;#246;tigt man einerseits komplexes Fachwissen
und andererseits mindestens ein mobiles Ger&amp;#228;t. Falsch; Mobile Computing ist nicht
so schwer, wie man vielleicht denkt. Viel schwerer ist es, die Angst davor zu verlieren.
Genau das bietet Torsten Weber in seinem &amp;#8222;Wo und wie beginne ich&amp;quot;-Vortrag.
Da die Begriffe AJAX und Web Irgendetwas.Null derzeit auf Entwickler viel magische
Anziehungskraft besitzen und manche Entwickler lieber bei den &amp;quot;guten alten&amp;quot;
Webanwendungen bleiben als bei Windows Forms, gibt es f&amp;#252;r alle Schmackes oben
drauf: Die Unterst&amp;#252;tzung vom Internet Explorer Mobile als auch von Windows Forms
f&amp;#252;r AJAX &amp;amp; Co. Abgerundet wird alles mit Best Practices bei mobilen Anwendungen. 
&lt;/p&gt;
&lt;h4&gt;&amp;#220;ber den Sprecher: 
&lt;/h4&gt;
&lt;p&gt;
Torsten Weber hat sich seit seinem ersten mobilen Ger&amp;#228;t vor &amp;#252;ber einem Jahrzehnt
in die Mobilit&amp;#228;t verliebt und schw&amp;#246;rt mit Beginn der ersten Version des
.NET Compact Frameworks auf genau diese Plattform. Als Wirtschaftsinformatiker, gelernter
Bankkaufmann, Technologieberater und Querdenker hat er langj&amp;#228;hrige Berufserfahrung
in der Softwareentwicklung, insbesondere wenn es um betriebswirtschaftliche Gesamtzusammenh&amp;#228;nge
geht. Ob bei seiner T&amp;#228;tigkeit bei Microsoft als Project Manager, ob als Buchautor
oder in seinem Engagement in der Leipziger .NET User Group mit Alexander Gro&amp;#223;
bis hin zu seinem MVP f&amp;#252;r Device Application Development &amp;#8211; es geht ihm
immer ein wenig um &amp;quot;so wird das Ganze dann mobil!&amp;quot;. 
&lt;/p&gt;
&lt;p&gt;
Anmeldungen werden unter: &lt;a title="https://www.xing.com/app/events?op=detail;id=259135;" href="https://www.xing.com/app/events?op=detail;id=259135;"&gt;https://www.xing.com/app/events?op=detail;id=259135;&lt;/a&gt; angenommen.
N&amp;#228;heres zur .NET Developer Group Koblenz kann unter &lt;a href="http://www.dnug-koblenz.de" target="_blank"&gt;http://www.dnug-koblenz.de&lt;/a&gt; nachgelesen
werden.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=00a2b888-daf3-408b-8deb-a560cd44f3c5" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,00a2b888-daf3-408b-8deb-a560cd44f3c5.aspx</comments>
      <category>.NET</category>
      <category>DNUG Koblenz</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=3e10e374-6d03-46df-b5c5-5cdab6a5d8eb</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,3e10e374-6d03-46df-b5c5-5cdab6a5d8eb.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,3e10e374-6d03-46df-b5c5-5cdab6a5d8eb.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=3e10e374-6d03-46df-b5c5-5cdab6a5d8eb</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Kürzlich installierte ich Visual Studio 2008 Service Pack 1. Nach der Installation
konnte ich keine neuen Solutions basierend auf der SCSF - April 2008 mehr anlegen.
Der Sourcecode wurde zwar generiert, beim Versuch das Projekt zu starten kam es jedoch
zu einer ModuleLoadException. Außerdem wurde auch das "Add View (With Presenter)"
Recipe nicht mehr angezeigt.
</p>
        <p>
          <a href="http://blog.codemurai.de/images/SCSFApril2008SolutionslaufennachInstalla_602E/image.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="263" alt="image" src="http://blog.codemurai.de/images/SCSFApril2008SolutionslaufennachInstalla_602E/image_thumb.png" width="456" border="0" />
          </a>
        </p>
        <p>
Glücklicherweise war das Problem bereits bekannt. Abhilfe in Form einer Anleitung
zum Patchen des Sourcecodes gibt es <a href="http://www.codeplex.com/smartclient/Wiki/View.aspx?title=Known%20Issues%3a%20SC-SF%20April%202008%20with%20Visual%20Studio%202008%20and%20SP1%20Beta" target="_blank">hier</a>.
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=3e10e374-6d03-46df-b5c5-5cdab6a5d8eb" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>SCSF - April 2008 Solutions laufen nach Installation des SP1 f&amp;uuml;r VS 2008 nicht mehr</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,3e10e374-6d03-46df-b5c5-5cdab6a5d8eb.aspx</guid>
      <link>http://blog.codemurai.de/2008/09/07/SCSFApril2008SolutionsLaufenNachInstallationDesSP1FuumlrVS2008NichtMehr.aspx</link>
      <pubDate>Sun, 07 Sep 2008 19:37:27 GMT</pubDate>
      <description>&lt;p&gt;
K&amp;#252;rzlich installierte ich Visual Studio 2008 Service Pack 1. Nach der Installation
konnte ich keine neuen Solutions basierend auf der SCSF - April 2008 mehr anlegen.
Der Sourcecode wurde zwar generiert, beim Versuch das Projekt zu starten kam es jedoch
zu einer ModuleLoadException. Au&amp;#223;erdem wurde auch das &amp;quot;Add View (With Presenter)&amp;quot;
Recipe nicht mehr angezeigt.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/images/SCSFApril2008SolutionslaufennachInstalla_602E/image.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="263" alt="image" src="http://blog.codemurai.de/images/SCSFApril2008SolutionslaufennachInstalla_602E/image_thumb.png" width="456" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Gl&amp;#252;cklicherweise war das Problem bereits bekannt. Abhilfe in Form einer Anleitung
zum Patchen des Sourcecodes gibt es &lt;a href="http://www.codeplex.com/smartclient/Wiki/View.aspx?title=Known%20Issues%3a%20SC-SF%20April%202008%20with%20Visual%20Studio%202008%20and%20SP1%20Beta" target="_blank"&gt;hier&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=3e10e374-6d03-46df-b5c5-5cdab6a5d8eb" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,3e10e374-6d03-46df-b5c5-5cdab6a5d8eb.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=7b79ef3b-4f2c-450b-8202-0c42cb0984c8</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,7b79ef3b-4f2c-450b-8202-0c42cb0984c8.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,7b79ef3b-4f2c-450b-8202-0c42cb0984c8.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=7b79ef3b-4f2c-450b-8202-0c42cb0984c8</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Protagonisten von Kriminalfilmen, die die Weisheit "<em>Traue niemandem</em>"
beherzigen, leben länger und gehören am Ende des Films meist zu denjenigen,
die nicht tot sind.  Was im Film gut ist, kann in der Softwareentwicklung doch
nicht nicht schlecht sein, oder? Genau! Dies ist der Grund, weshalb man aufrufendem
Code grundsätzlich misstrauen sollte! Glücklicherweise führt zuwiderhandeln
in der Softwareentwicklung zwar in den seltendsten Fällen zum Tod, zu einem Haufen
Überstunden kann es aber sehr schnell führen.
</p>
        <p>
Anhand folgenden Beispiels möchte ich dies gerne verdeutlichen:
</p>
        <p>
Unsere Aufgabe ist es, eine Methode zu schreiben, die eine angegebene, temporäre
Datei löscht. Im einfachsten Fall könnte dies so aussehen:
</p>
        <p>
          <!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red128\green128\blue128;\red0\green128\blue0;}??\fs20     \cf3 class\cf0  \cf4 Program\par ??\cf0     \{\par ??        \cf3 static\cf0  \cf3 void\cf0  Main(\cf3 string\cf0 [] args)\par ??        \{\par ??            DeleteFile(\cf3 null\cf0 );\par ??        \}\par ??        \cf5 ///\cf6  \cf5 &lt;summary&gt;\par ??\cf0         \cf5 ///\cf6  Deletes the file.\par ??\cf0         \cf5 ///\cf6  \cf5 &lt;/summary&gt;\par ??\cf0         \cf5 ///\cf6  \cf5 &lt;param name="fileName"&gt;\cf6 Please enter valid  (*.tmp)\par ??\cf0         \cf5 ///\cf6  and existing file names only!\cf5 &lt;/param&gt;\par ??\cf0         \cf3 public\cf0  \cf3 static\cf0  \cf3 void\cf0  DeleteTempFile(\cf3 string\cf0  fileName)\par ??        \{\par ??            System.IO.\cf4 File\cf0 .Delete(fileName);\par ??        \}\par ??    \}}
-->
        </p>
        <div style="font-size: 10pt; background: white; color: black; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>     <span style="color: blue">class</span><span style="color: #2b91af">FileHelper</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>     {
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>         <span style="color: gray">///</span><span style="color: green"></span><span style="color: gray">&lt;summary&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>         <span style="color: gray">///</span><span style="color: green"> Deletes
the file.</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>         <span style="color: gray">///</span><span style="color: green"></span><span style="color: gray">&lt;/summary&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>         <span style="color: gray">///</span><span style="color: green"></span><span style="color: gray">&lt;param
name="fileName"&gt;</span><span style="color: green">Please enter valid 
(*.tmp)</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>         <span style="color: gray">///</span><span style="color: green"> and
existing file names only!</span><span style="color: gray">&lt;/param&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>         <span style="color: blue">public</span><span style="color: blue">static</span><span style="color: blue">void</span> DeleteTempFile(<span style="color: blue">string</span> fileName)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>        
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>            
System.IO.<span style="color: #2b91af">File</span>.Delete(fileName);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>        
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>     }
</p>
        </div>
        <p>
        </p>
        <p>
Wie wir sehen, wurde ab der Zeile 8 die Methode "<em>DeleteTempFile"</em> implementiert,
die in Ihrem Kommentar höflich darum bittet, nur gültige und vor allem nur <strong>temporäre</strong> Dateinamen
zu übergeben.
</p>
        <p>
So freundlich der Kommentar zwar ist, so wenig nützlich ist er aber auch. Dem
Aufrufer unserer Methode wäre es ein leichtes, folgendes hinein zu geben:
</p>
        <p>
          <!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red163\green21\blue21;}??\fs20             DeleteFile(\cf3 null\cf0 );\par ??            DeleteTempFile(\cf4 @"c:\\diese\\Datei\\gibt\\es\\nicht.hahaha"\cf0 );\par ??            DeleteTempFile(\cf4 @"c:\\Diplomarbeit.doc"\cf0 );}
-->
        </p>
        <div style="font-size: 10pt; background: white; color: black; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>   FileHelper.DeleteTempFile(<span style="color: blue">null</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>   FileHelper.DeleteTempFile(<span style="color: #a31515">@"c:\diese\Datei\gibt\es\nicht.hahaha"</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>   FileHelper.DeleteTempFile(<span style="color: #a31515">@"c:\Diplomarbeit.doc"</span>);
</p>
        </div>
        <p>
        </p>
        <p>
Während die Aufrufe Eins und zwei "<em>nur</em>" zu störenden
Exceptions führt, wäre Aufruf Nr. Drei sicherlich schon ärgerlicher.
</p>
        <p>
Was tun, lautet also die Frage! "Validierung der Argumente", oder Einhalten
der Regel <a href="http://msdn.microsoft.com/de-de/library/ms182182.aspx">CA1062</a> -
wie fxCop so schön sagen würde - lautet die Antwort!
</p>
        <p>
Im einfachsten Fall sähe dies wie folgt aus:
</p>
        <p>
          <!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;\red0\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20         \cf3 ///\cf4  \cf3 &lt;summary&gt;\par ??\cf0         \cf3 ///\cf4  Deletes the file.\par ??\cf0         \cf3 ///\cf4  \cf3 &lt;/summary&gt;\par ??\cf0         \cf3 ///\cf4  \cf3 &lt;param name="fileName"&gt;\cf4 Please enter valid  (*.tmp)\par ??\cf0         \cf3 ///\cf4  and existing file names only!\cf3 &lt;/param&gt;\par ??\cf0         \cf5 public\cf0  \cf5 static\cf0  \cf5 void\cf0  DeleteTempFile(\cf5 string\cf0  fileName)\par ??        \{\par ??            \cf5 if\cf0  (fileName == \cf5 null\cf0 )\par ??            \{\par ??                \cf5 throw\cf0  \cf5 new\cf0  \cf6 ArgumentNullException\cf0 (\cf7 "fileName"\cf0 );\par ??            \}\par ??            \cf5 if\cf0  (System.IO.\cf6 Path\cf0 .GetExtension(fileName) != \cf7 "tmp"\cf0 )\par ??            \{\par ??                \cf5 throw\cf0  \cf5 new\cf0  \cf6 ArgumentOutOfRangeException\cf0 (\cf7 "fileName"\cf0 , \cf7 "Only temporary (*.tmp) files are allowed!"\cf0 );\par ??            \}\par ??            \cf5 if\cf0  (!System.IO.\cf6 File\cf0 .Exists(fileName))\par ??            \{\par ??                \cf5 throw\cf0  \cf5 new\cf0  \cf6 ArgumentException\cf0 (\cf7 "File Not Found"\cf0 , \cf7 "fileName"\cf0 , \par ??                    \cf5 new\cf0  System.IO.\cf6 FileNotFoundException\cf0 ());\par ??            \}\par ??            System.IO.\cf6 File\cf0 .Delete(fileName);\par ??        \}}
-->
        </p>
        <div style="font-size: 10pt; background: white; color: black; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>         <span style="color: gray">///</span><span style="color: green"></span><span style="color: gray">&lt;summary&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>         <span style="color: gray">///</span><span style="color: green"> Deletes
the file.</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>         <span style="color: gray">///</span><span style="color: green"></span><span style="color: gray">&lt;/summary&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>         <span style="color: gray">///</span><span style="color: green"></span><span style="color: gray">&lt;param
name="fileName"&gt;</span><span style="color: green">Please enter valid 
(*.tmp)</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>         <span style="color: gray">///</span><span style="color: green"> and
existing file names only!</span><span style="color: gray">&lt;/param&gt;</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>         <span style="color: blue">public</span><span style="color: blue">static</span><span style="color: blue">void</span> DeleteTempFile(<span style="color: blue">string</span> fileName)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>        
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span>             <span style="color: blue">if</span> (fileName
== <span style="color: blue">null</span>)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>            
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span>                 <span style="color: blue">throw</span><span style="color: blue">new</span><span style="color: #2b91af">ArgumentNullException</span>(<span style="color: #a31515">"fileName"</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>            
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>             <span style="color: blue">if</span> (System.IO.<span style="color: #2b91af">Path</span>.GetExtension(fileName)
!= <span style="color: #a31515">".tmp"</span>)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>            
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   14</span>                 <span style="color: blue">throw</span><span style="color: blue">new</span><span style="color: #2b91af">ArgumentOutOfRangeException</span>(<span style="color: #a31515">"fileName"</span>, <span style="color: #a31515">"Only
temporary (*.tmp) files are allowed!"</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   15</span>            
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   16</span>             <span style="color: blue">if</span> (!System.IO.<span style="color: #2b91af">File</span>.Exists(fileName))
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   17</span>            
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   18</span>                 <span style="color: blue">throw</span><span style="color: blue">new</span><span style="color: #2b91af">ArgumentException</span>(<span style="color: #a31515">"File
Not Found"</span>, <span style="color: #a31515">"fileName"</span>, 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   19</span>                     <span style="color: blue">new</span> System.IO.<span style="color: #2b91af">FileNotFoundException</span>());
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   20</span>            
}
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   21</span>            
System.IO.<span style="color: #2b91af">File</span>.Delete(fileName);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   22</span>        
}
</p>
        </div>
        <p>
        </p>
        <p>
Vom technischen Standpunkt aus gesehen gibt es an diesem Code nichts auszusetzen.
Das Argument <em>fileName</em> wurde ausreichend geprüft und abgesehen von unzureichenden
Berechtigungen auf Dateisystemebene dürfte eigentlich nichts mehr schief gehen.
</p>
        <p>
In der Praxis zeigt sich jedoch häufig, dass hier die Bequemheit siegt. Wirft
man noch ein Mal einen Blick auf den Quellcode, wird schnell deutlich, dass wir zur
Validierung eines Argumentes 13 Zeilen Quellcode geschrieben haben. Die Anzahl der
Methoden, die ihre Eingaben nur unzureichend validieren dürfte also klar in der
Überzahl sein.
</p>
        <p>
Eleganter und vor allem zeitsparender wäre es doch, wenn ich meinem Code auf
dem "kurzen Dienstweg" sagen könnte, welche Anforderungen ich an meine
Argumente habe, damit mein Code überhaupt laufen kann. Sahnebonbon wäre
es auch, wenn ich zusätzlich noch eine Möglichkeit hätte, dem aufrufenden
Code sicher mitzuteilen, ob das was mein Code versucht hat auch wirklich funktioniert
hat.
</p>
        <p>
Glücklicherweise gibt es all dies schon. Es hört auf den schönen Namen <a href="http://de.wikipedia.org/wiki/Design_By_Contract">Design
By Contract</a> und hat seinen Ursprung in der Programmiersprache <a href="http://de.wikipedia.org/wiki/Eiffel_%28Programmiersprache%29">Eiffel</a>.
Design By Contract baut auf Vorbedingungen (Preconditions), die erfüllt sein
müssen, damit eine Methode laufen kann, und auf Nachbedingungen (Postconditions)
auf, die angeben ob meine Methode erfolgreich war. Beides zusammen ergibt den Vertrag
(Contract)
</p>
        <p>
          <a href="http://www.codeproject.com/KB/cs/designbycontract.aspx">Hier</a> gibt es
einen sehr schönen Code Project Artikel inklusive einer DBC C# Library (basierend
auf .NET 1.x) zu diesem Thema. Übertragen auf unseren Fall sähe dies wie
folgt aus:
</p>
        <p>
          <!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red0\green128\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20         \cf3 public\cf0  \cf3 static\cf0  \cf3 void\cf0  DeleteTempFile(\cf3 string\cf0  fileName)\par ??        \{\par ??            \cf4 // Postconditions validieren\par ??\cf0             \cf5 Check\cf0 .Require(fileName != \cf3 null\cf0 , \cf6 "fileName may not be null"\cf0 );\par ??            \cf5 Check\cf0 .Require(System.IO.\cf5 Path\cf0 .GetExtension(fileName) == \cf6 ".tmp"\cf0 ,\par ??                \cf6 "Only temporary (*.tmp) files are allowed!"\cf0 );\par ??            \cf5 Check\cf0 .Require(System.IO.\cf5 File\cf0 .Exists(fileName), \cf6 "File not found"\cf0 );\par ??\par ??            System.IO.\cf5 File\cf0 .Delete(fileName);\par ??\par ??            \cf4 // Preconditions validieren\par ??\cf0             \cf5 Check\cf0 .Ensure(!System.IO.\cf5 File\cf0 .Exists(fileName), \cf6 "File could not be deleted!"\cf0 );\par ??        \}}
-->
        </p>
        <div style="font-size: 10pt; background: white; color: black; font-family: courier new">
          <p style="margin: 0px">
            <span style="color: #2b91af">    1</span>         <span style="color: blue">public</span><span style="color: blue">static</span><span style="color: blue">void</span> DeleteTempFile(<span style="color: blue">string</span> fileName)
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    2</span>        
{
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    3</span>             <span style="color: green">//
Postconditions validieren</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    4</span>             <span style="color: #2b91af">Check</span>.Require(fileName
!= <span style="color: blue">null</span>, <span style="color: #a31515">"fileName
may not be null"</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    5</span>             <span style="color: #2b91af">Check</span>.Require(System.IO.<span style="color: #2b91af">Path</span>.GetExtension(fileName)
== <span style="color: #a31515">".tmp"</span>,
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    6</span>                 <span style="color: #a31515">"Only
temporary (*.tmp) files are allowed!"</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    7</span>             <span style="color: #2b91af">Check</span>.Require(System.IO.<span style="color: #2b91af">File</span>.Exists(fileName), <span style="color: #a31515">"File
not found"</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    8</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">    9</span>            
System.IO.<span style="color: #2b91af">File</span>.Delete(fileName);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   10</span> 
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   11</span>             <span style="color: green">//
Preconditions validieren</span></p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   12</span>             <span style="color: #2b91af">Check</span>.Ensure(!System.IO.<span style="color: #2b91af">File</span>.Exists(fileName), <span style="color: #a31515">"File
could not be deleted!"</span>);
</p>
          <p style="margin: 0px">
            <span style="color: #2b91af">   13</span>        
}
</p>
        </div>
        <p>
        </p>
        <p>
Eigentlich sehr schön, oder? Sobald eine der Prüfungen fehlschlägt
wird übrigens eine <em>PreconditionException</em> bzw. <em>PostconditionExceptoin</em> geworfen.
Es gibt übrigens noch eine zusätzliche Überladung, die Angabe einer
InnerException, wie z. B. <em>ArgumentNullException</em> oder <em>FileNotFoundExceptoin</em> erlaubt. 
</p>
        <p>
Noch schöner fände ich es übrigens, wenn die Pre-/Postconditions nicht
im Quellcode der Methode stehen, sondern als Attribut annotiert werden würden.
</p>
        <p>
Eine kurze Suche bei Goolge ergab, dass es dazu bereits (mindestens) zwei Ansätze
gibt:
</p>
        <ul>
          <li>
            <a href="http://research.microsoft.com/specsharp/" target="_blank">Spec#</a>
          </li>
          <li>
            <a href="http://www.resolvecorp.com/" target="_blank">XC#</a>
          </li>
        </ul>
        <p>
Bisher hatte ich leider noch nicht die Zeit, mir eins von beidem anzusehen. Sollte
ein Leser dieses Blog-Posts bereits Erfahrung mit einer der beiden Varianten, oder
aber einer anderen Attribut-Basierten DBC Implmentierung Erfahrung haben, würde
ich mich über einen Kommentar freuen. 
</p>
        <p>
... in allen anderen Fällen freue ich mich natürlich auch über Kommentare
;-)
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=7b79ef3b-4f2c-450b-8202-0c42cb0984c8" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Traue niemandem! - oder wie Design By Contract zwar keine Leben, aber Zeit retten kann.</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,7b79ef3b-4f2c-450b-8202-0c42cb0984c8.aspx</guid>
      <link>http://blog.codemurai.de/2008/07/27/TraueNiemandemOderWieDesignByContractZwarKeineLebenAberZeitRettenKann.aspx</link>
      <pubDate>Sun, 27 Jul 2008 17:48:24 GMT</pubDate>
      <description>&lt;p&gt;
Protagonisten von Kriminalfilmen, die die Weisheit &amp;quot;&lt;em&gt;Traue niemandem&lt;/em&gt;&amp;quot;
beherzigen, leben l&amp;#228;nger und geh&amp;#246;ren am Ende des Films meist zu denjenigen,
die nicht tot sind.&amp;#160; Was im Film gut ist, kann in der Softwareentwicklung doch
nicht nicht schlecht sein, oder? Genau! Dies ist der Grund, weshalb man aufrufendem
Code grunds&amp;#228;tzlich misstrauen sollte! Gl&amp;#252;cklicherweise f&amp;#252;hrt zuwiderhandeln
in der Softwareentwicklung zwar in den seltendsten F&amp;#228;llen zum Tod, zu einem Haufen
&amp;#220;berstunden kann es aber sehr schnell f&amp;#252;hren.
&lt;/p&gt;
&lt;p&gt;
Anhand folgenden Beispiels m&amp;#246;chte ich dies gerne verdeutlichen:
&lt;/p&gt;
&lt;p&gt;
Unsere Aufgabe ist es, eine Methode zu schreiben, die eine angegebene, tempor&amp;#228;re
Datei l&amp;#246;scht. Im einfachsten Fall k&amp;#246;nnte dies so aussehen:
&lt;/p&gt;
&lt;p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red128\green128\blue128;\red0\green128\blue0;}??\fs20     \cf3 class\cf0  \cf4 Program\par ??\cf0     \{\par ??        \cf3 static\cf0  \cf3 void\cf0  Main(\cf3 string\cf0 [] args)\par ??        \{\par ??            DeleteFile(\cf3 null\cf0 );\par ??        \}\par ??        \cf5 ///\cf6  \cf5 &amp;lt;summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  Deletes the file.\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf5 ///\cf6  \cf5 &amp;lt;param name="fileName"&amp;gt;\cf6 Please enter valid  (*.tmp)\par ??\cf0         \cf5 ///\cf6  and existing file names only!\cf5 &amp;lt;/param&amp;gt;\par ??\cf0         \cf3 public\cf0  \cf3 static\cf0  \cf3 void\cf0  DeleteTempFile(\cf3 string\cf0  fileName)\par ??        \{\par ??            System.IO.\cf4 File\cf0 .Delete(fileName);\par ??        \}\par ??    \}}
--&gt;
&lt;/p&gt;
&lt;div style="font-size: 10pt; background: white; color: black; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;FileHelper&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; Deletes
the file.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param
name=&amp;quot;fileName&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;Please enter valid&amp;#160;
(*.tmp)&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; and
existing file names only!&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; DeleteTempFile(&lt;span style="color: blue"&gt;string&lt;/span&gt; fileName)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
System.IO.&lt;span style="color: #2b91af"&gt;File&lt;/span&gt;.Delete(fileName);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Wie wir sehen, wurde ab der Zeile 8 die Methode &amp;quot;&lt;em&gt;DeleteTempFile&amp;quot;&lt;/em&gt; implementiert,
die in Ihrem Kommentar h&amp;#246;flich darum bittet, nur g&amp;#252;ltige und vor allem nur &lt;strong&gt;tempor&amp;#228;re&lt;/strong&gt; Dateinamen
zu &amp;#252;bergeben.
&lt;/p&gt;
&lt;p&gt;
So freundlich der Kommentar zwar ist, so wenig n&amp;#252;tzlich ist er aber auch. Dem
Aufrufer unserer Methode w&amp;#228;re es ein leichtes, folgendes hinein zu geben:
&lt;/p&gt;
&lt;p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red163\green21\blue21;}??\fs20             DeleteFile(\cf3 null\cf0 );\par ??            DeleteTempFile(\cf4 @"c:\\diese\\Datei\\gibt\\es\\nicht.hahaha"\cf0 );\par ??            DeleteTempFile(\cf4 @"c:\\Diplomarbeit.doc"\cf0 );}
--&gt;
&lt;/p&gt;
&lt;div style="font-size: 10pt; background: white; color: black; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160; FileHelper.DeleteTempFile(&lt;span style="color: blue"&gt;null&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160; FileHelper.DeleteTempFile(&lt;span style="color: #a31515"&gt;@&amp;quot;c:\diese\Datei\gibt\es\nicht.hahaha&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160; FileHelper.DeleteTempFile(&lt;span style="color: #a31515"&gt;@&amp;quot;c:\Diplomarbeit.doc&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
W&amp;#228;hrend die Aufrufe Eins und zwei &amp;quot;&lt;em&gt;nur&lt;/em&gt;&amp;quot; zu st&amp;#246;renden
Exceptions f&amp;#252;hrt, w&amp;#228;re Aufruf Nr. Drei sicherlich schon &amp;#228;rgerlicher.
&lt;/p&gt;
&lt;p&gt;
Was tun, lautet also die Frage! &amp;quot;Validierung der Argumente&amp;quot;, oder Einhalten
der Regel &lt;a href="http://msdn.microsoft.com/de-de/library/ms182182.aspx"&gt;CA1062&lt;/a&gt; -
wie fxCop so sch&amp;#246;n sagen w&amp;#252;rde - lautet die Antwort!
&lt;/p&gt;
&lt;p&gt;
Im einfachsten Fall s&amp;#228;he dies wie folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;\red0\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20         \cf3 ///\cf4  \cf3 &amp;lt;summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  Deletes the file.\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;/summary&amp;gt;\par ??\cf0         \cf3 ///\cf4  \cf3 &amp;lt;param name="fileName"&amp;gt;\cf4 Please enter valid  (*.tmp)\par ??\cf0         \cf3 ///\cf4  and existing file names only!\cf3 &amp;lt;/param&amp;gt;\par ??\cf0         \cf5 public\cf0  \cf5 static\cf0  \cf5 void\cf0  DeleteTempFile(\cf5 string\cf0  fileName)\par ??        \{\par ??            \cf5 if\cf0  (fileName == \cf5 null\cf0 )\par ??            \{\par ??                \cf5 throw\cf0  \cf5 new\cf0  \cf6 ArgumentNullException\cf0 (\cf7 "fileName"\cf0 );\par ??            \}\par ??            \cf5 if\cf0  (System.IO.\cf6 Path\cf0 .GetExtension(fileName) != \cf7 "tmp"\cf0 )\par ??            \{\par ??                \cf5 throw\cf0  \cf5 new\cf0  \cf6 ArgumentOutOfRangeException\cf0 (\cf7 "fileName"\cf0 , \cf7 "Only temporary (*.tmp) files are allowed!"\cf0 );\par ??            \}\par ??            \cf5 if\cf0  (!System.IO.\cf6 File\cf0 .Exists(fileName))\par ??            \{\par ??                \cf5 throw\cf0  \cf5 new\cf0  \cf6 ArgumentException\cf0 (\cf7 "File Not Found"\cf0 , \cf7 "fileName"\cf0 , \par ??                    \cf5 new\cf0  System.IO.\cf6 FileNotFoundException\cf0 ());\par ??            \}\par ??            System.IO.\cf6 File\cf0 .Delete(fileName);\par ??        \}}
--&gt;
&lt;/p&gt;
&lt;div style="font-size: 10pt; background: white; color: black; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; Deletes
the file.&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; &lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;param
name=&amp;quot;fileName&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="color: green"&gt;Please enter valid&amp;#160;
(*.tmp)&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: gray"&gt;///&lt;/span&gt;&lt;span style="color: green"&gt; and
existing file names only!&lt;/span&gt;&lt;span style="color: gray"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; DeleteTempFile(&lt;span style="color: blue"&gt;string&lt;/span&gt; fileName)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (fileName
== &lt;span style="color: blue"&gt;null&lt;/span&gt;)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;throw&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;fileName&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (System.IO.&lt;span style="color: #2b91af"&gt;Path&lt;/span&gt;.GetExtension(fileName)
!= &lt;span style="color: #a31515"&gt;&amp;quot;.tmp&amp;quot;&lt;/span&gt;)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 14&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;throw&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ArgumentOutOfRangeException&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;fileName&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;Only
temporary (*.tmp) files are allowed!&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 15&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 16&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;if&lt;/span&gt; (!System.IO.&lt;span style="color: #2b91af"&gt;File&lt;/span&gt;.Exists(fileName))
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 17&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 18&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;throw&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ArgumentException&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;File
Not Found&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;fileName&amp;quot;&lt;/span&gt;, 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 19&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;new&lt;/span&gt; System.IO.&lt;span style="color: #2b91af"&gt;FileNotFoundException&lt;/span&gt;());
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 20&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 21&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
System.IO.&lt;span style="color: #2b91af"&gt;File&lt;/span&gt;.Delete(fileName);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 22&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Vom technischen Standpunkt aus gesehen gibt es an diesem Code nichts auszusetzen.
Das Argument &lt;em&gt;fileName&lt;/em&gt; wurde ausreichend gepr&amp;#252;ft und abgesehen von unzureichenden
Berechtigungen auf Dateisystemebene d&amp;#252;rfte eigentlich nichts mehr schief gehen.
&lt;/p&gt;
&lt;p&gt;
In der Praxis zeigt sich jedoch h&amp;#228;ufig, dass hier die Bequemheit siegt. Wirft
man noch ein Mal einen Blick auf den Quellcode, wird schnell deutlich, dass wir zur
Validierung eines Argumentes 13 Zeilen Quellcode geschrieben haben. Die Anzahl der
Methoden, die ihre Eingaben nur unzureichend validieren d&amp;#252;rfte also klar in der
&amp;#220;berzahl sein.
&lt;/p&gt;
&lt;p&gt;
Eleganter und vor allem zeitsparender w&amp;#228;re es doch, wenn ich meinem Code auf
dem &amp;quot;kurzen Dienstweg&amp;quot; sagen k&amp;#246;nnte, welche Anforderungen ich an meine
Argumente habe, damit mein Code &amp;#252;berhaupt laufen kann. Sahnebonbon w&amp;#228;re
es auch, wenn ich zus&amp;#228;tzlich noch eine M&amp;#246;glichkeit h&amp;#228;tte, dem aufrufenden
Code sicher mitzuteilen, ob das was mein Code versucht hat auch wirklich funktioniert
hat.
&lt;/p&gt;
&lt;p&gt;
Gl&amp;#252;cklicherweise gibt es all dies schon. Es h&amp;#246;rt auf den sch&amp;#246;nen Namen &lt;a href="http://de.wikipedia.org/wiki/Design_By_Contract"&gt;Design
By Contract&lt;/a&gt; und hat seinen Ursprung in der Programmiersprache &lt;a href="http://de.wikipedia.org/wiki/Eiffel_%28Programmiersprache%29"&gt;Eiffel&lt;/a&gt;.
Design By Contract baut auf Vorbedingungen (Preconditions), die erf&amp;#252;llt sein
m&amp;#252;ssen, damit eine Methode laufen kann, und auf Nachbedingungen (Postconditions)
auf, die angeben ob meine Methode erfolgreich war. Beides zusammen ergibt den Vertrag
(Contract)
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.codeproject.com/KB/cs/designbycontract.aspx"&gt;Hier&lt;/a&gt; gibt es
einen sehr sch&amp;#246;nen Code Project Artikel inklusive einer DBC C# Library (basierend
auf .NET 1.x) zu diesem Thema. &amp;#220;bertragen auf unseren Fall s&amp;#228;he dies wie
folgt aus:
&lt;/p&gt;
&lt;p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red0\green128\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20         \cf3 public\cf0  \cf3 static\cf0  \cf3 void\cf0  DeleteTempFile(\cf3 string\cf0  fileName)\par ??        \{\par ??            \cf4 // Postconditions validieren\par ??\cf0             \cf5 Check\cf0 .Require(fileName != \cf3 null\cf0 , \cf6 "fileName may not be null"\cf0 );\par ??            \cf5 Check\cf0 .Require(System.IO.\cf5 Path\cf0 .GetExtension(fileName) == \cf6 ".tmp"\cf0 ,\par ??                \cf6 "Only temporary (*.tmp) files are allowed!"\cf0 );\par ??            \cf5 Check\cf0 .Require(System.IO.\cf5 File\cf0 .Exists(fileName), \cf6 "File not found"\cf0 );\par ??\par ??            System.IO.\cf5 File\cf0 .Delete(fileName);\par ??\par ??            \cf4 // Preconditions validieren\par ??\cf0             \cf5 Check\cf0 .Ensure(!System.IO.\cf5 File\cf0 .Exists(fileName), \cf6 "File could not be deleted!"\cf0 );\par ??        \}}
--&gt;
&lt;/p&gt;
&lt;div style="font-size: 10pt; background: white; color: black; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 1&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; DeleteTempFile(&lt;span style="color: blue"&gt;string&lt;/span&gt; fileName)
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 2&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
{
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 3&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: green"&gt;//
Postconditions validieren&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 4&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Check&lt;/span&gt;.Require(fileName
!= &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;fileName
may not be null&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 5&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Check&lt;/span&gt;.Require(System.IO.&lt;span style="color: #2b91af"&gt;Path&lt;/span&gt;.GetExtension(fileName)
== &lt;span style="color: #a31515"&gt;&amp;quot;.tmp&amp;quot;&lt;/span&gt;,
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 6&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #a31515"&gt;&amp;quot;Only
temporary (*.tmp) files are allowed!&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 7&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Check&lt;/span&gt;.Require(System.IO.&lt;span style="color: #2b91af"&gt;File&lt;/span&gt;.Exists(fileName), &lt;span style="color: #a31515"&gt;&amp;quot;File
not found&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 8&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160; 9&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
System.IO.&lt;span style="color: #2b91af"&gt;File&lt;/span&gt;.Delete(fileName);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 10&lt;/span&gt;&amp;#160;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 11&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: green"&gt;//
Preconditions validieren&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 12&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Check&lt;/span&gt;.Ensure(!System.IO.&lt;span style="color: #2b91af"&gt;File&lt;/span&gt;.Exists(fileName), &lt;span style="color: #a31515"&gt;&amp;quot;File
could not be deleted!&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160; 13&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;
}
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Eigentlich sehr sch&amp;#246;n, oder? Sobald eine der Pr&amp;#252;fungen fehlschl&amp;#228;gt
wird &amp;#252;brigens eine &lt;em&gt;PreconditionException&lt;/em&gt; bzw. &lt;em&gt;PostconditionExceptoin&lt;/em&gt; geworfen.
Es gibt &amp;#252;brigens noch eine zus&amp;#228;tzliche &amp;#220;berladung, die Angabe einer
InnerException, wie z. B. &lt;em&gt;ArgumentNullException&lt;/em&gt; oder &lt;em&gt;FileNotFoundExceptoin&lt;/em&gt; erlaubt. 
&lt;/p&gt;
&lt;p&gt;
Noch sch&amp;#246;ner f&amp;#228;nde ich es &amp;#252;brigens, wenn die Pre-/Postconditions nicht
im Quellcode der Methode stehen, sondern als Attribut annotiert werden w&amp;#252;rden.
&lt;/p&gt;
&lt;p&gt;
Eine kurze Suche bei Goolge ergab, dass es dazu bereits (mindestens) zwei Ans&amp;#228;tze
gibt:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://research.microsoft.com/specsharp/" target="_blank"&gt;Spec#&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.resolvecorp.com/" target="_blank"&gt;XC#&lt;/a&gt; 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Bisher hatte ich leider noch nicht die Zeit, mir eins von beidem anzusehen. Sollte
ein Leser dieses Blog-Posts bereits Erfahrung mit einer der beiden Varianten, oder
aber einer anderen Attribut-Basierten DBC Implmentierung Erfahrung haben, w&amp;#252;rde
ich mich &amp;#252;ber einen Kommentar freuen. 
&lt;/p&gt;
&lt;p&gt;
... in allen anderen F&amp;#228;llen freue ich mich nat&amp;#252;rlich auch &amp;#252;ber Kommentare
;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=7b79ef3b-4f2c-450b-8202-0c42cb0984c8" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,7b79ef3b-4f2c-450b-8202-0c42cb0984c8.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=eb0bd9ce-a5e6-4d93-9f5c-86d09a165921</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,eb0bd9ce-a5e6-4d93-9f5c-86d09a165921.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,eb0bd9ce-a5e6-4d93-9f5c-86d09a165921.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=eb0bd9ce-a5e6-4d93-9f5c-86d09a165921</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Nachdem ich die letzten Jahre meine Software fast ausschließlich unter C# entwickelte,
musste ich kürzlich für einen Kunden an einem VB.NET Projekt arbeiten.
</p>
        <p>
Die Umgewöhnung in die Sprache klappte überraschend schnell und reibungslos.
Allerdings übersah ich, dass VB.NET von Haus aus keine Escape Sequenzen, wie
z. B. <strong>\n</strong> für neue Zeile oder <strong>\t</strong> für Tab
unterstützt. Entsprechend sahen auf der Oberfläche auch meine ausgegebenen
Strings aus.
</p>
        <p>
Auf der Suche nach einer Lösung bei der ich nicht sämtliche zuvor definierten
Strings anpacken musste, stolperte ich fast ausnahmslos auf Ansätze, die Über <strong>String.Replace()</strong> die
Escape Sequenzen gegen VB.NET Control Characters ersetzten.
</p>
        <p>
Eleganter fand ich allerdings folgende Lösung, die auf eine .NET Framework Standardklasse
setzt:
</p>
        <!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;}??\fs20 message = System.Text.RegularExpressions.Regex.Unescape(message)}
-->
        <div style="border-top-width: 1px; border-left-width: 1px; font-size: 10pt; background: white; border-bottom-width: 1px; color: black; font-family: courier new; border-right-width: 1px">
          <p style="margin: 0px">
myString = System.Text.RegularExpressions.Regex.Unescape(myString)
</p>
        </div>
        <p>
... Ist doch irgendwie eleganter, oder? :-)
</p>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=eb0bd9ce-a5e6-4d93-9f5c-86d09a165921" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Escape Sequenzen in Strings unter VB.NET aufl&amp;ouml;sen</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,eb0bd9ce-a5e6-4d93-9f5c-86d09a165921.aspx</guid>
      <link>http://blog.codemurai.de/2008/07/09/EscapeSequenzenInStringsUnterVBNETAufloumlsen.aspx</link>
      <pubDate>Wed, 09 Jul 2008 06:32:31 GMT</pubDate>
      <description>&lt;p&gt;
Nachdem ich die letzten Jahre meine Software fast ausschlie&amp;#223;lich unter C# entwickelte,
musste ich k&amp;#252;rzlich f&amp;#252;r einen Kunden an einem VB.NET Projekt arbeiten.
&lt;/p&gt;
&lt;p&gt;
Die Umgew&amp;#246;hnung in die Sprache klappte &amp;#252;berraschend schnell und reibungslos.
Allerdings &amp;#252;bersah ich, dass VB.NET von Haus aus keine Escape Sequenzen, wie
z. B. &lt;strong&gt;\n&lt;/strong&gt; f&amp;#252;r neue Zeile oder &lt;strong&gt;\t&lt;/strong&gt; f&amp;#252;r Tab
unterst&amp;#252;tzt. Entsprechend sahen auf der Oberfl&amp;#228;che auch meine ausgegebenen
Strings aus.
&lt;/p&gt;
&lt;p&gt;
Auf der Suche nach einer L&amp;#246;sung bei der ich nicht s&amp;#228;mtliche zuvor definierten
Strings anpacken musste, stolperte ich fast ausnahmslos auf Ans&amp;#228;tze, die &amp;#220;ber &lt;strong&gt;String.Replace()&lt;/strong&gt; die
Escape Sequenzen gegen VB.NET Control Characters ersetzten.
&lt;/p&gt;
&lt;p&gt;
Eleganter fand ich allerdings folgende L&amp;#246;sung, die auf eine .NET Framework Standardklasse
setzt:
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;}??\fs20 message = System.Text.RegularExpressions.Regex.Unescape(message)}
--&gt;
&lt;div style="border-top-width: 1px; border-left-width: 1px; font-size: 10pt; background: white; border-bottom-width: 1px; color: black; font-family: courier new; border-right-width: 1px"&gt;
&lt;p style="margin: 0px"&gt;
myString = System.Text.RegularExpressions.Regex.Unescape(myString)
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
... Ist doch irgendwie eleganter, oder? :-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=eb0bd9ce-a5e6-4d93-9f5c-86d09a165921" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,eb0bd9ce-a5e6-4d93-9f5c-86d09a165921.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Tips und Tricks</category>
      <category>VB.NET</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=315ccb7b-6a25-49ff-a252-8382540a112a</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,315ccb7b-6a25-49ff-a252-8382540a112a.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,315ccb7b-6a25-49ff-a252-8382540a112a.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=315ccb7b-6a25-49ff-a252-8382540a112a</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Bei meinen Streifzügen durchs Web bin ich über folgendes <a href="http://pixel8.infragistics.com/#Episode:8589" target="_blank">Video</a> gestolpert.
Es zeigt Rick Barraza, User Experience Architect bei Cynergy Systems, der aus einer
Wii-Remote, zwei Handschuhen, einer Funkmaus und WPF innerhalb von acht Tagen ein
Minority Report ähnliches User Interface gebaut hat. 
</p>
        <p>
          <a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/ProjectMaestrooderMinorityReport.NET_EAC6/minority.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="217" alt="minority" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/ProjectMaestrooderMinorityReport.NET_EAC6/minority_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Hat ein wenig etwas von <a href="http://de.wikipedia.org/wiki/MacGyver" target="_blank">MacGyver</a>,
oder :-)
</p>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:42180893-2884-41e1-b6c5-092c7a4889d1" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
tags: <a href="http://technorati.com/tags/WPF" rel="tag">WPF</a></div>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=315ccb7b-6a25-49ff-a252-8382540a112a" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Project Maestro - oder Minority Report.NET</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,315ccb7b-6a25-49ff-a252-8382540a112a.aspx</guid>
      <link>http://blog.codemurai.de/2008/04/07/ProjectMaestroOderMinorityReportNET.aspx</link>
      <pubDate>Mon, 07 Apr 2008 14:41:57 GMT</pubDate>
      <description>&lt;p&gt;
Bei meinen Streifz&amp;#252;gen durchs Web bin ich &amp;#252;ber folgendes &lt;a href="http://pixel8.infragistics.com/#Episode:8589" target="_blank"&gt;Video&lt;/a&gt; gestolpert.
Es zeigt Rick Barraza, User Experience Architect bei Cynergy Systems, der aus einer
Wii-Remote, zwei Handschuhen, einer Funkmaus und WPF innerhalb von acht Tagen ein
Minority Report &amp;#228;hnliches User Interface gebaut hat. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/ProjectMaestrooderMinorityReport.NET_EAC6/minority.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="217" alt="minority" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/ProjectMaestrooderMinorityReport.NET_EAC6/minority_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Hat ein wenig etwas von &lt;a href="http://de.wikipedia.org/wiki/MacGyver" target="_blank"&gt;MacGyver&lt;/a&gt;,
oder :-)
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:42180893-2884-41e1-b6c5-092c7a4889d1" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
tags: &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=315ccb7b-6a25-49ff-a252-8382540a112a" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,315ccb7b-6a25-49ff-a252-8382540a112a.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>WPF</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=19d93da9-2d3b-4c83-8857-70622da4c5ae</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,19d93da9-2d3b-4c83-8857-70622da4c5ae.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,19d93da9-2d3b-4c83-8857-70622da4c5ae.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=19d93da9-2d3b-4c83-8857-70622da4c5ae</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Wirft man einen Blick auf die Vielzahl der im Internet vorhandenen Silverlight 1.0
Demo Applikationen, stellt man in den meisten Fällen eine Gemeinsamkeit fest:
</p>
        <ul>
          <li>
Die Demo zeigt verblüffende grafische Effekte / Animationen im Web</li>
          <li>
Abgesehen von diesen Effekten hat die Demo keinerlei Nährwert :-)</li>
        </ul>
        <p>
Infragistics möchte die Lücke der wertvollen Silverlight Demos nun füllen.
</p>
        <p>
Zu diesem Zweck wird unter <a href="http://www.faceoutlive.com/" target="_blank">http://www.faceoutlive.com/</a> ein
Silverlight Dashboard für Vertriebsmitarbeiter gezeigt.
</p>
        <p>
          <a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/GeschftsanwendungenmitSilverlight2.0_E5C3/faceout.png">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="229" alt="faceout" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/GeschftsanwendungenmitSilverlight2.0_E5C3/faceout_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Registrierte Benutzer erhalten unter  <a href="http://www.infragistics.com/hot/silverlight.aspx#InfragisticsandSilverlight" target="_blank">http://www.infragistics.com/hot/silverlight.aspx#InfragisticsandSilverlight</a> zusätzlich
den kompletten Source Code sowie ein <a href="http://www.infragistics.com/uploadedFiles/WhatsHot/Silverlight/Images/FaceOut%20Overview.xps" target="_blank">12seitiges
Dokument</a>, in dem Infragistics einen kurzen Überblick über die Applikationsarchitektur
sowie die "lessons-learned" gibt. Gerade der "lessons-learned"
Bereich ist sehr interessant.
</p>
        <p>
In diesem Sinne: Viel Spaß mit Silverlight ;-)
</p>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:113f1371-1c19-4a54-bcdc-b8db1f28786d" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
tags: <a href="http://technorati.com/tags/Infragistics" rel="tag">Infragistics</a>, <a href="http://technorati.com/tags/Silverlight" rel="tag">Silverlight</a></div>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=19d93da9-2d3b-4c83-8857-70622da4c5ae" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Gesch&amp;auml;ftsanwendungen mit Silverlight 2.0</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,19d93da9-2d3b-4c83-8857-70622da4c5ae.aspx</guid>
      <link>http://blog.codemurai.de/2008/04/07/GeschaumlftsanwendungenMitSilverlight20.aspx</link>
      <pubDate>Mon, 07 Apr 2008 14:20:45 GMT</pubDate>
      <description>&lt;p&gt;
Wirft man einen Blick auf die Vielzahl der im Internet vorhandenen Silverlight 1.0
Demo Applikationen, stellt man in den meisten F&amp;#228;llen eine Gemeinsamkeit fest:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Die Demo zeigt verbl&amp;#252;ffende grafische Effekte / Animationen im Web&lt;/li&gt;
&lt;li&gt;
Abgesehen von diesen Effekten hat die Demo keinerlei N&amp;#228;hrwert :-)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Infragistics m&amp;#246;chte die L&amp;#252;cke der wertvollen Silverlight Demos nun f&amp;#252;llen.
&lt;/p&gt;
&lt;p&gt;
Zu diesem Zweck wird unter &lt;a href="http://www.faceoutlive.com/" target="_blank"&gt;http://www.faceoutlive.com/&lt;/a&gt; ein
Silverlight Dashboard f&amp;#252;r Vertriebsmitarbeiter gezeigt.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/GeschftsanwendungenmitSilverlight2.0_E5C3/faceout.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="229" alt="faceout" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/GeschftsanwendungenmitSilverlight2.0_E5C3/faceout_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Registrierte Benutzer erhalten unter&amp;#160; &lt;a href="http://www.infragistics.com/hot/silverlight.aspx#InfragisticsandSilverlight" target="_blank"&gt;http://www.infragistics.com/hot/silverlight.aspx#InfragisticsandSilverlight&lt;/a&gt; zus&amp;#228;tzlich
den kompletten Source Code sowie ein &lt;a href="http://www.infragistics.com/uploadedFiles/WhatsHot/Silverlight/Images/FaceOut%20Overview.xps" target="_blank"&gt;12seitiges
Dokument&lt;/a&gt;, in dem Infragistics einen kurzen &amp;#220;berblick &amp;#252;ber die Applikationsarchitektur
sowie die &amp;quot;lessons-learned&amp;quot; gibt. Gerade der &amp;quot;lessons-learned&amp;quot;
Bereich ist sehr interessant.
&lt;/p&gt;
&lt;p&gt;
In diesem Sinne: Viel Spa&amp;#223; mit Silverlight ;-)
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:113f1371-1c19-4a54-bcdc-b8db1f28786d" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
tags: &lt;a href="http://technorati.com/tags/Infragistics" rel="tag"&gt;Infragistics&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Silverlight" rel="tag"&gt;Silverlight&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=19d93da9-2d3b-4c83-8857-70622da4c5ae" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,19d93da9-2d3b-4c83-8857-70622da4c5ae.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>Silverlight</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=a5cf0cbc-6635-474e-9f74-cad95a095aef</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,a5cf0cbc-6635-474e-9f74-cad95a095aef.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,a5cf0cbc-6635-474e-9f74-cad95a095aef.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=a5cf0cbc-6635-474e-9f74-cad95a095aef</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Vorbereitend auf den Visual Studio 2008 Launch in Frankfurt hatte ich die Möglichkeit,
einen Artikel für Zoschkes <a href="http://www.devdorado.de" target="_blank">Devdorado.de</a> (01/2008)
über die Infragistics Excel Engine zu schreiben. 
</p>
        <p>
André Wiese, Geschäftsführer der <a href="http://www.zoschke.com" target="_blank">Zoschke
Data GmbH</a>, gab mir freundlicherweise die Genehmigung, den Artikel im PDF-Format
auf meiner Homepage zum Download anzubieten.
</p>
        <p>
Anbei ein kleiner Vorgeschmack:
</p>
        <p>
          <em>"Optisch ansprechende Excel-Dateien zu erzeugen, erfordert normalerweise
fehleranfälligen Automatisierungscode. Devdorado.de zeigt Ihnen, wie Sie mit
Hilfe der Infragistics Excel Engine fehlerfrei zu eindrucksvollen Ergebnissen kommen."</em>
        </p>
        <p>
Den kompletten Artikel gibt's <a href="http://www.codemurai.de/fileviewer.ashx?filename=dd_infra_excel.pdf" target="_blank">hier</a>.
(Link wurde am 7. April 2008 gefixt.)
</p>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:c2add951-08c1-476b-ad7a-47ea13981c7c" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
tags: <a href="http://technorati.com/tags/Infragistics" rel="tag">Infragistics</a></div>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=a5cf0cbc-6635-474e-9f74-cad95a095aef" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Wenn Excel mehr als eine Datensenke sein soll</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,a5cf0cbc-6635-474e-9f74-cad95a095aef.aspx</guid>
      <link>http://blog.codemurai.de/2008/04/04/WennExcelMehrAlsEineDatensenkeSeinSoll.aspx</link>
      <pubDate>Fri, 04 Apr 2008 07:50:43 GMT</pubDate>
      <description>&lt;p&gt;
Vorbereitend auf den Visual Studio 2008 Launch in Frankfurt hatte ich die M&amp;#246;glichkeit,
einen Artikel f&amp;#252;r Zoschkes &lt;a href="http://www.devdorado.de" target="_blank"&gt;Devdorado.de&lt;/a&gt; (01/2008)
&amp;#252;ber die Infragistics Excel Engine zu schreiben. 
&lt;/p&gt;
&lt;p&gt;
Andr&amp;#233; Wiese, Gesch&amp;#228;ftsf&amp;#252;hrer der &lt;a href="http://www.zoschke.com" target="_blank"&gt;Zoschke
Data GmbH&lt;/a&gt;, gab mir freundlicherweise die Genehmigung, den Artikel im PDF-Format
auf meiner Homepage zum Download anzubieten.
&lt;/p&gt;
&lt;p&gt;
Anbei ein kleiner Vorgeschmack:
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&amp;quot;Optisch ansprechende Excel-Dateien zu erzeugen, erfordert normalerweise
fehleranf&amp;#228;lligen Automatisierungscode. Devdorado.de zeigt Ihnen, wie Sie mit
Hilfe der Infragistics Excel Engine fehlerfrei zu eindrucksvollen Ergebnissen kommen.&amp;quot;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Den kompletten Artikel gibt's &lt;a href="http://www.codemurai.de/fileviewer.ashx?filename=dd_infra_excel.pdf" target="_blank"&gt;hier&lt;/a&gt;.
(Link wurde am 7. April 2008 gefixt.)
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:c2add951-08c1-476b-ad7a-47ea13981c7c" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
tags: &lt;a href="http://technorati.com/tags/Infragistics" rel="tag"&gt;Infragistics&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=a5cf0cbc-6635-474e-9f74-cad95a095aef" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,a5cf0cbc-6635-474e-9f74-cad95a095aef.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>Veröffentlichungen</category>
    </item>
    <item>
      <trackback:ping>http://blog.codemurai.de/Trackback.aspx?guid=0723fc34-5d50-4e2d-96e8-43afcd65ec65</trackback:ping>
      <pingback:server>http://blog.codemurai.de/pingback.aspx</pingback:server>
      <pingback:target>http://blog.codemurai.de/PermaLink,guid,0723fc34-5d50-4e2d-96e8-43afcd65ec65.aspx</pingback:target>
      <dc:creator>Andre</dc:creator>
      <wfw:comment>http://blog.codemurai.de/CommentView,guid,0723fc34-5d50-4e2d-96e8-43afcd65ec65.aspx</wfw:comment>
      <wfw:commentRss>http://blog.codemurai.de/SyndicationService.asmx/GetEntryCommentsRss?guid=0723fc34-5d50-4e2d-96e8-43afcd65ec65</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Als technologiebegeisteter Mensch lud ich mir kürzlich, wie wahrscheinlich außer
mir noch 100te andere, Infragistics NetAdvantage for WPF 2007 Vol 2 runter, um Infragistics
neueste Technologie zu evaluieren.
</p>
        <p>
Leider kam bereits beim öffnen der Beispielsapplikation "xamFeatureBrowser"
die erste Enttäuschung. Die Applikation zeigte nämlich nicht Infragistics
neueste Features, sondern präsentierte statt dessen den relativ langweiligen
Windows-Fehlerreportingdialog:
</p>
        <p>
          <a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/3ndmessage.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="117" alt="3ndmessage" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/3ndmessage_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Eine kurze Rückfrage bei meinem Kontakt zu Infragistics ergab, dass das Problem
anscheinend nur unter "nicht englischen Betriebssystemen" auftritt.
</p>
        <p>
Um der Sache nun auf den Grund zu gehen, öffnete ich die xamFeatureBrowser Solution
unter Visual Studio 2005 und warf den Debugger an. Sofort nach dem Start wurde mir
folgende Meldung mit anschließender Exception um die Ohren geworfen: 
</p>
        <p>
          <a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/1stmessage.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="147" alt="1stmessage" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/1stmessage_thumb.png" width="244" border="0" />
          </a>
        </p>
        <!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;}??\fs20 System.IO.IOException was unhandled\par ??Message="Cannot locate resource  \\"app.xaml\\"."}
-->
        <div style="border-right: #000000 1px solid; border-top: #000000 1px solid; font-size: 10pt; background: white; border-left: #000000 1px solid; color: black; border-bottom: #000000 1px solid; font-family: courier new">
          <p style="margin: 0px">
System.IO.IOException was unhandled
</p>
          <p style="margin: 0px">
Message="Cannot locate resource  \"app.xaml\"."
</p>
        </div>
        <p>
          <a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/2ndmessage.png">
            <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="107" alt="2ndmessage" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/2ndmessage_thumb.png" width="244" border="0" />
          </a>
        </p>
        <p>
Anschließend stürzte die Applikation wieder ab. Eine kurze Recherche im
Internet ergab, dass das Problem mit .NET 3.0 Solutions zusammen hängt, die unter
Visual Studio 2008 Beta 1 gespeichert und später unter Visual Studio 2005 wieder
geöffnet wurden. Einen Einfluss auf die von Infragistics ausgelieferte kompilierte
Version der Anwendung sollte diese Situation jedoch nicht haben.
</p>
        <p>
Um dem Fehler also auf die Spur zu kommen, warf ich als nächstes die Windows
Debugging Tools an. Hier bekam ich die recht interessante Meldung, dass er für
die angegebene Kultur keine Ressourcen finden kann. Dieses Verhalten würde auch
zum Phänomen passen, dass der xamFeatureBrowser nur unter englischen Betriebssystemen
läuft, da für die englische Kultur Ressourcen vorhanden sind. 
</p>
        <p>
          <!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;}??\fs20 0:000&gt; .loadby sos mscorwks\par ??0:000&gt; !pe\par ??*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\mscorwks.dll - \par ??PDB symbol for mscorwks.dll not loaded\par ??Exception object: 01429598\par ??Exception type: System.Resources.MissingManifestResourceException\par ??Message: F\'fcr die angegebene Kultur oder die neutrale Kultur konnten keine Ressourcen gefunden werden. \par ??Stellen Sie sicher, dass xamFeatureBrowser.g.resources beim Kompilieren richtig in die Assembly \par ??xamFeatureBrowser eingebettet wurde, oder dass die erforderlichen Satellitenassemblys geladen werden\par ?? k\'f6nnen und vollst\'e4ndig signiert sind.\par ??}
-->
        </p>
        <div style="border-right: #000000 1px solid; border-top: #000000 1px solid; font-size: 10pt; background: white; border-left: #000000 1px solid; color: black; border-bottom: #000000 1px solid; font-family: courier new">
          <p style="margin: 0px">
0:000&gt; .loadby sos mscorwks
</p>
          <p style="margin: 0px">
0:000&gt; !pe
</p>
          <p style="margin: 0px">
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
- 
</p>
          <p style="margin: 0px">
PDB symbol for mscorwks.dll not loaded
</p>
          <p style="margin: 0px">
Exception object: 01429598
</p>
          <p style="margin: 0px">
Exception type: System.Resources.MissingManifestResourceException
</p>
          <p style="margin: 0px">
Message: Für die angegebene Kultur oder die neutrale Kultur konnten keine Ressourcen
gefunden werden. 
</p>
          <p style="margin: 0px">
Stellen Sie sicher, dass xamFeatureBrowser.g.resources beim Kompilieren richtig in
die Assembly 
</p>
          <p style="margin: 0px">
xamFeatureBrowser eingebettet wurde, oder dass die erforderlichen Satellitenassemblys
geladen werden
</p>
          <p style="margin: 0px">
können und vollständig signiert sind.
</p>
        </div>
        <p>
        </p>
        <p>
          <strong>Die Lösung</strong>
        </p>
        <p>
Auf meinem System konnte ich das Problem wie folgt lösen:
</p>
        <ol>
          <li>
Öffnen der Solution. Diese lag bei mir unter: 
<br />
"C:\Users\Public\Documents\Infragistics\NetAdvantage for WPF 2007 Vol. 2\Samples\xamFeatureBrowser" 
<br /></li>
          <li>
Umschalten der Solution Konfiguration von "Debug - Full Trust" auf "Release".
Dieser Schritt ist eventuell nur unter VS 2005 notwendig. Zumindest kommt dann keine
Meldung mehr, dass die App.xaml fehlt. 
<br /><a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/projectconfiguration.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="54" alt="projectconfiguration" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/projectconfiguration_thumb.png" width="244" border="0" /></a><br /></li>
          <li>
Öffnen der App.xaml.cs und hinzufügen des folgenden Konstruktors: 
<br /><!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20         \cf3 public\cf0  App()\par ??        \{\par ??            \cf4 CultureInfo\cf0  objCI = \cf3 new\cf0  \cf4 CultureInfo\cf0 (\cf5 "en-US"\cf0 );\par ??            \cf4 Thread\cf0 .CurrentThread.CurrentCulture = objCI;\par ??            \cf4 Thread\cf0 .CurrentThread.CurrentUICulture = objCI;\par ??        \}}
--><div style="border-right: #000000 1px solid; border-top: #000000 1px solid; font-size: 10pt; background: white; border-left: #000000 1px solid; color: black; border-bottom: #000000 1px solid; font-family: courier new"><p style="margin: 0px">
        <span style="color: blue">public</span> App()
</p><p style="margin: 0px">
        {
</p><p style="margin: 0px">
            <span style="color: #2b91af">CultureInfo</span> objCI
= <span style="color: blue">new</span><span style="color: #2b91af">CultureInfo</span>(<span style="color: #a31515">"en-US"</span>);
</p><p style="margin: 0px">
            <span style="color: #2b91af">Thread</span>.CurrentThread.CurrentCulture
= objCI;
</p><p style="margin: 0px">
            <span style="color: #2b91af">Thread</span>.CurrentThread.CurrentUICulture
= objCI;
</p><p style="margin: 0px">
        }
</p></div><br />
Diesen Tipp bekam ich übrigens von heroic im <a href="http://forums.infragistics.com/forums/p/1141/22647.aspx#22647" target="_blank">Infragics
Forum</a><br /></li>
          <li>
Ändern der Eigenschaften für die Datei "TableOfContents.xml".
Die Build Action muss auf <em>Content</em> und die Copy to Output Directory auf <em>Copy
always</em> gesetzt werden. 
<br /><a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/toc.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="209" alt="toc" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/toc_thumb.png" width="244" border="0" /></a><br /></li>
          <li>
Starten des Projekts :-) 
<br /><a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/xambrowser.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="194" alt="xambrowser" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/xambrowser_thumb.png" width="244" border="0" /></a>  
<br /></li>
        </ol>
        <p>
Bleibt nun zu hoffen, dass Infragistics den Bug in der nächsten Version behebt
...
</p>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:d60bb899-46cc-400a-8715-79afde28252e" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
tags: <a href="http://technorati.com/tags/Infragistics" rel="tag">Infragistics</a>, <a href="http://technorati.com/tags/WPF" rel="tag">WPF</a>, <a href="http://technorati.com/tags/xamFeatureBrowser" rel="tag">xamFeatureBrowser</a>, <a href="http://technorati.com/tags/.NET" rel="tag">.NET</a></div>
        <img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=0723fc34-5d50-4e2d-96e8-43afcd65ec65" />
        <br />
        <hr />
        <a href="http://blog.codemurai.de">blog.codemurai.de</a> © André Krämer |<a href="http://www.codemurai.de/pages/de/impress.aspx">Impressum </a>| <a href="http://feeds2.feedburner.com/codemurai/qlrN">Abonieren </a></body>
      <title>Die Geschichte vom Infragistics xamFeatureBrowser und nicht englischen Betriebssystemen</title>
      <guid isPermaLink="false">http://blog.codemurai.de/PermaLink,guid,0723fc34-5d50-4e2d-96e8-43afcd65ec65.aspx</guid>
      <link>http://blog.codemurai.de/2008/04/02/DieGeschichteVomInfragisticsXamFeatureBrowserUndNichtEnglischenBetriebssystemen.aspx</link>
      <pubDate>Wed, 02 Apr 2008 12:52:18 GMT</pubDate>
      <description>&lt;p&gt;
Als technologiebegeisteter Mensch lud ich mir k&amp;#252;rzlich, wie wahrscheinlich au&amp;#223;er
mir noch 100te andere, Infragistics NetAdvantage for WPF 2007 Vol 2 runter, um Infragistics
neueste Technologie zu evaluieren.
&lt;/p&gt;
&lt;p&gt;
Leider kam bereits beim &amp;#246;ffnen der Beispielsapplikation &amp;quot;xamFeatureBrowser&amp;quot;
die erste Entt&amp;#228;uschung. Die Applikation zeigte n&amp;#228;mlich nicht Infragistics
neueste Features, sondern pr&amp;#228;sentierte statt dessen den relativ langweiligen
Windows-Fehlerreportingdialog:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/3ndmessage.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="117" alt="3ndmessage" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/3ndmessage_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Eine kurze R&amp;#252;ckfrage bei meinem Kontakt zu Infragistics ergab, dass das Problem
anscheinend nur unter &amp;quot;nicht englischen Betriebssystemen&amp;quot; auftritt.
&lt;/p&gt;
&lt;p&gt;
Um der Sache nun auf den Grund zu gehen, &amp;#246;ffnete ich die xamFeatureBrowser Solution
unter Visual Studio 2005 und warf den Debugger an. Sofort nach dem Start wurde mir
folgende Meldung mit anschlie&amp;#223;ender Exception um die Ohren geworfen: 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/1stmessage.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="147" alt="1stmessage" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/1stmessage_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;}??\fs20 System.IO.IOException was unhandled\par ??Message="Cannot locate resource  \\"app.xaml\\"."}
--&gt;
&lt;div style="border-right: #000000 1px solid; border-top: #000000 1px solid; font-size: 10pt; background: white; border-left: #000000 1px solid; color: black; border-bottom: #000000 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
System.IO.IOException was unhandled
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
Message=&amp;quot;Cannot locate resource&amp;#160; \&amp;quot;app.xaml\&amp;quot;.&amp;quot;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/2ndmessage.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="107" alt="2ndmessage" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/2ndmessage_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
Anschlie&amp;#223;end st&amp;#252;rzte die Applikation wieder ab. Eine kurze Recherche im
Internet ergab, dass das Problem mit .NET 3.0 Solutions zusammen h&amp;#228;ngt, die unter
Visual Studio 2008 Beta 1 gespeichert und sp&amp;#228;ter unter Visual Studio 2005 wieder
ge&amp;#246;ffnet wurden. Einen Einfluss auf die von Infragistics ausgelieferte kompilierte
Version der Anwendung sollte diese Situation jedoch nicht haben.
&lt;/p&gt;
&lt;p&gt;
Um dem Fehler also auf die Spur zu kommen, warf ich als n&amp;#228;chstes die Windows
Debugging Tools an. Hier bekam ich die recht interessante Meldung, dass er f&amp;#252;r
die angegebene Kultur keine Ressourcen finden kann. Dieses Verhalten w&amp;#252;rde auch
zum Ph&amp;#228;nomen passen, dass der xamFeatureBrowser nur unter englischen Betriebssystemen
l&amp;#228;uft, da f&amp;#252;r die englische Kultur Ressourcen vorhanden sind. 
&lt;/p&gt;
&lt;p&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;}??\fs20 0:000&amp;gt; .loadby sos mscorwks\par ??0:000&amp;gt; !pe\par ??*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\mscorwks.dll - \par ??PDB symbol for mscorwks.dll not loaded\par ??Exception object: 01429598\par ??Exception type: System.Resources.MissingManifestResourceException\par ??Message: F\'fcr die angegebene Kultur oder die neutrale Kultur konnten keine Ressourcen gefunden werden. \par ??Stellen Sie sicher, dass xamFeatureBrowser.g.resources beim Kompilieren richtig in die Assembly \par ??xamFeatureBrowser eingebettet wurde, oder dass die erforderlichen Satellitenassemblys geladen werden\par ?? k\'f6nnen und vollst\'e4ndig signiert sind.\par ??}
--&gt;
&lt;/p&gt;
&lt;div style="border-right: #000000 1px solid; border-top: #000000 1px solid; font-size: 10pt; background: white; border-left: #000000 1px solid; color: black; border-bottom: #000000 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
0:000&amp;gt; .loadby sos mscorwks
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
0:000&amp;gt; !pe
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
*** ERROR: Symbol file could not be found.&amp;#160; Defaulted to export symbols for C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
- 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
PDB symbol for mscorwks.dll not loaded
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
Exception object: 01429598
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
Exception type: System.Resources.MissingManifestResourceException
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
Message: F&amp;#252;r die angegebene Kultur oder die neutrale Kultur konnten keine Ressourcen
gefunden werden. 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
Stellen Sie sicher, dass xamFeatureBrowser.g.resources beim Kompilieren richtig in
die Assembly 
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
xamFeatureBrowser eingebettet wurde, oder dass die erforderlichen Satellitenassemblys
geladen werden
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
k&amp;#246;nnen und vollst&amp;#228;ndig signiert sind.
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Die L&amp;#246;sung&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Auf meinem System konnte ich das Problem wie folgt l&amp;#246;sen:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&amp;#214;ffnen der Solution. Diese lag bei mir unter: 
&lt;br /&gt;
&amp;quot;C:\Users\Public\Documents\Infragistics\NetAdvantage for WPF 2007 Vol. 2\Samples\xamFeatureBrowser&amp;quot; 
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;
Umschalten der Solution Konfiguration von &amp;quot;Debug - Full Trust&amp;quot; auf &amp;quot;Release&amp;quot;.
Dieser Schritt ist eventuell nur unter VS 2005 notwendig. Zumindest kommt dann keine
Meldung mehr, dass die App.xaml fehlt. 
&lt;br /&gt;
&lt;a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/projectconfiguration.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="54" alt="projectconfiguration" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/projectconfiguration_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;
&amp;#214;ffnen der App.xaml.cs und hinzuf&amp;#252;gen des folgenden Konstruktors: 
&lt;br /&gt;
&lt;!--
{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20         \cf3 public\cf0  App()\par ??        \{\par ??            \cf4 CultureInfo\cf0  objCI = \cf3 new\cf0  \cf4 CultureInfo\cf0 (\cf5 "en-US"\cf0 );\par ??            \cf4 Thread\cf0 .CurrentThread.CurrentCulture = objCI;\par ??            \cf4 Thread\cf0 .CurrentThread.CurrentUICulture = objCI;\par ??        \}}
--&gt;
&lt;div style="border-right: #000000 1px solid; border-top: #000000 1px solid; font-size: 10pt; background: white; border-left: #000000 1px solid; color: black; border-bottom: #000000 1px solid; font-family: courier new"&gt;
&lt;p style="margin: 0px"&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt; App()
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt; objCI
= &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;CultureInfo&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;en-US&amp;quot;&lt;/span&gt;);
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Thread&lt;/span&gt;.CurrentThread.CurrentCulture
= objCI;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Thread&lt;/span&gt;.CurrentThread.CurrentUICulture
= objCI;
&lt;/p&gt;
&lt;p style="margin: 0px"&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
Diesen Tipp bekam ich &amp;#252;brigens von heroic im &lt;a href="http://forums.infragistics.com/forums/p/1141/22647.aspx#22647" target="_blank"&gt;Infragics
Forum&lt;/a&gt; 
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;
&amp;#196;ndern der Eigenschaften f&amp;#252;r die Datei &amp;quot;TableOfContents.xml&amp;quot;.
Die Build Action muss auf &lt;em&gt;Content&lt;/em&gt; und die Copy to Output Directory auf &lt;em&gt;Copy
always&lt;/em&gt; gesetzt werden. 
&lt;br /&gt;
&lt;a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/toc.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="209" alt="toc" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/toc_thumb.png" width="244" border="0" /&gt;&lt;/a&gt; 
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;
Starten des Projekts :-) 
&lt;br /&gt;
&lt;a href="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/xambrowser.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="194" alt="xambrowser" src="http://blog.codemurai.de/content/binary/WindowsLiveWriter/images/DieGeschichtevomInfragisticsXAMShowcaseu_C39D/xambrowser_thumb.png" width="244" border="0" /&gt;&lt;/a&gt;&amp;#160; 
&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Bleibt nun zu hoffen, dass Infragistics den Bug in der n&amp;#228;chsten Version behebt
...
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:d60bb899-46cc-400a-8715-79afde28252e" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
tags: &lt;a href="http://technorati.com/tags/Infragistics" rel="tag"&gt;Infragistics&lt;/a&gt;, &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;, &lt;a href="http://technorati.com/tags/xamFeatureBrowser" rel="tag"&gt;xamFeatureBrowser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://blog.codemurai.de/aggbug.ashx?id=0723fc34-5d50-4e2d-96e8-43afcd65ec65" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
&lt;a href="http://blog.codemurai.de"&gt;blog.codemurai.de&lt;/a&gt; © André Krämer |&lt;a href="http://www.codemurai.de/pages/de/impress.aspx"&gt;Impressum &lt;/a&gt;| &lt;a href="http://feeds2.feedburner.com/codemurai/qlrN"&gt;Abonieren &lt;/a&gt;
</description>
      <comments>http://blog.codemurai.de/CommentView,guid,0723fc34-5d50-4e2d-96e8-43afcd65ec65.aspx</comments>
      <category>.NET</category>
      <category>DotNetGerman Bloggers</category>
      <category>Infragistics</category>
      <category>WPF</category>
    </item>
  </channel>
</rss>