<?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/"
	>

<channel>
	<title>BigBasti&#039;s Blog &#187; ASP</title>
	<atom:link href="http://blog.bigbasti.com/category/asp/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.bigbasti.com</link>
	<description>About Me &#38; my Digital Lifestyle</description>
	<lastBuildDate>Wed, 25 Jan 2012 12:31:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>ASP.NET MVC: HTML5 Elemente mit jQuery Fallback nutzen</title>
		<link>http://blog.bigbasti.com/asp-net-mvc-html5-elemente-mit-jquery-fallback-nutzen/</link>
		<comments>http://blog.bigbasti.com/asp-net-mvc-html5-elemente-mit-jquery-fallback-nutzen/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 09:47:45 +0000</pubDate>
		<dc:creator>Sebastian Gross</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Workaround]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/?p=1955</guid>
		<description><![CDATA[Soo, nachdem ich die Überschrift mit all den hippen Begriffen vollgepackt habe die es in Sachen Web momentan so gibt möchte ich euch kurz erklären worum es in diesem Artikel gehen soll.

Ihr werdet sicher mitbekommen haben, dass HTML5 auf dem Vormarsch ist und auch wenn es immer noch nicht offiziell fertig ist findet man ...]]></description>
			<content:encoded><![CDATA[<p>Soo, nachdem ich die Überschrift mit all den hippen Begriffen vollgepackt habe die es in Sachen Web momentan so gibt möchte ich euch kurz erklären worum es in diesem Artikel gehen soll.</p>
<p>Ihr werdet sicher mitbekommen haben, dass HTML5 auf dem Vormarsch ist und auch wenn es immer noch nicht offiziell fertig ist findet man immer häufiger den HTML5-Header &lt;!DOCTYPE html&gt; auf diversen Seiten.</p>
<p>Eins der meiner Meinung nach nützlichsten Features die wir mit HTML5 erhalten sind die <a href="http://www.w3schools.com/html5/html5_form_input_types.asp" target="_blank">neuen Input-Typen</a>. Denn bisher hatten wir keine Wahl und mussten type="text" benutzen!</p>
<p>Die Eingabefelder vom Typ Text konnten natürlich alles enthalten, sind aber nicht gerade Benutzerfreundlich wenn man etwas komplexere Daten eingeben soll wie zum Beispiel ein Datum.</p>
<p>In HTML5 wurden deswegen spezifische Typen für solche immer wieder einkehrende Eingaben eingeführt. Eine von ihnen ist &amp;quot;Date&amp;quot;:</p>
<pre>
<pre class="brush: html; ">

Birthday: &lt;input type=&quot;date&quot; name=&quot;bday&quot; /&gt;
</pre>
</pre>
<p>Der große Vorteil hier ist, dass die Browser nun eine eigene Implementierung für diesen Typ von Eingabefeldern machen können. Falls der Browser nun also diesen neuen Eingabe Typ unterstützt blendet er automatisch einem (mehr oder weniger) schönen Date-Picker ein in dem man bequem das Datum wählen kann:</p>
<div class="wp-caption aligncenter" style="width: 510px"><a href="http://server.bigbasti.com/uploads/uploads/251212842982966.png "><img title="Browsersupport" src="http://server.bigbasti.com/uploads/uploads/251212842982966.png " alt="" width="500" height="300" /></a><p class="wp-caption-text">Ansicht des neuen Typen in verschiedenen Browsern</p></div>
<p>Ein weiterer großer Vorteil ist, dass auch die mobilen Browser wie z.B. auf dem iPhone diese neuen Elemente ebenfalls unterstützen und einen passenden Picker einblenden:</p>
<div class="wp-caption alignleft" style="width: 148px"><a href="http://server.bigbasti.com/uploads/uploads/2512128448977966.png "><img class="   " title="Date-Picker auf dem iPhone" src="http://server.bigbasti.com/uploads/uploads/2512128448977966.png " alt="" width="138" height="208" /></a><p class="wp-caption-text">Date-Picker auf dem iPhone</p></div>
<p>Wie ihr in dem ersten Screenshot sehen könnt unterstützt der FireFox (zumindest zum Zeitpunkt des Screenshots) den neuen Typ nicht. In diesem Fall blendet er ein gewöhnliches Textfeld ein wo wir nun gezwungen sind das Datum auf die gewohnte (unbequeme) Weise einzutragen.</p>
<p>Übrigens, ich glaube ich muss euch nicht sagen warum der Internet Explorer hier nicht mit aufgeführt ist oder? <img src='http://blog.bigbasti.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Und genau das ist das Problem um das es in diesem Blogpost geht. Wenn wir die tollen neuen Elemente nutzen gehen wir das Risiko ein, dass Nutzer die einen älteren Browser nutzen nicht in den Genuss einer bequemen Eingabe kommen.</p>
<div class="wp-caption alignright" style="width: 245px"><a href="http://jqueryui.com/demos/datepicker/"><img title="jQuery Date-Picker" src="http://server.bigbasti.com/uploads/uploads/251212852193838138.png " alt="" width="235" height="196" /></a><p class="wp-caption-text">jQuery Date-Picker</p></div>
<p>Wir könnten auch komplett auf das HTML5 Element verzichten und direkt alles mit jQuery machen, welches auch einen Date-Picker bietet, aber das ist auch nicht das gelbe vom Ei, denn dann wären die Mobilen Nutzer in Nachteil, da dort die Browser diese Elemente für gewöhnlich unterstützen und eine gewohnte Oberfläche für die Eingabe bieten.</p>
<p>Die Optimale Lösung ist offensichtlich eine Mischung beider Welten. Wenn der Benutzer die Seite mit einem kompatiblen Browser aufruft soll der Date-Picker des Browsers genutzt werden, wenn der Browser aber veraltet ist soll stattdessen der jQuery Fallback greifen und der JavaScript Date-Picker (siehe links) genutzt werden.</p>
<p>Zu unserem Glück macht uns ASP.NET MVC die Umsetzung dieses Plans sehr leicht, da es an den nötigen Stellen sehr einfach erweitert werden kann.</p>
<p>Schauen wir uns mal ein kleines Beispiel an. Wir haben eine Klasse Person, und wollen auch dessen Geburtstag speichern, hier wollen wir die tolle neue Funktionalität nutzen. Implementieren wir das Ganze jedoch erstmal wie gewohnt:</p>
<pre>
<pre class="brush: csharp; ">

    public class Person
    {
        public int ID { get; set; }
        public String Name { get; set; }
        public DateTime Geburtstag { get; set; }
    }
</pre>
</pre>
<p>Wenn wir die Model-Klasse haben können wir das MVC Scaffolding nutzen um für uns eine View zum Erstellen neuer Personen anzulegen:</p>
<div class="wp-caption aligncenter" style="width: 521px"><a href="http://server.bigbasti.com/uploads/uploads/25121296125932661.png "><img class=" " title="MVC Scaffolding kommt uns zu Hilfe" src="http://server.bigbasti.com/uploads/uploads/25121296125932661.png " alt="" width="511" height="504" /></a><p class="wp-caption-text">MVC Scaffolding kommt uns zu Hilfe</p></div>
<p>Schauen wir uns nun doch mal an was da für uns tolles generiert wurde:</p>
<pre>
<pre class="brush: html; ">

    &lt;div class=&quot;editor-field&quot;&gt;
        @Html.EditorFor(model =&gt; model.Geburtstag)
        @Html.ValidationMessageFor(model =&gt; model.Geburtstag)
    &lt;/div&gt;
</pre>
</pre>
<p>Auffällig hierbei ist, dass hier @Html.EditorFor genutzt wird und nicht etwa @Html.TextBoxFor! Der Hintergrund ist der, dass MVC bei der Generierung versuchen wird ein passendes Element für den angegebenen Datentyp (DateTime) zu bestimmen, aber da MVC standardmäßig nur den Typ Text kennt wird hier eigentlich immer ein Input-Element vom Typ text generiert.</p>
<p>Hier kommt uns die Erweiterbarkeit von MVC zu gute, denn wir können ganz einfach NuGet nutzen um uns die nötige Funktionalität zu verschaffen. Wir installieren das Packet MvcHtml5Templates.</p>
<div class="wp-caption aligncenter" style="width: 438px"><a href="http://server.bigbasti.com/uploads/uploads/251212929533298753.png "><img title="Installation über NuGet" src="http://server.bigbasti.com/uploads/uploads/251212929533298753.png " alt="" width="428" height="46" /></a><p class="wp-caption-text">Installation über NuGet</p></div>
<div class="wp-caption alignleft" style="width: 220px"><a href="http://server.bigbasti.com/uploads/uploads/25121293434438753.png "><img title="Neue Templates" src="http://server.bigbasti.com/uploads/uploads/25121293434438753.png " alt="" width="210" height="251" /></a><p class="wp-caption-text">Neue Templates</p></div>
<p>Nachdem NuGet alles erledigt hat werdet ihr feststellen, dass ihr ein paar neue Dateien in eurem Views/Shared Verzeichnis habt (siehe Bild links). Und wie ihr schon an dem Namen erkennen könnt sind das die neuen Input-Typen aus HTML5.</p>
<p>Diese Templates machen im Grunde nichts anderes als die MVC-Eigenen zu überschreiben und versehen die mit dem passendem Type-Attribut.</p>
<p>Hier sind euch keine Grenzen gesetzt ihr könnt natürlich auch eire eigenen Templates definieren mit euren eigenen Typen. (Auch wenn man das eher selten benötigt)</p>
<p>Das Tolle: mehr müssen wir nicht machen. MVC wird nun zur Laufzeit statt einem Text ein Date Input-Element für uns anlegen. Beachtet, dass das nur geht wenn wir in der View die allgemeine Funktion @Html.EditorFor nutzen und keinen Spezifischen Typ angeben.</p>
<p>Schauen wir mal in den Sourcecode der zur Laufzeit für das Geburtstagsfeld generiert wird:</p>
<pre>
<pre class="brush: html; ">

&lt;input class=&quot;text-box single-line&quot;
data-val=&quot;true&quot;
data-val-required=&quot;Das Feld &#039;Geburtstag&#039; ist erforderlich&quot;
id=&quot;Geburtstag&quot;
name=&quot;Geburtstag&quot;
type=&quot;datetime&quot;
value=&quot;&quot;; /&gt;
</pre>
</pre>
<p>Wie ihr seht wird nun der Korrekte Typ, nämlich datetime verwendet. Wenn wir die Seite nun also mit einem kompatiblen Browser aufrufen können wir ganz bequem das Datum wählen.</p>
<p>Leider ist der Opera Browser momentan wohl der einzige Desktop Browser der uns hier einen Benutzerfreundlichen Dialog einblendet (siehe erstes Bild oben), somit müssen wir dafür sorgen, dass die Benutzer mit anderen oder alten Browsern nicht benachteiligt werden.</p>
<div class="wp-caption alignleft" style="width: 248px"><a href="http://server.bigbasti.com/uploads/uploads/251212124663987.png "><img title="JavaScript Magie" src="http://server.bigbasti.com/uploads/uploads/251212124663987.png " alt="" width="238" height="272" /></a><p class="wp-caption-text">JavaScript Magie</p></div>
<p>Auch für diese Problematik bringt MVC bereits alles mit was nötig ist sie zu lösen. Werfen wir doch mal einen Blick in unseren Scripts Ordner finden wir alle nötigen jQuery und jQuery UI Skripte, dazu kommt noch die modernizr Bibliothek die uns auch zu Gute kommen wird.</p>
<p>Die jQuery Bibliotheken liefern und die nötige Funktionalität die wir benötigen um diesen hübschen Date-Picker einzublenden.</p>
<p>Die modernizr Bibliothek dagegen hilft uns herauszufinden ob der Browser, den der Benutzer momentan verwendet die gewünschten HTML5 Features unterstützt.</p>
<p>Nun müssen wir also bei unseren Formularen prüfen, ob der Browser die nötigen Funktionen kennt und bei Bedarf die jQuery Klassen einbinden. Das Ganze ist dank der Einfachheit von Modernizr und jQuery ziemlich simpel.</p>
<p>Wechseln wir zu unserer View und fügen die Referenzen auf die nötigen Skripte und CSS Dateien ein:</p>
<pre>
<pre class="brush: html; ">

&lt;script src=&quot;@Url.Content(&quot;~/Scripts/jquery-1.5.1.js&quot;)&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;@Url.Content(&quot;~/Scripts/jquery-ui-1.8.11.js&quot;)&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;@Url.Content(&quot;~/Scripts/modernizr-1.7.js&quot;)&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
&lt;link href=&quot;@Url.Content(&quot;~/Content/themes/base/jquery.ui.all.css&quot;)&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
</pre>
</pre>
<p>Unten in der View fügen wir nun eine Modernizr Abfrage ein und prüfen, ob der Browser das DateTime-Feld unterstützt, und wenn nicht lassen wir jQuery das Ganze für uns regeln:</p>
<pre>
<pre class="brush: html; ">

&lt;script type=&quot;text/javascript&quot;&gt;
    $(function () {
        if (!Modernizr.inputtypes.date) {
            $(&quot;input[type=&#039;datetime&#039;]&quot;).datepicker();
        }
    });
&lt;/script&gt;
</pre>
</pre>
<p>Mit dem Befehl $("input[type='datetime']").datepicker(); werden alle Input-Felder vom Typ DateTime durch den jQuery Picker ersetzt. Coole Sache!</p>
<div class="wp-caption alignleft" style="width: 293px"><a href="http://server.bigbasti.com/uploads/uploads/2512121394635647.png "><img src="http://server.bigbasti.com/uploads/uploads/2512121394635647.png " alt="Unser Browser kennt den Typ nicht :(" width="283" height="262" /></a><p class="wp-caption-text">Unser Browser kennt den Typ nicht <img src='http://blog.bigbasti.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p></div>
<p>Kleiner Hinweis am Rande: Das ist nicht wirklich best practice da die Skripte auch geladen werden wenn sie gar nicht benötigt werden (der Browser kennt das HTML5 Feld) ich habe das hier der Einfachheit geopfert.</p>
<p>Und das wars auch schon! Alle Browser die das Feld unterstützen blenden nun ihren Picker ein, ansonsten wird der jQuery Fallback genutzt.</p>
<p>Wir müssen uns auch nicht mit irgendwelchen UserAgent-Prüfungen herumschlagen und lassen das alles Modernizr erledigen, der das intern über JavaScript prüft und somit immer aktuell ist. Das heißt dass wenn irgendwann der IE plötzlich die neuen Typen kennt werden diese auch funktionieren!</p>
<p>Genauso könnt ihr auch bei all den anderen neuen HTML5 Typen vorgehen und euren Usern ein bestmögliches Bedienerlebnis bereiten <img src='http://blog.bigbasti.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fblog.bigbasti.com%2fasp-net-mvc-html5-elemente-mit-jquery-fallback-nutzen%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.bigbasti.com%2fasp-net-mvc-html5-elemente-mit-jquery-fallback-nutzen%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1955&amp;md5=6f4995620c5babc5f3ed2b2f69c89eaa" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/asp-net-mvc-html5-elemente-mit-jquery-fallback-nutzen/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC: Zugriff auf Dateien einschraenken</title>
		<link>http://blog.bigbasti.com/asp-net-mvc-zugriff-auf-dateien-einschraenken/</link>
		<comments>http://blog.bigbasti.com/asp-net-mvc-zugriff-auf-dateien-einschraenken/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 18:45:08 +0000</pubDate>
		<dc:creator>Sebastian Gross</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/?p=1935</guid>
		<description><![CDATA[Oft kommt es vor dass man bestimmte Inhalte nicht der breiten Öffentlichkeit präsentieren möchte. So will man beispielsweise bestimmte Inhalte nur autorisierten Benutzern oder nur Admins zur Verfügung stellen, andere User die nicht eingeloggt sind sollen diese Inhalte nicht abrufen können. Ein weiterer Anwendungsfall wäre auch hotlinking zu verhindern.

Dieses Verhalten kann man in ASP.NET ...]]></description>
			<content:encoded><![CDATA[<p>Oft kommt es vor dass man bestimmte Inhalte nicht der breiten Öffentlichkeit präsentieren möchte. So will man beispielsweise bestimmte Inhalte nur autorisierten Benutzern oder nur Admins zur Verfügung stellen, andere User die nicht eingeloggt sind sollen diese Inhalte nicht abrufen können. Ein weiterer Anwendungsfall wäre auch <a href="http://de.wikipedia.org/wiki/Hotlinking" target="_blank">hotlinking</a> zu verhindern.</p>
<p>Dieses Verhalten kann man in ASP.NET MVC über verschiedene Wege erreichen. Eine beliebte Möglichkeit ist es</p>
<p><strong>die Dateien über einen Controller zu verteilen.</strong></p>
<p>Hierbei erstellt man einen Controller der eine Action hat in der die gewünschte Datei geladen und an den Browser zurückgegeben wird. Hier hat man dann die Bequemlichkeit, dass man problemlos prüfen kann ob der User eingeloggt ist und über die nötigen Rechte für das Bild verfügt. Das geht zum Beispiel mit dem Authorized-Attribut für die Actions.</p>
<p>Implementiert würde so eine Action dann wohl ca so aussehen:</p>
<pre>
<pre class="brush: csharp; ">

public ActionResult Image(string id)
{
    var dir = Server.MapPath(&quot;/Private/Images&quot;);
    var path = Path.Combine(dir, id + &quot;.jpg&quot;);
    return base.File(path, &quot;image/jpeg&quot;);
}
</pre>
</pre>
<p>Das Bild kann man dann so abrufen:</p>
<pre>
<pre class="brush: html; ">

&lt;img src=&quot;@Html.Content(&quot;~/Content/Image/&quot; + model.pictureID)&quot; /&gt;
</pre>
</pre>
<p>Dieser Ansatz funktioniert problemlos hat aber den kleinen Nachteil, dass er nicht so performant ist wie der direkte Zugriff auf die Ressource.</p>
<p>Eine weitere (und auch meine bevorzugte) Möglichkeit eine solche Zugriffskontrolle zu implementieren ist es durch</p>
<p><strong>einen eigenen RouteHandler.</strong></p>
<p>Eine Beispielimplementierung wie man auf diese Weise Hotlinking verhindern kann habe ich in <a href="http://www.mikesdotnetting.com/Article/126/ASP.NET-MVC-Prevent-Image-Leeching-with-a-Custom-RouteHandler" target="_blank">Mike Brinds Blog</a> gefunden.</p>
<p>Hier sind im Grunde drei kleine Schritte nötig um einen eigenen RouteHandler zum Laufen zu bekommen. (Code von Mikes Blog)</p>
<p>Zunächst müssen wir die RouteHandler Klasse anlegen, die das IRouteHandler Interface und dessen einzige Methode GetHttpHandler implementiert:</p>
<pre>
<pre class="brush: csharp; ">

public class ImageRouteHandler : IRouteHandler
{
  public IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
    return new ImageHandler(requestContext);
  }
}
</pre>
</pre>
<p>Als nächstes erstellen wir die oben genutzte ImageHandler Klasse in der wir das das IHttpHandler Interface implementieren:</p>
<pre>
<pre class="brush: csharp; ">

public class ImageHandler : IHttpHandler
{
  public ImageHandler(RequestContext context)
  {
    ProcessRequest(context);
  }

  private static void ProcessRequest(RequestContext requestContext)
  {
    var response = requestContext.HttpContext.Response;
    var request = requestContext.HttpContext.Request;
    var server = requestContext.HttpContext.Server;

    var validRequestFile = requestContext.RouteData.Values[&quot;filename&quot;].ToString();
    const string invalidRequestFile = &quot;thief.gif&quot;;
    var path = server.MapPath(&quot;~/graphics/&quot;);

    response.Clear();
    response.ContentType = GetContentType(request.Url.ToString());

    if (request.ServerVariables[&quot;HTTP_REFERER&quot;] != null &amp;&amp;
        request.ServerVariables[&quot;HTTP_REFERER&quot;].Contains(&quot;yourdomain.com&quot;))
    {
      response.TransmitFile(path + validRequestFile);
    }
    else
    {
      response.TransmitFile(path + invalidRequestFile);
    }
    response.End();
  }

  private static string GetContentType(string url)
  {
    switch (Path.GetExtension(url))
    {
      case &quot;.gif&quot;:
        return &quot;Image/gif&quot;;
      case &quot;.jpg&quot;:
        return &quot;Image/jpeg&quot;;
      case &quot;.png&quot;:
        return &quot;Image/png&quot;;
      default:
        break;
    }
    return null;
  }

  public bool IsReusable
  {
    get { return false; }
  }
}
</pre>
</pre>
<p>Zu Schluss müssen wir diesen neuen Handler mit einer Route in der Global.asax registrieren:</p>
<pre>
<pre class="brush: csharp; ">

routes.Add(&quot;ImagesRoute&quot;,
                 new Route(&quot;images/{filename}&quot;, new ImageRouteHandler()));
</pre>
</pre>
<p>Hierbei ist noch wichtig, dass ihr die Route an der passenden Stelle registriert, sodass diese nicht ungewollt von einer anderen Route blockiert wird weil diese auch auf dieses Pattern matcht.</p>
<p>Nun werden alle Requests die auf die Route "images/{filename}" gehen und von einer anderen Domain stammen als eurer eigenen auf eine andere Grafik umgeleitet.</p>
<p>Nun bleibt noch ein kleines Problem, denn wenn das Verzeichnis mit den Bildern in eurem Content Verzeichnis liegt kann immer noch darauf verlinkt werden wenn man den vollen Pfad nimmt, also statt dem virtuellem Pfad</p>
<pre>
<pre class="brush: html; ">
http://localhost/images/myimg.jpg
</pre>
</pre>
<p>die URL benutzt unter der tatsächlich alle Bilder liegen:</p>
<pre>
<pre class="brush: html; ">
http://localhost/Content/graphics/myimg.jpg
</pre>
</pre>
<p>Dies liegt daran, dass der neue RouteHandler in diesem Fall nicht greift und die Default Route genutzt wird. Am einfachsten kann man dies verhindern wenn man den Zugriff für Unbefugte über die web.config sperrt:</p>
<pre>
<pre class="brush: xml; ">

  &lt;location path=&quot;Content/graphics&quot;&gt;
    &lt;system.web&gt;
      &lt;authorization&gt;
        &lt;allow roles=&quot;admin&quot; /&gt;
        &lt;deny users=&quot;*&quot; /&gt;
      &lt;/authorization&gt;
    &lt;/system.web&gt;
  &lt;/location&gt;
</pre>
</pre>
<p>Das war dann auch schon, ich nutze gern den zweiten Weg, da dieser mir einfacher und sauberer erscheint. Wenn euch noch andere Möglichkeiten einfallen wie man das anstellen kann dann immer her damit!</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1935&amp;md5=4370312dd926703596c6baf8858b1f24" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/asp-net-mvc-zugriff-auf-dateien-einschraenken/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nice2Know: Attribut-basierende Routen in ASP.NET MVC</title>
		<link>http://blog.bigbasti.com/nice2know-attribut-basierende-routen-in-asp-net-mvc/</link>
		<comments>http://blog.bigbasti.com/nice2know-attribut-basierende-routen-in-asp-net-mvc/#comments</comments>
		<pubDate>Sat, 17 Sep 2011 15:47:31 +0000</pubDate>
		<dc:creator>Sebastian Gross</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/?p=1850</guid>
		<description><![CDATA[Für Routen ist in ASP.NET MVC für gewöhnlich die Global.asax zuständig, so werden hier alle Routen definiert und gemappt. Doch wenn man viele verschiedene Routen nutzen will wird es schnell voll in der eigentlich sehr übersichtlichen Klasse.

Da wäre es doch eigentlich cool wenn wir die Routen direct in unseren Controllern definieren könnten. Genau das ...]]></description>
			<content:encoded><![CDATA[<p>Für Routen ist in ASP.NET MVC für gewöhnlich die Global.asax zuständig, so werden hier alle Routen definiert und gemappt. Doch wenn man viele verschiedene Routen nutzen will wird es schnell voll in der eigentlich sehr übersichtlichen Klasse.</p>
<p>Da wäre es doch eigentlich cool wenn wir die Routen direct in unseren Controllern definieren könnten. Genau das können wir mit der Erweiterung <a href="https://github.com/mccalltd/AttributeRouting/wiki/_pages" target="_blank">AttributeRouting</a> machen.</p>
<div class="wp-caption aligncenter" style="width: 459px"><a href="http://server.bigbasti.com/uploads/uploads/179211172286.png "><img title="Installation" src="http://server.bigbasti.com/uploads/uploads/179211172286.png " alt="Installation" width="449" height="96" /></a><p class="wp-caption-text">Installation über NuGet</p></div>
<p style="text-align: left;">Dank NuGet ist die Installation in wenigen Sekunden abgeschlossen und wir können unsere Actions mit Routing-Attributen dekorieren.</p>
<p style="text-align: left;">Die Attribute sind hierbei sehr einfach gestaltet und bieten uns alles was wir benötigen.</p>
<pre>
<pre class="brush: csharp; ">

    public class DemoController : Controller
    {
        [GET(&quot;Ist/Das/Cool/Oder/Was&quot;)]
        public ActionResult Start()
        {
            return View();
        }
    }
</pre>
</pre>
<p>Nun muss man nur noch die Attribut-basierten Routen registrieren:</p>
<pre>
<pre class="brush: csharp; ">

    public static void RegisterRoutes(RouteCollection routes) {
        routes.IgnoreRoute(&quot;{resource}.axd/{*pathInfo}&quot;);

        routes.MapAttributeRoutes(); //--- das wars!

        routes.MapRoute(
            &quot;Default&quot;, // Route name
            &quot;{controller}/{action}/{id}&quot;, // URL with parameters
            new { controller = &quot;Home&quot;, action = &quot;Start&quot;,
                id = UrlParameter.Optional } // Parameter defaults
        );
    }
</pre>
</pre>
<p>Und fertig! Nun können wir die Seite starten und unsere Route testen:</p>
<div class="wp-caption aligncenter" style="width: 530px"><a href="http://server.bigbasti.com/uploads/uploads/1792111731231336.png "><img title="Das Ergebnis" src="http://server.bigbasti.com/uploads/uploads/1792111731231336.png " alt="Das Ergebnis" width="520" height="186" /></a><p class="wp-caption-text">Das Ergebnis</p></div>
<p>Die Routen die wir definieren können, beschränken sich nicht darauf, so können diese auch problemlos parametrisiert werden, inklusive Defaultparameter:</p>
<pre>
<pre class="brush: csharp; ">

    public class DemoController : Controller
    {
        [GET(&quot;Artikel/{artikelid}/{version?}&quot;)]
        [RouteDefault(&quot;artikelid&quot;, &quot;120&quot;)]
        public ActionResult Start(int artikelid, string version)
        {
            ViewBag.ArtikelId = artikelid;
            ViewBag.Version = version;

            return View();
        }
    }
</pre>
</pre>
<p>Hier wird der Parameter artikelid mit einem Defaultwert ausgestattet und der zweite optional gemacht. Das Ergebnis kann sich sehen lasen:</p>
<div class="wp-caption aligncenter" style="width: 463px"><a href="http://server.bigbasti.com/uploads/uploads/1792111742255336.png "><img title="Läuft!" src="http://server.bigbasti.com/uploads/uploads/1792111742255336.png " alt="Läuft!" width="453" height="558" /></a><p class="wp-caption-text">Läuft!</p></div>
<p>Hier hört das Framework nicht auf, so könnt ihr auch Regular Expressions in die Routen integrieren und auch mehrere Routen an eine Action heften. Die Möglichkeiten sind grenzenlos <img src='http://blog.bigbasti.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Für weitere Infos schaut einfach auf der <a href="https://github.com/mccalltd/AttributeRouting/wiki/2.-Usage" target="_blank">Projekthomepage </a>vorbei, es lohnt sich!</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1850&amp;md5=e86fd31c11e06da4d9708006f221b747" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/nice2know-attribut-basierende-routen-in-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nice2Know: Errorlogging mit ELMAH</title>
		<link>http://blog.bigbasti.com/nice2know-errorlogging-mit-elmah/</link>
		<comments>http://blog.bigbasti.com/nice2know-errorlogging-mit-elmah/#comments</comments>
		<pubDate>Sat, 17 Sep 2011 11:16:04 +0000</pubDate>
		<dc:creator>Sebastian Gross</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/nice2know-errorlogging-mit-elmah/</guid>
		<description><![CDATA[Errorlogging? Ist das nicht dieses Zeugs das die ganzen Java Programmierer und Linux Fuzies nutzen werdet ihr euch jetzt denken? Stimmt, aber auch in der .NET Welt ist es sehr nützlich ein Log zu führen und hier gibt es einige Tools für uns Entwickler die für uns diese unschöne Arbeit deutlich ersparen.

Das Tool dass ...]]></description>
			<content:encoded><![CDATA[<p>Errorlogging? Ist das nicht dieses Zeugs das die ganzen Java Programmierer und Linux Fuzies nutzen werdet ihr euch jetzt denken? Stimmt, aber auch in der .NET Welt ist es sehr nützlich ein Log zu führen und hier gibt es einige Tools für uns Entwickler die für uns diese unschöne Arbeit deutlich ersparen.</p>
<p>Das Tool dass ich euch heute vorstellen möchte ist ELMAH, was für Error Logging Modules and Handlers steht.</p>
<p>Was kann ELMAH? Hier ein Ausschnitt von der <a href="http://code.google.com/p/elmah/" target="_blank">Hompage</a>:</p>
<ul>
<li>Logging of nearly all unhandled exceptions.</li>
<li>A web page to remotely view the entire log of recoded exceptions.</li>
<li>A web page to remotely view the full details of any one logged exception, including colored stack traces.</li>
<li>In many cases, you can review the original <a href="http://en.wikipedia.org/wiki/Yellow_Screen_of_Death#ASP.NET">yellow screen of death</a> that ASP.NET generated for a given exception, even with <tt>customErrors</tt>mode turned off.</li>
<li>An e-mail notification of each error at the time it occurs.</li>
<li>An RSS feed of the last 15 errors from the log</li>
</ul>
<p>&nbsp;</p>
<p>Zusammengefasst gesagt schnappt ELMAH sich jede Exception die ihr nicht abgefangen habt und loggt diese für euch im Speicher oder in einer Datenbank und fasst diese auch noch schön zusammen auf einer Übersichtswebseite, in einem RSS Feed oder schickt euch diese direkt per Mail zu.</p>
<p>So könnt ihr jeder Zeit nach der Exception schauen was schiefgelaufen ist und euch den kompletten Stacktrace anschauen und (fast) jeden Yellow Screen of Death nachstellen.</p>
<p>Was mir an diesem Tool besonders gefällt ist die sehr einfach Integration in ein Projekt. Alles was ihr machen müsst ist es dafür zu sorgen dass die DLL in eurem bin-Verzeichnis und einen Handler in eure web.config einzutragen. Nun werden alle eure unbehandelten Exceptions geloggt.</p>
<p>Und es geht sogar noch einfacher, wenn ihr NuGet nutzt werden euch sogar diese Schritte abgenommen, einfach NuGet anwerfen, nach ELMAH suchen und installieren - fertig.</p>
<p><img src="http://server.bigbasti.com/uploads/uploads/1792111247365398.png" alt="" /></p>
<p>Das Schöne an NuGet ist, dass es nicht nur die Bibliothek herunterlädt sondern auch alle nötigen Einträge für uns anpasst, so werdet ihr nun auch ein paar neue Zeilen in eurer web.config entdecken:</p>
<p><a href="http://server.bigbasti.com/uploads/uploads/179211125242222.png"><img src="http://server.bigbasti.com/uploads/uploads/179211125242222.png" alt="" width="606" height="402" /></a></p>
<p>Diese Arbeit blieb uns zum Glück erspart <img src='http://blog.bigbasti.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Da nun eigentlich schon alles konfiguriert ist können wir fröhlich ein paar Fehler erzeugen:</p>
<p><a href="http://server.bigbasti.com/uploads/uploads/1792111255544865.png"><img src="http://server.bigbasti.com/uploads/uploads/1792111255544865.png" alt="" width="487" height="314" /></a></p>
<p>Ich habe hier also eine URL aufgerufen für die kein Controller und keine View bestimmt werden konnte. Dass wir hier so “viele” Informationen angezeigt bekommen liegt daran, dass wir die Seite lokal aufrufen, würden wir das ganze von einem anderem System machen würden uns noch weniger Informationen zur Verfügung stehen.</p>
<p>Nun wollen wir mal gucken, was ELMAH für uns aufgezeichnet hat, das können wir machen, in dem wir diese Seite aufrufen: /elmah.axd</p>
<p><a href="http://server.bigbasti.com/uploads/uploads/1792111346775.png"><img src="http://server.bigbasti.com/uploads/uploads/1792111346775.png" alt="" width="522" height="342" /></a></p>
<p>Alle aufgetretenen Exceptions für uns übersichtlich dargestellt. Wenn Bedarf besteht kann man natürlich auch tiefer bohren und die Details aufklappen:</p>
<p><a href="http://server.bigbasti.com/uploads/uploads/179211133145525.png"><img src="http://server.bigbasti.com/uploads/uploads/179211133145525.png" alt="" width="521" height="422" /></a></p>
<p>Hier hat man nun den vollen Stacktrace und viele weitere Informationen wie z.B. die Servervariablen. Eine sehr coole Sache wie ich finde, da ihr nun auch von unterwegs eure Fehler untersuchen könnt.</p>
<p>Falls ihr nicht wollt, dass jeder eure Exceptions sehen kann ist dies <a href="http://stackoverflow.com/questions/1245364/securing-elmah-in-asp-net-website" target="_blank">natürlich auch möglich</a>.</p>
<p><span style="color: #800000;">UPDATE: Ich habe hier die normale Version von ELMAH genutzt, für ein MVC Projekt würde ich aber <a href="http://nuget.org/List/Packages/Elmah.MVC" target="_blank"><span style="color: #800000;">ELMAH.MVC </span></a>empfehlen (Ebenfalls auf NuGet verfügbar). Dieses integriert sich besser in eine MVC Umgebung da es einen AdminController anlegt und somit über /Admin/Elmah erreichbar ist.</span></p>
<p>ELMAH gibt es übrigens schon eine halbe Ewigkeit aber ich (Langschläfer) bin erst vor ein paar Wochen drüber gestolpert. Wie schaut es bei euch aus? Nutzt ihr ELMAH?</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1848&amp;md5=45f3beda6028dc0e54ae84e516d24d39" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/nice2know-errorlogging-mit-elmah/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ausgeben einer Meldung nach dem Anmelden des Benutzers an einer ASP.NET Webseite</title>
		<link>http://blog.bigbasti.com/ausgeben-einer-meldung-nach-dem-anmelden-des-benutzers-an-einer-asp-net-webseite-2/</link>
		<comments>http://blog.bigbasti.com/ausgeben-einer-meldung-nach-dem-anmelden-des-benutzers-an-einer-asp-net-webseite-2/#comments</comments>
		<pubDate>Fri, 12 Aug 2011 11:15:46 +0000</pubDate>
		<dc:creator>Michael Bernhard</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[Anmeldung]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[VB.NET]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/?p=1805</guid>
		<description><![CDATA[Neulich habe ich auf einer meiner Seiten neben dem normalen Zugang für Benutzer auch einen Gastzugang eingerichtet.
Meldet sich jemand als Gast an meinem System an, stehen im alle Seiten des Adminbereiches zur Ansicht zur Verfügung, ein Speichern der Änderungen wird jedoch nicht erlaubt.
Um den Gastnutzer meiner Seite auf diese Einschränkungen und andere Besonderheiten hinzuweisen ...]]></description>
			<content:encoded><![CDATA[<p>Neulich habe ich auf einer meiner Seiten neben dem normalen Zugang für Benutzer auch einen Gastzugang eingerichtet.<br />
Meldet sich jemand als Gast an meinem System an, stehen im alle Seiten des Adminbereiches zur Ansicht zur Verfügung, ein Speichern der Änderungen wird jedoch nicht erlaubt.</p>
<p>Um den Gastnutzer meiner Seite auf diese Einschränkungen und andere Besonderheiten hinzuweisen - wollte ich eine Meldung ausgeben - sobald der Gast sich beim System angemeldet hat.</p>
<p>Ich verwende zur Anmeldung der Benutzer die vom Visual Studio 2010 automatisch generierte Seite LogIn.aspx.</p>
<p>Im Folgenden möchte ich zeigen wie man diese automatisch generierte Seite abändern muss um oben beschriebenes umzusetzen zu können.</p>
<p>Die Meldung möchte ich als ModalPopup ausgeben. Hierfür erweiterte ich die LogIn.aspx um den Code für das ModalPopup</p>
<pre>
<pre class="brush: html; ">

...
&lt;div style=&quot;display:none;&quot;&gt;
    &lt;asp:Button ID=&quot;ButtonGastLogIn&quot; runat=&quot;server&quot; /&gt;
&lt;/div&gt;
&lt;asp:ToolkitScriptManager ID=&quot;ToolkitScriptManagerGastLogIn&quot; runat=&quot;server&quot;/&gt;
&lt;asp:ModalPopupExtender ID=&quot;ModalPopupExtenderGastLogInt&quot; runat=&quot;server&quot;
    TargetControlID=&quot;ButtonGastLogIn&quot;
    PopupControlID=&quot;PopupGastLogIn&quot;
    cancelControlID=&quot;ButtonClose&quot;
    backgroundcssclass=&quot;ModalPopupBG&quot;&gt;
&lt;/asp:ModalPopupExtender&gt;
&lt;div id=&quot;PopupGastLogIn&quot; runat=&quot;server&quot;&gt;
...
    &lt;asp:imageButton ID=&quot;ImageButtonOK&quot; runat=&quot;server&quot; ImageUrl=&quot;~/image.png&quot; /&gt;
&lt;/div&gt;
</pre>
</pre>
<p>Zu beachten ist hier, dass der Button zum Anzeigen des Popup nicht sichtbar ausgeführt wird.<br />
Immerhin soll das Popup, abhängig davon ob sich ein normaler Benutzer oder ein Gast anmeldet, angezeigt werden oder eben nicht.</p>
<p>Die Codebehind-Datei wird wie folgt erweitert.</p>
<pre>
<pre class="brush: vb; ">

Protected Sub LoginUser_Authenticate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles LoginUser.Authenticate
    If ClassLogIn.CheckUser(Me.LoginUser.UserName, Me.LoginUser.Password)  String.Empty Then
        &#039;Anmeldung ok
        FormsAuthentication.RedirectFromLoginPage(Me.LoginUser.UserName, True)
    Else
        &#039;Anmeldung fehlgeschagen
        e.Authenticated = False
    End If
End Sub
</pre>
</pre>
<p>Diese Sub wird mit dem Drücken des Anmelden Buttons ausgeführt.<br />
ClassLogIn.CheckUser ist eine von mir geschriebene Funktion die die Benutzereingaben prüft.<br />
Sie werden vermutlich eine ähnliche Vorgehensweise gewählt haben, entscheidend für die Authentifizierung des Benutzers ist FormsAuthentication.RedirectFromLoginPage(…).<br />
Dadurch wird der Benutzer angemeldet (authentication) und an die Ursprungsseite weitergeleitet.</p>
<p>Dieses Vorgehen wollen wir, für alle normalen Benutzer unseres Systems, weiterhin nutzen.</p>
<p>Es gilt nun zwischen „normalen Nutzern“ und „Gästen“ zu unterscheiden.<br />
Da FormsAuthentication.RedirectFromLoginPage(..) den Response an die Ursprungsseite weiterleitet eignet sich dieses Vorgehen, zum Anmelden, für das Anzeigen eines ModalPopup nicht.</p>
<p>FormsAuthentication.SetAuthCookie(..) erfüllt unsere Bedürfnisse nach einer Authentifizierung ohne Weiterleitung perfekt. Zu beachten ist hier aber das die Authentifizierung erst vollständig ausgeführt wurde wenn ein Response stattgefunden hat.</p>
<p>Wir teilen die notwendigen Schritte also in zwei Teile auf.<br />
Im ersten Schritt ändern wir unsere Sub von oben ein wenig ab.</p>
<pre>
<pre class="brush: vb; ">

Protected Sub LoginUser_Authenticate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles LoginUser.Authenticate
    If ClassLogIn.CheckUser(Me.LoginUser.UserName, Me.LoginUser.Password)  String.Empty Then
        &#039;Anmeldung ok
        If ClassLogIn.IsGast(Me.LoginUser.UserName) = True Then
            FormsAuthentication.SetAuthCookie(Me.LoginUser.UserName, True)
            Me.ModalPopupExtenderGastLogInt.Show()
        Else
            FormsAuthentication.RedirectFromLoginPage(Me.LoginUser.UserName, True)
        End If
    Else
        &#039;Anmeldung fehlgeschagen
        e.Authenticated = False
    End If
End Sub
</pre>
</pre>
<p>Eine weitere Funktion prüft ob sich ein Gast oder ein normaler User am System anmelden will.<br />
Handelt es sich um einen Gast, führen wir den ersten Teil der Authentifizierung aus und zeigen das ModalPopup an.</p>
<p>Wird das ModalPopup geschlossen leiten wir den Response an eine andere Seite unseres Systems weiter.<br />
Damit wird der Anmeldevorgang abgeschlossen.</p>
<pre>
<pre class="brush: vb; ">

Protected Sub ImageButtonOK_Click(sender As Object, e As System.Web.UI.ImageClickEventArgs) Handles ImageButtonOK.Click
    Server.Transfer(&quot;~/Default.aspx&quot;)
End Sub
</pre>
</pre>
<p>Einen Nachteil hat das Ganze, ein Gast wird – im Gegensatz zu einem normalen Benutzer - immer auf eine bestimmte Seite (hier Default.aspx) weitergeleitet.</p>
<h3>Über den Autor</h3>
<p><img class="alignleft" src="http://server.bigbasti.com/uploads/uploads/86211149149524767.png" alt="" width="134" height="100" /></p>
<p><strong>Michael   Bernhard</strong><br />
Hobby-Programmierer von VB.NET, C# und   ASP.NET Anwendungen. Hauptberuflich als Inbetriebnehmer bei der <a href="http://www.boewe-systec.de/">Böwe Systec GmbH</a> beschäftigt. Vorzeigbare Projekte – <a href="http://timezonenotifier.free-file-download.de/">TimeZone Notifier</a> und <a href="http://www.tsv-neusaess-junioren.de/">TSV Neusäß Junioren</a>.</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1805&amp;md5=872e5d6663ea998c552d53186dc554d1" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/ausgeben-einer-meldung-nach-dem-anmelden-des-benutzers-an-einer-asp-net-webseite-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Entstehung einer ASP.NET Webanwendung anhand eines Beispiels</title>
		<link>http://blog.bigbasti.com/entstehung-einer-asp-net-webanwendung-anhand-eines-beispiels/</link>
		<comments>http://blog.bigbasti.com/entstehung-einer-asp-net-webanwendung-anhand-eines-beispiels/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 12:22:55 +0000</pubDate>
		<dc:creator>Michael Bernhard</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[VB]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/?p=1724</guid>
		<description><![CDATA[Mit diesem Artikel will ich skizzieren wie eine Webanwendung mittels ASP.NET entworfen und umgesetzt wird. Ich will einen Einblick in die Vorüberlegungen, sowie in die Umsetzung des Projektes geben. Nicht mehr, aber auch nicht weniger.
Vorüberlegungen
Wie fast alle Hobbyprogrammierer erstelle auch ich eine Unzahl unnötiger und zum Teil auch unsinniger Anwendungen. Dies ist der Luxus ...]]></description>
			<content:encoded><![CDATA[<p>Mit diesem Artikel will ich skizzieren wie eine Webanwendung mittels ASP.NET entworfen und umgesetzt wird. Ich will einen Einblick in die Vorüberlegungen, sowie in die Umsetzung des Projektes geben. Nicht mehr, aber auch nicht weniger.</p>
<h3>Vorüberlegungen</h3>
<p>Wie fast alle Hobbyprogrammierer erstelle auch ich eine Unzahl unnötiger und zum Teil auch unsinniger Anwendungen. Dies ist der Luxus den man sich leisten kann, wenn man damit nicht sein Geld verdienen muss.</p>
<p>Da ich ab und zu auf Dienstreise gehe, ist die aktuelle Uhrzeit am gegenwärtigen Standort immer ein Thema. Oft kommt auch die Frage auf, wie spät es denn bei den Lieben zu Hause wohl sein mag.</p>
<p>Hierfür  kommt natürlich nur, mein neuestes Steckenpferd, eine Webanwendung in Frage.</p>
<h3>Die ersten Überlegungen:</h3>
<p><span style="text-decoration: underline;"> </span></p>
<ol>
<li>Welcher Aufbau einer Webanwendung ist der beste</li>
<li>Wie ermittle ich meinen aktuellen Standort</li>
<li>Welche zusätzlichen Informationen kann ich noch anzeigen</li>
</ol>
<h4>1. Welcher Aufbau einer Webanwendung ist der beste?</h4>
<p>Ich hab mich hier, sehr schnell, für eine Webanwendung entschieden, die ihre Informationen aus einem RSS-Feed bezieht. Vorteil hierbei, es handelt sich um ein XML-Format, welches leicht zu lesen ist und auch anderweitig verwendet werden kann.<br />
Eine Windows-, Linux-, MacOS- oder Android Anwendung könnte den RSS-Feed ebenfalls nutzen.</p>
<h4>2. Wie ermittle ich meinen aktuellen Standort</h4>
<p>Im Prinzip wäre GPS das ideale Werkzeug um den aktuellen Standort auf der Welt bestimmen zu können. Da ich jedoch nur ein Notebook auf meinen Dienstreisen zur Verfügung habe, fällt das mit dem GPS aus, denn die wenigsten Notebooks verfügen über GPS – meines schon gar nicht.</p>
<p>Eine weitere Möglichkeit meinen Standort zu bestimmen wäre über die IP Adresse, mit der sich mein Computer über den jeweiligen Provider mit dem Internet verbindet. Nicht sehr genau, aber wenn es um die Zeitzone geht – genau genug.</p>
<p>Eine andere Alternative, die mir erst vor kurzem bekannt wurde, ist die Ermittlung des Standortes via HTML 5 – Voraussetzung hierfür sind ein Browser der diese neue Technologie unterstützt und aktiviertes JavaScript.</p>
<p>Die Umsetzung via HTML 5 ist zudem genauer als der Weg über die IP-Adresse. Ideal wäre also die Verknüpfung beider Techniken.</p>
<p>Da meine Seite aktuell mit der IP-Adresse arbeitet, möchte ich das als Basis der folgenden Abhandlungen nehmen.</p>
<h4>3. Welche zusätzlichen Informationen kann ich noch anzeigen</h4>
<p>Weitere Informationen bietet ASP.NET von allein. IP-Adresse, Sprache, Browser, Auflösung usw.</p>
<p>&nbsp;</p>
<h3>Die Umsetzung:</h3>
<p>Wie schon erwähnt ist ein RSS-Feed nichts anderes als eine XML Datei. Diese wird als Antwort (Response) auf eine Anfrage (Request) vom Webservice zurückgegeben.</p>
<p>Im Prinzip also recht einfach</p>
<ol>
<li>Daten ermitteln</li>
<li>XML erstellen</li>
<li>Daten zurückgeben</li>
</ol>
<h4>Überlegung:</h4>
<p>Welche Daten benötigen wir und welche Daten soll der RSS-Feed zusätzlich enthalten?</p>
<p>Im Prinzip benötigen wir nur drei Werte um die aktuelle Uhrzeit und Zeitzone übermitteln zu können.</p>
<ol>
<li>Die Zeitzone als ID – damit kann dann ganz einfach die passende      Zeitzone auf dem Windows-PC gefunden werden.<br />
(Wie das auf einem MAC OS oder einem Linux Rechner umgesetzt werden kann      wäre eine weitere Überlegung wert)</li>
<li>Die Zeitverschiebung in Stunden (Als Basis gilt hier immer die      koordinierte Weltzeit)</li>
<li>Die Zeitverschiebung in Minuten (Als Basis gilt hier immer die      koordinierte Weltzeit)</li>
</ol>
<p>&nbsp;</p>
<p>Alle weiteren Daten sind Beiwerk und blähen unseren RSS-Feed nur auf. Aber wer kommt denn schon ohne Beiwerk aus?</p>
<p>Interessant sind natürlich auch</p>
<ol>
<li>Die momentane IP-Adresse</li>
<li>Die eingestellte Sprache</li>
<li>Der aktuelle Ort (Stadt) bzw. das Land</li>
<li>Die Region (hier kommen wir später darauf zurück)</li>
<li>Die Geokoordinaten (geographische Länge und Breite)</li>
</ol>
<h4>Umsetzung:</h4>
<p>Die erste Schwierigkeit besteht darin aus der IP-Adresse den aktuellen Standort zu ermitteln.</p>
<p>Hierfür gibt es eine Menge Webservices, die aber alle nicht sehr aktuell sind und ihre Daten nicht so einfach zur Verfügung stellen wollen.</p>
<p>Als die beste aller Möglichkeiten hat sich die <a href="http://www.maxmind.com/app/geolitecity">MaxMind GeoLight City</a> Datenbank in Verbindung mit dem <a href="http://de.googlemaps.subgurim.net/">Google Maps UserControl von SubGurim.net</a> gezeigt.<br />
Nachteil hier – die Datenbank ist 30MB schwer und muss jeden Monat aktualisiert werden, da sich die IP-Adressen ständig ändern. Was soviel heißt wie, je länger der Monat dauert je ungenauer die Angaben.</p>
<p>Abhilfe würde hier die kostenpflichtige Datenbank schaffen – diese ist zwar noch Größer wird aber in einem kürzeren Zyklus aktualisiert. Da ich das Ganze aber nur als Hobby-Projekt umsetzen will, sind mir die Kosten dafür zu hoch.</p>
<p>Die kostenpflichtige Datenbank gibt es ebenfalls <a href="http://www.maxmind.com/app/geolitecity">hier (GeoCity)</a> und kann natürlich auch mit dem gleichen UserControl betrieben werden.</p>
<p>Ich hab mich für das Binary Format der Datenbank entschieden, da diese Version in Verbindung mit dem SubGurim UserControl sehr schnell ist. Die Zugriffszeiten auf meinen RSS-Feed liegen bei etwa 0.5 Sekunden.</p>
<p>Das SubGurim Control wurde für ASP.NET 2.0 entwickelt, arbeitet aber auch im Framework 4 ohne Probleme.</p>
<p>Bindet man nun alles ein – ein Lesen der Dokumentation hilft wie immer weiter - reduziert sich der Code zur Ermittlung der Geokoordinaten auf</p>
<pre>
<pre class="brush: vb; ">

Dim location As Location = GetLocationFromIP(userIP)
</pre>
</pre>
<p>Im Prinzip schon fast alles. Nur war es nicht unser Ziel die Geokoordinaten zu ermitteln, wir wollten die Uhrzeit und Zeitzone am aktuellen Standort ermitteln.</p>
<h4>Anmerkung:</h4>
<p>Die Klasse Location ist hier ein Teil des SubGurim.Net UserControls und enthält neben den GeoKoordinaten auch die ermittelte Stadt, das Land (beides als Klartext) und die Region als Kürzel (z.B. 02 = Bayern, 05 = Hessen).</p>
<p>Da ich für die nächsten Schritte keine weiteren Controls, Dll’s oder anderes frei verfügbares Werkzeug gefunden habe, musste ich die Verknüpfung der Standortdaten zur Zeitzone und das Decodieren des Regionkürzels selbst erledigen.</p>
<h4>Überlegung:</h4>
<p>Ein jeder Punkt dieser Welt gehört einer bestimmten Zeitzone an. Hier gilt es 3 Fälle zu beachten.</p>
<ol>
<li>Länder die als Ganzes einer Zeitzone angehören (z.B. Deutschland,      Österreich, Schweiz)</li>
<li>Länder die mehreren Zeitzonen angehören (z.B. USA, Russland,      Indonesien)</li>
<li>Gebiete die nicht erfasst werden können (Oceane und Wüsten)</li>
</ol>
<p><strong>1. Länder die als Ganzes einer Zeitzone angehören</strong></p>
<p>Die einfachste Form, die Inhalte der Klasse Location können direkt zur Ermittlung der Zeitzone herangezogen werden.</p>
<p>Vereinfacht: Land = Zeitzone = Zeitverschiebung</p>
<p><strong>2. Länder die mehreren Zeitzonen angehören</strong></p>
<p>Nicht mehr ganz so einfach. Die Zeitzone wird hier anhand des Landes und der Region bestimmt.</p>
<p>Vereinfacht: Land (z.B. USA) - Region (z.B. CA - Kalifornien) = Zeitzone = Zeitverschiebung</p>
<p>Sonderfall: Eine Region enthält mehrere Zeitzonen (z.B. USA/Indiana – Eastern- und Central Time)</p>
<p>Hierfür habe ich noch keine Lösung – mir fehlen die genauen Daten – aber vermutlich wird es dann eine weitere Unterteilung anhand der ermittelten Stadt geben.</p>
<p>Land (z.B. USA) – Region (z.B. IN - Indiana) – Stadt (?) = Zeitzone = Zeitverschiebung</p>
<p><strong>3. Gebiete die nicht erfasst werden können</strong></p>
<p>Da es auf dem Meer oder in der Wüste keinen Provider bzw. keine Empfang gibt, kann dieser Fall ausgeschlossen werden.</p>
<p>Lösung hierfür wäre eine Ermittlung des Standortes via Geokoordinaten (GPS), was im Moment noch nicht umgesetzt wurde.</p>
<p>Die beschriebene Funktionalität hab ich in eine DLL gepackt, das alles beschreiben zu wollen würde hier aber zu weit führen.</p>
<p>Die Punkte 1. und 2. werden komplett durch eine List(of Structure) abgebildet, die alle Länder dieser Welt, inkl. den unter 2. beschriebenen Fällen, enthält.</p>
<pre>
<pre class="brush: vb; ">

    Public Structure myTimeZone
        Public Country As String
        Public Region As String
        Public TimeZoneInfo As TimeZoneInfo

        Public Sub New(ByVal c As String, ByVal r As String, ByVal tzi As TimeZoneInfo)
            Country = c
            Region = r
            TimeZoneInfo = tzi
        End Sub
    End Structure

Private mytimezones As New List(Of myTimeZone)
</pre>
</pre>
<p>Die Klasse „TimeZoneInfo“ ist schon Bestandteil des Frameworks und bildet die auf dem jeweiligen System installierten Zeitzonen ab.</p>
<p>Die durch das SubGurim.Net UserControl bereitgestellten Informationen (Klasse Location) dienen somit als Filter für die Suche innerhalb der Liste. Die dadurch ermittelten Daten können nun den RSS-Feed füllen.</p>
<h3>Erstellen eines RSS-Feeds:</h3>
<p>Wie schon erwähnt ist ein RSS-Feed nichts anderes als eine XML-Datei welche durch eine Webseite zurückgegeben wird.</p>
<p>Dies kann auf vielfältige Art und Weiße geschehen.</p>
<p>Anfangs erstellte ich meinen Feed innerhalb einer WebForm (*.aspx). Später jedoch bin ich auf eine <a href="http://www.aspcode.net/Creating-an-RSS-feed-for-your-ASPNET-site.aspx">Methode</a> gestoßen, die mir eleganter erschien, nämlich das Erstellen eines RSS-Feeds mittels eines „Generic Handlers“ (*.ashx)</p>
<p>Im Prinzip wird nichts anderes gemacht, als den kompletten Feed mittels LINQ zusammenzubauen und am Schluss als Response zurückzugeben.</p>
<pre>
<pre class="brush: vb; ">

Dim doc As New XDocument()

Dim rss As New XElement(&quot;rss&quot;)
rss.Add(New XAttribute(&quot;version&quot;, &quot;2.0&quot;))

Dim channel As New XElement(&quot;channel&quot;)
rss.Add(channel)

channel.Add(New XElement(&quot;title&quot;, &quot;The TimeZoneNotifier RSS-Feed&quot;))
channel.Add(New XElement(&quot;link&quot;, &quot;http://TimeZoneNotifier.free-file-download.de&quot;))
channel.Add(New XElement(&quot;description&quot;, &quot;This site detects the timezone you&#039;re currently staying in !&quot;))
channel.Add(New XElement(&quot;ttl&quot;, &quot;60&quot;))

Dim item As New XElement(&quot;item&quot;)

Channel.Add(item)

item.Add(New XElement(&quot;userIP&quot;, userIP))
item.Add(New XElement(&quot;userBrowser&quot;, userBrowser))
item.Add(New XElement(&quot;userLanguage&quot;, userLanguage))
item.Add(New XElement(&quot;userCity&quot;, userCity))
item.Add(New XElement(&quot;userRegion&quot;, userRegion))
item.Add(New XElement(&quot;userLongitude&quot;, userLongitude))
item.Add(New XElement(&quot;userLatitude&quot;, userLatitude))
item.Add(New XElement(&quot;userTimeOffsetHours&quot;, userTimeOffsetHours))
item.Add(New XElement(&quot;userTimeOffsetMinutes&quot;, userTimeOffsetMinutes))
item.Add(New XElement(&quot;CurrentUTCTime&quot;, CurrentUTCTime.ToString))
item.Add(New XElement(&quot;userTimeZone&quot;, userTimeZone))

doc.Add(rss)
</pre>
</pre>
<p>(Den RSS-Feed wie er dann ausgegeben wird, sehen Sie am Ende dieses Artikels)</p>
<p>Sind wir erst einmal hier angekommen, wurde die meiste Arbeit schon erledigt. Der Rest besteht nur noch im Anzeigen der ermittelten Daten.</p>
<h3>Anzeigen der Daten mittels einer WebForm:</h3>
<p>Hier zum Verständnis, noch der Code für die Anzeige der Daten.</p>
<p>Da wir den Feed mittels einer Webanwendung abfragen, sind manche Informationen für den RSS-Feed nicht sichtbar. Bei diesen Daten verwerfen wir die Informationen die der RSS-Feed enthält einfach und füllen die Ausgabe mit den Werten der WebForm.</p>
<pre>
<pre class="brush: vb; ">

Protected Sub Page_Load(ByVal sender As Object, _
                    ByVal e As System.EventArgs) Handles Me.Load

if Postback Then
&#039;RSS-Feed holen
    Dim retRss As New Xml.XmlDocument
    retRss.Load(&quot;http://timezonenotifier.free-file-download.de/rss.ashx?ip=&quot; &amp;amp;amp; _
                Request.UserHostAddress)
    &#039;IP-Adresse das Feeds stimmt
    Me.LabelIP.Text = retRss.SelectSingleNode(&quot;/rss/channel/item/userIP&quot;).InnerText
    &#039;Wurde eine nicht gültige IP-Adresse erkannt -&gt; Anzeigen der Daten abbrechen
    If Me.LabelIP.Text = &quot;No valid IP-Adress !!&quot; Then
        Exit Sub
    End If
    &#039;Kein Browser im RSS-Feed vorhanden, da vom Server aus angefragt wird
    Me.LabelBrowser.Text = Request.Browser.Browser
    &#039;Keine Sprache im RSS-Feed vorhanden, da vom Server aus angefragt wird
    Try
        Dim ci As New CultureInfo(Request.UserLanguages(0))
        Me.LabelLanguage.Text = ci.DisplayName
    Catch ex As Exception
        Me.LabelLanguage.Text = &quot;Unknown&quot;
    End Try
    &#039;erkannte Stadt
    Me.LabelCity.Text =
        retRss.SelectSingleNode(&quot;/rss/channel/item/userCity&quot;).InnerText
    &#039;erkannte Region
    Me.LabelRegion.Text =
        retRss.SelectSingleNode(&quot;/rss/channel/item/userRegion&quot;).InnerText
    &#039;erkannte Geogr. Länge
    Me.LabelLong.Text =
        retRss.SelectSingleNode(&quot;/rss/channel/item/userLongitude&quot;).InnerText
    &#039;erkannte Geogr. Breite
    Me.LabelLat.Text =
        retRss.SelectSingleNode(&quot;/rss/channel/item/userLatitude&quot;).InnerText
    &#039;erkannte Zeitverschiebung
    Dim _offsethours As Integer =
        CInt(retRss.SelectSingleNode(&quot;/rss/channel/item/userTimeOffsetHours&quot;).InnerText)
    Dim _offsetminutes As Integer =
        CInt(retRss.SelectSingleNode(&quot;/rss/channel/item/userTimeOffsetMinutes&quot;).InnerText)
    &#039;aktuelle Zeit am Standort berechnen
    Dim tempRSS As String =
        retRss.SelectSingleNode(&quot;/rss/channel/item/CurrentUTCTime&quot;).InnerText
    Me.LabelCurrentTime.Text =
        CDate(tempRSS).AddHours(_offsethours).AddMinutes(_offsetminutes).ToLongDateString &amp;amp;amp; &quot; - &quot; &amp;amp;amp; CDate(tempRSS).AddHours(_offsethours).AddMinutes(_offsetminutes).ToLongTimeString

    Me.LabelCurrentTimeDiff.Text = _offsethours.ToString &amp;amp;amp; _
        &quot; h &quot; &amp;amp;amp; _offsetminutes.ToString &amp;amp;amp; &quot; min&quot;
    &#039;erkannte Zeitzone
    Me.LabelCurrentTimezone.Text =
        retRss.SelectSingleNode(&quot;/rss/channel/item/userTimeZone&quot;).InnerText
Else
    &#039;kein Postback
End If
End Sub
</pre>
</pre>
<h3>Die Ergebnisse meiner Arbeit:</h3>
<p>Das oben beschriebene hab ich unter <a href="http://timezonenotifier.free-file-download.de/">http://timezonenotifier.free-file-download.de</a> als ASP.NET Webseite veröffentlicht.<br />
Den RSS-Feed gibt es unter <a href="http://timezonenotifier.free-file-download.de/rss.ashx">http://timezonenotifier.free-file-download.de/rss.ashx</a><br />
RSS-Feed (mein Standort)<br />
&lt;pre&gt;
<pre class="brush: xml; ">

&lt;rss version=&quot;2.0&quot;&gt;
    &lt;channel&gt;
        &lt;title&gt;The TimeZoneNotifier RSS-Feed&lt;/title&gt;
        &lt;link&gt;http://TimeZoneNotifier.free-file-download.de&lt;/link&gt;
        &lt;description&gt;
            This site detects the timezone you&#039;re currently staying in !
        &lt;/description&gt;
        &lt;ttl&gt;60&lt;/ttl&gt;
        &lt;item&gt;
            &lt;userIP&gt;79.249.177.227&lt;/userIP&gt;
            &lt;userBrowser&gt;Chrome&lt;/userBrowser&gt;
            &lt;userLanguage&gt;Deutsch (Deutschland)&lt;/userLanguage&gt;
            &lt;userCity&gt;Mering / Germany&lt;/userCity&gt;
            &lt;userRegion&gt;Bayern&lt;/userRegion&gt;
            &lt;userLongitude&gt;10,9833&lt;/userLongitude&gt;
            &lt;userLatitude&gt;48,2667&lt;/userLatitude&gt;
            &lt;userTimeOffsetHours&gt;2&lt;/userTimeOffsetHours&gt;
            &lt;userTimeOffsetMinutes&gt;0&lt;/userTimeOffsetMinutes&gt;
            &lt;CurrentUTCTime&gt;07.06.2011 09:40:14&lt;/CurrentUTCTime&gt;
            &lt;userTimeZone&gt;
                (UTC+01:00) Amsterdam, Berlin, Bern, Rom, Stockholm, Wien
            &lt;/userTimeZone&gt;
       &lt;/item&gt;
    &lt;/channel&gt;
&lt;/rss&gt;
</pre>
<p><strong><span style="text-decoration: underline;">Quellen:</span></strong></p>
<p><strong><span style="text-decoration: underline;"> </span></strong></p>
<p><a href="http://www.maxmind.com/app/geolitecity">http://www.maxmind.com/app/geolitecity</a><br />
<a href="http://de.googlemaps.subgurim.net/">http://de.googlemaps.subgurim.net/</a><br />
<a href="http://lukencode.com/2010/05/19/ip-to-geo-location-in-asp-net-mvc/">http://lukencode.com/2010/05/19/ip-to-geo-location-in-asp-net-mvc/</a><br />
<a href="http://www.aspcode.net/Creating-an-RSS-feed-for-your-ASPNET-site.aspx">http://www.aspcode.net/Creating-an-RSS-feed-for-your-ASPNET-site.aspx</a></p>
<p><strong><span style="text-decoration: underline;">Copyright:</span></strong></p>
<p>Die Rechte der verwendeten Datenbanken und des UserControls liegt bei den Autoren.</p>
<p>Der angebotene RSS-Feed darf frei verwendet werden – eine Nennung der Quelle des Feeds bzw. der Adresse dieses Artikels wird vorausgesetzt.</p>
<p>Ein Dank geht an Sebastian Gross der mir einige Anregungen gegeben hat.</p>
<p>Dieser Service bleibt kostenlos, die Bedingungen zur Nutzung des RSS-Feed können sich jedoch jederzeit ändern.</p>
<h3>Über den Autor</h3>
<p><img class="alignleft" src="http://server.bigbasti.com/uploads/uploads/86211149149524767.png" alt="" width="134" height="100" /></p>
<p><strong>Michael   Bernhard</strong><br />
Hobby-Programmierer von VB.NET, C# und   ASP.NET Anwendungen. Hauptberuflich als Inbetriebnehmer bei der <a href="http://www.boewe-systec.de/">Böwe Systec GmbH</a> beschäftigt. Vorzeigbare Projekte – <a href="http://timezonenotifier.free-file-download.de/">TimeZone Notifier</a> und <a href="http://www.tsv-neusaess-junioren.de/">TSV Neusäß Junioren</a>.</p>
<p><a href="http://dotnet-kicks.de/kick/?url=http%3a%2f%2fblog.bigbasti.com%2fentstehung-einer-asp-net-webanwendung-anhand-eines-beispiels%2f"><img src="http://dotnet-kicks.de/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.bigbasti.com%2fentstehung-einer-asp-net-webanwendung-anhand-eines-beispiels%2f" border="0" alt="kick it on dotnet-kicks.de" /></a></p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1724&amp;md5=bd784c748bb963ab313ceb590366fd31" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/entstehung-einer-asp-net-webanwendung-anhand-eines-beispiels/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unterlagen zu meinem &#8216;ASP.NET MVC 3 von 0 an&#8217; Vortrag</title>
		<link>http://blog.bigbasti.com/unterlagen-zu-meinem-asp-net-mvc-3-von-0-an-vortrag/</link>
		<comments>http://blog.bigbasti.com/unterlagen-zu-meinem-asp-net-mvc-3-von-0-an-vortrag/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 19:19:29 +0000</pubDate>
		<dc:creator>Sebastian Gross</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/?p=1631</guid>
		<description><![CDATA[Gestern am 04.04.2011 habe ich für die .NET Online Usergroup einen Vortrag für ASP.NET MVC 3 Einsteiger gegeben, vielleicht wart ihr sogar dabei.

Da schnell die Frage nach den Folien und dem Beispielcode der während der Präsentation entstand aufkam, möchte ich diese hiermit nachliefern.
Installation
In meinem Vortrag ging ich nicht darauf ein, wie man ASP.NET MVC ...]]></description>
			<content:encoded><![CDATA[<p>Gestern am 04.04.2011 habe ich für die .NET Online Usergroup einen Vortrag für ASP.NET MVC 3 Einsteiger gegeben, vielleicht wart ihr sogar dabei.</p>
<p>Da schnell die Frage nach den Folien und dem Beispielcode der während der Präsentation entstand aufkam, möchte ich diese hiermit nachliefern.</p>
<h3>Installation</h3>
<p>In meinem Vortrag ging ich nicht darauf ein, wie man ASP.NET MVC installiert, dies will ich hiermit nachliefern. Die Installation erfolgt schnell und einfach über den ASP.NET MVC Installer den ihr auf der <a href="http://www.asp.net/mvc/mvc3" target="_blank">ASP.NET MVC Homepage</a> bekommt oder über diesen <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=d2928bc1-f48c-4e95-a064-2a455a22c8f6&amp;displaylang=en" target="_blank">Direktlink</a>. Die Installation an sich ist nicht weiter erwähnenswert <img src='http://blog.bigbasti.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
Nach der Installation werden ihr die Projektvorlage in Visual Studio vorfinden.</p>
<h3>Kostenlos ASP.NET MVC Entwickeln</h3>
<p>Falls ihr keine Visual Studio Lizenz besitzt könnt ihr den Visual Web Developer benutzen um MVC zu entwickeln:<br />
<a href="http://www.microsoft.com/germany/express/products/web.aspx">http://www.microsoft.com/germany/express/products/web.aspx</a></p>
<h3>Aufzeichnung</h3>
<p><object width="400" height="225"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=22117382&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=1&amp;color=00ADEF&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" /><embed type="application/x-shockwave-flash" width="400" height="225" src="http://vimeo.com/moogaloop.swf?clip_id=22117382&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=1&amp;color=00ADEF&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><a href="http://vimeo.com/22117382">ASP.NET MVC von 0 an</a> from <a href="http://vimeo.com/noug">.NET Online User Group</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<h3>Präsentation</h3>
<p><a href="http://server.bigbasti.com/uploads/uploads/asp.net_mvc_von_0_an.pptx "><img class=" alignnone" title="Die Präsentation im Powerpoint 2010 (PPTX) Format" src="http://server.bigbasti.com/uploads/uploads/66211231723871999.png" alt="" /></a> <a href="http://server.bigbasti.com/uploads/uploads/asp.net_mvc_von_0_an.pdf "><img class="alignnone" title="Die Präsentation als PDF (Ohne Aanimationen)" src="http://server.bigbasti.com/uploads/uploads/662112317363681999.png" alt="" /></a></p>
<h3>Code (mit Kommentaren)</h3>
<p><a href="http://server.bigbasti.com/uploads/uploads/MyMVCGuestbook.zip "><img class="alignnone" title="Download das Projekt aus dem Vortrag" src="http://server.bigbasti.com/uploads/uploads/662112317592981999.png" alt="" /></a></p>
<h3>Feedback &amp; Fragen</h3>
<p>Falls du bei dem Vortrag dabei warst und noch Fragen hast oder einen (Verbesserungs)vorschlag oder Feedback hast kannst du das auch gerne als Kommentar posten.</p>
<p>Bis zum nächsten Mal!</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1631&amp;md5=de19ebed67eb6357342a957ce2b030a9" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/unterlagen-zu-meinem-asp-net-mvc-3-von-0-an-vortrag/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC3: Remote Attribut &#8220;richtig&#8221; nutzen</title>
		<link>http://blog.bigbasti.com/asp-net-mvc3-remote-attribut-richtig-nutzen/</link>
		<comments>http://blog.bigbasti.com/asp-net-mvc3-remote-attribut-richtig-nutzen/#comments</comments>
		<pubDate>Thu, 11 Nov 2010 23:16:32 +0000</pubDate>
		<dc:creator>Sebastian Gross</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[VB]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/asp-net-mvc3-remote-attribut-richtig-nutzen/</guid>
		<description><![CDATA[Seit gestern probiere ich die neuen Attribute in dem ASP.NET MVC3 RC aus und bin eigentlich sehr zufrieden. Nur ein Attribut wollte bisher einfach nicht funktionieren, nämlich das Remote-Attribut.

In den offiziellen Release Notes ist dieses Attribut beschrieben und es wird folgendes Beispiel benutzt um es dem Leser näher zubringen:



Dies habe ich auch als Vorlage ...]]></description>
			<content:encoded><![CDATA[<p>Seit gestern probiere ich die neuen Attribute in dem ASP.NET MVC3 RC aus und bin eigentlich sehr zufrieden. Nur ein Attribut wollte bisher einfach nicht funktionieren, nämlich das Remote-Attribut.</p>
<p>In den offiziellen <a href="http://goo.gl/ZaKwr" target="_blank">Release Notes</a> ist dieses Attribut beschrieben und es wird folgendes Beispiel benutzt um es dem Leser näher zubringen:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image10.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb10.png" border="0" alt="image" width="442" height="186" /></a></p>
<p>Dies habe ich auch als Vorlage genommen und meine Methode im Controller implementiert:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image11.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb11.png" border="0" alt="image" width="575" height="200" /></a></p>
<p>Doch das hat nicht funktioniert. Nun weiß ich auch wieso, denn hier wird ein falsches Ergebnis zurück gesendet. Das Ergebnis dieser Methode liefert ein “False” oder “True” ab, mit einem großen Buchstaben am Anfang – und das macht uns alles kaputt!</p>
<p>Hier ist unser Request den jQuery für uns erzeugt:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image12.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb12.png" border="0" alt="image" width="553" height="359" /></a></p>
<p>Dieser Request kommt erfolgreich auf dem Server an und wird korrekt verarbeitet. Als Response kommt dann folgendes zurück:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image13.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb13.png" border="0" alt="image" width="599" height="119" /></a></p>
<p>Man beachte hier das großgeschriebene “False”. Also arbeitet der Controller völlig korrekt, nur müsste er ein kleines “false” zurückgeben.</p>
<p>Nun wenn man es Quick &amp; Dirty haben will kann man einfach einen String zurückgeben:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image14.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb14.png" border="0" alt="image" width="549" height="199" /></a></p>
<p>Der bessere Weg wäre wohl ein JSON Result:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image15.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb15.png" border="0" alt="image" width="547" height="195" /></a></p>
<p>Nun funktioniert auch alles wie es soll und ich kann ruhig schlafen <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://blog.bigbasti.com/uploads/wlEmoticon-smile1.png" alt="Smiley" /></p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1412&amp;md5=7fd2cfde77871e94509952a248bf83f9" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/asp-net-mvc3-remote-attribut-richtig-nutzen/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC3: Was gibts neues?</title>
		<link>http://blog.bigbasti.com/asp-net-mvc3-was-gibts-neues/</link>
		<comments>http://blog.bigbasti.com/asp-net-mvc3-was-gibts-neues/#comments</comments>
		<pubDate>Thu, 11 Nov 2010 19:53:00 +0000</pubDate>
		<dc:creator>Sebastian Gross</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/asp-net-mvc3-was-gibts-neues/</guid>
		<description><![CDATA[Einige von euch haben es sicher mitbekommen, dass vor Kurzem der Release Candidate (RC) von ASP.NET MVC3 veröffentlich wurde. Download, Changelog. Diese neue Version bringt einige für uns Entwickler tolle neue Funktionen und Vereinfachungen mit.

Die wohl auffälligste Neuerung ist die neue ViewEngine namens Razor, diese sorgt dafür, dass die Views um einiges schlanker und ...]]></description>
			<content:encoded><![CDATA[<p>Einige von euch haben es sicher mitbekommen, dass vor Kurzem der Release Candidate (RC) von ASP.NET MVC3 veröffentlich wurde. <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=a920ccee-1397-4feb-824a-2dfefee47d54&amp;displaylang=en">Download</a>, <a href="http://www.asp.net/learn/whitepapers/mvc3-release-notes">Changelog</a>. Diese neue Version bringt einige für uns Entwickler tolle neue Funktionen und Vereinfachungen mit.</p>
<p>Die wohl auffälligste Neuerung ist die neue ViewEngine namens Razor, diese sorgt dafür, dass die Views um einiges schlanker und lesbarer werden durch die Einführung einer neuen Syntax.</p>
<p>Ich will mit euch ein kleines Beispielprojekt erstellen in dem wir Schritt für Schritt einige der Neuerungen durchgehen.</p>
<p>Fangen wir an und erstellen ein neues MVC3 Projekt in Visual Studio und bereits hier gibts es was Neues zu betrachten:</p>
<p><img src="http://blog.bigbasti.com/uploads/new-proj.png" alt="" /></p>
<p><em>Bild 1: Der Neue Projekt erstellen Dialog</em></p>
<p>Da wir von Vorn beginnen möchten erstellen wir ein neues Leeres Projekt und wählen die neue Razor ViewEngine.</p>
<p><strong>Layout</strong></p>
<p>Wenn man nun einen Blick auf den Projektmappenexplorer wirft, wird man drin nicht viel finden, lediglich eine CSS- und zwei cshtml-Dateien. Die cshtml-Dateien fangen auch noch mit einem Unterstrich (_) an und haben irgendwas mit Layout im Namen.</p>
<p>Was ist das?</p>
<p>Öffnen wir zunächst im Shared-Ordner die Datei _Layout.cshtml.</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb.png" border="0" alt="image" width="608" height="282" /></a></p>
<p>Diese Datei kann man mit einer MasterPage aus MVC2 vergleichen. Wenn ihr genau hinschaut werdet ihr im Title-Tag einen Platzhalter finden und auch im body-div ist einer namens „@RenderBody()“.</p>
<p>Die Layoutseiten in MVC3 funktionieren anders als die in MVC2, auch wenn diese Seite auch Platzhalter besitzt die später mit Inhalt befüllt werden fällt dennoch die Methode RenderBody() auf. Diese Methode ist in jeder Layout-Seite drin und steht immer an der Stelle wo später der Inhalt der Seite  stehen wird. Neben der RenderBody()-Methode gibt es auch die RenderSection()-methode, die auch einen Namen bekommen und auch als optional markiert werden können.</p>
<p>Was auch neu ist, ist dass wir keine &lt;% %&gt; Tags mehr haben in die wir den ASP.NET Code schrieben können, das alles übernimmt nun das @-Zeichen. Das System ist dabei so intelligent, dass es erkennt bis wohin der Code geht weswegen man auch kein schließen Tag benötigt. <a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx">Weitere Informationen zu der Razor Syntax</a>.</p>
<p>Wie man sieht sind die ganzen JavaScript Verweise auskommentiert. Bitte entfernt die Kommentarmarkierung, da wir diese Skripte bald benötigen.</p>
<p>Gut, schleißen wir diese Datei und werfen nun einen Blick in die „_ViewStat.cshtml“ in unserem Views-Ordner:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image1.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb1.png" border="0" alt="image" width="383" height="54" /></a></p>
<p>Der Inhalt hier ist wie man sieht sehr übersichtlich <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://blog.bigbasti.com/uploads/wlEmoticon-smile.png" alt="Smiley" /></p>
<p>Was macht diese Datei nun? Wie man sieht verweist diese auf die _Layout.cshtml die wir eben betrachtet haben, dabei sorgt dieser Verweis dafür, dass alle Views in dem Views-Ordner inkl Unterordner diesen Verweis auch erhalten. Das hat zur Folge, dass man nun nicht mehr in jeder einzelnen View diese Referenz auf die Layoutdatei eintragen muss und spart sich so den redundanten Code.</p>
<p>Viel mehr gibt es dazu eigentlich auch nicht zu sagen. Gehen wir nun zum nächsten Schritt und erstellen eine neue View.</p>
<p><strong>Views</strong></p>
<p>Wenn ihr den View-Hinzufügen Dialog wählt werdet ihr auch hier eine Veränderung feststellen:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb2.png" border="0" alt="image" width="384" height="388" /></a></p>
<p>Wie man sieht kann man nun auch bei jeder einzelnen View wählen, welche ViewEngine man hier gern verwenden möchte. Legen wir eine gewöhnliche View an.</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image3.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb3.png" border="0" alt="image" width="412" height="112" /></a></p>
<p>Die neue View enthält nun nur diese paar Zeilen Code (siehe Bild oben).</p>
<p>Zuerst wird ein Codeblock aufgemacht mit der @{ … } Syntax, das bedeutet, dass nun nur noch ASP.NET Code kommt bis die schließen Klammer kommt, auch über mehrere Zeilen.</p>
<p>Innerhalb dieses Codeblocks füllen wir nun den Titel unserer Seite, wenn ihr euch erinnern könnt wurde diese Variable in der MasterPage im Title-Tag wieder ausgegeben.</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image4.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; float: left; padding-top: 0px; border-width: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb4.png" border="0" alt="image" width="353" height="115" align="left" /></a></p>
<p>Man beachte hier, dass diese Property dynamisch erstellt wird und es die Property „Title“ eigentlich gar nicht gibt. Diese wird dann zur Laufzeit generiert und mit Inhalt befüllt. So kann man beliebig viele solcher Properties anlegen.</p>
<p>In Zeile 3 geben wir an welche MasterPage hier verwendet werden soll, da wir aber bereits die Datei „_ViewStat.cshtml“ in unserem Views-Ordner liegen haben müssen wir innerhalb der View keinen Verweis mehr auf eine Masterpage setzen. (Außer wir wollen eine andere Nutzen) Also können wir diese Zeile aus unserem Code löschen.</p>
<p>Nun fängt schon ab Zeile 6 der normale HTML Quelltext an, ohne dass wir irgendwo einen Zugehörigkeitsbereich definiert haben. Das ist ein weiteres MVC3 / Razor Feature, denn alles wird an der stelle in der MasterPage eingesetzt wo wir die Methode RenderBody() aufrufen. Eine Ausnahme besteht, wenn wir Sektionen in der Masterpage definiert haben, diese würden dann dementsprechend der passenden Sektion zugeordnet werden.</p>
<p>So könnte eine Sektion aussehen:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image5.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb5.png" border="0" alt="image" width="327" height="107" /></a></p>
<p>Das wars nun soweit zu dieser View. Wenn ihr mögt könnt ihr nun weiter damit arbeiten wie mit einer gewöhnlichen View.</p>
<p>Nun wollen wir mal ein Formular anlegen, dass wir zum Registrieren eines Benutzers nutzen wollen. Dazu benötigen wir zunächst ein Model auf das wir dann unsere View mit der Form  typisieren.</p>
<p>Legen wir also eine neue Klasse im Models-Verzeichnis an. Die Model Klassen verhalten sich in MVC3 eigentlich genauso wie in MVC2, nun sind aber einige neue Attribute hinzugekommen die ich euch hier mal vorstellen möchte:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image6.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb6.png" border="0" alt="image" width="444" height="406" /></a></p>
<p>Wie ihr seht hat meine Modelklasse 5 Eigenschaften. Die ersten drei sind mit dem Attribut [Required] markiert und sind somit Pflichtfelder. Alle Eigenschaften besitzen ein [DisplayName()] Attribut, dass den Text enthält, der später in der View angezeigt werden soll.</p>
<p>Kommen wir nun zu den neuen Attributen. Erstmal das [Required, Compare(…)] Attribut. Dieses Attribut sorgt hier dafür, dass „RepeatEmail“ mit „Email“ verglichen wird und übereinstimmen muss damit die Validierung erfolgreich ist. So müssen wir diese zwei Werte nun nicht mehr im Controller manuell vergleichen.</p>
<p>Weiter unten bei der About-Eigenschaft finden wir ein weiteres neues Attribut namens [SkipRequestValidation] – Im Prinzip sagt der Name schon alles aus. Dieses Attribut sorgt dafür, dass diese Property beim Binding keine Exception wirft wenn dort HTML enthalten ist.</p>
<p>Früher musste man dann im Controller die Action mit einem [ValidateInput(false)] markieren, was natürlich immer noch funktioniert, aber nun kann man auch einzelne Properties bequem markieren ohne gleich für die ganze Methode den Validationinput abzuschalten.</p>
<p>Hier gibts es nun sogar die Möglichkeit bestimmte Properties von der Validierung auszuschließen:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image7.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb7.png" border="0" alt="image" width="371" height="66" /></a></p>
<p>Hier werden die Properties “Body” und “Summary” nicht auf HTML Inhalt überprüft.</p>
<p>Wie ihr sehen könnt habe ich ein Attribut auskommentiert. Auf dieses Attribut habe ich mich persönlich sehr gefreut, aber es scheint nicht zu funktionieren (oder ich mache etwas falsch, wenn ihr meinen Fehler seht bitte kommentieren ACHTUNG: dazu habe ich<a href="http://blog.bigbasti.com/asp-net-mvc3-remote-attribut-richtig-nutzen/" target="_blank"> hier ein Update</a> geschrieben)</p>
<p>Dieses RemoteAttribut erlaubt es eine Eigenschaft an eine Methode in einem Controller zu binden und währen der Ausführung der View beim Client im Hintergrund über Ajax aufzurufen. Für den Fall von der Property Name würde die Methode UserNameAvailabla im Controller Register aufgerufen werden, welche ein boolean zurück gibt. So wird dann dynamisch eine Fehlermeldung auf der View erscheinen.</p>
<p>Wenn man dieses RemoteAttribut nun benutzen möchte muss man natürlich die oben angegebene Methode im angegebenen Controller implementieren, zB so:</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image8.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px initial initial;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb8.png" border="0" alt="image" width="724" height="185" /></a></p>
<p>Diese Methode wird dann beim Validieren per Ajax aufgerufen und zeigt dann dementsprechend auch eine Fehlermeldung an (Falls nötig):</p>
<p><a class="thickbox" href="http://blog.bigbasti.com/uploads/image9.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://blog.bigbasti.com/uploads/image_thumb9.png" border="0" alt="image" width="489" height="50" /></a></p>
<p>Zum Schluss möchte ich noch darauf hinweisen, dass ich ein bestimmtes kleines Feature vermisst habe, nämlich eine bequeme Möglichkeit einen String auszugeben ohne diesen mit HTML zu Encoden. Denn soweit bietet Razor leider keine Möglichkeit dafür. Deswegen muss man hier mit einer eigenen kleinen Extension Methode aushelfen.</p>
<p>Das wäre es dann nun auch für heute. Ich habe ein kleines Beispiel Projekt vorbereitet, dass ihr <a href="http://blog.bigbasti.com/uploads/NewAttributes.zip" target="_blank">hier herunterladen</a> könnt. (.NET 4.0 VS2010)</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1396&amp;md5=401b772f11d0ab6d2e5710989c59b794" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/asp-net-mvc3-was-gibts-neues/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC 2: Custom ErrorPages anlegen</title>
		<link>http://blog.bigbasti.com/asp-net-mvc-2-custom-errorpages-anlegen/</link>
		<comments>http://blog.bigbasti.com/asp-net-mvc-2-custom-errorpages-anlegen/#comments</comments>
		<pubDate>Thu, 21 Oct 2010 13:17:21 +0000</pubDate>
		<dc:creator>Sebastian Gross</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://blog.bigbasti.com/?p=1323</guid>
		<description><![CDATA[Wenn man Webseiten entwickelt möchte man diese natürlich möglichst anschaulich für den Nutzer gestalten, und dazu gehört es auch für den Benutzer anschauliche und auch verständliche Seiten zu präsentieren, auch wenn mal ein Fehler auftaucht. Im Normalfall passen die Default-Fehlerseiten von ASP.NET leider nicht ins Bild der restlichen Seite, weswegen wir gezwungen sind unsere ...]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.bigbasti.com/uploads/error404_alt.png"><img class="alignleft size-medium wp-image-1324" title="error404_alt" src="http://blog.bigbasti.com/uploads/error404_alt-300x230.png" alt="" width="126" height="97" /></a>Wenn man Webseiten entwickelt möchte man diese natürlich möglichst anschaulich für den Nutzer gestalten, und dazu gehört es auch für den Benutzer anschauliche und auch verständliche Seiten zu präsentieren, auch wenn mal ein Fehler auftaucht. Im Normalfall passen die Default-Fehlerseiten von ASP.NET leider nicht ins Bild der restlichen Seite, weswegen wir gezwungen sind unsere eigenen Fehlerseiten anzulegen.</p>
<p style="text-align: center;"><a href="http://blog.bigbasti.com/uploads/404errorpagedefault.png"><img class="aligncenter size-full wp-image-1327" title="404errorpagedefault" src="http://blog.bigbasti.com/uploads/404errorpagedefault.png" alt="" width="452" height="240" /></a><em>Bild 1: Typische 404 Fehlermeldung von ASP.NET</em></p>
<p>Eigene Fehlerseiten sind unter ASP.NET MVC 2 schnell in vier Schritten eingerichtet.</p>
<p><strong>1. Änderungen an der Web.config vornehmen</strong></p>
<p>Zunächst müssen in der Web.config die <a href="http://msdn.microsoft.com/de-de/library/h0hfz6fc%28VS.80%29.aspx" target="_blank">customErrors</a> eingeschaltet werden. Hier können die Attribute "defaultRedirect", welches die Adresse definiert die im Falle eines Fehlers aufgerufen wird und "mode", dass einstellt ob Fehler angezeigt werden sollen oder nicht.</p>
<p><a href="http://blog.bigbasti.com/uploads/xmlcode.png"><img class="aligncenter size-full wp-image-1330" title="xmlcode" src="http://blog.bigbasti.com/uploads/xmlcode.png" alt="" width="499" height="95" /></a>Mit den inneren "error"-Ästen kann man dazu noch spezifische Seiten zu einzelnen Fehlercodes zuweisen. Man kann hier sowohl eine  absolute Adresse angeben oder nur eine relative. Für alle nicht spezifizierten Errorcodes wird die Url aus dem customError Tag benutzt.</p>
<p>Wenn ihr diese Einstellungen Lokal testen wollt dann solltet ihr auch den "mode" auf "On" stellen, da ihr euere Seiten sonst nicht zu Gesicht bekommt.</p>
<p><strong>2. Anlegen des Controllers für die Fehlerbehandlung</strong></p>
<p>Wie ihr sehen könnt habe ich hier eine lokale Adresse angegeben. Hierbei wird der Controller "Error" aufgerufen und je nach Fehlercode eine andere Methode.</p>
<p>Im Controller haben wir hier eigentlich nichts besonderes:</p>
<p><a href="http://blog.bigbasti.com/uploads/contollercode.png"><img class="aligncenter size-full wp-image-1332" title="contollercode" src="http://blog.bigbasti.com/uploads/contollercode.png" alt="" width="569" height="426" /></a>Ich war an dieser Stelle mal faul und habe nur eine einzige View für alle Fehler angelegt, die dann die übergebene message ausgibt. Dazu kommt noch, dass wir der Response noch den passenden HttpStatusCode übergeben, da manche Anwendungen danach gehen und so prüfen, ob ein Aufruf erfolgreich war.</p>
<p><strong>3. Die View</strong></p>
<p>Wie eben erwähnt macht die View in meinem Beispiel nichts anderes als den Inhalt der Messagevariable auszugeben. Hier könnt ihr natürlich eurer Kreativität freien Lauf lassen und auch für jeden Error eine einzelne View anfertigen.</p>
<p><a href="http://blog.bigbasti.com/uploads/viewcontent.png"><img class="aligncenter size-full wp-image-1334" title="viewcontent" src="http://blog.bigbasti.com/uploads/viewcontent.png" alt="" width="547" height="83" /></a><strong>4. Glogal.asax - Catch All Route registrieren</strong></p>
<p>Zum Schluss sollten wir noch eine sogenannte Catchall Route einrichten, <span style="text-decoration: underline;">die wir nach allen unseren Routen positionieren</span> damit diese nur greifen kann, wenn keine der anderen gepasst hat, diese Route wird in jedem Fall aufgerufen, wenn keine der vorderen gepasst hat.</p>
<p><a href="http://blog.bigbasti.com/uploads/globalasax.png"><img class="aligncenter size-full wp-image-1335" title="globalasax" src="http://blog.bigbasti.com/uploads/globalasax.png" alt="" width="585" height="289" /></a>Wenn die CatchAll Route greift wird der Home Controller aufgerufen und die Action "NotFound" ausgeführt.</p>
<p>Im Grunde sind wir nun fertig, alle von uns eingetragenen Fehler werden nun abgefangen und durch von uns präparierten Seiten ersetzt. Das einzige was noch passieren kann ist dass ihr im IIS andere ErrorPages eingestellt habt, dann dann werden diese angezeigt und nicht die von euch erstellten. Hier müsst ihr die "Error Responses" auf "<em>Detailed errors" </em>stellen.</p>
<p class="wp-flattr-button"></p> <p><a href="http://blog.bigbasti.com/?flattrss_redirect&amp;id=1323&amp;md5=4a30b1ed784ba5fe53a221a2695a0b3f" title="Flattr" target="_blank"><img src="http://blog.bigbasti.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigbasti.com/asp-net-mvc-2-custom-errorpages-anlegen/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

