<?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>Kay&#039;s Technologie Backlog &#187; ASP.NET</title>
	<atom:link href="http://www.herzam.com/blog/category/aspnet/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.herzam.com/blog</link>
	<description>So much technology, so little time</description>
	<lastBuildDate>Thu, 11 Feb 2010 09:11:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Routing mit ASP.NET WebForms, Teil 2</title>
		<link>http://www.herzam.com/blog/2009/10/29/routing-mit-asp-net-webforms-teil-2/</link>
		<comments>http://www.herzam.com/blog/2009/10/29/routing-mit-asp-net-webforms-teil-2/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 20:11:15 +0000</pubDate>
		<dc:creator>kay.herzam</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Routing]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.herzam.com/blog/?p=234</guid>
		<description><![CDATA[In Teil 1 ging es darum, wie die ASP.NET 3.5 Routing Engine in einer WebForms Applikation genutzt werden kann. Angeschaut wurde die Konfiguration der Applikation für die Engine, und das Definieren und Auswerten eigener Routen.
In diesem zweiten Teil werden nun die Security Aspekte angeschaut.
Das Routing Modul verarbeitet die Events in der Request Pipeline nachdem die [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.herzam.com/blog/2009/10/28/routing-mit-asp-net-webforms-teil-1/trackback/">Teil 1</a> ging es darum, wie die ASP.NET 3.5 Routing Engine in einer WebForms Applikation genutzt werden kann. Angeschaut wurde die Konfiguration der Applikation für die Engine, und das Definieren und Auswerten eigener Routen.<br />
In diesem zweiten Teil werden nun die Security Aspekte angeschaut.</p>
<p>Das Routing Modul verarbeitet die Events in der Request Pipeline nachdem die Authentisierung und Autorisierung bereits stattgefunden hat. Das bedeutet, dass die Benutzer anhand der sichtbaren URL autorisiert werden und nicht über den virtuellen Pfad zum WebForm.</p>
<p>Wenn also der Zugriff auf unsere Beispiel URL &#8220;customer/&#8221; nur authentisierten Benutzern gestattet sein soll, kann dies über einen Eintrag im Root web.config erreicht werden:</p>
<pre class="brush: xml;">
&lt;location path=&quot;customer&quot;&gt;
  &lt;system.web&gt;
    &lt;authorization&gt;
      &lt;deny users=&quot;?&quot; /&gt;
    &lt;/authorization&gt;
  &lt;/system.web&gt;
&lt;/location&gt;
</pre>
<p>Anonyme Benutzer der Applikation können nun nicht mehr auf Adressen wie &#8220;customer&#8221; oder &#8220;customer/42&#8243; zugreifen, sondern werden auf eine Login Seite umgeleitet. Diese enthält sogar den Pfad unserer Route:</p>
<div id="attachment_237" class="wp-caption alignnone" style="width: 453px"><a href="http://www.herzam.com/blog/wp-content/uploads/2009/10/login.gif"><img class="size-full wp-image-237" title="Login mit Return URL" src="http://www.herzam.com/blog/wp-content/uploads/2009/10/login.gif" alt="Login mit Return URL" width="443" height="210" /></a><p class="wp-caption-text">Login mit Return URL</p></div>
<p>Nun muss noch sichergestellt werden, dass die Authorisation Prüfung über den virtuellen Pfad erfolgt, den der RouteHandler verwendet. Die Methode GetHttpHandler sieht also wie folgt aus:</p>
<pre class="brush: csharp;">
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
    if (!UrlAuthorizationModule.CheckUrlAccessForPrincipal(_virtualPath, requestContext.HttpContext.User, requestContext.HttpContext.Request.HttpMethod))
    {
        requestContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        requestContext.HttpContext.Response.End();
    }

    var page = BuildManager.CreateInstanceFromVirtualPath(_virtualPath, typeof(Page));

    var queryString = new StringBuilder(&quot;?&quot;);
    foreach (var rdv in requestContext.RouteData.Values)
    {
        queryString.Append(requestContext.HttpContext.Server.UrlEncode(rdv.Key));
        queryString.Append(&quot;=&quot;);
        queryString.Append(requestContext.HttpContext.Server.UrlEncode(rdv.Value.ToString()));
        queryString.Append(&quot;&amp;&quot;);
    }
    queryString.Remove(queryString.Length - 1, 1);

    HttpContext.Current.RewritePath(string.Concat(_virtualPath, queryString));

    return (IHttpHandler)page;
}
</pre>
<p>Eine letzte Einstellung ist noch nötig. Anonyme Benutzer können immer noch direkt über den physikalischen Pfad (z.B. ~/Customers/CustomerDetail.aspx) auf die WebForms zugreifen. Dies kann verhindert werden, indem eine web.config Datei im entsprechenden Verzeichnis angelegt wird:</p>
<pre class="brush: xml;">
&lt;configuration&gt;
  &lt;system.web&gt;
    &lt;authorization&gt;
      &lt;deny users=&quot;?&quot; /&gt;
    &lt;/authorization&gt;
  &lt;/system.web&gt;
&lt;/configuration&gt;
</pre>
<p>Ich habe ein Beispielprojekt zusammengestellt, welches alle besprochenen Elemente zeigt: <a href="http://www.herzam.com/blog/wp-content/uploads/2009/10/RoutingWebApplication.zip">RoutingWebApplication.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.herzam.com/blog/2009/10/29/routing-mit-asp-net-webforms-teil-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Routing mit ASP.NET WebForms, Teil 1</title>
		<link>http://www.herzam.com/blog/2009/10/28/routing-mit-asp-net-webforms-teil-1/</link>
		<comments>http://www.herzam.com/blog/2009/10/28/routing-mit-asp-net-webforms-teil-1/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 19:58:05 +0000</pubDate>
		<dc:creator>kay.herzam</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[Routing]]></category>

		<guid isPermaLink="false">http://www.herzam.com/blog/?p=228</guid>
		<description><![CDATA[Einer der Gründe, weshalb ich das ASP.NET MVC Framework mag, ist die durchgehende Verwendung der sehr flexiblen Routing Engine. In einem MVC Projekt ist das Addressierungsschema komplett vom physikalischen Filesystem getrennt. So lassen sich einfach Applikationen im REST Stil bauen. Adressen wie &#8220;http://applikation/Kunde/42&#8243; oder &#8220;http://applikation/Kunde/42/Bestellungen&#8221; sind auch deutlich SEO freundlicher als die direkte Adressierung auf [...]]]></description>
			<content:encoded><![CDATA[<p>Einer der Gründe, weshalb ich das ASP.NET MVC Framework mag, ist die durchgehende Verwendung der sehr flexiblen Routing Engine. In einem MVC Projekt ist das Addressierungsschema komplett vom physikalischen Filesystem getrennt. So lassen sich einfach Applikationen im <a href="http://de.wikipedia.org/wiki/Representational_State_Transfer">REST</a> Stil bauen. Adressen wie &#8220;http://applikation/Kunde/42&#8243; oder &#8220;http://applikation/Kunde/42/Bestellungen&#8221; sind auch deutlich <a href="http://de.wikipedia.org/wiki/Search_Engine_Optimization">SEO</a> freundlicher als die direkte Adressierung auf ein physikalisch vorhandenes File.</p>
<p>Die Routing Engine ist jedoch nicht Bestandteil des MVC Frameworks, sondern wurde mit .NET 3.5 SP1 eingeführt. Somit kann sie auch in einem WebForm Projekt verwendet werden. Der Aufwand hält sich dabei in Grenzen, das ganze ist recht schnell umgesetzt.</p>
<p>Teil 1 dieses Artikels zeigt die Konfiguration der Routing Engine in einer WebForms Applikation und das Anlegen eigener Routen. In einem zweiten Teil werden dann die Security Einstellungen betrachtet.</p>
<h3>Konfiguration der WebForms Applikation</h3>
<p>Um die Routing Engine nutzen zu können, müssen im Projekt zwei Verweise gesetzt werden: System.Web.Routing und System.Web.Abstractions sind beide im GAC installiert, sie können einfach über &#8220;Add Reference&#8221; hinzugefügt werden.</p>
<p>Danach muss das Routing Modul im web.config in die Request Pipeline konfiguriert werden. Unter <strong>IIS 6</strong> geschieht dies wie folgt:</p>
<pre class="brush: xml;">
&lt;httpModules&gt;
  ...
  &lt;add name=&quot;RoutingModule&quot;
       type=&quot;System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&quot; /&gt;
</pre>
<p>Wenn <strong>IIS 7</strong> verwendet wird, müssen die folgenden Einträge gemacht werden:</p>
<pre class="brush: xml;">
&lt;system.webServer&gt;
  &lt;modules runAllManagedModulesForAllRequests=&quot;true&quot;&gt;
    ...
    &lt;add name=&quot;UrlRoutingModule&quot;
         type=&quot;System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;&quot; /&gt;
    ...
  &lt;/modules&gt;

  &lt;handlers&gt;
    ...
    &lt;add name=&quot;UrlRoutingHandler&quot;
         preCondition=&quot;integratedMode&quot;
         verb=&quot;*&quot; path=&quot;UrlRouting.axd&quot;
         type=&quot;System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&quot; /&gt;
    ...
  &lt;/handlers&gt;
&lt;/system.webServer&gt;
</pre>
<p>Wenn die Zielumgebung bekannt ist, kann auf die eine Variante verzichtet werden, Einträge für IIS 6 werden allerdings vom IIS 7 ignoriert, und umgekehrt auch, so dass getrost beide Varianten eingetragen werden können.</p>
<h3>Konfiguration der Routen</h3>
<p>Falls nicht bereits vorhanden, wird eine global.asax Datei zum Projekt hinzugefügt. In dessen Application_Start Event können die Routen eingetragen werden. Eine Route hat immer einen eindeutigen Namen, definiert ein Adressenmuster und legt fest, von welchem Handler Anfragen an diese Adresse bearbeitet werden:</p>
<pre class="brush: csharp;">
RouteTable.Routes.Add(&quot;Customers&quot;, new Route(&quot;customer/&quot;, new PageRouteHandler(&quot;~/Customers/Customers.aspx&quot;)));
RouteTable.Routes.Add(&quot;CustomerDetails&quot;, new Route(&quot;customer/{id}&quot;, new PageRouteHandler(&quot;~/Customers/CustomerDetails.aspx&quot;)));
</pre>
<p>Dies erstellt zwei Einträge in der Routing Tabelle. Der zweite Eintrag verwendet einen Parameter &#8220;id&#8221;, wenn also ein Request in der Form &#8220;customer/42&#8243; eintrifft, wird dieser Eintrag verwendet.</p>
<p>Zu beachten ist, dass beim Eintreffen eines Requests diese Routing Tabelle von oben nach unten abgearbeitet wird, und der erste zur Request Adresse passende Eintrag verwendet wird. Nachfolgende Einträge werden ignoriert.</p>
<p>Nun muss der PageRouteHandler angelegt werden, welcher diese Anfragen bearbeiten kann. Dies ist eine Klasse, welche das IRouteHandler Interface implementiert:</p>
<pre class="brush: csharp;">
public class PageRouteHandler : IRouteHandler
{
    private readonly string _virtualPath;

    public PageRouteHandler(string virtualPath)
    {
        _virtualPath = virtualPath;
    }

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
       var page = BuildManager.CreateInstanceFromVirtualPath(_virtualPath, typeof(Page));
       return (IHttpHandler)page;
    }
}
</pre>
<p>Dies ist bereits alles, was benötigt wird, um eigene Routen zu definieren und an Webforms weiterzuleiten. Jedoch gelangt im zweiten Fall, wenn eine ID übergeben wird, diese nicht bis zum Webform. Dies kann gelöst werden, indem innerhalb des Routing Handlers die Routing Daten des RequestContext an das Webform weitergeleitet werden. Die Methode GetHttpHandler sieht also wie folgt aus:</p>
<pre class="brush: csharp;">
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
    var page = BuildManager.CreateInstanceFromVirtualPath(_virtualPath, typeof(Page));

    var queryString = new StringBuilder(&quot;?&quot;);
    foreach (var rdv in requestContext.RouteData.Values)
    {
        queryString.Append(requestContext.HttpContext.Server.UrlEncode(rdv.Key));
        queryString.Append(&quot;=&quot;);
        queryString.Append(requestContext.HttpContext.Server.UrlEncode(rdv.Value.ToString()));
        queryString.Append(&quot;&amp;&quot;);
    }
    queryString.Remove(queryString.Length - 1, 1);

    HttpContext.Current.RewritePath(string.Concat(_virtualPath, queryString));

    return (IHttpHandler)page;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.herzam.com/blog/2009/10/28/routing-mit-asp-net-webforms-teil-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Security Trimming mit ASP.NET MVC</title>
		<link>http://www.herzam.com/blog/2009/10/14/security-trimming-mit-asp-net-mvc/</link>
		<comments>http://www.herzam.com/blog/2009/10/14/security-trimming-mit-asp-net-mvc/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 19:35:02 +0000</pubDate>
		<dc:creator>kay.herzam</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[Membership]]></category>
		<category><![CDATA[SQLite]]></category>

		<guid isPermaLink="false">http://www.herzam.com/blog/?p=193</guid>
		<description><![CDATA[Einer der grossen Pluspunkte des ASP.NET MVC Frameworks ist, dass viel von der bestehenden ASP.NET Infrastruktur weiterverwendet werden kann. In einigen wenigen Fällen lassen sich auch die WebForm Server Controls sinnvoll einsetzen. Dies ist möglich, solange die Standard WebFormViewEngine verwendet wird.
Ein sehr praktisches Feature der klassischen Webforms ist das Security Trimming, also das Anzeigen von [...]]]></description>
			<content:encoded><![CDATA[<p>Einer der grossen Pluspunkte des ASP.NET MVC Frameworks ist, dass viel von der bestehenden ASP.NET Infrastruktur weiterverwendet werden kann. In einigen wenigen Fällen lassen sich auch die WebForm Server Controls sinnvoll einsetzen. Dies ist möglich, solange die Standard WebFormViewEngine verwendet wird.</p>
<p>Ein sehr praktisches Feature der klassischen Webforms ist das Security Trimming, also das Anzeigen von rollenbasierten Inhalten. Je nach Rolle, welche der eingeloggte Benutzer zugewiesen hat, werden ihm nur für diese Rolle passende Inhalte angezeigt. Das ganze Membership System der Webforms wird vom MVC Framework unterstützt. Auch das LoginView Control lässt sich im MVC Framework verwenden, da es keinen ViewState benötigt:</p>
<pre class="brush: xml;">&lt;asp:LoginView ID=&quot;LoginView1&quot; runat=&quot;server&quot;&gt;
  &lt;AnonymousTemplate&gt;I can be seen when the user is Anonymous.&lt;/AnonymousTemplate&gt;
  &lt;LoggedInTemplate&gt;I can only be seen when a user without group membership is logged in.&lt;/LoggedInTemplate&gt;
  &lt;RoleGroups&gt;
    &lt;asp:RoleGroup Roles=&quot;Admin,User&quot;&gt;
      &lt;ContentTemplate&gt;Only users with the &quot;Admin&quot; and &quot;User&quot; role can see this.&lt;/ContentTemplate&gt;
    &lt;/asp:RoleGroup&gt;
    &lt;asp:RoleGroup Roles=&quot;Admin&quot;&gt;
      &lt;ContentTemplate&gt;Only users with the &quot;Admin&quot; role can see this.&lt;/ContentTemplate&gt;
    &lt;/asp:RoleGroup&gt;
    &lt;asp:RoleGroup Roles=&quot;User&quot;&gt;
      &lt;ContentTemplate&gt;Only users with the &quot;User&quot; role can see this.&lt;/ContentTemplate&gt;
    &lt;/asp:RoleGroup&gt;
  &lt;/RoleGroups&gt;
&lt;/asp:LoginView&gt;</pre>
<p>Zu beachten ist, dass die RoleGroups Templates der Reihe nach ausgewertet werden. Nur das erste zu einer Benutzerrolle passende Template wird angezeigt, die anderen nicht. Wenn sich also im Beispielprojekt ein Benutzer mit einer &#8220;User&#8221; Rolle einloggt, wird er nur das erste RoleGroup Template sehen.<br />
Das LoggedInTemplate wird nur dann angezeigt, wenn kein RoleGroup Template zur Benutzerrolle passt.</p>
<p>Ich habe ein Beispielprojekt zusammengestellt, welches das LoginView Control im Einsatz zeigt. Das Projekt verwendet eine <a href="http://www.sqlite.org">SQLite</a> Datenbank und die <a href="http://www.codeproject.com/KB/aspnet/SQLite-Providers.aspx">SQLite Membership Provider</a> von <a href="http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=1173489">Roger Martin</a>.</p>
<p>Download des Beispielprojekts: <a href="http://www.herzam.com/blog/wp-content/uploads/2009/10/SecurityTrimming.zip">SecurityTrimming.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.herzam.com/blog/2009/10/14/security-trimming-mit-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsofts Chart Control</title>
		<link>http://www.herzam.com/blog/2008/11/27/microsofts-chart-control/</link>
		<comments>http://www.herzam.com/blog/2008/11/27/microsofts-chart-control/#comments</comments>
		<pubDate>Thu, 27 Nov 2008 20:49:37 +0000</pubDate>
		<dc:creator>kay.herzam</dc:creator>
				<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://www.herzam.com/blog/?p=95</guid>
		<description><![CDATA[Ich schreibe mal wieder nur ab: Microsoft veröffentlich endlich auch ein eigenes Chart Control. Das ganze wird im Blog von Scott Guthrie als ASP.NET Charting Control angepriesen. Gerüchten zufolge werkelt unter der Haube Technologie von Dundas, dies ist schon mal ein Garant für gut designte Controls und durchdachte APIs. Der Komponenten Pionier lieferte bereits die [...]]]></description>
			<content:encoded><![CDATA[<p>Ich schreibe mal wieder nur ab: Microsoft veröffentlich endlich auch ein eigenes Chart Control. Das ganze wird <a href="http://weblogs.asp.net/scottgu/archive/2008/11/24/new-asp-net-charting-control-lt-asp-chart-runat-quot-server-quot-gt.aspx">im Blog von Scott Guthrie</a> als<strong> ASP.NET Charting Control</strong> angepriesen. Gerüchten zufolge werkelt unter der Haube Technologie von <a href="http://www.dundas.com">Dundas</a>, dies ist schon mal ein Garant für gut designte Controls und durchdachte APIs. Der Komponenten Pionier lieferte bereits die <a href="http://www.dundas.com/Company/Media/PressSQL2008.aspx">Charting Technologie</a> für die Reporting Services von SQL Server 2008.<br />
Bislang musste man ja entweder auf das Angebot eines Drittherstellers zurückgreifen, oder eben selber in die Tasten greifen, wenn man Charts oder ganz allgemein dynamische Grafiken serverseitig erzeugen wollte. Mit GDI+ war das grundsätzlich auch recht einfach machbar, aber eben von Microsoft nicht unterstützt.<br />
Die <a href="http://msdn.microsoft.com/en-us/library/system.drawing.aspx">offizielle MSDN Dokumentation des System.Drawing Namespaces</a> ist zu diesem Punkt nicht allzu ausführlich:</p>
<blockquote><p>Classes within the System.Drawing namespace <strong>are not supported</strong> for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions.</p></blockquote>
<p>Obwohl es nahezu nie Probleme gab, alles immer auch performant funktionierte, hatte ich immer ein ungutes Gefühl während der Entwicklung solcher .NET Komponenten.<br />
Wenn mal was schiefgehen sollte, hat man keine Hilfe zu erwarten. Die sehr komplexe und aufwändige Entwicklung von GDI COM Komponenten kommt kaum als Alternative in Frage.</p>
<p>Während sich nun die ganze .NET Entwickler Welt über das längst fällige Control für die Webentwicklung freut, nehme ich zufrieden zur Kenntnis, dass das ganze auch für die in letzter Zeit von Microsoft stark vernachlässigten WinForms funktioniert. Schade ist nur, dass die Controls .NET 3.5 SP1 voraussetzen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.herzam.com/blog/2008/11/27/microsofts-chart-control/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

