<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Schädler und .NET</title>
	<atom:link href="http://schaedlerdaniel.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://schaedlerdaniel.wordpress.com</link>
	<description>.NET verstehen und lernen</description>
	<lastBuildDate>Tue, 24 Apr 2012 06:07:51 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='schaedlerdaniel.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Schädler und .NET</title>
		<link>http://schaedlerdaniel.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://schaedlerdaniel.wordpress.com/osd.xml" title="Schädler und .NET" />
	<atom:link rel='hub' href='http://schaedlerdaniel.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Schritt für Schritt zum eigenen generischen Repository</title>
		<link>http://schaedlerdaniel.wordpress.com/2012/03/28/schritt-fur-schritt-zum-eigenen-generischen-repository/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2012/03/28/schritt-fur-schritt-zum-eigenen-generischen-repository/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 09:41:43 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[EntityKey]]></category>
		<category><![CDATA[Generic Repository]]></category>
		<category><![CDATA[Generic Repository with Entity Framework]]></category>
		<category><![CDATA[ObjectSet]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=614</guid>
		<description><![CDATA[Das Speichern und Abfragen von Daten wäre mit dem klassischen Repository-Pattern viel zu aufwändig für kleinere Projekte. In Anlehnung an das hier, in Verbindung mit dem Unit Of Work Pattern, verwendete generische Repository, habe ich mir überlegt, dass es doch für kleinere Projekte auch eine Lösung geben sollte, die nicht so viel Aufwand nach sich [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=614&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Das Speichern und Abfragen von Daten wäre mit dem klassischen Repository-Pattern viel zu aufwändig für kleinere Projekte. In Anlehnung an das hier, in Verbindung mit dem <a href="http://msdn.microsoft.com/en-us/magazine/dd882510.aspx" target="_blank">Unit Of Work Pattern</a>, verwendete generische Repository, habe ich mir überlegt, dass es doch für kleinere Projekte auch eine Lösung geben sollte, die nicht so viel Aufwand nach sich zieht. </p>
<p>Als Grundlage, oder besser gesagt als Ausgangspunkt habe ich mir diesen <a href="http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application" target="blank">Artikel</a> zur Brust genommen.</p>
<p>Wie wollen wir vorgehen?</p>
<ol>
<li>Wir erstellen uns ein ganz triviales Model (Adressverwaltung)</li>
<li>Dann erstellen wir uns Schritt für Schritt das Repository</li>
<li>Am Schluss ziehen wir noch ein Fazit aus dem Artikel</li>
<ol>
<h4 style="color:Black;">Erstellung des Models</h4>
<p>In Anbetracht, dass nicht zwingend die Korrektheit der Datenmodellierung und der verwendeten Typen im Mittelpunkt steht, erstellen wir uns das Modell wie folgt.</p>
<p><a href="http://schaedlerdaniel.files.wordpress.com/2012/03/generisches-repository.jpg"><img src="http://schaedlerdaniel.files.wordpress.com/2012/03/generisches-repository.jpg?w=600" alt="Das Modell unserer Adressverwaltung" title="Generisches Repository"   class="aligncenter size-full wp-image-618" /></a></p>
<p>Wichtig an diesem Punkt ist, dass die Pluralisierung nicht geändert wird (hierzu später mehr bei der Erstellung des Repositories). Die Eigenschaften für die Personen-Entität sind hier represäntativ für alle anderen auch.</p>
</p>
<p><a href="http://schaedlerdaniel.files.wordpress.com/2012/03/generisches-repository.jpg"><img src="http://schaedlerdaniel.files.wordpress.com/2012/03/generisches-repository.jpg?w=600" alt="Das Modell unserer Adressverwaltung" title="Generisches Repository"   class="aligncenter size-full wp-image-618" /></a></p>
<p>Eine Spezialität ist die komplexe Eigenschaft Persistance, welch die Attribute für </p>
<ul>
<li>CreateDate</li>
<li>ModifyDate</li>
<li>Creator</li>
<li>Modifier</li>
</ul>
<p>beherbergt. Schön wäre es ja, wenn alle Attribute bei der entsprechenden Operation des Repositories, Add, Update automatisch aktualisiert wird (dazu später mehr).</p>
<p>Soweit so gut, wir haben unsere Modell für die 1001 Adressverwaltung erstellt. Wollen wir doch zum nächsten Schritt übergehen, die Erstellung des Repositories.</p>
<h5>Die Repository Erstellung</h5>
</p>
<p>Damit wir mit unserem Repository die CRUD Operation unterstützen können brauchen wir folgende Methoden:</p>
<ul>
<li>Rumpf des Repositories</li>
<li>Add</li>
<li>Remove</li>
<li>Update</li>
<li>GetObjectById</li>
<li>GetObjectByQuery</li>
<li>Persistance Attribute automatisch erstellen /aktualisieren</li>
</ul>
<h6>Rumpf des Repositories</h6>
<p>Damit wir die restlichen Methoden implementieren können müssen wir das Repository wie folgt erstellen:</p>
<p><pre class="brush: csharp;">
namespace GenericRepositoryPattern
{
    public class Repository&lt;T&gt; : IDisposable where T: EntityObject
    {
        /// &lt;summary&gt;
        /// The context of the database.
        /// &lt;/summary&gt;
        private readonly AddressModelContainer context;
        /// &lt;summary&gt;
        /// The related objectSet to the context. Is dependent
        /// of the context.
        /// &lt;/summary&gt;
        private readonly ObjectSet&lt;T&gt; objectSet;
        /// &lt;summary&gt;
        /// Constructor to initialize the context and the
        /// objectSet.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;context&quot;&gt;The context of the model.&lt;/param&gt;
        public Repository(AddressModelContainer context)
        {
            this.context = context;

            if (context != null) 
            { 
                this.objectSet = context.CreateObjectSet&lt;T&gt;();
                this.context.SavingChanges +=new EventHandler(context_SavingChanges);
            }
        }
</pre></p>
<p>(Anmerkung: Die Wiedergabe des Code’s ist gekürzt).<br />
Wichtig hierbei ist, dass der Context von aussen her dem Konstruktor übergeben werden muss und das <a href="http://msdn.microsoft.com/de-de/library/dd412719.aspx" target="_blank">ObjectSet</a> vom instantiierten Context das ObjectSet erhält.</p>
<h6>Add Methode</h6>
<p>Damit wir ein neues Objekt zu unserem ObjectContex hinzufügen können müssen wir die Methode wie folgt implementieren.</p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// Add's a newly created entity to the
        /// objectSet
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The newly created entity.&lt;/param&gt;
        public void Add(T entity)
        {
            this.objectSet.AddObject(entity);            
            this.context.SaveChanges();                    
        }
</pre></p>
<p>Also eine ganz einfache Sache. Als nächstes wenden wir uns der Remove Methode zu.</p>
<h6>Remove Methode</h6>
<p>Das Entfernen eines Objektes ist relativ rasch implementiert:</p>
<p><pre class="brush: csharp;">
        public void Remove(T entity)
        {
            if (entity != null)
            {
                this.objectSet.Attach(entity);
                this.context.DeleteObject(entity);
                this.context.SaveChanges();
            }
        }
</pre></p>
<p>Also keine Hexerei. Als nächstes wenden wir uns der Update Methode zu und schauen diese genauer an.</p>
<h6>Update Methode</h6>
<p>Die Update Methode zeigt sich in ihrer Ausprägung so:</p>
<p><pre class="brush: csharp;">
        public void Update(T entity)
        {
            this.objectSet.Attach(entity);
            this.context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);        
            this.context.SaveChanges();
        }
</pre></p>
<p>Damit der Context weiss, dass sich was geändert hat muss die Entität an den Context wieder „Attached“ und im <a href="http://msdn.microsoft.com/de-de/library/system.data.objects.objectstatemanager.aspx" target="_blank">ObjectStateManager</a> der EntityState auf Modified gestellt werden. Dann speichert der Context die Daten aktualisiert.</p>
<h6>GetObjectById</h6>
<p>Damit wir ein Object vom Typ Person erhalten, anhand der übergebenen Id, erstellen wir uns in der Methode einen EntityKey und einem KeyValuePair. Das Attribut dass die Id verkörpert heiss auch „Id“.</p>
<p><pre class="brush: csharp;">
        public T GetById(Int32 id)
        {
            string entitySet = string.Format(@&quot;{0}Set&quot;, typeof(T).Name);
            KeyValuePair&lt;string, object&gt; member = new KeyValuePair&lt;string, object&gt;(&quot;Id&quot;, id);
            IEnumerable&lt;KeyValuePair&lt;string, object&gt;&gt; values = new KeyValuePair&lt;string, object&gt;[] { member };

            EntityKey key = new EntityKey(entitySet, values);

            return (T)this.context.GetObjectByKey(key);
        }
</pre></p>
<p>Und hier sehen wir auch wieso wir die Pluralisierung PersonSet belassen haben. Damit der Context weiss in welchem Set er suchen soll müssen wir dieses übergeben. Das erreichen wird mit dem kleinen Codeschnipsel</p>
<p><pre class="brush: csharp;">
string entitySet = string.Format(@&quot;{0}Set&quot;, typeof(T).Name);
</pre></p>
<p>Danach wird der <a href="http://msdn.microsoft.com/de-de/library/dd283138.aspx" target="_blank">EntityKey</a> erstellt und dem Context zur Abfrage übergeben. Das gefundene Object casten wird dann in den generischen Typ den wir übergeben haben.</p>
<h6>GetObjectByQuery</h6>
<p>Damit wir spezifisch ein Objekt, oder auch mehrere zurück erhalten können wir diese mit dem entsprechenden Methode und einer Func zurück holen. Als Beispiel: Wenn ich eine Person haben möchte bei welchem ich nur den Vornahmen und den Nachnamen haben möchte, dann lege ich beim Aufrufer der Methode folgende Funktion fest:</p>
<p><pre class="brush: csharp;">
Func&lt;Person, bool&gt; functionPerson = person =&gt; person.FirstName.ToLower().Equals(&quot;hans&quot;);
</pre></p>
<p>Die kann dann der Methode übergeben werden und diese erstellt dann auch das Resultat anhand der übergebenen Methode.</p>
<p><pre class="brush: csharp;">
        public IEnumerable&lt;T&gt; GetObjectByQuery(Func&lt;T, bool&gt; customQuery)
        {
            if (customQuery == null)
            {
                throw new ArgumentNullException(&quot;parameter: customquery must be given by caller!&quot;);
            }

            List&lt;T&gt; result = this.objectSet.Where(customQuery).ToList();
            result.ForEach(this.objectSet.Detach);
            return result;
        }
[/csharp]
&lt;p&gt;Wichtig ist nur, dass die gefundenen Objekte vom Context getrennt werden, damit diese auch ausserhalb der Verwendung des Contextes verwendet werden können.&lt;/p&gt;
&lt;h6&gt;Persistance Attribute aktualisieren&lt;/h6&gt;
&lt;p&gt;Dem Leser wird nicht entgangen sein, dass im Konstruktor der Context mit seinem Ereignis SavingChanges verknüpft worden ist. Hier werden alle relevanten Attribute vom komplexen Property IPersistance aktualisiert oder erstellt. Die Ereignisbehandlung sieht dann so aus:&lt;/p&gt;
[code language=&quot;csharp&quot;]
        void context_SavingChanges(object sender, EventArgs e)
        {
            this.context.ObjectStateManager.GetObjectStateEntries(EntityState.Added).ToList().ForEach(entity =&gt; {
                if (entity != null &amp;&amp; entity.Entity != null &amp;&amp; entity.Entity.GetType().GetProperty(&quot;Persistance&quot;) != null)
                {
                    IPersistance persistance = CreatePersistance();
                    entity.Entity.GetType().GetProperty(&quot;Persistance&quot;).SetValue(entity.Entity, persistance, null);
                }
            });

            this.context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified).ToList().ForEach(entity =&gt;
            {
                if (entity != null &amp;&amp; entity.Entity != null &amp;&amp; entity.Entity.GetType().GetProperty(&quot;Persistance&quot;) != null)
                {
                    UpdatePersistance(entity.Entity);
                }
            });
        }
</pre></p>
<p>Hier wird eigentlich nicht’s anderes gemacht, als das alle Entitäten die den Status Added oder Modified haben das Persistance komplexe Property angepasst. Für das sind dann die zwei Methoden zuständig.</p>
<p><pre class="brush: csharp;">
        private IPersistance CreatePersistance()
        {
            IPersistance persistance = new IPersistance();
            persistance.CreateDate = DateTime.Now;
            persistance.ModifyDate = DateTime.Now;
            persistance.Creator = WindowsIdentity.GetCurrent().Name;
            persistance.Modifier = persistance.Creator;
            return persistance;
        }
</pre></p>
<p>Wird verwendet wenn eine neue Entität persistiert wird und die nachfolgende wenn eine Entität geändert worden ist.</p>
<p><pre class="brush: csharp;">
        private void UpdatePersistance(object entity)
        {
            if (typeof(T).GetProperty(&quot;Persistance&quot;) != null)
            {
                IPersistance persistance = (IPersistance)typeof(T).GetProperty(&quot;Persistance&quot;).GetValue(entity, null);
                if (persistance != null)
                {
                    persistance.Modifier = WindowsIdentity.GetCurrent().Name;
                    persistance.ModifyDate = DateTime.Now;
                }
            }
        }
</pre></p>
<p>Zur Übersicht noch der vollständige Code des gesamten Repositories.</p>
<p><pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects.DataClasses;
using GenericRepositoryPattern.Model;
using System.Data.Objects;
using System.Data;
using System.Security.Principal;
using System.Reflection;

namespace GenericRepositoryPattern
{
    /// &lt;summary&gt;
    /// Generic repository.
    /// &lt;/summary&gt;
    /// &lt;typeparam name=&quot;T&quot;&gt;For example it could be a model entity Person&lt;/typeparam&gt;
    public class Repository&lt;T&gt; : IDisposable where T: EntityObject
    {
        /// &lt;summary&gt;
        /// The context of the database.
        /// &lt;/summary&gt;
        private readonly AddressModelContainer context;
        /// &lt;summary&gt;
        /// The related objectSet to the context. Is dependent
        /// of the context.
        /// &lt;/summary&gt;
        private readonly ObjectSet&lt;T&gt; objectSet;
        /// &lt;summary&gt;
        /// Constructor to initialize the context and the
        /// objectSet.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;context&quot;&gt;The context of the model.&lt;/param&gt;
        public Repository(AddressModelContainer context)
        {
            this.context = context;

            if (context != null) 
            { 
                this.objectSet = context.CreateObjectSet&lt;T&gt;();
                this.context.SavingChanges +=new EventHandler(context_SavingChanges);
            }
        }
        /// &lt;summary&gt;
        /// Get's a specific entity by it's key.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;id&quot;&gt;The id from the object to retrieve.&lt;/param&gt;
        /// &lt;returns&gt;The object if it's present in the db, or NULL if not existent.&lt;/returns&gt;
        public T GetById(Int32 id)
        {
            string entitySet = string.Format(@&quot;{0}Set&quot;, typeof(T).Name);
            KeyValuePair&lt;string, object&gt; member = new KeyValuePair&lt;string, object&gt;(&quot;Id&quot;, id);
            IEnumerable&lt;KeyValuePair&lt;string, object&gt;&gt; values = new KeyValuePair&lt;string, object&gt;[] { member };

            EntityKey key = new EntityKey(entitySet, values);

            return (T)this.context.GetObjectByKey(key);
        }
        /// &lt;summary&gt;
        /// Allows the user to query the db with a custom
        /// function to retrieve data from the specific type
        /// of entity.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;customQuery&quot;&gt;Created outisde by caller&lt;/param&gt;
        /// &lt;returns&gt;A queryable of T with the possibility to treat it further.&lt;/returns&gt;
        /// &lt;example&gt;
        /// Func&lt;Person, bool&gt; functionPerson = person =&gt; person.FirstName.ToLower().Contains(&quot;da&quot;)
        /// &lt;/example&gt;
        public IEnumerable&lt;T&gt; GetObjectByQuery(Func&lt;T, bool&gt; customQuery)
        {
            if (customQuery == null)
            {
                throw new ArgumentNullException(&quot;parameter: customquery must be given by caller!&quot;);
            }

            List&lt;T&gt; result = this.objectSet.Where(customQuery).ToList();
            result.ForEach(this.objectSet.Detach);
            return result;
        }

        /// &lt;summary&gt;
        /// Updates the values of the entity.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;entity&quot;&gt;Updates a given entity with new values.&lt;/param&gt;
        public void Update(T entity)
        {
            this.objectSet.Attach(entity);
            this.context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);        
            this.context.SaveChanges();
        }
        /// &lt;summary&gt;
        /// Add's a newly created entity to the
        /// objectSet
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The newly created entity.&lt;/param&gt;
        public void Add(T entity)
        {
            this.objectSet.AddObject(entity);            
            this.context.SaveChanges();                    
        }
        /// &lt;summary&gt;
        /// Occurs every time an entity is saved or updated.
        /// It goes through the entity properties to update or craete
        /// the persistance attributes that are necessary for saving.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;sender&quot;&gt;The context&lt;/param&gt;
        /// &lt;param name=&quot;e&quot;&gt;The eventargs from the context.&lt;/param&gt;
        void context_SavingChanges(object sender, EventArgs e)
        {
            this.context.ObjectStateManager.GetObjectStateEntries(EntityState.Added).ToList().ForEach(entity =&gt; {
                if (entity != null &amp;&amp; entity.Entity != null &amp;&amp; entity.Entity.GetType().GetProperty(&quot;Persistance&quot;) != null)
                {
                    IPersistance persistance = CreatePersistance();
                    entity.Entity.GetType().GetProperty(&quot;Persistance&quot;).SetValue(entity.Entity, persistance, null);
                }
            });

            this.context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified).ToList().ForEach(entity =&gt;
            {
                if (entity != null &amp;&amp; entity.Entity != null &amp;&amp; entity.Entity.GetType().GetProperty(&quot;Persistance&quot;) != null)
                {
                    UpdatePersistance(entity.Entity);
                }
            });
        }
        /// &lt;summary&gt;
        /// Set's the createdate to the datetime
        /// where the creation of the entity
        /// object has been executed.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The entity to create the IPersistance creator and update attributes.&lt;/param&gt;
        private IPersistance CreatePersistance()
        {
            IPersistance persistance = new IPersistance();
            persistance.CreateDate = DateTime.Now;
            persistance.ModifyDate = DateTime.Now;
            persistance.Creator = WindowsIdentity.GetCurrent().Name;
            persistance.Modifier = persistance.Creator;
            return persistance;
        }
        /// &lt;summary&gt;
        /// Set's the modifydate to the datetime
        /// where the modification of the entity
        /// object has been executed.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The entity to update the IPersistance modify attributes.&lt;/param&gt;
        private void UpdatePersistance(object entity)
        {
            if (typeof(T).GetProperty(&quot;Persistance&quot;) != null)
            {
                IPersistance persistance = (IPersistance)typeof(T).GetProperty(&quot;Persistance&quot;).GetValue(entity, null);
                if (persistance != null)
                {
                    persistance.Modifier = WindowsIdentity.GetCurrent().Name;
                    persistance.ModifyDate = DateTime.Now;
                }
            }
        }
        /// &lt;summary&gt;
        /// Removes an entity from the database.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The entity to remove. Must be loaded prior to remove.&lt;/param&gt;
        public void Remove(T entity)
        {
            if (entity != null)
            {
                this.objectSet.Attach(entity);
                this.context.DeleteObject(entity);
                this.context.SaveChanges();
            }
        }

        #region IDisposable Members
        /// &lt;summary&gt;
        /// Dispose the context.
        /// &lt;/summary&gt;
        public void Dispose()
        {
            if (this.context != null)
            {
                this.context.Dispose();
            }
        }

        #endregion
    }
}
</pre></p>
<h4 style="color:Black;">Fazit</h4>
<p>Mit dem hier vorgestellten Ansatz ist es uns , auch für kleinere Projekte möglich, rasch und einfach <a href="http://de.wikipedia.org/wiki/CRUD" target="_blank">CRUD</a> Methoden zur Verfügung zu stellen ohne, dass wir das Unit of Work und das Repositoriy Pattern in ihren grössten Ausprägungen implementieren müssen.</p>
<p>Wenn Ihnen der Artikel gefallen hat, würde ich mich über einen KICK freuen. Auf Verbesserungsvorschläge und Kritik bin ich natürlich auch offen.</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f03%2f28%2fschritt-fur-schritt-zum-eigenen-generischen-repository%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f03%2f28%2fschritt-fur-schritt-zum-eigenen-generischen-repository%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/614/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/614/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/614/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/614/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/614/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/614/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/614/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=614&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2012/03/28/schritt-fur-schritt-zum-eigenen-generischen-repository/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/03/generisches-repository.jpg" medium="image">
			<media:title type="html">Generisches Repository</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/03/generisches-repository.jpg" medium="image">
			<media:title type="html">Generisches Repository</media:title>
		</media:content>

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f03%2f28%2fschritt-fur-schritt-zum-eigenen-generischen-repository%2f" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
		<item>
		<title>WCF DataContracts synchronisieren mit Entity Framework Klassen</title>
		<link>http://schaedlerdaniel.wordpress.com/2012/02/28/wcf-datacontracts-synchronisieren-mit-entity-framework-klassen/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2012/02/28/wcf-datacontracts-synchronisieren-mit-entity-framework-klassen/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 15:32:33 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[WCF]]></category>
		<category><![CDATA[DataContract Mapping to Entity Framework]]></category>
		<category><![CDATA[Generischer DataContract zu Entity Framework Synchronisierer]]></category>
		<category><![CDATA[Synchronization of DataContracts to it's Entitties]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=595</guid>
		<description><![CDATA[Im Rahmen einer Projektarbeit haben wir das Ziel Businessdaten über die WCF zu transportieren. Die Daten sind im Entity Framework gespeichert. Schön wäre es wenn wir diese Entitäten direkt über den Kommunikationskanal schicken könnten. Leider ist dies nicht möglich da ein direktes Versenden der Entitäten, durch Projektrestriktionen nicht erlaubt ist, oder man ganz einfach keine [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=595&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Im Rahmen einer Projektarbeit haben wir das Ziel Businessdaten über die WCF zu transportieren. Die Daten sind im Entity Framework gespeichert. Schön wäre es wenn wir diese Entitäten direkt über den Kommunikationskanal schicken könnten. Leider ist dies nicht möglich da ein direktes Versenden der Entitäten, durch Projektrestriktionen nicht erlaubt ist, oder man ganz einfach keine Referenzen auf dem Client auf den Namespace <a href="http://msdn.microsoft.com/en-us/library/system.data.aspx" target="_blank">System.Data</a> haben möchte.</p>
<p>Also muss eine Lösung her die einigermassen hilfreich sein kann. Diese Lösung erledigt das Mapping eines einkommenden DatenVertrages mit der entsprechenden Entität.</p>
<h5>Vorbereitungen</h5>
<ul>
<li>AddressManagement.BusinessModel</li>
<li>AddressManagement.PersistanceModel</li>
<li>AddressManagement.ServiceLayer </li>
</ul>
<p>Für das Hosten der WCF können wir verschiedene Möglichkeiten nutzen, die aber in diesem Blogpost nicht abgedeckt werden. Es soll nur die Möglichkeit einer generischen Mapping Methode aufgezeigt werden, damit die Daten vom <a href="http://msdn.microsoft.com/en-us/library/aa697427(v=vs.80).aspx" target="_blank">Entity Framework </a> nicht direkt über den Kommunikationskanal versendet werden müssen, sondern gekapselt werden.</p>
<p>Wir erstellen uns ein Entity-Modell dass wie folgt aussieht: (Dieses erstellen wir im Projekt AddressManagement.Persistance)</p>
<p><a href="http://schaedlerdaniel.files.wordpress.com/2012/02/entitydesignerdiagram.jpg"><img src="http://schaedlerdaniel.files.wordpress.com/2012/02/entitydesignerdiagram.jpg?w=600" alt="Das Entity Data Design Model" title="EntityDesignerDiagram"   class="aligncenter size-full wp-image-599" /></a></p>
<p>Anschliessend erstellen wir uns unseres eigentliche Businessklassenmodell welches wir im Projekt AddressManagement.BusinessModel anlegen.</p>
<div id="attachment_597" class="wp-caption alignleft" style="width: 610px"><a href="http://schaedlerdaniel.files.wordpress.com/2012/02/addressmanagementclassdiagram.jpg"><img src="http://schaedlerdaniel.files.wordpress.com/2012/02/addressmanagementclassdiagram.jpg?w=600&#038;h=363" alt="" title="AddressManagementClassDiagram" width="600" height="363" class="size-full wp-image-597" /></a><p class="wp-caption-text">Das Businessklassen Model</p></div>
<p>Wichtig hierbei ist, dass die Beziehungen, Phones, Addresses genau gleich heissen wie im Entity Model. Auch alle anderen Eigenschaften müssen die gleiche Schreibweise haben, da sonst im Mapper keine Übereinstimmung gefunden wird.</p>
<p>Die Businessklassen sollen dann mit der WCF übertragen werden. Hierzu werden die Klassen mit den entsprechenden Attributen versehen.</p>
<p><strong>Die Klasse Person</strong><br />
<pre class="brush: csharp;">
namespace AddressManagement.BusinessModel
{
    [DataContract]
    [KnownType(typeof(Address))]
    [KnownType(typeof(Phone))]
    public class Person : IPersistance
    {        
        #region IPersistance Members
        [DataMember]
        public Int32 Id { get; set; }
        #endregion
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public string LastName { get; set; }
        [DataMember]
        public IEnumerable&lt;IPersistance&gt; Addresses { get; set; }
        [DataMember]
        public IEnumerable&lt;IPersistance&gt; Phones { get; set; }
    }
}
</pre>
</p>
<p><strong>Die Klasse Phone</strong><br />
<pre class="brush: csharp;">
namespace AddressManagement.BusinessModel
{
    [DataContract(IsReference = true)]
    [KnownType(typeof(ObjectType))]
    public class Phone : IPersistance
    {
        #region IPersistance Members
        [DataMember]
        public Int32 Id { get; set; }
        #endregion
        [DataMember]
        public string SubScriberNumber { get; set; }
        [DataMember]
        public ObjectType PhoneType { get; set; }
    }
}
</pre></p>
<p><strong>Die Klasse Address</strong><br />
<pre class="brush: csharp;">
namespace AddressManagement.BusinessModel
{
    [DataContract(IsReference = true)]
    [KnownType(typeof(ObjectType))]
    public class Address : IPersistance
    {
        #region IPersistance Members
        [DataMember]
        public Int32 Id { get; set; }
        #endregion
        [DataMember]
        public string StreetName { get; set; }
        [DataMember]
        public Int16 StreetNumber { get; set; }
        [DataMember]
        public Int16 PostalCode { get; set; }
        [DataMember]
        public string CityName { get; set; }
        [DataMember]
        public ObjectType AddressType { get; set; }
    }
    [DataContract]
    public enum ObjectType
    {
        [EnumMember]
        Private,
        [EnumMember]
        Business
    }
}
</pre></p>
<h5>Der Mapper/Synchronisierer</h5>
<p>Damit wir nun beide Welten miteinander abgleichen können ist der Mapper zu erstellen, welche ich Schritt für Schritt erläutere. Wir erstellen uns als erstes eine Statische Klasse mit dem Namen DataContractToEntityMapper oder DataContractAndEntitySynchronizer und erstellen als erstes folgende Methode:</p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// Maps a given datacontract to the appropriate entity.
        /// Check's if the datacontract is new or must be updated
        /// and return the newly persisted contract back or it's updated
        /// values, if it was already persisted before.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;Type of the datacontract&lt;/typeparam&gt;
        /// &lt;typeparam name=&quot;U&quot;&gt;Type of the entity&lt;/typeparam&gt;
        /// &lt;param name=&quot;dataContract&quot;&gt;The datacontract to interact with.&lt;/param&gt;
        /// &lt;returns&gt;A new or updated datacontract from the database.&lt;/returns&gt;
        public static IPersistance SynchronizeDataContractAndEntity&lt;T, U&gt;(T dataContract)
            where T : IPersistance
            where U : EntityObject
        {
            IPersistance persistance = Activator.CreateInstance&lt;T&gt;();
            // 1. a) Determine if the datacontract is already persisted.
            if (dataContract.Id == 0)
            {
                // 1. b) Map the newly created entity to the datacontract.                
                PersistDataContract&lt;T, U&gt;(dataContract);
            }
            else
            // 2.) Map an existing entity to it's datacontract pendant
            {
                U persistedEntity = Activator.CreateInstance&lt;U&gt;();
                using (AddressRepository&lt;U&gt; repository = new AddressRepository&lt;U&gt;(new AddressManagementPersistanceModelContainer()))
                {
                    persistedEntity = repository.GetByKey&lt;U&gt;(dataContract.Id);
                    persistance = UpdateProperties&lt;T, U&gt;(dataContract, persistedEntity);
                }
            }
            return persistance;
        }
</pre></p>
<p>Diese Methode führ folgende Aktionen durch:</p>
<ol>
<li>Existiert der eingetroffene DataContract schon in der Datenbank?</li>
<li>Ist die Id 0, dann muss eine neue Entität angelegt werden</li>
<li>Ist die Id &gt; 0 ist der Contract bereits in der Datenbank vorhanden und muss mit den vorliegenden Werten aktualisiert werden.</li>
<li>Zum Schluss, nachdem die Entity und der DataContract miteinander synchronisiert worden sind, wird ein aktualisierter DataContract zurück gegeben.</li>
</ol>
<p>Als nächster Schritt erstellen wir uns eine Methode die für den Abgleich der Property-Werte zuständig ist. Diese unterscheidet ob es sich bei der Eigenschaft um eine Collection oder um eine einfache Eigenschaft handelt und führt dementsprechend die Aktualisierung aus:</p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// Updates the properties from a datacontract.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;The type of datacontract&lt;/typeparam&gt;
        /// &lt;typeparam name=&quot;U&quot;&gt;The type of the entity&lt;/typeparam&gt;
        /// &lt;param name=&quot;dataContract&quot;&gt;The datacontract to update the values.&lt;/param&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The entity that is persisted and owns the actual values.&lt;/param&gt;
        /// &lt;returns&gt;Updated datacontract.&lt;/returns&gt;
        private static IPersistance UpdateProperties&lt;T, U&gt;(T dataContract, U entity)
            where T : IPersistance
            where U : EntityObject
        {
            IPersistance persistance = (IPersistance)CreateInstance&lt;T, U&gt;(dataContract, entity);
            entity.GetType().GetProperties().ToList().ForEach(entityPropertyInfo =&gt;
            {
                string propertyName = entityPropertyInfo.Name;
                PropertyInfo dataContractPropertyInfo = persistance.GetType().GetProperty(propertyName);
 
                if (entityPropertyInfo != null &amp;&amp; !entityPropertyInfo.PropertyType.Name.Contains(typeof(EntityCollection&lt;U&gt;).Name))
                {
                    var entityPropertyValue = entityPropertyInfo.GetValue(entity, null);
                    if (entityPropertyValue != null &amp;&amp; dataContractPropertyInfo != null &amp;&amp; !dataContractPropertyInfo.PropertyType.IsEnum)
                    {                        
                        dataContractPropertyInfo.SetValue(persistance, entityPropertyValue, BindingFlags.Default, null, null, null);
                    }
                }
                else if (entityPropertyInfo != null &amp;&amp; dataContract.GetType().GetProperty(entityPropertyInfo.Name) != null)
                {
                    var ienumerableValues = (IEnumerable)HandleRelatedEnds&lt;T&gt;(dataContract, (IEnumerable)entityPropertyInfo.GetValue(entity, null));
                    persistance.GetType().GetProperty(entityPropertyInfo.Name).SetValue(persistance, ienumerableValues, BindingFlags.Default, null, null, null);
                }
            });
            return persistance;
        }

</pre></p>
<p>Der erste Teil aktualisiert alle flachen Eigenschaften des DatenContracts. Der zweite Teil kümmert sich um die Collections.</p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// Handles the collections an creates for the datacontract
        /// appropriate items to add them to the list.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;Type of datacontract&lt;/typeparam&gt;
        /// &lt;param name=&quot;dataContract&quot;&gt;The specific contract where the list belongs to.&lt;/param&gt;
        /// &lt;param name=&quot;entityCollectionToDuplicate&quot;&gt;The entitycollection to map to the datacontract.&lt;/param&gt;
        /// &lt;returns&gt;A List of IPersistance objects (BusinessModel Objects).&lt;/returns&gt;
        private static List&lt;IPersistance&gt; HandleRelatedEnds&lt;T&gt;(T dataContract, IEnumerable entityCollectionToDuplicate) where T : IPersistance
        {
            List&lt;IPersistance&gt; persistances = new List&lt;IPersistance&gt;();
            IEnumerator it = entityCollectionToDuplicate.GetEnumerator();
 
            while (it.MoveNext())
            {
                EntityObject entity = ((EntityObject)it.Current);
                IPersistance ipersistance = CreateInstance&lt;T, EntityObject&gt;(dataContract, entity);
                ipersistance = UpdateProperties&lt;T, EntityObject&gt;(dataContract, entity);
                persistances.Add(ipersistance);
            }
 
            return persistances;
        }

</pre></p>
<p>Damit die Items erstellt werden können braucht es eine weitere Hilfsmethode die uns entsprechende Instanzen zurück gibt.</p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// This method creates a specific instance from the Businessmodell Assembly
        /// given by the entity type.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;The IPersistanceObject to create&lt;/typeparam&gt;
        /// &lt;typeparam name=&quot;U&quot;&gt;The entity that contains the values&lt;/typeparam&gt;
        /// &lt;param name=&quot;dataContract&quot;&gt;The datacontract to add /remove or update&lt;/param&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The entity that was created /updated depending on the passed datacontract.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        private static IPersistance CreateInstance&lt;T, U&gt;(T dataContract, U entity) where T : IPersistance
        {
            IPersistance persistance;
            string typeOfEntity = entity.GetType().Name;
            Assembly assembly = Assembly.GetAssembly(typeof(IPersistance));
            Type type = assembly.GetTypes().FirstOrDefault(assemblyType =&gt; assemblyType.Name.ToLower().Equals(typeOfEntity.ToLower()));
            persistance = (IPersistance)assembly.CreateInstance(type.FullName);
 
            return persistance;
        }

[/csharp]
&lt;p&gt;Der Funktionsumfang der oben beschriebenen Methode ist einfach. Nimm den Entity-Namen und suche in der BusinessModel Library nach dem entsprechenden Typ und instanziiere einen solchen und gib diesen dann zurück, damit er in der aufrufenden Methode in die Liste eingefügt werden kann.
Eine weitere Methode brauchen wir, damit wir einen DataContract, der über keinen Wert in der Id verfügt, persistieren können. (Das Repository ist nicht Teil dieses).
&lt;/p&gt;
[sourcecode language=&quot;csharp&quot;]
        /// &lt;summary&gt;
        /// A newly passed datacontract with it's properties
        /// will be persisted in the entity framework.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;DataContractType&lt;/typeparam&gt;
        /// &lt;typeparam name=&quot;U&quot;&gt;EntityType (must macht with the datacontract type)&lt;/typeparam&gt;
        /// &lt;param name=&quot;dataContract&quot;&gt;The datacontract to persist.&lt;/param&gt;
        private static void PersistDataContract&lt;T, U&gt;(T dataContract) where T : IPersistance where U : EntityObject
        {
            U entityToPersist = Activator.CreateInstance&lt;U&gt;();
            entityToPersist.GetType().GetProperties().ToList().ForEach(dataContractPropertyInfo =&gt;
            {
                string propertyName = dataContractPropertyInfo.Name;
                PropertyInfo entityPropertyInfo = dataContract.GetType().GetProperty(propertyName);
 
                if (entityPropertyInfo != null &amp;&amp; entityPropertyInfo.PropertyType != (typeof(RelatedEnd)))
                {
                    var entityPropertyValue = entityPropertyInfo.GetValue(dataContract, null);
                    if (entityPropertyValue != null)
                    {
                        dataContractPropertyInfo.SetValue(entityToPersist, entityPropertyValue, BindingFlags.Default, null, null, null);
                    }
                }
            });
 
            using (AddressRepository&lt;U&gt; repository = new AddressRepository&lt;U&gt;(new AddressManagementPersistanceModelContainer()))
            {
                repository.Add(entityToPersist);
                repository.SaveChanges();
            }
        }
</pre></p>
<p>Mit dieser letzten Methode haben wir den Mapper erstellt. Nun ist es uns möglich von einem Sender ein Objekt der Businessklassen zu erstellen und müssen uns keine Sorgen machen, ob dies bereits persistiert worden ist oder nicht. Wir erhalten als dann die aktualisierten oder neuen Werte von der Datenbank als Resultat zurück und können somit auf dem Client weiter arbeiten.</p>
<h5>Fazit</h5>
<p>Der Mapper hat nicht den Anspruch 100% aller Fälle abzudecken, er versucht zu zeigen wie man eine grösstmögliche Modularisierung anstreben kann, ohne dass auf dem Client Server DLL’s refernziert werden müssen. Und natürlich ein nicht zu unterschätzender Punkt ist der Aufwand einmal für die WCF Seite und einmal für die Persistance-Seite ein Modell zu führen.</p>
<p>Sollte Ihnen der Artikel gefallen haben, würde ich mich über einen kick freuen. Gerne beantworte ich auch Fragen und Kritik.</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f02%2f28%2fwcf-datacontracts-synchronisieren-mit-entity-framework-klassen%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f02%2f28%2fwcf-datacontracts-synchronisieren-mit-entity-framework-klassen%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/595/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/595/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/595/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/595/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/595/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/595/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/595/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/595/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/595/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/595/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/595/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/595/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/595/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/595/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=595&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2012/02/28/wcf-datacontracts-synchronisieren-mit-entity-framework-klassen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/02/entitydesignerdiagram.jpg" medium="image">
			<media:title type="html">EntityDesignerDiagram</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/02/addressmanagementclassdiagram.jpg" medium="image">
			<media:title type="html">AddressManagementClassDiagram</media:title>
		</media:content>

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f02%2f28%2fwcf-datacontracts-synchronisieren-mit-entity-framework-klassen%2f" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
		<item>
		<title>WCF Service über JQuery ansprechen leicht gemacht</title>
		<link>http://schaedlerdaniel.wordpress.com/2012/01/31/wcf-service-uber-jquery-ansprechen-leicht-gemacht/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2012/01/31/wcf-service-uber-jquery-ansprechen-leicht-gemacht/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 13:13:13 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[ASP.NET /AJAX /ASP.NET MVC]]></category>
		<category><![CDATA[WCF]]></category>
		<category><![CDATA[JQuery AJAX]]></category>
		<category><![CDATA[WCF ImageGallery]]></category>
		<category><![CDATA[WCF und ASP.NET]]></category>
		<category><![CDATA[WCF und JQuery]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=539</guid>
		<description><![CDATA[Zur Zeit bin ich an einer Weiterbildung für die Verwendung von .NET im Grossfirmenumfeld. Ein Thema darin ist ist Windows Communication Foundation (kurz WCF genannt). Da ich aus der Ecke der Webprogrammierer komme interessiert es mit primär, wie ich einen WCF-Service von einer Webseite her ansprechen kann. Was brauchen wir denn für einen Service der [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=539&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Zur Zeit bin ich an einer Weiterbildung für die Verwendung von .NET im Grossfirmenumfeld. Ein Thema darin ist ist <a href="http://msdn.microsoft.com/de-de/library/dd456779.aspx" target="_blank">Windows Communication Foundation (kurz WCF genannt)</a>.</p>
<p>Da ich aus der Ecke der Webprogrammierer komme interessiert es mit primär, wie ich einen WCF-Service von einer Webseite her ansprechen kann.</p>
<p>Was brauchen wir denn für einen Service der auf der Basis der WCF für einen Webseitenzugriff konfiguriert ist?</p>
<h3>Vorbereitungen</h3>
<ol>
<li>Erstellen eines neues ASP.NET Projektes über den Menüpunkt &#8220;Neues Projekt erstellen&#8230;&#8221;</li>
<li>Mit <a href="" target="_blank">NuGet</a> zuerst die JQueryUI und dann die JQuery<br />
            Libraries hinzufügen</li>
<li>Erstellen Sie einen Ordner Services in der Solution</li>
<li>In den zuvor erstellten Service fügen Sie ein neues Item hinzu (Vorlage für einen<br />
            WCF-Service) und benennen Sie diesen mit &#8220;ImageService&#8221;</li>
<li>Visual Studio erstellt uns eine .svc und ein entsprechendes Interface ImageService.cs.<br />
            Hier stehen noch nicht allzu viele Sachen drin sodass wir die DoWork Methode im<br />
            Interface ein wenig anpassen. Nach dem Hinzufügen des Service sollte die Solution<br />
            mit den aktuellen JQuery Referenzen ausgestattet sein und folgende .NET Dll’s als<br />
            Referenz aufweisen:</p>
<ul>
<li>System.Service.Model</li>
<li>System.Runtime.Serializatin</li>
</ul>
</ol>
<h3>WCF Konfiguration</h3>
<p>Soweit so gut. Wir sind bereit den WCF Service zu implementieren. Hierzu wird in die Solution noch ein Verzeichnis Images hinzugefügt, dass einfach mit den Beispiel Bildern von Windows befüllt wird. Zuerst fangen wir mit der Konfiguration der Web.Config für unseren Dienst an.</p>
<p>Konfiguration der Web.Config mit dem „WCF Service Configurator“ (Finden Sie unter Tools bei Visual Studio 2010)</p>
<ol>
<li>Erstellen eines neuen Services <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/01_wcfservicekonfigurieren.jpg"><br />
            <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/01_wcfservicekonfigurieren.jpg?w=600" alt="" title="WCF Service konfigurieren"   class="aligncenter size-full wp-image-553" /></a>
        </li>
<p></p>
<li>Auswahl der DLL von welcher her der Service generiert werden soll. Sollte im bin<br />
            Verzeichnis keine DLL vorliegen so kann man dies mit dem „Erstellen der Solution“<br />
            beheben<a href="http://schaedlerdaniel.files.wordpress.com/2012/01/02_wcfservicekonfigurieren.jpg"><img src="http://schaedlerdaniel.files.wordpress.com/2012/01/02_wcfservicekonfigurieren.jpg?w=600" alt="" title="DLL Auswählen"   class="aligncenter size-full wp-image-556" /></a></li>
<li>Den Vertrag (Contract) können wir stehen lassen und weiter klicken. <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/03_wcfservicekonfigurieren.jpg"><br />
            <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/03_wcfservicekonfigurieren.jpg?w=600" alt="" title="Contract Auswahl"   class="aligncenter size-full wp-image-561" /></a></li>
<li>Da wir einen ImageService für’s Internet bereitstellen wollen, lassen wir die Konfiguration<br />
                auf http sein. <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/04_wcfservicekonfigurieren.jpg"><br />
                    <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/04_wcfservicekonfigurieren.jpg?w=600" alt="" title="Protokoll Auswahl"   class="aligncenter size-full wp-image-562" /></a>
                </li>
<p></p>
<li>Auch weitere Optionen belassen wir auf dem Standard. Wir wollen einen einfachen<br />
                    ImageService ohne Duplex Funktion und lassen den Vorschlag des Assistenten so wie<br />
                    er ist. <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/05_wcfservicekonfigurieren.jpg"><br />
                        <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/05_wcfservicekonfigurieren.jpg?w=600" alt="" title="Interopabilität wählen"   class="aligncenter size-full wp-image-563" /></a>
                </li>
<p></p>
<li>Zum Schluss erstellen wir die Endpunkt-Adresse über welche der Service erreicht<br />
                    werden soll. <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/06_wcfservicekonfigurieren.jpg"><br />
                        <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/06_wcfservicekonfigurieren.jpg?w=600" alt="" title="Endpunkt Konfiguration"   class="aligncenter size-full wp-image-564" /></a>
                </li>
<p></p>
<li>Wir haben einen neuen Service erstellt, wie uns der Assistent nun mitteilt. <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/07_wcfservicekonfigurieren.jpg"><br />
                    <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/07_wcfservicekonfigurieren.jpg?w=600" alt="" title="Finish Wizard Dialog"   class="aligncenter size-full wp-image-565" /></a>
                </li>
</ol>
<h3>Anpassen des WCF Service für unsere Bedürfnisse</h3>
<p>Nun haben wir den Service deklarativ in der Web.Config erstellt. Nun müssen wir noch Anpassungen vornehmen, damit der Service auch mit einer <a href="http://msdn.microsoft.com/de-de/library/system.servicemodel.webhttpbinding.aspx" target="_blank">WebHttpBinding</a> angesprochen werden kann (das Programmiermodell http von WCF).</p>
<p><strong>Anpassen des erstellten Service für die Verwendung mit ASP.NET (WCF Service Configurator).</strong></p>
<ol>
<li>Selektieren Sie den zuvor erstellten Endpunkt <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/01_enpointanpassen.jpg"><br />
            <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/01_enpointanpassen.jpg?w=600" alt="" title="Endpunkt anpassen"   class="aligncenter size-full wp-image-566" /></a>
        </li>
<p></p>
<li>Das Binding muss mit der DropDownListe auf webHttpBinding gewechselt werden.
        </li>
<p></p>
<li>Nun müssen wir dem Binding noch eine Konfiguration zuordnen. Dies können wir tun<br />
            indem wir den Punkt „Bindings“ auswählen und ein neues hinzufügen. <strong>ACHTUNG</strong>:<br />
            Man muss das WebHttpBinding auswählen, damit die erstellte Konfiguration darauf<br />
            wirkt. </li>
<p></p>
<li>Wir geben der neu erstellen Konfiguration einen Namen und belassen die Standardwerte<br />
            so wie sie sind (Die Ausnahmen werden nachstehend aufgelistet).</p>
<table>
<tr>
<th>
                        <strong>Konfigurationselement</strong>
                    </th>
<th>
                        <strong>Wert</strong>
                    </th>
<th>
                        <strong>Grund</strong>
                    </th>
<tr>
<td>
                            ByPassProxyOnLocal
                        </td>
<td>
                            True
                        </td>
<td>
                            Lokale Adressen werden nicht über einenProxy-Server aufgelöst.
                        </td>
</tr>
<tr>
<td>
                            CrossDomainScriptAccessEnabled
                        </td>
<td>
                            True
                        </td>
<td>
                            Zugriff von überall her möglich per Script (Internet Service).
                        </td>
</tr>
</tr>
</table>
</li>
<p></p>
<li>Nun wechseln wir wieder zu den Endpunkten und wählen unseren erstellten Endpunkt<br />
            aus. Danach können wir in der Bindungskonfiguration die neu erstellte Bindung auswählen.<br />
            <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/02_enpointanpassen.jpg"><br />
                <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/02_enpointanpassen.jpg?w=600" alt="" title="02_EnpointAnpassen"   class="aligncenter size-full wp-image-568" /></a>
        </li>
<p>
    </ol>
</p>
<h3>Den WCF Service zum Leben erwecken</h3>
<p>Wir erstellen uns eine Global.asax die für das Starten und Beenden der WebApplikationen die entsprechenden Methoden bereitstellt. Interessant sind die Methoden Application_Start und die Application_End.</p>
<ol>
<li>Wir fügen unserem Webprojekt eine Global.asax mit dem Befehl Add new Item… hinzu.
        </li>
<p></p>
<li>Damit wir webHttp verwenden können müssten wir System.ServiceModel.Web referenzieren<br />
            damit wir ein Objekt vom Typ WebserviceHost erstellen können. </li>
<li>
<p>
                Die Global.asax sieht dann wie folgt aus:</p>
<p>
                <pre class="brush: csharp;"> using System; using System.ServiceModel.Web; using
                Sample.WebHttpImageService.Services; namespace Sample.WebHttpImageService { public
                class Global : System.Web.HttpApplication { ///
                &lt;summary&gt;
        /// Host is declared here to not been removed by
        /// the carbage collector.
        /// &lt;/summary&gt;
                private static WebServiceHost host = new WebServiceHost(typeof(ImageService), new
                Uri(&quot;http://localhost:8099&quot;)); ///
                &lt;summary&gt;
        /// Occurs when application is staring up.
        /// &lt;/summary&gt;
                ///
                &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;
                ///
                &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;
                protected void Application_Start(object sender, EventArgs e) { try { host.Open();
                } catch (Exception exception) { host.Abort(); } } ///
                &lt;summary&gt;
        /// Occurs at application shutdown.
        /// &lt;/summary&gt;
                ///
                &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;
                ///
                &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;
                protected void Application_End(object sender, EventArgs e) { host.Close(); } } }
                </pre></p>
</li>
<p></p>
<li>
<p>
                Startet man nun das Projekt kann unter Umständen die Fehlermedung kommen, dass man<br />
                eine nicht registrierte URL versucht aufzurufen. Abhilfe schafft hier das Visual<br />
                Studio als Administrator zu starten (generell mit WCF zu empfehlen).</p>
</li>
<p></p>
<li>
<p>
                Nun wollen wir prüfen ob der Service mit der Methode GetImages angesprochen werden<br />
                kann. Die machen wir indem wir http://localhost:8099/ImageService/GetImages in den<br />
                Browser eingeben. Wir eine Fehlermeldung, die besagt dass die Methode nicht ausgeführt<br />
                werden kann.
            </p>
<p>
                Ist ja eigentlich logisch, denn unsere momentane Service Methode erwartet einen<br />
                Parameter der über Web „GET“ übermittelt wird. Dies wurde noch nicht implementiert.
            </p>
</li>
<p></p>
<li>
<p>
                Ist das Attribut im Interface angegeben können wir zum Beispiel mit dem Auftruf<br />
                http://localhost:8099/ImageService/GetAllImages?path=Test einen Methodenaufruf machen<br />
                und erhalten das folgende Beispiel Resultat.</p>
<p>            <a href="http://schaedlerdaniel.files.wordpress.com/2012/01/resultatnachwebget.jpg"><br />
                <img src="http://schaedlerdaniel.files.wordpress.com/2012/01/resultatnachwebget.jpg?w=600&#038;h=274" alt="" title="ResultatNachWebGET" width="600" height="274" class="aligncenter size-full wp-image-571" /></a>
        </li>
</ol>
<h3>Anpassen der WCF Methode GetImages</h3>
<p>Nun wollen wir doch, dass der Service über einen AJAX Aufruf per JQuery angesprochen werden kann. Hierzu gehen wir wie folgt vor. Da die Service-Methode noch nicht so tut wie wir das gerne wollen, dekorieren wir die Methode im Interface mit dem Attribute WebGet. Das Interface sieht nun wie folgt aus:</p>
<p><pre class="brush: csharp;">
[ServiceContract]
public Interface IImageService{
[OperationContract]
[WebGet]
public List&lt;string&gt; GetImages(string path);
}
</pre></p>
<p>Die Implementierungsklasse sieht dann so aus:</p>
<p><pre class="brush: csharp;">
public class ImageService : IImageService{
public List&lt;string&gt; GetImages(string path){
List&lt;string&gt; result = new List&lt;string&gt;(){ &quot;Hello WCF&quot;};
return result;
}
}
</pre></p>
<h3>Clientseitige Implementierung</h3>
<p>Nun kommen wir auf die Clientseite. Wir fügen, falls es nicht schon getan wurde, ein Default.aspx WebForms zur Solution hinzu.</p>
<p>
Hierzu erstellen wir uns unter dem Verzeichnis (Scripts) ein Unterverzeichnis mit dem Namen „Custom“ und fügen uns dort eine ImageService.js Datei hinzu, die folgenden Inhalt aufweist. (Vergessen Sie nicht die JQuery Scriptreferenz im Header der Default.aspx hinzuzufügen).
</p>
<p>Unser erstelltes Clientscript sieht dann so aus:</p>
<p><pre class="brush: jscript;">
$(document).ready(function () {
    var imagesUri = &quot;http://localhost:7777/Images/&quot;;

    jQuery.support.cors = true;

    $.ajax({

        type: &quot;GET&quot;,
        url: &quot;http://localhost:8099/ImageService/GetImages?path=&quot; + imagesUri,
        dataType: &quot;text&quot;,
        contentType: &quot;application/text; charset=utf-8&quot;,
        success: function (message) {
            //$('#Result').append(message);
            var xmlDocument = jQuery.parseXML(message);
            var images = xmlDocument.getElementsByTagName(&quot;string&quot;);

            for (var index = 0; index &lt;= images.length - 1; index++) {

                $('#Result').append(&quot;&lt;img src=\'&quot; + images[index].textContent + &quot;\' /&gt;&quot;);

            }
        },
        error: function (message) {

        }
    });

});
</pre></p>
<p>
Die Default.aspx braucht dann nur noch eine Script-Referenz auf diese Datei.
</p>
<p><pre class="brush: xml;">
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;Zugreifen auf WCF mittels JQuery&lt;/title&gt;  
    &lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; src=&quot;Scripts/jquery-1.7.1.js&quot;&gt;&lt;/script&gt;  
    &lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; src=&quot;Scripts/Custom/ImageService.js&quot; &gt;&lt;/script&gt;
&lt;/head&gt;
</pre></p>
<p>Der httpQuery muss mit dem Parameter der im Inteface für die Servicedefinition festgelegt worden ist übereinstimmen. Nun ist es nicht wirklich ansprechend ein Hallo reinzugeben und dann als Resultat Hallo WCF, mit den geschweiften Klammern zu erhalten.</p>
<p>
 Wichtig hierfür ist das JQuery für CrossDomain zugriff konfiguriert wird. Dies geschieht wie folgt:</p>
<p>
<pre class="brush: jscript;">
	jQuery.support.cors = true;
</pre>
</p>
<p>
Nun da WCF und ASP.NET nicht im gleichen Kontext beheimatet sind kann die Grundlage beider genommen werden. Beide bauen auf System.Web.Hosting auf. Folgenes Beispiel lässt alle Bilder die vom Pfad übergeben worden sind mit dem <a href="http://msdn.microsoft.com/de-de/library/system.io.directoryinfo(v=vs.100).aspx" target="_blank">DirectoryInfo</a> suchen und finden.
</p>
<p><pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.IO;
using System.Web.Hosting;
using System.Linq;

namespace Sample.WebHttpImageService.Services
{
    /// &lt;summary&gt;
    /// Get's the images from the path given by parameter.
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;path&quot;&gt;ImagePath to look for images.&lt;/param&gt;
    public class ImageService : IImageService
    {
        public string[] GetImages(string path)
        {
            List&lt;string&gt; result = new List&lt;string&gt;();
            
            Uri uri = new Uri(path, UriKind.Absolute);
            
            FileInfo[] images = new DirectoryInfo(HostingEnvironment.MapPath(uri.LocalPath)).GetFiles();

            images.ToList().ForEach(image =&gt;
                                        {
                                            string imageUrl = string.Format(@&quot;{0}{1}&quot;, path, image.Name);
                                            result.Add(imageUrl);
                                        });

            return result.ToArray();
        }   
</pre></p>
<p>
Unser Image Service muss so dann nicht im ApsNetCompatibilityMode betrieben werden und wir können trotzdem auf Files auf dem WebServer zugreifen. Nähere Details können hier gefunden werden <a href="http://msdn.microsoft.com/en-us/library/aa702682.aspx" target="_blank">WCF Service and ASP.NET</a>
</p>
<p>Zu guter Letzt Verarbeiten wir Client-seitig das XML das wir vom Server zurück erhalten und zeigen die Bilder an.</p>
<p>
Das Bilder anzeigen haben wir ja in die ImageService.js ausgelagert.
</p>
<h3>Fazit</h3>
<p>Mit eigentlich ganz wenig Aufwand ist es möglich einen Service zur Verfügung zu stellen der von allen Interessierten konsumiert werden kann. Trickreich an den ganzen Recherchen war auf jeden Fall das Zusammenspiel zwischen ASP.NET und der WCF die ja nicht im gleichen Kontext laufen, ohne dass man das AspNetCompatibilityReruirement Attribut braucht, oder den WCF-Service im Kompatibilitätsmodus laufen lässt. Weiter werde ich versuchen in den nächsten Wochen ein wenig mehr um die Daten die ausgetauscht werden, zu beleuchten.</p>
<p>Wenn Ihnen dieser Artikel gefallen hat, würde ich mich über einen Kick freuen und bin auch empfänglich für Rückmeldungen und Kritik.</p>
<p>
<a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f01%2f31%2fwcf-service-uber-jquery-ansprechen-leicht-gemacht%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f01%2f31%2fwcf-service-uber-jquery-ansprechen-leicht-gemacht%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/539/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/539/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/539/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/539/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/539/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/539/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/539/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/539/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/539/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/539/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/539/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/539/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/539/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/539/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=539&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2012/01/31/wcf-service-uber-jquery-ansprechen-leicht-gemacht/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/01_wcfservicekonfigurieren.jpg" medium="image">
			<media:title type="html">WCF Service konfigurieren</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/02_wcfservicekonfigurieren.jpg" medium="image">
			<media:title type="html">DLL Auswählen</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/03_wcfservicekonfigurieren.jpg" medium="image">
			<media:title type="html">Contract Auswahl</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/04_wcfservicekonfigurieren.jpg" medium="image">
			<media:title type="html">Protokoll Auswahl</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/05_wcfservicekonfigurieren.jpg" medium="image">
			<media:title type="html">Interopabilität wählen</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/06_wcfservicekonfigurieren.jpg" medium="image">
			<media:title type="html">Endpunkt Konfiguration</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/07_wcfservicekonfigurieren.jpg" medium="image">
			<media:title type="html">Finish Wizard Dialog</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/01_enpointanpassen.jpg" medium="image">
			<media:title type="html">Endpunkt anpassen</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/02_enpointanpassen.jpg" medium="image">
			<media:title type="html">02_EnpointAnpassen</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2012/01/resultatnachwebget.jpg" medium="image">
			<media:title type="html">ResultatNachWebGET</media:title>
		</media:content>

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2012%2f01%2f31%2fwcf-service-uber-jquery-ansprechen-leicht-gemacht%2f" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
		<item>
		<title>Entity Framework ein pragmatischer Ansatz</title>
		<link>http://schaedlerdaniel.wordpress.com/2011/12/23/entity-framework-ein-pragmatischer-ansatz/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2011/12/23/entity-framework-ein-pragmatischer-ansatz/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 11:49:48 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[Creating query depending on properties in search object Entity Framework]]></category>
		<category><![CDATA[Custom Query]]></category>
		<category><![CDATA[Entity Framework one Method to get all object types]]></category>
		<category><![CDATA[Generic Query]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=494</guid>
		<description><![CDATA[Was meine ich damit? Ganze einfach, da ich recht pragmatisch bin und nicht gerne all zu viel schreibe, dachte ich mir es muss doch eine Möglichkeit geben, dass ich genau eine Methode habe, die mir aufgrund eines übergebenen Typ&#8217;s die Resultate der Datenbank zurückliefert. Normalerweise hätte ich das mit einer Vererbung gelöst. 1.) Eine BaseEntität [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=494&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h3>Was meine ich damit?</h3>
<p>Ganze einfach, da ich recht pragmatisch bin und nicht gerne all zu viel schreibe, dachte ich mir es muss doch eine Möglichkeit geben, dass ich genau eine Methode habe, die mir aufgrund eines übergebenen Typ&#8217;s die Resultate der Datenbank zurückliefert.</p>
<p>Normalerweise hätte ich das mit einer Vererbung gelöst.</p>
<ul>
<li>1.) Eine BaseEntität erstellen</li>
<li>2.) Alle anderen Entitäten erben von dieser Basis-Entität.</li>
</ul>
<p>So ist es mir möglich mit folgendem Code die entsprechenden Tabellen anzusprechen.</p>
<p><pre class="brush: csharp;">
using(MyContext context = new Context())
{
      context.BaseEntity.OfType&lt;Person&gt;().ToList();
}
</pre></p>
<p>Nun der Ansatz ist nicht schlecht, hat aber seine Tücken, nähmlich dann wenn man grosse Datenmengen verarbeiten muss, dann muss er zuerst alle Daten die dem übergebenen Typ in der BaseEntität entsprechen laden und nochmals die der vererbten Entität.</p>
<h3>Was wäre die Lösung?</h3>
<p>Keine Vererbung. Gibt natürlich ein wenig mehr zu tun, man hat aber bei einem nicht bekannten Mengengerüst den Vorteil, dass die Datenbank schneller wachsen kann, ohne dass man ein Refactoring am Code vornehmen müsste.</p>
<p>Das ganze einfache Model sieht man nachstehend.</p>
<p><a href="http://schaedlerdaniel.files.wordpress.com/2011/12/blogmodel.jpg"><img src="http://schaedlerdaniel.files.wordpress.com/2011/12/blogmodel.jpg?w=400" alt="" title="BlogModel" width="400" class="aligncenter" /></a><br />
</p>
<p>Jetzt kommt aber der entscheidende Punkt, den man beim Desing der Eintitäten beachten soll. Das Entity FrameWork kann mit dem EntitySet Namen umgehen. Wenn wir den EntitSet Namen gleich wie die Entität erfassen, so kann man ohne Probleme mit</p>
<p><pre class="brush: csharp;"> myEntity.GetType().Name; </pre></p>
<p> das EntitySet so angeben. Wenn man aber den generierten Namen lassen möchte, muss man bewusst sein, dass man sich dann den EntitySet-Name, bestehend aus dem Objekt-Typ Namen und einem Postfix vor einer Abfrage erstellen sollte.</p>
<p>Ich habe den ersten Weg gewählt und mir den EntitySet Namen gleichgesetzt wie der EntityName (im Grunde weiss ich ja dass die Tabelle Person heisst, die Menge aber Personen sind).</p>
<p><a href="http://schaedlerdaniel.files.wordpress.com/2011/12/entitydesigner.jpg"><img src="http://schaedlerdaniel.files.wordpress.com/2011/12/entitydesigner.jpg?w=400" alt="" title="EntityDesigner" width="400" class="aligncenter" /></a><br />
</p>
<h3>Wie sieht den nun der Ansatz aus?</h3>
<p>Zu diesem Zweck habe ich mir einen ContextHelper erstellt. Interssant ist hier die Methode Get, die anhand eines <a href="http://msdn.microsoft.com/de-de/library/bb738995.aspx" target="_blank">ObjectQuery</a> die Abfrage an den Kontext sendet.</p>
<p>Was brauchen wir dazu?</p>
<ul>
<li> 1.) Ein ObjectQuery mit entsprechenden <a href="http://msdn.microsoft.com/de-de/library/system.data.objects.objectparameter.aspx" target="_blank">ObjectParametern</a> dass sich aus dem übergebenen Objekt und dessen Eigenschaften zusammensetzt.</li>
<li> 2.) Ein string Query, welches die die Parameter aufnimmt und anhand des übergebenen Objekts erstellt wird. </li>
</ul>
<p></br></p>
<p>Die Get Methode sind dann so aus:</p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// Get method for deleting a row in the database.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;Type of object to get.&lt;/typeparam&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The search object which has to retrieve all matching entires in the database.&lt;/param&gt;
        public static IEnumerable&lt;T&gt; Get&lt;T&gt;(T entity) where T : EntityObject
        {
            IEnumerable&lt;T&gt; result = null;
            using (BlogModelContainer container = new BlogModelContainer())
            {
                string queryCommand = string.Format(&quot;SELECT VALUE {1} FROM {0}.{1} WHERE 1=1&quot;, container.DefaultContainerName, entity.GetType().Name);

                // Creating the query, depending on how much of the properties in the given object are filled out
                // In this case only string properties will be read.
                queryCommand = CreateQueryString&lt;T&gt;(entity, queryCommand);

                ObjectQuery&lt;T&gt; entityQuery = new ObjectQuery&lt;T&gt;(queryCommand, container);
                CreateParameters&lt;T&gt;(entity).ForEach(entityQuery.Parameters.Add);

                result = entityQuery.ToList();
            }

            return result;
        }
</pre></p>
<p>Damit diese Methode bedient werden kann sind drei weitere notwendig.</p>
<ul>
<li>1.) Eine die nur <a href="http://msdn.microsoft.com/de-de/library/system.reflection.propertyinfo(v=VS.100).aspx" target="_blank">PropertyInfo&#8217;s</a> zurückgibt welche auch einen Wert haben.</li>
<li>2.) Eine die den QueryString anhand der PropertyInfo&#8217;s abfüllt.</p>
<li>3.) Last but not least eine Methode die anhand der PropertyInfo&#8217;s die ObjectParameter erstellt.</li>
</ul>
<p></p>
<p>Die PropertyInfo Methode sieht wie folgt aus:</p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// Get's all properties from an object that where
        /// filled, or they have a value and returns it.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;&lt;/typeparam&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The entity to look for the properties.&lt;/param&gt;
        /// &lt;returns&gt;List of propertyInfos (each propertyInfo has a value)&lt;/returns&gt;
        private static List&lt;PropertyInfo&gt; GetProperty&lt;T&gt;(T entity) where T : EntityObject
        {
            List&lt;PropertyInfo&gt; result = new List&lt;PropertyInfo&gt;();

            entity.GetType().GetProperties().ToList().ForEach(property =&gt;
            {
                if (property.PropertyType.Equals(typeof(string)))
                {
                    string propertyValue = property.GetValue(entity, new object[] { }) as string;

                    // Determining if the the property value of type string is filled out.
                    if (!string.IsNullOrWhiteSpace(propertyValue))
                    {
                        result.Add(property);
                    }
                }
            });

            return result;
        }
</pre></p>
<p>Da nur PropertyInfo&#8217;s zurückkommen die auch einen Wert aufweisen (momentan nur einen string-Typen, werde auch keine leeren Properties zurückgegeben.</p>
<p>Die Methode für den QueryString sieht dann so aus: </p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// Creates the appropriate querystring depending
        /// on the object that was passed.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;The specific objectType&lt;/typeparam&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The entity to query against&lt;/param&gt;
        /// &lt;param name=&quot;queryString&quot;&gt;The&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        private static string CreateQueryString&lt;T&gt;(T entity, string queryString) where T : EntityObject
        {
            List&lt;ObjectParameter&gt; parameters = new List&lt;ObjectParameter&gt;();
            GetProperty&lt;T&gt;(entity).ForEach(p =&gt;
            {
                string propertyValue = p.GetValue(entity, new object[] { }) as string;
                queryString += string.Format(&quot; AND {0}.{1} = @{1}&quot;, entity.GetType().Name, p.Name);
            });

            return queryString;
        }
</pre></p>
<p>Für die ObjectParameter Erstellung wird eine ähnliche Methode verwendet:</p>
<p><pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// Creates the queryparameters to pass to the objectquery
        /// depending on the filled out properties in the parameter
        /// object.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;Specific objectType which must be at least of type EntityObject&lt;/typeparam&gt;
        /// &lt;param name=&quot;entity&quot;&gt;The entity with the filled properties for use in the query.&lt;/param&gt;
        /// &lt;returns&gt;The ObjectParameters Array to add it to the ObjectQuery.&lt;/returns&gt;
        private static List&lt;ObjectParameter&gt; CreateParameters&lt;T&gt;(T entity) where T : EntityObject
        {
            List&lt;ObjectParameter&gt; parameters = new List&lt;ObjectParameter&gt;();
            GetProperty&lt;T&gt;(entity).ForEach(p =&gt;
            {
                string propertyValue = p.GetValue(entity, new object[] { }) as string;
                ObjectParameter parameter = new ObjectParameter(p.Name, propertyValue);
                parameters.Add(parameter);
            });

            return parameters;
        }
</pre></p>
<p>Somit werden die QueryParameter und der Query generisch anhand des &#8220;Suchobjektes&#8221;, das an die Get-Methode übergeben wird zusammengestellt.</p>
<p>Für Fragen, Kritik und Anregungen freue ich mich über einen Kommentar.</p>
<p>Ich wünsche allen frohe Festtage und einen guten Rutsch ins 2012, auf dass weider viele neue Sachen im .NET 4.5 endeckt werden können.</p>
<p>Das Beispielprojekt kann <a href="http://dl.dropbox.com/u/49243648/Sample.GenericEntity.zip" target="_blank">hier</a> heruntergeladen werden.</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fbit.ly%2fsR6seW"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fbit.ly%2fsR6seW" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/494/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/494/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/494/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/494/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/494/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/494/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/494/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/494/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/494/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/494/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/494/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/494/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/494/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/494/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=494&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2011/12/23/entity-framework-ein-pragmatischer-ansatz/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2011/12/blogmodel.jpg?w=300" medium="image">
			<media:title type="html">BlogModel</media:title>
		</media:content>

		<media:content url="http://schaedlerdaniel.files.wordpress.com/2011/12/entitydesigner.jpg" medium="image">
			<media:title type="html">EntityDesigner</media:title>
		</media:content>

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fbit.ly%2fsR6seW" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
		<item>
		<title>Heirate mich (ASP.NET und JQuery Accordion)</title>
		<link>http://schaedlerdaniel.wordpress.com/2011/10/27/heirate-mich-asp-net-und-jquery-accordion/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2011/10/27/heirate-mich-asp-net-und-jquery-accordion/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 08:18:29 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[ASP.NET /AJAX /ASP.NET MVC]]></category>
		<category><![CDATA[JavaScript / HTML /CSS /XML]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=478</guid>
		<description><![CDATA[Was ganz nützlich für die Darstellung von Daten ist, ist das Accordion, welches ja auch bereits im AjaxControlToolkit vorkommt. Nun die meisten werden das Ganze sicherlich rein nativ client-seitig mit JQuery und der Herumschlagerei von Div-Elementen verwendet haben. Meine Überlegung war es, in Abhängigkeit zu einer Quelle (IEnumerable) die Accordion-Items generieren zu lassen. Wie bin [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=478&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Was ganz nützlich für die Darstellung von Daten ist, ist das Accordion, welches ja auch bereits im AjaxControlToolkit vorkommt.</p>
<p>Nun die meisten werden das Ganze sicherlich rein nativ client-seitig mit JQuery und der Herumschlagerei von Div-Elementen verwendet haben.</p>
<p>Meine Überlegung war es, in Abhängigkeit zu einer Quelle (IEnumerable) die Accordion-Items generieren zu lassen.</p>
<h3>Wie bin ich vorgegangen?</h3>
<p>Als erstes habe ich mir das Markup eines Demo-Accordions auf der Webseite von JQuery angesehen.</p>
<p>Da es im .NET die Klasse <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.htmlcontrols.htmlgenericcontrol.aspx">HtmlGeneric</a> gibt kann man mit dieser mit ein wenig Geschick viel anstellen</p>
<p>Also wir brauchen folgendes:</p>
<ul>
<li>Eine ASP.Seite mit einem Div-Element dass den Container für das Accordion darstellt</li>
<li>Als nächstes brauchen wir eine Klasse, die uns den Accordion Markup generiert</li>
<li>Und last but not least ein Model Element (Klassenelement aus unserem Modell</li>
<h4 style="color:black;">1. Erstellen der ASPX Seite </h4>
<p></p>
<p>Der nachfolgende Markup-Code ist keine Magie und ziemlich schlank</p>
<p><pre class="brush: xml;">
&lt;%@ Page Title=&quot;&quot; Language=&quot;C#&quot; MasterPageFile=&quot;~/Site.Master&quot; AutoEventWireup=&quot;true&quot; CodeBehind=&quot;Index.aspx.cs&quot; Inherits=&quot;AspNetWebFromJQueryUI.Index&quot; %&gt;
&lt;asp:Content ID=&quot;Content1&quot; ContentPlaceHolderID=&quot;HeadContent&quot; runat=&quot;server&quot;&gt;
&lt;link type=&quot;text/css&quot; href=&quot;Content/themes/base/jquery.ui.all.css&quot; rel=&quot;Stylesheet&quot; /&gt;	
&lt;script type=&quot;text/javascript&quot; src=&quot;/Scripts/jquery-1.6.4.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/Scripts/jquery-ui-1.8.16.js&quot;&gt;&lt;/script&gt;
&lt;/asp:Content&gt;
&lt;asp:Content ID=&quot;Content2&quot; ContentPlaceHolderID=&quot;MainContent&quot; runat=&quot;server&quot;&gt;
&lt;script&gt;
    $(function () {
        $(&quot;#Accordion&quot;).accordion();
    });
	&lt;/script&gt;
&lt;div id=&quot;ResultDiv&quot; runat=&quot;server&quot;&gt;
&lt;/div&gt;

&lt;/asp:Content&gt;
</pre></p>
<p>Einzig das Referenzieren von JQuery und JQueryUI sollte beachtet werden. Hierzu findet man auf JQueryUI die entsprechende Anleitung im <a href="http://jqueryui.com/docs/Getting_Started">Get started</a> Teil.</p>
<h4 style="color:black;">2. Den Helper für das Accordion </h4>
<p></p>
<p>Nun kommen wir zum Helper für die Erstellung des Markups für das Accordion, der wie folgt aufgebaut ist: </p>
<p><pre class="brush: csharp;">
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.UI;
using System.Web.UI.HtmlControls;

namespace AspNetWebFromJQueryUI.Controls
{
    /// &lt;summary&gt;
    /// Responsible for creating an accordion base
    /// for using it with JQueryUI
    /// &lt;/summary&gt;
    public static class AccordionHelper
    {
        /// &lt;summary&gt;
        /// Returns the complete HTML code for the accordion.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;The model type.&lt;/typeparam&gt;
        /// &lt;param name=&quot;datasource&quot;&gt;The items to show in the accordion&lt;/param&gt;
        /// &lt;see cref=&quot;http://jqueryui.com/demos/accordion/&quot;/&gt;
        /// &lt;returns&gt;The HTML Markup for an accordion in JQuery manner&lt;/returns&gt;
        public static HtmlGenericControl CreateAccordion&lt;T&gt;(IEnumerable&lt;T&gt; datasource)
        {
            HtmlGenericControl accordion = new HtmlGenericControl {TagName = &quot;div&quot;, ClientIDMode = ClientIDMode.Static, ID = &quot;Accordion&quot;};
            accordion.InnerHtml = CreateContentDiv(datasource);

            return accordion;
        }

        /// &lt;summary&gt;
        /// Creates the content div's for putting the model
        /// content to it.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;The model item (for example from the businessmodel)&lt;/typeparam&gt;
        /// &lt;param name=&quot;datasource&quot;&gt;The items that are the datasource for the accordion&lt;/param&gt;
        /// &lt;returns&gt;The HTML string for the accordion&lt;/returns&gt;
        private static string CreateContentDiv&lt;T&gt;(IEnumerable&lt;T&gt; datasource)
        {
            StringBuilder sb = new StringBuilder();

            if (datasource != null)
                for (int index = datasource.Count() - 1; index &gt;= 0; index--)
                {
                    if (index == 0)
                    {
                        sb.AppendLine(string.Format(&quot;&lt;h3&gt;&lt;a href=\&quot;#\&quot;&gt;{0}&lt;/a&gt;&lt;/h3&gt;&quot;, CreateTitleElement(datasource.ToList()[index])));
                        sb.AppendLine(string.Format(&quot;&lt;div&gt;{0}&lt;/div&gt;&quot;, CreateContentItemFromModel(datasource.ToList()[index])));
                    }
                    else
                    {
                        sb.AppendLine(string.Format(&quot;&lt;h3&gt;&lt;a href=\&quot;#\&quot;&gt;{0}&lt;/a&gt;&lt;/h3&gt;&quot;, CreateTitleElement(datasource.ToList()[index])));
                        sb.AppendLine(string.Format(&quot;&lt;div&gt;{0}&lt;/div&gt;&quot;, CreateContentItemFromModel(datasource.ToList()[index])));
                    }
                }

            return sb.ToString();
        }

        /// &lt;summary&gt;
        /// Foreach property in the model item it will be crated a desing
        /// like label: value of the property.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;The model object&lt;/typeparam&gt;
        /// &lt;param name=&quot;model&quot;&gt;The model item to treat&lt;/param&gt;
        /// &lt;returns&gt;The content for the contentItems in the accordion&lt;/returns&gt;
        private static string CreateContentItemFromModel&lt;T&gt;(T model)
        {
            StringBuilder sb = new StringBuilder();
            model.GetType().GetProperties().ToList().ForEach(property =&gt; sb.AppendLine(string.Format(@&quot;{0}: {1} &lt;BR/&gt;&quot;, property.Name, property.GetValue(model, null))));

            return sb.ToString();
        }

        /// &lt;summary&gt;
        /// Takes the first property of an object an set's it 
        /// as title.
        /// &lt;/summary&gt;
        /// &lt;typeparam name=&quot;T&quot;&gt;The model object&lt;/typeparam&gt;
        /// &lt;param name=&quot;model&quot;&gt;The model item to treat&lt;/param&gt;
        /// &lt;returns&gt;The content for the title in the accordion&lt;/returns&gt;
        private static string CreateTitleElement&lt;T&gt;(T model)
        {
            StringBuilder sb = new StringBuilder();
            PropertyInfo info = model.GetType().GetProperties().FirstOrDefault();
            string title = string.Format(@&quot;{0}: {1}&quot;, info.Name, info.GetValue(model, null));

            return title;
        }
    }
}
</pre></p>
<p>Was macht der Code?</p>
<ul>
<li>Er erstellt das Grundgerüst in welchem die Items reingepflanzt werden.</li>
<li>Er erstellt einen Titel aus dem ersten Property des Modells und setzt diesen mit dem Wert des ersten gefundenen Properties von der Modellklasse </li>
<li>Ist alles erledigt, gibt er den gesamten erstellen Markup zurück</li>
</ul>
<h4 style="color:black;">3. Die Modellklasse</h4>
<p>Meistens findet ja so ein Accordion bei einem Newsreader Verwendung. Eine solches News-Items hat die folgenden Eigenschaften:</p>
<ul>
<li>Titel</li>
<li>Inhalt</li>
<li>Veröffentlichungsdatum</li>
</ul>
<p>Nachstehend die sehr einfache Modellklasse für ein News-Item.</p>
<p><pre class="brush: csharp;">
using System;

namespace AspNetWebFromJQueryUI.Model
{
    public class NewsItem
    {
        public string Title { get; set; }

        public string Content { get; set; }

        public DateTime PublishDate { get; set; }

    }
}
</pre></p>
<p>Wirklich ganz trivial&#8230; </p>
</p>
<h4 style="color:black;">4. Einbindung in unsere Seite</h4>
<p>Die Einbindung in die Seite geschieht dann wie folgt:</p>
<ul>
<li>ResultatDiv der Seite mit einem runat=&#8221;server&#8221; versehen</li>
<li>Im Codebehind dem Control das generierte Accordion hinzufügen.</li>
</ul>
<p><pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using AspNetWebFromJQueryUI.Controls;
using AspNetWebFromJQueryUI.Model;

namespace AspNetWebFromJQueryUI
{
    public partial class Index : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            //Create dummyData
            List&lt;NewsItem&gt; datasource = new List&lt;NewsItem&gt;();

            for (int index = 0; index &lt; 10; index++)
            {
                datasource.Add(new NewsItem() { Content = string.Format(@&quot;Neuigkeitsinhalt {0}&quot;, index.ToString()), 
                                                Title = string.Format(@&quot;Neuigkeit {0}&quot;, index.ToString()), 
                                                PublishDate = DateTime.Now.Subtract(new TimeSpan(index, index, index)) });
            }
            
            this.ResultDiv.Controls.Add(AccordionHelper.CreateAccordion(datasource.OrderByDescending(n =&gt; n.PublishDate)));
            
        }
    }
}
</pre></p>
<p>Somit wird beim Starten, alles in einem schönen von JQuery verwalteten Accordion gerendet.</p>
<p>ACHTUNG: Reflection funktioniert nicht in Abhängigkeit zu den .NET Sicherheitseinstellungen, daher muss zuerst überprüft werden, ob mit Reflection gearbeitet werden kann.</p>
<p>Für Anregungen und Fragen würde ich mich auf einen Kommentar freuen</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f10%2f27%2fheirate-mich-asp-net-und-jquery-accordion%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f10%2f27%2fheirate-mich-asp-net-und-jquery-accordion%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/478/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/478/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/478/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/478/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/478/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/478/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/478/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/478/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/478/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/478/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/478/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/478/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/478/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/478/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=478&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2011/10/27/heirate-mich-asp-net-und-jquery-accordion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f10%2f27%2fheirate-mich-asp-net-und-jquery-accordion%2f" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
		<item>
		<title>Vorlagen mal anders&#8230;</title>
		<link>http://schaedlerdaniel.wordpress.com/2011/10/23/vorlagen-mal-anders/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2011/10/23/vorlagen-mal-anders/#comments</comments>
		<pubDate>Sun, 23 Oct 2011 17:24:22 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[ASP.NET /AJAX /ASP.NET MVC]]></category>
		<category><![CDATA[JavaScript / HTML /CSS /XML]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=453</guid>
		<description><![CDATA[&#8230; und die Möglichkeit auch ohne JQuery Templates auszukommen. Wie soll man das verstehen? Nun ganz einfach, wenn wir eine XML basierte Daten getriebene Webanwendung haben, so ist es nicht immer notwendig mit JQuery Templates das Verschönern der Seite vorzunehmen. Hierzu kann XML /XSL(T) ein wahres Traumpaar sein. Anhand von drei Beispielen soll dann auch [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=453&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>&#8230; und die Möglichkeit auch ohne JQuery Templates auszukommen. Wie soll man das verstehen? Nun ganz einfach, wenn wir eine XML basierte Daten getriebene Webanwendung haben, so ist es nicht immer notwendig mit JQuery Templates das Verschönern der Seite vorzunehmen. Hierzu kann XML /XSL(T) ein wahres Traumpaar sein. Anhand von drei Beispielen soll dann auch gezeigt werden wie es mit dem XMLControl von ASP.NET, rein Client seitig und rein Code-behind bewerkstelligt wird.</p>
<h5>XML Data Control</h5>
<p>Zuerst erstellen wir uns eine neue ASP.NET WebForms Anwendung und fügen in unsere Seite das XML Data Control ein.</p>
<p><pre class="brush: xml;">
&lt;%@ Page Title=&quot;Home Page&quot; Language=&quot;C#&quot; MasterPageFile=&quot;~/Site.master&quot; AutoEventWireup=&quot;true&quot;
    CodeBehind=&quot;Default.aspx.cs&quot; Inherits=&quot;XMLDataDrivenWeb._Default&quot; %&gt;

&lt;asp:Content ID=&quot;HeaderContent&quot; runat=&quot;server&quot; ContentPlaceHolderID=&quot;HeadContent&quot;&gt;
&lt;/asp:Content&gt;
&lt;asp:Content ID=&quot;BodyContent&quot; runat=&quot;server&quot; ContentPlaceHolderID=&quot;MainContent&quot;&gt;
    &lt;h2&gt;
        XML Driven Web Development
    &lt;/h2&gt;
    &lt;p&gt;
        XML DataControl to apply XSL to the XML Document.

        &lt;asp:Xml ID=&quot;XmlContainer&quot; runat=&quot;server&quot; 
            DocumentSource=&quot;~/App_Data/KontaktAngaben.xml&quot; 
            TransformSource=&quot;/App_Data/KontaktFormatierung.xsl&quot; onload=&quot;XmlContainer_Load&quot; &gt;&lt;/asp:Xml&gt;
    &lt;/p&gt;
&lt;/asp:Content&gt;
</pre></p>
<p>Damit wir das Control mit den notwendigen Daten füttern können, erstellen wir zwei Dateien im App_Code Ordner.</p>
<h6>Die XML Datendatei</h6>
<p><pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;?xml-stylesheet type=&quot;text/xsl&quot; href=&quot;KontaktFormatierung.xsl&quot;?&gt;
&lt;Kontakangaben&gt;
    &lt;Person&gt;
        &lt;Salutation&gt;Herr&lt;/Salutation&gt;
        &lt;FirstName&gt;Hans&lt;/FirstName&gt;
        &lt;LastName&gt;Müller&lt;/LastName&gt;
        &lt;Street&gt;Müllerstrasse 14&lt;/Street&gt;
        &lt;City&gt;3205 Müllhausen&lt;/City&gt;
        &lt;Phone&gt;0132542254&lt;/Phone&gt;
        &lt;Phone&gt;0123655447&lt;/Phone&gt;
        &lt;Role&gt;Präsident&lt;/Role&gt;
        &lt;EMail href=&quot;hans.mueller@muellergmbh.com&quot;&gt;Müller Hans&lt;/EMail&gt;
    &lt;/Person&gt;
    &lt;Person&gt;
        &lt;Salutation&gt;Frau&lt;/Salutation&gt;
        &lt;FirstName&gt;Heidi&lt;/FirstName&gt;
        &lt;LastName&gt;Müller&lt;/LastName&gt;
        &lt;Street&gt;Müllerstrasse 14&lt;/Street&gt;
        &lt;City&gt;3205 Müllhausen&lt;/City&gt;
        &lt;Phone&gt;0766778939&lt;/Phone&gt;
        &lt;Phone&gt;0324546688&lt;/Phone&gt;
        &lt;Role&gt;Vizepräsidentin&lt;/Role&gt;
        &lt;EMail href=&quot;heidi.mueller@muellergmbh.com&quot;&gt;Heidi Müller&lt;/EMail&gt;
    &lt;/Person&gt;
&lt;/Kontakangaben&gt;
</pre></p>
<p>Die dazugehörige XSL(T) Datei sieht dann wie folgt aus.</p>
<p><pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;xsl:stylesheet version=&quot;2.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; &gt;
    &lt;!-- Define the outputtype --&gt;
    &lt;xsl:output method=&quot;html&quot;/&gt;
    &lt;xsl:template match=&quot;/*&quot;&gt;
        &lt;table class=&quot;tableStyle&quot;&gt;
            &lt;tr&gt;
                &lt;th&gt;Kontaktangaben&lt;/th&gt;
                &lt;th&gt;Rolle&lt;/th&gt;
                &lt;th&gt;Telefon(e)&lt;/th&gt;
                &lt;th&gt;E-Mail&lt;/th&gt;
            &lt;/tr&gt;
            &lt;xsl:for-each select=&quot;Person&quot;&gt;
                &lt;tr&gt;
                    &lt;td&gt;
                        &lt;xsl:value-of select=&quot;FirstName&quot;/&gt; &lt;xsl:value-of select=&quot;LastName&quot;/&gt;
                        &lt;br/&gt;
                        &lt;xsl:value-of select=&quot;Street&quot;/&gt;
                        &lt;br/&gt;
                        &lt;xsl:value-of select=&quot;City&quot;/&gt;
                    &lt;/td&gt;
                    &lt;td&gt;
                        &lt;xsl:value-of select=&quot;Role&quot;/&gt;
                    &lt;/td&gt;
                    &lt;td&gt;
                        &lt;ul&gt;
                            &lt;xsl:for-each select=&quot;./Phone&quot;&gt;
                                &lt;li&gt;
                                        &lt;xsl:value-of select=&quot;.&quot;/&gt;                            
                                &lt;/li&gt;
                            &lt;/xsl:for-each&gt;
                        &lt;/ul&gt;
                    &lt;/td&gt;
                    &lt;td&gt;
                        &lt;a&gt;
                            &lt;!-- The xml attribute sets the value for the &lt;a&gt; tag and adds an attribute to it--&gt;
                            &lt;xsl:attribute name=&quot;href&quot;&gt;mailto:&lt;xsl:value-of select=&quot;../Person/EMail/@href&quot;/&gt;&lt;/xsl:attribute&gt;
                            &lt;xsl:value-of select=&quot;../Person/FirstName&quot;/&gt;
                            &lt;xsl:value-of select=&quot;../Person/LastName&quot;/&gt;
                        &lt;/a&gt;                                                                                                                               
                    &lt;/td&gt;
                &lt;/tr&gt;
            &lt;/xsl:for-each&gt;
        &lt;/table&gt;
    &lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;
</pre></p>
<p>Wichtig ist dass der output mode auf HTML gestellt wird, ansonsten wird es mit dem Link in der E-Mail Adresse schwierig diesen korrekt darzustellen.</p>
<p>Der Ouput wird dann automatisch vom XML Control gerendert.</p>
<h5>Reine clientseitige Verarbeitung</h5>
<p>Eine weitere Möglichkeit, für alle die JavaScript über alles lieben, ist mit JQuery die Transformation vorzunehmen.</p>
<p><pre class="brush: xml;">
&lt;%@ Page Title=&quot;&quot; Language=&quot;C#&quot; MasterPageFile=&quot;~/Site.Master&quot; AutoEventWireup=&quot;true&quot; CodeBehind=&quot;Index.aspx.cs&quot; Inherits=&quot;XMLDataDrivenWeb.Index&quot; %&gt;
&lt;asp:Content ID=&quot;Content1&quot; ContentPlaceHolderID=&quot;HeadContent&quot; runat=&quot;server&quot;&gt;    
    &lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot;&gt;
        var xml = null;
        var xsl = null;

        $(document).ready(function () {

            $.ajax({
                type: &quot;GET&quot;,
                url: &quot;XMLData/KontaktAngaben.xml&quot;,
                data: &quot;{}&quot;,
                contentType: &quot;application/xml; charset=utf-8&quot;,
                dataType: &quot;xml&quot;,
                success: function (msg) {
                    xml = msg;
                },
                error: function (msg) {
                    alert(msg);
                }
            });

            $.ajax({
                type: &quot;GET&quot;,
                url: &quot;XMLData/KontaktFormatierung.xsl&quot;,
                data: &quot;{}&quot;,
                contentType: &quot;application/xml; charset=utf-8&quot;,
                dataType: &quot;xml&quot;,
                success: function (msg) {
                    xsl = msg;
                    TransformXml();
                },
                error: function (msg) {
                    alert(msg);
                }
            });
        });

        function TransformXml() {

            $('#ResultDiv')[0].innerHTML = xml.transformNode(xsl);
        }
    &lt;/script&gt;
&lt;/asp:Content&gt;
&lt;asp:Content ID=&quot;Content2&quot; ContentPlaceHolderID=&quot;MainContent&quot; runat=&quot;server&quot;&gt;
&lt;div id=&quot;ResultDiv&quot;&gt;

&lt;/div&gt;
&lt;/asp:Content&gt;
</pre></p>
<h5>Code behind Bearbeitung</h5>
<p>Zu guter letzt kann alles natürlich mit C# erledigt werden, was eigentlich auch keine Hexerei darstellt.</p>
<p><pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
using System.Xml;
using System.Xml.Xsl;
using System.IO;
using System.Text;

namespace XMLDataDrivenWeb
{
    public partial class PureDotNet : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            GetDocument();
        }

        private void GetDocument()
        {
            XmlDocument x = new XmlDocument();
            x.Load(XmlReader.Create(Server.MapPath(@&quot;/App_Data/Kontaktangaben.xml&quot;)));

            XslCompiledTransform transform = new XslCompiledTransform();
            transform.Load(XmlReader.Create(Server.MapPath(@&quot;/App_Data/KontaktFormatierung.xsl&quot;)));
            transform.Transform(x.BaseURI, Server.MapPath(@&quot;/App_Data/Result.xml&quot;));

            // Loading the generated result file
            string[] xmlResult = File.ReadAllLines(Directory.GetFiles(Server.MapPath(@&quot;/App_Data&quot;)).ToList().Where(f =&gt; f.ToLower().Contains(&quot;result&quot;)).FirstOrDefault());
            
            xmlResult.ToList().ForEach(s =&gt;
                                           {
                                               ResultDiv.InnerHtml += s;
                                           });
            
        }
    }
}
</pre></p>
<p>Zu guter letzt soll das Ganze auch ein wenig ansprechend aussehen. Dies machen wir wie gewohnt über CSS. Die folgenen Styles werden nachfolgend aufgeführt:</p>
<p><pre class="brush: css;">
th 
{
    font-size: x-large;
    font-family: cursive;
    background-color: silver;  
    padding: 2px;    
}

td 
{
    font-size:medium;
    font-style: normal;
    border: thin solid black;
}
</pre></p>
<p>Wie wir sehen gibt es immer mehrere Wege nach Rom und das Ganze, ach Microsoft will C# etc. abschaffen und nur noch Richtung JavaScript gehen, eher übertrieben. Es kommt immer noch auf uns Entwickler an wie wir eine Lösung zu einem Problem finden.</p>
<p>Anhand dieses einfachen Beispiels sehen wird, dass es möglich ist für ein Problem die eine oder andere Lösung zu wählen, je nachdem was einem beliebt.</p>
<p>Für Anregungen und Kritik bin ich gerne offen</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f10%2f23%2fvorlagen-mal-anders%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f10%2f23%2fvorlagen-mal-anders%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/453/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/453/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/453/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/453/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/453/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/453/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/453/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/453/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/453/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/453/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/453/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/453/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/453/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/453/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=453&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2011/10/23/vorlagen-mal-anders/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f10%2f23%2fvorlagen-mal-anders%2f" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
		<item>
		<title>ASP.NET Optimization Bundling</title>
		<link>http://schaedlerdaniel.wordpress.com/2011/09/18/asp-net-optimization-bundling/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2011/09/18/asp-net-optimization-bundling/#comments</comments>
		<pubDate>Sun, 18 Sep 2011 10:08:26 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[ASP.NET /AJAX /ASP.NET MVC]]></category>
		<category><![CDATA[ASP.NET 4.0]]></category>
		<category><![CDATA[ASP.NET 4.5]]></category>
		<category><![CDATA[ASP.NET Optimization]]></category>
		<category><![CDATA[CSS Minifiyng]]></category>
		<category><![CDATA[CSS minimieren]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JavaScript / HTML /CSS /XML]]></category>
		<category><![CDATA[JavaScript Minifying]]></category>
		<category><![CDATA[JavaScript Minimierung]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=429</guid>
		<description><![CDATA[Im ganzen HTML 5/ CSS3 etc. Gepredige habe ich doch noch was gefunden was im ASP.NET 4.5 kommen wird. Nun wenn man NuGet mal durchsucht, dann wird man es auch für ASP.NET 4.0 finden. Das Optimization Bundling (Im .NET 4.0 wird es mit Microsoft.Web.Optimization, und dann später mit System.Web.Optimization referenziert). Das Video ASP.NET 4.5 loves [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=429&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Im ganzen HTML 5/ CSS3 etc. Gepredige habe ich doch noch was gefunden was im ASP.NET 4.5 kommen wird. Nun wenn man NuGet mal durchsucht, dann wird man es auch für ASP.NET 4.0 finden. Das Optimization Bundling (Im .NET 4.0 wird es mit Microsoft.Web.Optimization, und dann später mit System.Web.Optimization referenziert). Das Video <a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-796T" target="_blank">ASP.NET 4.5 loves HTML5, CSS3 &amp; JavaScript</a> habe ich als sehr informativ empfunden, obwohl nicht wirklich viel neues kommt, oder die Änderunge nicht gerade revolutionär sind.</p>
<p>Damit ich das Pack auch produktiv nutzen kann, habe ich es mal analog dem Video nachgespielt, damit ich, falls ich in meinem gesetzten Alter, nicht mehr alles auswendig weiss, nachlesen kann. Also anfangen, ich von meiner Warte aus entwickle immer noch mit ASP.NET WebForms entgegen dem Hype zu MVC. Also starten wir wie folgt, indem wir eine neue WebForms Solution erstellen.</p>
<p>Kurzübersicht was wir alles machen werden</p>
<ul>
<li>Erstellen einer ASP.NET 4.0 Solution</li>
<li>Installation des Optimization Bundling per NuGet</li>
<li>Analyse Vorher /Nachher</li>
<li>Fazit</li>
</ul>
<p>Also fangen wir damit an:</p>
<h3>Erstellen einer ASP.NET Solution</h3>
<p>Wir starten unser Visual Studio 2010 (Express/Professional/Premium/Ultimae), wählen die Rubrik Web und dann die Vorlage für ASP.NET WebForms. Ein Klick darauf und unsere Solution ist erstellt.</p>
<p><img src="https://byfiles.storage.live.com/y1pTvdxKpi-cdwvi_KtR87IIh3rbIPackUG9rf1fO-VGOT_9sboltT0YI6kSp7RmyVGTdNbRmIfCpA/Frisch%20erstelle%20Solution%20ASP.NET%20Optimization%20Bundling.jpg?psid=1" /></p>
</p>
<h3>Installieren des ASP.NET Optimization &#8211; Bundling</h3>
<p>Ist eigentlich keine Hexerei und kann bequem über NuGet erfolgen, dass dann alle notwendigen Schritte übernimmt, und auch die Referenzen im Projekt richtig setzt.</p>
<p><img src="https://byfiles.storage.live.com/y1pHL7UKB50SawiDa3qLnxkn7DE_q2XFgJ7QdrM4XpHQtUzAa3c6Rl0PgFG1q1N0KTRbB9IqgKsuVI/NuGet%20Package%20ASP.NET%20Optimization%20Bundling.jpg?psid=1" /></p>
<p>Nach der Installation ist alles bereit, damit wir unsere ASP.NET Lösung optimieren können</p>
<h3>Analyse  Vorher /Nachher</h3>
<p>In diesem kleinen Beispiel hole ich per XHTML-Request drei Personen aus meinem Model und zeige diese an (der XHTML Request kann in seiner Dauer variieren, da interessiert uns die Zeit primär erstmal nicht.) Starten wir die jungfräuliche Solution und drücken im IE9 die Developer Tools mit F12 sehen wir folgende Verkehr:</p>
<p><img src="https://byfiles.storage.live.com/y1pKIRQl4cRQj_vGMJ64It_WBoX5oKx2urrwgqasVE7cChTrVUfUgUXWMr9cY9l4ZcNjD73Aia9vz8/IE9%20Network%20Traffic%20before%20ASP.NET%20Optimization%20Bundling.jpg?psid=1" /></p>
<p>Interssant sind folgende zwei Punkte</p>
<ul>
<li>/Styles/Site.css</li>
<li>/Scripts/jquery-1.4.4.min.js</li>
</ul>
<p>Nun, da wir das Optimization Pack bereits mit NuGet installiert haben, entfällt eine Referenz darauf, denn diese ist bereits vorhanden. Was wir noch machen müssen ist in der Global.asax dafür sorgen, dass die Dateien auch wirklich gebündelt übertragen werden. </p>
<p><pre class="brush: csharp;">
        void Application_Start(object sender, EventArgs e)
        {
            BundleTable.Bundles.EnableDefaultBundles();
            Bundle myBundle = new Bundle(&quot;~/Scripts&quot;, typeof(JsMinify));
            myBundle.AddFile(&quot;~/Scripts/jquery-1.4.4.min.js&quot;);
            myBundle.AddFile(&quot;~/Scripts/PersonScript.js&quot;);
        }
</pre></p>
<p>Anschliessend passen wir in der Site.Master die Referenz auf JQuery an:</p>
<p>Vorher:<br />
<pre class="brush: xml;">
&lt;script type=&quot;text/javascript&quot; src=&quot;Scripts/jquery-1.4.4.min.js&quot;&gt;&lt;/script&gt;
</pre>
</p>
<p>Nachher:<br />
<pre class="brush: xml;">
&lt;script type=&quot;text/javascript&quot; src=&quot;Scripts/js&quot;&gt;&lt;/script&gt;
</pre></p>
<p>Anschliessend starten wir unsere Solution wieder und analysieren mit den Developer Tools nocheinmal den Netzwerk-Verkehr. Und siehe da, die zwei vorherigen Kandidaten (Scripts und CSS) haben einen kleinen Hypersprung ausgefürht</p>
<p><img src="https://byfiles.storage.live.com/y1pBqMsDvfJXHP2Y4yzhEMMGhNBlRNX2okDUnkQgMEmH4qatz09s-eNWaHe5zPz1pjU0NRts_1G6ds/IE9%20Network%20Traffic%20after%20ASP.NET%20Optimization%20Bundling.jpg?psid=1" /></p>
<h3>Fazit</h3>
<p>Wir haben einen Performance Anstieg erhalten, der unsere Webseite schneller übertragen lässt. In diesem sehr, sehr kleinen Beispiel und auch dem localhost mögen die Einsparungen vielleicht nicht enorm sein, betrachtet es man aber so, dass viele Wege zu einer Webseite führen können und nicht immer alles übertragen wird (Package los), dann ist dies sicher ein guter Weg die Daten zu komprimieren.</p>
<p>
Bei sehr vielen JavaScript- und CSS-Dateien lohnt es sich auf alle Fälle. Die Demo Lösung kann <a href="https://skydrive.live.com/?cid=ce67b0bb158a026d&amp;sc=documents&amp;id=CE67B0BB158A026D%214391" target="_blank">hier</a> heruntergeladen werden. (Das MVC Beispiel wird im Video erläuter, sodass ich dies nicht erstellt habe.)</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f09%2f18%2fasp-net-optimization-bundling%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f09%2f18%2fasp-net-optimization-bundling%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/429/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/429/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/429/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/429/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/429/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/429/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/429/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/429/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/429/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/429/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/429/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/429/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/429/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/429/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=429&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2011/09/18/asp-net-optimization-bundling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="https://byfiles.storage.live.com/y1pTvdxKpi-cdwvi_KtR87IIh3rbIPackUG9rf1fO-VGOT_9sboltT0YI6kSp7RmyVGTdNbRmIfCpA/Frisch%20erstelle%20Solution%20ASP.NET%20Optimization%20Bundling.jpg?psid=1" medium="image" />

		<media:content url="https://byfiles.storage.live.com/y1pHL7UKB50SawiDa3qLnxkn7DE_q2XFgJ7QdrM4XpHQtUzAa3c6Rl0PgFG1q1N0KTRbB9IqgKsuVI/NuGet%20Package%20ASP.NET%20Optimization%20Bundling.jpg?psid=1" medium="image" />

		<media:content url="https://byfiles.storage.live.com/y1pKIRQl4cRQj_vGMJ64It_WBoX5oKx2urrwgqasVE7cChTrVUfUgUXWMr9cY9l4ZcNjD73Aia9vz8/IE9%20Network%20Traffic%20before%20ASP.NET%20Optimization%20Bundling.jpg?psid=1" medium="image" />

		<media:content url="https://byfiles.storage.live.com/y1pBqMsDvfJXHP2Y4yzhEMMGhNBlRNX2okDUnkQgMEmH4qatz09s-eNWaHe5zPz1pjU0NRts_1G6ds/IE9%20Network%20Traffic%20after%20ASP.NET%20Optimization%20Bundling.jpg?psid=1" medium="image" />

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f09%2f18%2fasp-net-optimization-bundling%2f" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
		<item>
		<title>Mein erstes Mal&#8230;.</title>
		<link>http://schaedlerdaniel.wordpress.com/2011/08/21/mein-erstes-mal/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2011/08/21/mein-erstes-mal/#comments</comments>
		<pubDate>Sun, 21 Aug 2011 10:00:04 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=417</guid>
		<description><![CDATA[an der See # Party in Kreuzlingen war super und ich werde auf jeden fall, sollte sie auch nächstes Jahr statt finden wieder hingegen Wieso denn? Ganz einfach man sieht dort wirklich alle die in der Community aktiv sind und mit denen man per Facebook, Twitter oder irgendeinem Social Tool in Kontakt steht und kann [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=417&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>an der <a href="http://www.seesharpparty.de/de/Start/page38393.htm" title="See # Party" target="_blank">See # Party</a> in Kreuzlingen war super und ich werde auf jeden fall, sollte sie auch nächstes Jahr statt finden wieder hingegen </p>
<p>Wieso denn? Ganz einfach man sieht dort wirklich alle die in der Community aktiv sind und mit denen man per Facebook, Twitter oder irgendeinem Social Tool in Kontakt steht und kann ein wenig fachsimpeln oder auch über Gott und die Welt reden. Schon fast familiäre Stimmung </p>
<p>
<h1>Welche Session&#8217;s habe ich den besucht?</h1>
</p>
<p>Da die Autofahr ziemlich reibungslos verlief, trudelten ich und mein Fahrer bereits um 07.45 Uhr in Kreuzlingen ein. Ein bisschen früh für den Einlass. </p>
<p>Um 08.25 Uhr blickten wir noch mal rein und konnten uns dann die Badges für SFr. 110.&#8211; (was ich für einen sehr günstigen Preis halte) abholen. </p>
<p>
<h2>Begrüssungsfazit</h2>
</p>
<p>War nicht so show geladen wie an den Techdays und dass macht die Veranstaltung auch so sympathisch! Weiter so Jungs!</p>
<p>
<h2>Keynote</h2>
</p>
<p>Die Keynote war mal ein ganz anderes Thema als, C#, Silverlight und dergleichen. Es ging um den Stress den man sich selber machen kann, oder der durch äussere Faktoren ausgelöst wird. Sehr interessant fand ich dann auch wie sich der Wandel in der IT-Branche vollzogen hat (bis auf ein paar Namensänderungen der Ziele und Verschiebung unter den Top 15 Themen gabs keine grossen Wandel).
<p>Nun ja, da ich meine Mail&#8217;s erst am Morgen und dann wieder am Abend kontrolliere und mein Handy so oder so auf lautlos eingestellt ist, hält sich mein Stressfaktor zum Glück in Grenzen. </p>
<p>Danach mal den Plan hervorgenommen und die Session&#8217;s gemerkt. Lustigerweise hatte ich 4 mal die Gelegenheit im gleichen Raum die Vorlesungen zu geniessen, was wiederum der Suche für die Örtlichkeit der nächsten Session, erheblich vereinfacht.</p>
<p>
<h2>Die Sessions</h2>
<p><p>Beruflich habe ich eigentlich immer mit <a href="http://www.asp.net" target="_blank">ASP.NET WebForms</a> zu tun. Da auch ich im Wandel bin habe ich die Sessions die sich mit ASP.NET befassten aussen vor gelassen und richtetet meinen Fokus eher Silverlight, XAML, Workflow Foundation.</p>
<p>
<h3>XAML Deep Dive &#8211; Mehr als nur WPF</h3>
</p>
<p>Dieser Vortrag war sehr lehrreich. Ich fand es super, dass die Einsatzmöglichkeiten von XAML, auch ausserhalb von WPF /Silverlight /Workflow Foundation verwendet werden kann und es ein offener Standard ist. Mein Fazit zu dieser Session: Gut</p>
<p>Falls man die Folien nicht herunterladen kann, findet man auf <a href="http://www.neovelop.de/blog/xaml-mehr-als-nur-eine-einfache-beschreibungssprache" Title="XAML mehr als nur WPF" target="_blank">XAML &#8211; Mehr als nur eine einfache Beschreibungssprache</a> einen sehr guten Blogartikel.</p>
<p>
<h3>Windows Communication Foundation 4.0 &#8211; Die Neuerungen</h3>
</p>
<p>Die Session hat sich mit den Neuerungen der Windows Communication Foundation 4.0 befasst und deren Änderungen die eingeflossen sind. Die Codebeispiele, liefen zu 80%. Es war für mich in dieser Hinsicht schade dass nicht alles funktioniert hat, aber einen positiven Teil kann man dem Ganzen auch abgewinnen: So qualifiziert und auch hohes Fachwissen die Speaker auch habe, auch sie sind Menschen denen Fehler passieren können und das ist sicherlich auch ein guter Aspekt. Schön fand ich wie die einzelnen WCF Neuerungen vorgeführt worden sind. Der Router blieb mir besonders, wegen Performanceeinschränkunen wenn man nicht alles bachtet im Gedächtnis und ich denke dass man dann diesen auch eher seltener einsetzen wird.</p>
<p>Mein Fazit zu dieser Session: Gut (Ich wusste gar nicht das hochdeutsch eine gleiche Geschwindigkeit wie Französisch an den Tag legen kann <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  )</p>
<p>
<h3>Accessebility</h3>
</p>
<p>Auf diese Session habe ich mich besonders gefreut, zumal man den Jürgen mal live sehen konnte. Die Aspekte unter welchen man eine barriere freie Webseite baut sind sehr gut dargestellt worden. Auch die anschliessende Diskussion und Fragerunde war sehr aufschluss- und lehrreich. Was habe ich für mich mitgenommen? Am besten Back to the roots, die Webseite in purem HTML erstellen und dynamische Inhalte soweit es geht per CSS zu erstellen. Eine weitere Erkenntnis von mir auch ist dass ASP.NET WebForms eher weniger dazu geeignet ist mit den Boardmitteln einen solche barriere freie Webseite zu erstellen, da muss man eben bei der Generierung der Controls auf der Seite Einfluss nehmen und so kann man in ASP.NET MVC das Ziel einer barriere freien optimaler erreichen.</p>
<p>Mein Fazit zu dieser Session: Gut (ein paar Einstiegslacher lockerten das ganze ein wenig auf (obwohl es wohl Insiderlacher von Jürgen und Karsten waren)).</p>
<p>
<h3>User Interface Pattern mit Silverlight</h3>
</p>
<p>Eigentlich hätte ich es mir sparen können diese Session zu besuchen&#8230;. Dachte ich zumindest in den ersten 5 Minuten. Aber weit gefehlt: Denn es ist immer wieder gut wenn man die Do&#8217;s und Dont&#8217;s der UI-Erstellung auf erfrischende Art präsentiert bekommt. Der Sprecher war sehr versiert und auch die Fokusierung von Inhalten durch das menschliche Auge hat, hat mir einen anderen Einblick gegeben.</p>
<p>Rein theoretisch hätte man aber nicht unbedingt <a href="http://www.silverlight.net" title="Silverlight" target="_blank">Silverlight</a> nehmen müssen.</p>
<p>Mein Fazit zu dieser Session: Gut </p>
<p>
<h3>Workflow Foundation 4.0</h3>
</p>
<p>Das Ziel war eine Getting Started Session zu machen die einen Einblick in die Workflow Fondatin 4.0 bieten soll. Dieser Einblick ist nur teilweise geglückt. Dies hat zum einen damit zu tun, dass Features die selbstverständlich sind, also das suchen von Namepsaces à la Expression Blend, nicht wirklich neu waren. Es hätte mir auch mehr gefallen, wenn man eventuell nicht dass klassische Hellow World Beispiel genommen hätte, sonder ein wenig einen kleinen Geschäftsfall erstellt hätte.</p>
<p>Mein Fazit zu dieser Session: Schlecht</p>
<p>
<h2>Schlusswort</h3>
</p>
<p>Ich finde es war ein gelungeren Anlass und es hätte auch paar mehr Entwickler kommen können. Meiner Meinung hat ausser berufliche Besuch an einer Koferenz nicht&#8217;s mit Geek zu tun sondern mit Interesse an der Arbeit die man macht. Ein Koch der leidenschaftlich kocht, der wird auch zuhause noch gerne kochen und sich auch ausserhalb der Arbeitszeit weiter bilden, weil es ihm Spass macht. Wenn man das nun so auf die Entwickler abmüntzen möchte, dann könnte man es überspitzt sagen, dass diese den Job gar nicht gerne machen (ich weiss es ist überspitzt, aber ich denke dass entspricht so dem Wahrheit). </p>
<p>Auch möchte ich erwähnen dass die geübte Kritik an den Sessions keinesfalls persönlich gemeint sind. Ich selber könnte nicht vor so vielen reden ohne Schweissperlen zu entwickeln, also jedem der vor so vielen Leuten redet, der ist schon, unabhängig von der Kritik, ein Gewinner. </p>
<p>Es würde mich sehr freuen, wenn auch nächstes Jahr wieder eine See # Party statt finden und vielleicht ein wenig mehr Entwickler den Weg dorthin finden würden.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/417/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/417/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/417/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/417/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/417/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/417/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/417/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/417/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/417/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/417/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/417/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/417/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/417/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/417/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=417&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2011/08/21/mein-erstes-mal/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>
	</item>
		<item>
		<title>Prism 4.0 Navigation</title>
		<link>http://schaedlerdaniel.wordpress.com/2011/07/12/prism-4-0-navigation/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2011/07/12/prism-4-0-navigation/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 11:17:06 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[WPF /SilverLight]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=394</guid>
		<description><![CDATA[Momentan sitze ich gerade an der Navigation für Prism 4.0. Der Blogpost auf MSDN-Blogs war dafür sehr hilfreich. Mein Ziel war es wie so etwas darzustellen: - Erste Seite - Zweite Seite - Dritte Seite Diese sollten von sich aus auf die nächste navigieren können. Hierfür wurden die ViewModel erstellt die von der ViewModelBase erben. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=394&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Momentan sitze ich gerade an der Navigation für <a href="http://compositewpf.codeplex.com/" title="Prism 4.0" target="_blank">Prism 4.0</a>. Der Blogpost auf <a href="http://blogs.msdn.com/b/kashiffl/archive/2010/10/04/prism-v4-region-navigation-pipeline.aspx" title="MSDN-Blogs" target="_blank">MSDN-Blogs</a> war dafür sehr hilfreich. Mein Ziel war es wie so etwas darzustellen:<br />
- Erste Seite<br />
- Zweite Seite<br />
- Dritte Seite</p>
<p>Diese sollten von sich aus auf die nächste navigieren können. Hierfür wurden die ViewModel erstellt die von der ViewModelBase erben. Wichtig hierbei ist, dass die ViewModelBase Klasse das Interface INavigateAsync implementiert (gemäss diesem <a href="http://i.msdn.microsoft.com/dynimg/IC448592.png" title="Flow-Diagramm" target="_blank">Flow-Diagramm</a>, das einzig zwingend notwendige für die Navigation unter Prism 4.0).</p>
<p>Damit die Views an der Navigation partizipieren können, dürfen sie nicht wie nachstehend in der InitializeModule-Methode registriert werden:</p>
<h5> Falsch </h5>
<p><pre class="brush: csharp;">
regionManager.Regions[&quot;MainRegion&quot;].Add(new MainView(), &quot;MainView&quot;);
</pre></p>
<h5> Richtig </h5>
<p><pre class="brush: csharp;">
regionManager.Regions[&quot;MainRegion&quot;].RequestNavigate(new Uri(&quot;MainView&quot;, UriKind.Relative));
</pre><br />
Der kleine, aber feine Unterschied liegt darin, dass mit RequestNavigate bereits das NavigationJournal &#8220;gefüttert&#8221; wird und man später darauf zugreifen kann. Der Nachteil an der Sache ist, dass die Views nicht in der Views-Collection der Region mit einem Schlüssel auffindbar sind.</p>
<p>Ein kleines Beispiel soll zeigen, wie man auf einfache Art und Weise eine Navigation mit den ViewModels in Prism erstellt.</p>
<p>Schlussendlich soll von Seite eins bis Seite 3 navigiert werden können, hierfür kann man wie folgt vorgehen:<br />
1.) Erstellen eines WPF Projektes (Referenzen auf Prism und Prism Unity Extension mit NuGet durchführen)<br />
2.) Erstellen eines WPF Projektes (In den Eigenschaften keine Windows Applikation auswählen, sondern anschliessend die Main.xaml und die App.xaml löschen, NuGetReferenzen wie vorhin hinzufügen).</p>
<p>Anschliessend kann mit dem WPF Projekt begonnen werden:<br />
1.) Öffnen Sie die App.xaml und ändern sie diese so ab, dass sie wie unten aufgeführt aussieht (Ansonsten wird das MainWindow zwei mal gestartet).<br />
<pre class="brush: xml;">
&lt;Application x:Class=&quot;Prism.NavigationTryOut.App&quot;
             xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;&gt;
    &lt;Application.Resources&gt;
         
    &lt;/Application.Resources&gt;
&lt;/Application&gt;
</pre></p>
<p>2.) Erstellen Sie eine Klasse die von UnityBootstrapper erbt und implementieren diese wie folgt:<br />
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.UnityExtensions;
using System.Windows;
using Microsoft.Practices.Unity;
using Microsoft.Practices.ServiceLocation;
using Prism.NavigationTryOut.NavigationModule;

namespace Prism.NavigationTryOut
{
    public class BootStrapper : UnityBootstrapper
    {
        protected override void InitializeShell()
        {
            base.InitializeShell();
            App.Current.MainWindow = (Window)Shell;
            App.Current.MainWindow.Show();
        }

        protected override DependencyObject CreateShell()
        {
            return ServiceLocator.Current.GetInstance&lt;Shell&gt;();
        }

        protected override void ConfigureModuleCatalog()
        {
            base.ConfigureModuleCatalog();       

            Microsoft.Practices.Prism.Modularity.ModuleCatalog catalog = (Microsoft.Practices.Prism.Modularity.ModuleCatalog)this.ModuleCatalog;

            // Nicht geeignet! Nehmen Sie stattdessen die Möglichkeit den catalog per XAML auszulesen.
            catalog.AddModule(typeof(NavigationModuleInitializer));
        }

        protected override void InitializeModules()
        {
            base.InitializeModules();
            
        }
    }
}
</pre><br />
Anmerkung: Zum jetztigen Zeitpunkt kann noch nicht kompilliert werden.</p>
<p>3.) Öffnen Sie die App.xaml.cs Codebehind und ändern Sie diese wie folgt ab:<br />
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;

namespace Prism.NavigationTryOut
{
    /// &lt;summary&gt;
    /// Interaction logic for App.xaml
    /// &lt;/summary&gt;
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            BootStrapper bootstrapper = new BootStrapper();
            bootstrapper.Run();
        }
    }
}
</pre><br />
Wir sind fast am Ziel und müssen noch zwei kleine Sachen erledigen. Die eine wäre<br />
4.) Benennen Sie die Datei MainWindow.xaml um in Shell und machen Sie dies auch im Codebehind mit der von Visual Studio 2010 gebotenen Funktion &#8220;refactore&#8221; &#8211;&gt; rename.</p>
<p>Jetzt haben wir das StartUp Projekt fertig konfiguriert und müssen uns an das zu implementierende Module zuwenden (ACHTUNG: in diesem Post wird eine Referenz, der Einfachheit halber auf das Module erstellt, was in der Praxis vermieden werden sollte).</p>
<p>5.) Erstellen Sie eine Klasse die das Initialisieren des Moduls und das Registrieren der Views übernimmt.<br />
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Prism.Regions;
using System.Windows.Input;
using Prism.NavigationTryOut.NavigationModule.Views;
using System.Windows.Controls;

namespace Prism.NavigationTryOut.NavigationModule
{
    public class NavigationModuleInitializer : IModule
    {
        private readonly IUnityContainer container;
        private readonly IRegionManager regionManager;      

        public NavigationModuleInitializer(IUnityContainer container, IRegionManager regionManager)
        {
            this.container = container;
            this.regionManager = regionManager;
        }

        public void Initialize()
        {
            this.container.RegisterType&lt;Object, MainView&gt;(&quot;MainView&quot;);
            this.container.RegisterType&lt;Object, ViewOne&gt;(&quot;ViewOne&quot;);
            this.container.RegisterType&lt;Object, ViewTwo&gt;(&quot;ViewTwo&quot;);
            
            regionManager.Regions[&quot;MainRegion&quot;].RequestNavigate(new Uri(&quot;MainView&quot;, UriKind.Relative));
        }
    }
}
</pre></p>
<p>6.) Anschliessen können wir auch gleich die ViewModelBase Klasse erstellen, die von jeder anderen ViewModel Klasse geertbt wird. Diese sieht dann so aus:<br />
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.ServiceLocation;
using System.Windows.Input;
using Microsoft.Practices.Unity;

namespace Prism.NavigationTryOut.NavigationModule
{
    public class ViewModelBase : INavigateAsync 
    {        
        private IRegionManager regionManager;
        private IUnityContainer container;
        protected IRegion mainRegion;

        /// &lt;summary&gt;
        /// Das NavigationsJournal beeinhaltet alle relevanten Uri's
        /// die in der Navigation betroffen sind und waren.
        /// &lt;/summary&gt;
        public virtual IRegionNavigationJournal NavigationJournal
        {
            get;
            private set;
        }

        /// &lt;summary&gt;
        /// Command für das Anzeigen der nächsten Seite.
        /// &lt;/summary&gt;
        public virtual ICommand NextCommand
        {
            get;
            private set;
        }

        /// &lt;summary&gt;
        /// Command für das Schliessen der Applikation.
        /// &lt;/summary&gt;
        public virtual ICommand CloseCommand
        {
            get;
            private set;
        }

        /// &lt;summary&gt;
        /// Command für das Navigieren zur vorherigen Seite.
        /// &lt;/summary&gt;
        public virtual ICommand PreviousCommand
        {
            get;
            private set;
        }        

        /// &lt;summary&gt;
        /// Konstruktor lokalisiert mit dem ServiceLocator bereits instantiierte Klassen
        /// die mit dem UnityContainer bereits registriert worden sind.
        /// &lt;/summary&gt;
        public ViewModelBase()
        {
            regionManager = ServiceLocator.Current.GetInstance&lt;IRegionManager&gt;();
            IRegionNavigationService navigationService = regionManager.Regions[&quot;MainRegion&quot;].NavigationService;           

            this.NavigationJournal = navigationService.Journal;
            mainRegion = regionManager.Regions[&quot;MainRegion&quot;];
        }

        public void RequestNavigate(Uri target, Action&lt;NavigationResult&gt; NavigationCallback)
        {
            regionManager.RequestNavigate(mainRegion.Name, target, NavigationCallback);
        }

        /// &lt;summary&gt;
        /// Notwendige Methode um auf .RequestNavigate reagiren zu können.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;res&quot;&gt;&lt;/param&gt;
        public void NavigationCallback(NavigationResult res)
        {
            ClearUnusedViewsFromReagion(mainRegion, res.Context.Uri.OriginalString);
        }

        /// &lt;summary&gt;
        /// Diese Methode übernimmt, das Entfernen von Views, die nicht mehr angezeigt
        /// werden sollen. Da die Views nicht mit .Add zur Region hinzugefügt wurden, 
        /// werden hier die Namen mit dem ViewModel verglichen.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;region&quot;&gt;&lt;/param&gt;
        /// &lt;param name=&quot;viewName&quot;&gt;&lt;/param&gt;
        protected void ClearUnusedViewsFromReagion(IRegion region, string viewName)
        {
            foreach (var view in region.Views.ToList())
            {
                if (!view.GetType().Name.Contains(viewName))
                {
                    region.Remove(view);
                }                
            }
        }
    }
}
</pre></p>
<p>7.) Erstellen der VieModels (vgl. SourceCode zum herunterladen). Exemplarische zeige ich hier nur das erste ViewModel (die anderen sind ähnlich aufgebaut)<br />
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;

namespace Prism.NavigationTryOut.NavigationModule.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        private ICommand _nextCommand;
        public override ICommand NextCommand
        {
            get { return _nextCommand; }
        }

        private ICommand _closeCommand;
        public override ICommand CloseCommand
        {
            get { return _closeCommand; }
        }

        private ICommand _previousCommand;
        public override ICommand PreviousCommand
        {
            get { return _previousCommand; }
        }

        public MainViewModel()
        {
            _nextCommand = new DelegateCommand(new Action(OnNavigateNext));
            _closeCommand = new DelegateCommand(new Action(OnClose));
            _previousCommand = new DelegateCommand(new Action(OnPrevious));
        }

        private void OnNavigateNext()
        {
            base.RequestNavigate(new Uri(&quot;ViewOne&quot;, UriKind.Relative), base.NavigationCallback);
        }

        private void OnClose()
        {
            
        }

        private void OnPrevious()
        {
            base.NavigationJournal.GoBack();
        }
    }
}
</pre><br />
Die entsprechende View (die anderen zeigen nur ein aderes Bild an) werden wie in Punkt 8.) erstellt:<br />
<pre class="brush: xml;">
&lt;UserControl x:Class=&quot;Prism.NavigationTryOut.NavigationModule.Views.MainView&quot;
             xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
             xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot; 
             xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot; 
             mc:Ignorable=&quot;d&quot; 
             xmlns:mvvm=&quot;clr-namespace:Prism.NavigationTryOut.NavigationModule.ViewModel&quot;
             d:DesignHeight=&quot;300&quot; d:DesignWidth=&quot;300&quot; Background=&quot;Beige&quot;&gt;
    &lt;UserControl.Resources&gt;
        &lt;mvvm:MainViewModel x:Key=&quot;MainMvvM&quot;&gt;&lt;/mvvm:MainViewModel&gt;
    &lt;/UserControl.Resources&gt;
    &lt;DockPanel&gt;
        &lt;Image Source=&quot;/Prism.NavigationTryOut.NavigationModule;component/Images/Autumn Leaves.jpg&quot; DockPanel.Dock=&quot;Top&quot; MaxHeight=&quot;400&quot; MaxWidth=&quot;600&quot;&gt;&lt;/Image&gt;
        &lt;Grid x:Name=&quot;NavigationGrid&quot; VerticalAlignment=&quot;Bottom&quot; DataContext=&quot;{Binding Source={StaticResource MainMvvM}}&quot;&gt;
            &lt;Grid.ColumnDefinitions&gt;
                &lt;ColumnDefinition Width=&quot;0.3*&quot; /&gt;
                &lt;ColumnDefinition Width=&quot;*&quot; /&gt;
                &lt;ColumnDefinition Width=&quot;0.3*&quot; /&gt;
            &lt;/Grid.ColumnDefinitions&gt;
            &lt;Grid.RowDefinitions&gt;
                &lt;RowDefinition Height=&quot;0.2*&quot; /&gt;
            &lt;/Grid.RowDefinitions&gt;
            &lt;Button x:Name=&quot;Previous&quot; Content=&quot;Previous&quot; Grid.Column=&quot;0&quot; Grid.Row=&quot;0&quot; Margin=&quot;5&quot; Command=&quot;{Binding PreviousCommand}&quot; IsEnabled=&quot;{Binding NavigationJournal.CanGoBack}&quot;&gt;&lt;/Button&gt;
            &lt;Button x:Name=&quot;Close&quot; Content=&quot;Close&quot; Grid.Column=&quot;1&quot; Grid.Row=&quot;0&quot; Margin=&quot;5&quot; Command=&quot;{Binding CloseCommand}&quot;&gt;&lt;/Button&gt;
            &lt;Button x:Name=&quot;Next&quot; Content=&quot;Next&quot; Grid.Column=&quot;2&quot; Grid.Row=&quot;0&quot; Margin=&quot;5&quot; Command=&quot;{Binding NextCommand}&quot;&gt;&lt;/Button&gt;
        &lt;/Grid&gt;
    &lt;/DockPanel&gt;
&lt;/UserControl&gt;
</pre><br />
Anmerkung: Das ViewModel kann nicht erstellt werden, da im Konstruktor der ServiceLocator von Unity für das Auflösen des IRegionManagers verwendet wird. Dieser wird erst zur Laufzeit erstellt und daher erhält man eine NULL-Reference-Exeption im GUI-Design.</p>
<p>So damit hätten wir eine kleine, aber noch mit Verbesserungspotenzial versehene Navigationslösung erstellt, deren Ansatz man sicher weiter verfolgen kann. In diesem Sinne danke ich für das Lesen des Blogpost&#8217;s und freue mich auf konstruktive Kritiken.</p>
<p>Die dazugehörige Solution kann <a href="https://skydrive.live.com/?cid=ce67b0bb158a026d&amp;sc=documents&amp;id=CE67B0BB158A026D%214673#" title="hier" target="_blank">hier</a> heruntergeladen werden.</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f07%2f12%2fprism-4-0-navigation%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f07%2f12%2fprism-4-0-navigation%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/394/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/394/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/394/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/394/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/394/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/394/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/394/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/394/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/394/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/394/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/394/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/394/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/394/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/394/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=394&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2011/07/12/prism-4-0-navigation/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f07%2f12%2fprism-4-0-navigation%2f" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
		<item>
		<title>Dynamisch generiertes Bilder-Menu erweitern mit JQueryUI</title>
		<link>http://schaedlerdaniel.wordpress.com/2011/06/12/dynamisch-generiertes-bilder-menu-erweitern-mit-jqueryui/</link>
		<comments>http://schaedlerdaniel.wordpress.com/2011/06/12/dynamisch-generiertes-bilder-menu-erweitern-mit-jqueryui/#comments</comments>
		<pubDate>Sun, 12 Jun 2011 16:55:09 +0000</pubDate>
		<dc:creator>schaedlerdaniel</dc:creator>
				<category><![CDATA[ASP.NET /AJAX /ASP.NET MVC]]></category>
		<category><![CDATA[Bildergallery]]></category>
		<category><![CDATA[dynamisches Bildermenu]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[Modaler PopUpExtender auf selektiertes Bild]]></category>

		<guid isPermaLink="false">http://schaedlerdaniel.wordpress.com/?p=385</guid>
		<description><![CDATA[Im letzten Blogbeitrag wurden die Bilder im Verzeichnisbaum in das Menu gerendert (also die Struktur). Damit man noch ein wenig mehr Pepp in das Ganze bringen kann, ist es möglich JQueryUI zu verwenden. Zu diesem Zweck habe ich mir den Modal Dialog ausgesucht, dass wenn der Benutzer ein Bild, das verkleinert dargestellt wird, in einem [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=385&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Im letzten Blogbeitrag wurden die Bilder im Verzeichnisbaum in das Menu gerendert (also die Struktur). Damit man noch ein wenig mehr Pepp in das Ganze bringen kann, ist es möglich <a href="http://jqueryui.com/home">JQueryUI</a> zu verwenden. Zu diesem Zweck habe ich mir den <a href="http://jqueryui.com/demos/dialog/">Modal Dialog</a> ausgesucht, dass wenn der Benutzer ein Bild, das verkleinert dargestellt wird, in einem Dialog angezeigt bekommt.</p>
<h5>Was ist denn da alles notwendig?</h5>
<p>Eigentlich nicht ganz viel:<br />
1.) Man lade eines der vielen <a href="http://jqueryui.com/themeroller/">Themen</a> herunter, dass von JQueryUI schon zur Verfügung gestellt wird.<br />
2.) Grundlage bildet der vorherige Blogpost &#8220;Dynamisch generiertes Bilder-Menu&#8221;. Die Source kann <a href="http://cid-ce67b0bb158a026d.office.live.com/self.aspx/Public/Development/Blog%20Post%20Solutions/DynamicImageGalleryMenu.zip" target="blank">hier</a> herunter geladen werden.<br />
Wie kommen wir denn nun zu dem modalen Bild</h5>
<p>Als erstes passen wird den Menu-Click Event an. Hier werden dann dynamisch anhand der Anzahl Bilder die IMAGE-ASP.NET Controls in das entsprechende DIV gerendert.<br />
<pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// If menu is clicked the image will be rendered as image tag into the site
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;sender&quot;&gt;&lt;/param&gt;
        /// &lt;param name=&quot;e&quot;&gt;&lt;/param&gt;
        protected void GalleryMenu_ItemClick(object sender, MenuEventArgs e)
        {
            MenuItem menuItem = (MenuItem)e.Item;
            string path = string.Format(@&quot;Images/{0}&quot;, menuItem.ValuePath);
            DirectoryInfo directoryInfo = new DirectoryInfo(Server.MapPath(path));
            FileInfo[] files = directoryInfo.GetFiles(&quot;*.jpg&quot;);

            foreach (var picture in files)
            {
                Image image = new Image();
                image.Height = 200;
                image.Width = 200;
                image.ClientIDMode = System.Web.UI.ClientIDMode.AutoID;
                image.ID = string.Format(@&quot;Image_{0}&quot;, picture.Length);
                image.ImageUrl = string.Format(&quot;{0}/{1}&quot;, path, picture.Name);
                image.Attributes.Add(&quot;onclick&quot;, string.Format(@&quot;ShowImageInOriginalSize('{0}')&quot;, image.ClientID));
                ImageResultDiv.Controls.Add(image);
            }
        }
</pre><br />
Das Ganze kann dann noch mit ein wenig JavaScript (JQuery) gepfeffert werden und sie dann auch entsprechend schön aus (sofern man das entsprechende Thema anhand der <a href="http://jqueryui.com/docs/Getting_Started">JQueryUI Hilfe</a> eingebunden hat).<br />
<pre class="brush: xml;">
    &lt;script type=&quot;text/javascript&quot;&gt;
        function ShowImageInOriginalSize(imageClientId) {
            var image = $('#' + imageClientId + '');

            var modalPopUpImage = $('#ModalPopUpImage');
            modalPopUpImage[0].width = image[0].naturalWidth;
            modalPopUpImage[0].height = image[0].naturalHeight;
            modalPopUpImage[0].src = image[0].src;

            $('#ModalPopUp').dialog({ modal: true, height: image[0].naturalWidth, width: image[0].naturalWidth, maxHeight: image[0].naturalHeight, maxWidth: image[0].naturalWidth });
        }
    &lt;/script&gt;
</pre><br />
ACHTUNG:Die Stolperfalle, wenn man das angeklickte Bild dem ModalpopUp-Extender übergeben hat, dann wird es zwar angezeigt, aber nicht mehr in die Source (dort wo es angeklickt worden ist) &#8220;zurück&#8221; gelegt. Aus diesem Grund ist es wichtig ein modales Bild zu haben dass die Höhe und die Breite als 0 aufweist und erst, wenn der Dialog angezeigt wird, in die entsprechende Grösse verändert wird.<br />
<pre class="brush: xml;">
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
    &lt;div runat=&quot;server&quot;  id=&quot;ResultDiv&quot;&gt;
    &lt;div style=&quot;float:left; margin:5px;&quot;&gt;
        &lt;asp:Menu ID=&quot;GalleryMenu&quot; runat=&quot;server&quot; RenderingMode=&quot;List&quot; 
            OnMenuItemClick=&quot;GalleryMenu_ItemClick&quot;&gt;
        &lt;/asp:Menu&gt;
        &lt;/div&gt;
        &lt;div id=&quot;ImageResultDiv&quot; runat=&quot;server&quot; style=&quot;float:left; position:relative; margin-left:200px; margin-top:5px;&quot;&gt;            
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;/form&gt;
    &lt;div id=&quot;ModalPopUp&quot; style=&quot;margin-bottom:2px;&quot;&gt;
        &lt;img id=&quot;ModalPopUpImage&quot; src=&quot;#&quot; alt=&quot;Alternate Text&quot; width=&quot;0&quot; height=&quot;0&quot; /&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre><br />
Somit kann das &#8220;Fake&#8221;-Bildchen versteckt und spielt erst wieder eine Rolle, wenn es gebraucht wird. Für Anregungen und Kritik bin ich offen und hoffe auf Rückmeldungen.</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f06%2f12%2fdynamisch-generiertes-bilder-menu-erweitern-mit-jqueryui%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f06%2f12%2fdynamisch-generiertes-bilder-menu-erweitern-mit-jqueryui%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/schaedlerdaniel.wordpress.com/385/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/schaedlerdaniel.wordpress.com/385/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/schaedlerdaniel.wordpress.com/385/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/schaedlerdaniel.wordpress.com/385/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/schaedlerdaniel.wordpress.com/385/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/schaedlerdaniel.wordpress.com/385/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/schaedlerdaniel.wordpress.com/385/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/schaedlerdaniel.wordpress.com/385/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/schaedlerdaniel.wordpress.com/385/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/schaedlerdaniel.wordpress.com/385/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/schaedlerdaniel.wordpress.com/385/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/schaedlerdaniel.wordpress.com/385/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/schaedlerdaniel.wordpress.com/385/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/schaedlerdaniel.wordpress.com/385/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=schaedlerdaniel.wordpress.com&amp;blog=16378069&amp;post=385&amp;subd=schaedlerdaniel&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://schaedlerdaniel.wordpress.com/2011/06/12/dynamisch-generiertes-bilder-menu-erweitern-mit-jqueryui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e50530c3e478a8a210b7df39006fdc68?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">schaedlerdaniel</media:title>
		</media:content>

		<media:content url="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fschaedlerdaniel.wordpress.com%2f2011%2f06%2f12%2fdynamisch-generiertes-bilder-menu-erweitern-mit-jqueryui%2f" medium="image">
			<media:title type="html">kick it on dotnet-kicks.de</media:title>
		</media:content>
	</item>
	</channel>
</rss>
