8/24/2010

NGem – Private Libraries verwalten

Was Ruby-Entwickler mit gem schon lange kennen, schwappt mit Nu langsam auch in die .NET-Welt. Beides sind Packetverwaltungen (wobei Nu auf Gem basiert) für diverse gängige Open-Source Libraries. Ich bin von diesem Konzept ziemlich begeistert, jedoch fehlt meines Wissens die Möglichkeit private Assemblies darüber zu verwalten.

In der Nacht auf Sonntag habe ich mit Daniel ein kleines Projekt entwickelt, welches genau diese Anforderung erfüllt.

Wer Interesse hat es auszuprobieren kann sich das Projekt auf GitHub auschecken.

Nach dem Download empfiehlt es sich den Pfad zur “NGem.exe” der Umgebungsvariable “Path” hinzuzufügen.

image

Die Eingabe von “ngem” in der Konsole liefert folgende Ausgabe:

 image

Eigene Pakete bzw. Gems erstellen

image 

Zum erstellen eigener Gems wird einfach “ngem make {path} {manufacturer} {library}” in die Konsole eingegeben.

Bestehen Referenzen auf andere Projekte, wird einfach eine Datei mit dem Namen “References.xml” in dem Verzeichnis des Gems erstellt:

<?xml version="1.0"?>
<references>
    <add name="PP.AnotherAssembly" />
</references>

Sämtliche Referenzen werden selbstständig heruntergeladen.

Anschließend wird ein Zip-Archiv erstellt, welches auf einen Web-Server kopiert werden kann.

Eingene Pakete bzw. Gems herunterladen
Um eigene Gems herunterladen zu können muss zu allererst die URL in der app.config angepasst:

image

Anschließend steht dem Download über “ngem install {name des gems}” nichts mehr im Wege.

8/8/2010

OpenType-Fonts im Visual Studio 2010 nutzen

Da das Visual Studio 2010 (aufgrund des WPF-Editors) ausschließlich TrueType-Fonts unterstützt, lassen sich Schriften wie z.B. Inconsolata (OpenType) nicht auf Anhieb verwenden.

Lösung des Problems?
Die Schrift einfach von einem Konverter (z.B. onlinefontconverter) umwandeln lassen.

Die Inconsolata kann hier heruntergeladen werden.

7/25/2010

Fehlerbehandlung in ASP.NET MVC

image Manchmal lassen sich Fehler in einer Anwendung nicht vermeiden. Sei es weil ein externer Service nicht erreichbar ist, die Datenbank streikt oder irgendwas anderem. Ich bin mir sicher das JEDEM haufenweise Gründe hierfür einfallen würden.

Damit man seinen Besuchern aber nicht regelmäßig voller Scham den Yellow Screen of Death präsentieren muss gibt es in ASP.NET MVC das HandleError-Attribut.

[HandleError]
public class HomeController : BaseController
{
    public ActionResult Index()
    {
        return View();
    }
}

Das Attribut wird einfach auf die Klasse des Controllers oder aber auf einzelne Resultmethoden gesetzt. Tritt im Code nun eine Exception auf wird im Verzeichnis des aktuellen Controllers nach einer Datei mit dem Namen “Error.aspx” gesucht und dorthin weitergeleitet. Falls die Datei nicht existiert wird als nächstes das “Shared”-Verzeichnis durchsucht. Darüberhinaus besteht die Möglichkeit explizit eine View anzugeben:

[HandleError(View = "ItemNotFound")]

Schön ist auch das man nur auf bestimmte Exceptions reagieren kann bzw. diese jeweils anders behandeln kann.

[HandleError(View = "ItemNotFound", ExceptionType = typeof(NullReferenceException))]
[HandleError(View = "InvalidArgument", ExceptionType = typeof(ArgumentNullException))]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}


Damit die Fehlerseiten angezeigt werden müssen die “customErrors” in der Web.config eingeschaltet werden.

<system.web>
    <customErrors mode="On" />
</system.web>

7/21/2010

Plug-Ins für den Windows Live Writer erstellen (Part 1)

In diesem ersten Teil werde ich versuchen die Entwicklung von Header- bzw. Footerelementen zu erklären. Diese Art von Erweiterungen sind entweder aktiviert oder deaktiviert. Eine gezielte Verwendung für einzelne Posts ist nicht möglich (nur durch deaktivieren des Plugins).

Der Weg zum eigenen Plug-In:

image Als erstes muss eine neue Klassenbibliothek erstellt, welche gegen .NET 3.5 kompiliert wird. Anschließend muss eine Referenz auf die Datei “WindowsLive.Writer.Api.dll” hinzugefügt werden, die sich im Installationsverzeichnis des Windows Live Writer befindet.

Im nächsten Schritt wird eine neue Klasse angelegt, die von “HeaderFooterSource” erben und mit dem Attribut “WriterPlugin” versehen werden muss. Die Eigenschaften des Attributs sollten selbsterklärend sein.

[WriterPlugin("97DC180D-8B6F-4787-91AC-8EAC9C4787D0", "Flattr button",
    ImagePath = "flattr.png",
    PublisherUrl = "http://philipproplesch.de/",
    HasEditableOptions = false,
    Description = "Embeds the Flattr button in your blog posts.")]
public class FlattrHeaderFooterSource : HeaderFooterSource
{
    public override string GeneratePreviewHtml(ISmartContent smartContent, IPublishingContext publishingContext, out Position position)
    {
        position = Position.Footer;
        return string.Concat(publishingContext.BlogName, " ist toll.");
    }

    public override string GeneratePublishHtml(IWin32Window dialogOwner, ISmartContent smartContent, IPublishingContext publishingContext, bool publish, out Position position)
    {
        position = Position.Footer;
        return string.Concat(publishingContext.BlogName, " ist toll.");
    }
}

Das Bild für den “ImagePath” sollte sich als eingebettete Ressource im Projekt befinden.

Sofern das Plug-In keine Einstellungsmöglichkeiten haben soll reicht es an dieser Stelle die beiden Methoden “GeneratePreviewHtml” und “GeneratePublishHtml” zu überschreiben und einen String mit dem gewünschten Markup zurückzugeben.

Über die Variable “publishingContext” kann auf den Inhalt des Posts und auf diverse Eigenschaften des Blogs zugegriffen werden.

Dem out-Parameter “position” muss mitgeteilt werde ob die Erweiterung vor oder nach dem eigentlichen Post gerendert werden soll.


Wie kann ich mein Plug-In testen?

Um das Plug-In testen zu können reicht es die kompilierte *.dll in den Ordner “Plugins” im Installationsverzeichnis zu kopieren. Ich finde es ganz hilfreich diesen Vorgang im “Post-build event” zu automatisieren.

image

xcopy "$(TargetPath)" "C:\Program Files (x86)\Windows Live\Writer\Plugins" /i /d /y

Wenn alles funktioniert hat sollte die Erweiterung im WLW auftauchen.

image 

Taucht das Plug-In nicht auf, solltet ihr euch vergewissern das ihr NICHT gegen .NET 4.0 kompiliert habt.


Ein kleines Beispiel (mit Einstellungsdialog) findet ihr auf GitHub.

7/19/2010

Erweiterbare Anwendungen mit MEF erstellen

MEF (Managed Extensibility Framework) ist ein Framework, welches seit .NET 4.0 fester Bestandteil des .NET Frameworks ist (Mono wird bald wohl auch unterstützt) und mit welchem sich ohne viel Aufwand erweiterbare Anwenungen erstellen lassen.

Um MEF nutzen zu können braucht man zuallererst eine Referenz auf “System.ComponentModel.Composition”. Anschließend muss ein Katalog konfiguriert werden um MEF mitzuteilen wo nach möglichen Erweiterungen gesucht werden soll.

Hierbei hat man die Möglichkeit zwischen:
  • AssemblyCatalog (sucht in bestimmten Assemblies)
  • DirectoryCatalog (sucht im angegebenen Verzeichnis)
  • TypeCatalog (explizit Typen hinzufügen)

Darüberhinaus gibt es noch den AggregateCatalog, in welchem sämtliche der oben angegebenen Arten kombiniert werden können.

[ImportMany]
public IEnumerable<IPlugin> Plugins { get; private set; }

private void ImportExtensions()
{
    var catalog = new AggregateCatalog();

    // Erweiterungen (Assemblies) im Verzeichnis "Plugins" suchen.
    catalog.Catalogs.Add(
        new DirectoryCatalog(
            HttpContext.Current.Server.MapPath("~/Plugins")));

    // Erweiterungen in der Assembly suchen, in der sich die Klasse "User" befindet.
    catalog.Catalogs.Add(new AssemblyCatalog(typeof(User).Assembly));

    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);
}

Gefundene Implementierungen würden der mit dem Attribut “ImportMany” gekennzeichneten Eigenschaft “Plugins” (Zeile 2) hinzugefügt werden. Für den Fall das “nur” eine Erweiterung geladen werden soll wird einfach das Attribut “Import” verwendet.

[Import]
public IPlugin Plugins { get; private set; }

Die Implementierungen werden aber nicht ohne jegliches dazutun gefunden. Jede Klasse muss mit dem Attribut “Export” ausgestattet werden, welches angibt was sie zur Verfügung stellt.

[Export(typeof(IPlugin))]
public class VeryCoolPlugin : IPlugin
{
    // ...
}
Previous posts