code it

Martins Tech Blog

maxRequestLength vs. maxAllowedContentLength

Wer sich mit Dateiuploads beschäftigt wird sich früher oder später Gedanken über Dateigrößenbeschränkungen machen wollen oder müssen.

Die Einstellung dafür findet sich in der web.config. Jedoch gibt es dabei gewisse Dinge zu beachten:

  1. Die MSDN ist sehr spärlich mit Informationen zu den Stellen an denen Änderungen notwendig sind und den vorhandenen Abhängigkeiten.
  2. Je nach verwendeter IIS-Version sind unterschiedliche Werte anzupassen.

Konfiguration des IIS

Relevant ist das Attribut maxAllowedContentLength im Element system.webServer / security / requestFiltering / requestLimits. Zu beachten ist hier, dass dieser Wert in Byte ist. Für Dateigrößen von 20 MB ist hier daher 20971520 einzutragen.

Konfiguration der ASP.NET Runtime

Relevant ist das Attribut maxRequestLength im Element system.web / httpRuntime. Zu beachten ist, dass dieser Wert in Kilobyte ist. Für Dateigrößen von 20 MB ist hier daher 20480 einzutragen. Wird der IIS 6 verwendet, spielt maxAllowedContentLength keine Rolle und es muss nur maxRequestLength angepasst werden.

 

Entwickler erobern Leipzig

Jedes Jahr im Oktober gibt es in Leipzig eine Invasion von Entwicklern. Was als Event für .NET Entwickler begann wurde dieses Jahr konzeptionell etwas erweitert und hat nun den Namen Developer OpenSpace. So richtig hat sich mir die Notwendigkeit dieser Änderung noch nicht erschlossen, schließlich war es auch bisher schon so, dass sich immer auch Sessions zu eher .NET-fremden Themen oder sagen wir mal besser Randthemen aus dem Blickwinkel eines .NET Entwicklers gefunden haben. Das ist auch ganz gut - ergibt sich so doch der ein oder andere Blick über den Tellerrand. Und es schadet auf keinen Fall, mal was von Java oder Ruby gesehen zu haben. Ich persönlich sehe dieses Wochenende immer wieder als gute Gelegenheit für einen Austausch über Erfahrungen oder um neue Ideen oder Denkanstöße zu bekommen. Mehr...

In die JSON-Serialisierung eingreifen

Der Anwendungsfall

In einer Seite sollen Diagramme angezeigt werden. Für die Darstellung habe ich mich für flot entschieden. Dabei handelt es sich um eine JavaScript-Bibliothek, die in einem Platzhalter mit Hilfe von Canvas-Elementen Charts in diversen Formaten zeichnen kann. 

Im ersten Beispiel soll ein Tortendiagramm erzeugt werden. 

Die Datenstruktur ist dabei recht simpel. Es handelt sich um ein Array von Objekten mit jeweils einem Label und einem Zahlenwert für die Daten.

var pieData = [{ label: "geschieden", data: 5 }, { label: "verheiratet", data: 25 }, { label: "ledig", data: 30 }];
$.plot($("#myChart"), pieData, {
    series: {
        pie: {
            show: true
        }
    },
    grid: {
        hoverable: true
    },
    legend: {
        labelBoxBorderColor: "none"
    }
});

Im zweiten Beispiel soll ein Liniendiagramm erzeugt werden, das Werte mehrerer Serien über einen Zeitraum darstellen kann.

Die Datenstruktur ist ähnlich wie die des Tortendiagramms. Nur nun enthält data nicht mehr einen einzelnen Wert, sondern ein Array von x-y-Werten. das Beispiel beinhaltet die Daten vom 01.11. bis 03.11.2012. Die x-Achse ist auf den Zeitraum 31.10. bis 04.11. arretiert, damit der erste Datenwert nicht direkt am Rand des Charts liegt.

var lineData = [
    { label: "aktive Kunden", data: [[1351724400000, 213], [1351810800000, 215], [1351897200000, 217]] },
    { label: "Support Tickets", data: [[1351724400000, 100], [1351810800000, 80], [1351897200000, 70]] }
];
$.plot($("#myChart"), lineData, {
    xaxis: {
        mode: "time",
        min: new Date(2012, 09, 31).getTime(),
        max: new Date(2012, 10, 4).getTime(),
    },
    yaxis: {
        tickDecimals: 0,
        min: 0,
        max: 300
    },
    series: {
        lines: { show: true },
        points: {
            radius: 3,
            show: true,
            fill: true
        }
    },
    grid: {
        hoverable: true
    },
    legend: {
        labelBoxBorderColor: "none"
    }
});

So weit so gut. Mehr...

Als Sprecher bei der .NET Usergroup Dresden

Im Grunde war es ein Heimspiel. Beim letzten Treffen der .NET Usergroup Dresden vor gut einer Woche war ich dort mal wieder zur Abwechslung als Sprecher.

Thematisch ging es dabei eher um ein Randgebiet für .NET Entwickler. Gemeinsam mit Matthias Wendt widmeten wir den Abend dem SQL Server 2012. Während Matthias das Thema Datenqualität und die in dieser Version neu hinzugekommenen Data Quality Services näher beleuchtete und anhand von Beispielen erklärte, ging ich auf Neuerungen in TSQL ein und zeigte anhand von Vorher-Nachher-Statements, ob und wo sich hier Vereinfachungen ergeben.

Es war ein sehr spannender Abend und anhand der doch recht großen Teilnehmerzahl von über 15 die auch den Abend mit aktivem Mitmachen und Rückfragen bereichert haben war eindeutig erkennbar, dass es auch noch .NET-Entwickler gibt, die sich um Datenspeicherung kümmern und nicht nur im Frontend unterwegs sind.

Englische Version Englische Version

IIS Express komfortabel konfigurieren

... oder "Ich hab da mal was vorbereitet".

Wer schon einmal versucht hat, seinen IIS Express mit SSL mit einem abweichenden Hostnamen (also nicht localhost oder der tatsächliche Rechnername) laufen zu lassen wird es kennen - mit nur sieben winzigen Schritten kommt man zum Erfolg:

  1. hosts-Datei anpassen
  2. Bindings in der applicationhost.config des IIS Express anpassen
  3. mit netsh die Urls für gesicherte und ungesicherte Verbindungen in http.sys reservieren
  4. ggf. mit netsh die entsprechenden Ports an der Windows Firewall öffnen
  5. mit makecert selbstsigniertes Zertifikat erstellen
  6. in der Management-Konsole den Fingerabdruck des neuen Zertifikats suchen
  7. das erstellte Zertifikat mit netsh dem gewünschten SSL-Port zuweisen

Und da das RequireSSL-Attribut fest auf Port 443 verweist und man ggf. einen anderen Port verwendet, kann es sein, dass man noch eine URL-Rewrite-Rule in der web.config einrichten muss.

Die ganzen Schritte hat Scott Hanselmann sehr detailliert in seinem Post Working with SSL at Development Time is easier with IISExpress zusammengefasst.

Interessant ist der letzte Abschnitt des genannten Posts - denn dort zeigt er, dass es noch einen undokumentierten Weg gibt, der uns die meisten der genannten Schritte abnimmt. Mit Hilfe des Kommandozeilentools IISExpressAdminCmd können solche benutzerfreundlichen Urls in http.sys und hosts-Datei hinzugefügt und auch wieder entfernt werden - und das sowohl für ungesicherte als auch ssl-gesicherte Urls. Einzig um die Anpassung der applicationhost.config und ggf. notwendiger Url-Rewrite-Regeln kommt man auch damit nicht herum. 

Ein kleines Manko hat dieses Tool - es werden nur reine Rechnernamen akzeptiert (z.B. contoso); also die Konfiguration einer kompletten Url mit verschiedenen Levels (z.B. dev.contoso.com) ist damit nicht möglich. In diesem Fall kann man nicht die Abkürzung verwenden, sondern ist auf den langen Weg angewiesen.

Englische Version Englische Version

Array-Parameter im WCF Test-Client

Zugegeben, die Eingabe von Array-Parametern im WCF-Test-Client ist nicht sehr intuitiv. Und eben weil man es auf den ersten Blick nicht erkennt, hier an dieser Stelle ein kleiner Tipp für alle die schon daran gescheitert sind.

Gegeben ist ein WCF-Service, der einen Array-Parameter hat - in meinem Beispiel gibt es den EmployeeService, welcher in der Methode Create eine Auflistung an Objekten vom Typ Employee entgegennimmt.

[ServiceContract]
public interface IEmployeeService
{
    [OperationContract]
    void Create(IEnumerable<Employee> employees);
}

Soweit nicht weiter kompliziert.

Startet man im Visual Studio nun eine neue Instanz des Services, so öffnet sich der WCF Test-Client und man kann den Service aufrufen, wenn man es denn schafft, hier Objekte vom Typ Employee einzutragen. Mehr...

Als Sprecher bei der .NET Usergroup Leipzig

Am 25.06. war ich zu Gast bei der .NET Usergroup Leipzig. Thema das Abends war modulares Anwendungsdesign und wie Prism dabei unterstützen kann. Nach ein paar Slides, in denen die theoretischen Grundlagen etwas beleuchtet wurden, ging es auch schon ans Live-Coding.

Die Gruppe war mit unter 10 Teilnehmern recht überschaubar, was aber den großen Vorteil hatte, dass wir bei einigen aufgetretenen Fragen direkt einsteigen konnten. Und auch ich habe dank Marcel dort noch etwas gelernt zu einem Feature von Resharper, das mir bisher unbekannt war.

Ich fand es einen sehr gelungenen Abend und auch das netzwerken im kleinen Kreis nach der Usergroup im Kesselhaus war ein kleiner Event.

Für alle diejenigen, die das Live-Beispiel noch einmal nachvollziehen wollen, sind hier die Slides - 20120625_UGLeipzig_Prism.zip (1,78 mb) - und das Code-Sample - Prism_Slides.pdf (753,54 kb).

PS: Bitte denkt daran, dass das Beispiel Directory-Discovery verwendet.

Flagged Enums und XAML-Syntax

In meinem letzten Post habe ich mich mit den Besonderheiten der XAML-Syntax bei Nested Types auseinandergesetzt. Ähnlich gewöhnungsbedürftig ist die Syntax bei Flagged Enums.

Standard-Enum-Werte können mit Hilfe der Textrepräsentation recht einfach zugewiesen werden. Ein Beispiel dafür ist die Eigenschaft Visibility.

<TextBlock Text="Sampletext" Visibility="Collapsed" />

Hier sorgt der TypeConverter für Enums dafür, dass aus dem String "Collapsed"  der Wert System.Windows.Visibility.Collapsed generiert wird.

Etwas anders sieht das Ganze bei Flagged Enums aus. Als Beispiel soll ein UserControl dienen, an dem per DependencyProperty eingestellt werden kann, welche Eingabemethoden gültig sind. Da hier mehrere Werte möglich sind, wird das Ganze über ein Flagged Enum gelöst.

Mehr...

Nested Types und XAML-Syntax

Ich gebe zu, ich bin kein großer Freund von Nested Types, da sie an einigen Stellen umständlicher zu behandeln sind als Typen, die "ganz normal" in Namespaces liegen. Aber es soll API-Hersteller geben, die Nested Types verwenden. Um dann nicht Dinge mehrfach entwickeln zu müssen, bietet es sich an, diese Typen gleich weiterzuverwenden.

Was ist ein Nested Type?

Das ist recht einfach erklärt: Ein Nested Type ist ein Datentyp, der in einem anderen Datentyp deklariert ist - also eine Klassendefinition innerhalb einer anderen Klasse und eben nicht direkt in einem Namespace. Das folgende Beispiel soll das etwas verdeutlichen:

public class Constants
{
    public class Colors
    {
        public const string Red = "#FF0000";
        public const string Green = "#00FF00";
        public const string Blue = "#0000FF";
    }

    public class Alignments
    {
        public const string Left = "Left";
        public const string Right = "Right";
    }
}

Zugriff im Code

Der Zugriff im Code ist ähnlich wie wenn die Klasse in einem Namespace liegt - man verwendet die Punkt-Syntax.

var color = Constants.Colors.Blue;

Zu beachten ist hier lediglich, dass man sich ab dem obersten Typ durch die Struktur hangeln muss und eben nicht wie im Fall von Namespaces eine using-Direktive verwenden kann. Ok, einen Trick gibt es doch - man kann einen Alias für den Typ vergeben:

using ColorConstants = Constants.Colors;

public class MainViewModel
{
    public MainViewModel()
    {
        LoadData();
    }

    public void LoadData()
    {
        var color = ColorConstants.Blue;
    }
}

Zugriff im XAML

In meinem Beispiel handelt es sich um Konstanten, auf die ich im XAML auch gern im statischen Kontext zugreifen möchte . Dafür bietet sich x:Static an. Verwende ich hier die gleiche Syntax wie im Code, so erhalte ich eine Fehlermeldung die besagt, dass der Typ nicht gefunden werden kann.

Alles kein Problem - dabei handelt es sich nämlich um einen Syntaxfehler. Der Zugriff auf Nested Types erfolgt nicht mit "." sondern mit "+". Korrekt ist es also wie folgt:

<TextBlock Text="{x:Static local:Constants+Colors.Blue}" />

Damit funktioniert der Zugriff nun zur Laufzeit, und auch in Expression Blend wird alles korrekt angezeigt. Aber ab diesem Zeitpunkt streikt nun der Designer von Visual Studio.

Englische Version Englische Version

InvalidOperationException in WebBrowserTask.Show

In Windows Phone 7 hat man mit Hilfe der Launcher und Chooser die Möglichkeit, auf im System integrierte Funktionen zuzugreifen - sei es nun die Kamera, der Emailclient oder wie in meinem Fall der Browser. Meine Anwendung hat mehrere Buttons über die zu unterschiedlichen Webseiten weiternavigiert werden kann - hauptsächlich als weiterführende Information im Impressum.

Dafür hab ich abstrakt gesehen folgende zentrale Methode:

public static void OpenInWebBrowser(string url)
{
    var openBrowserTask = new WebBrowserTask { Uri = new Uri(url) };
    openBrowserTask.Show();
}

Diese Methode wird direkt in dem Command aufgerufen, das an dem Button hängt - alles kein Hexenwerk. Was mich nun wunderte: Gelegentlich bekam ich Error-Reports mit diesem Inhalt:

Navigation is not allowed when the task is not in the foreground. Error: -2147220990

Da stellte sich mir folgende Frage: Wie kann jemand den Button klicken, wenn die Anwendung nicht im Vordergrund ist?

Die Lösung ist ganz einfach: Der Benutzer hat kurz nacheinander auf den Button geklickt - sei es nun weil er so aufgeregt war, eine schöne Webseite zu sehen oder weil er gerade unterwegs auf einer holprigen Straße war - die Möglichkeiten sind da ja sehr vielfältig. Das ist möglich, weil der Launcher eine Weile braucht, um den Browser in den Vordergrund zu holen. Der Nutzer kann also dafür sorgen, dass der Click-Event zweimal ausgelöst wird - der zweite Event wird aber erst dann verarbeitet, wenn der erste WebBrowserTask den Browser geöffnet hat und damit die eigentliche Anwendung nicht mehr im Vordergrund ist. Und dann kommt es zu dieser Exception.

Wie geht man nun damit um? Es gibt mehrere Ansätze. Zum einen kann man natürlich mit Try-Catch-Blöcken arbeiten und genau diesen Exception-Typ abfangen. Da diese Exception bei dieser Methode bisher in der MSDN nicht dokumentiert ist, ist es etwas schwierig hier von allein auf die Idee zu kommen, diesen speziellen Typ abzufangen, aber nachher weiß man es immer besser. Zusätzlich könnte man noch den Click-Handler abhängen bzw. den Button oder das Command deaktivieren. 

Ich bin nicht der einzige, dem dieses Problem untergekommen ist - und Niko hat einen sehr ausführlichen Blogpost zum Thema geschrieben, der auch alle hier genannten Lösungsmöglichkeiten aufführt.