ASP.NET MVC: Ein Benachrichtigungssystem implementieren

von Lennart Montag, 5. November 2012

Die eingebaute Validierung von ASP.NET MVC ermöglicht es mit der Methode "@Html.ValidationSummary()" Fehlermeldungen über falsche Benutzereingaben auszugeben, oft möchte man aber nur eine Warnung anzeigen oder über den Erfolg einer Aktion informieren. Was fehlt in ASP.NET MVC ist ein kleines Benachrichtigungssystem, welches folgend implementiert werden soll.

 

Eine Benachrichtigung soll im Controller über die Methode "this.Notify(notification)" hinzugefügt werden können. Damit die Benachrichtigungen auch nach einer Weiterleitung zu einer anderen Seite noch angezeigt werden, ist es wichtig diese nicht im "ViewDataDictionary" sondern im "TempDataDictionary" abzulegen. Dafür implementieren wir uns eine Liste welche unsere Benachrichtigungen enthält. Eine Benachrichtigung ist vom Typ "object", so können wir Benachrichtigungen mit beliebigen Informationen ausstatten, z.B. mit einem Verweis zu dem Benutzer der gerade erstellt wurde.

public class Notifications : Collection<object>
{
    public static Notifications From(TempDataDictionary tempData)
    {
        var notifications = tempData[typeof(Notifications).FullName] as Notifications;

        if (notifications == null)
        {
            notifications = new Notifications();
            tempData[typeof(Notifications).FullName] = notifications;
        }

        return notifications;
    }
}

Um eine Benachrichtigung hinzufügen zu können, implementieren wir eine Erweiterungsmethode für die Controller-Klasse.

public static void Notify(this Controller controller, object notification)
{
    Notifications.From(controller.TempData).Add(notification);
}

Alle Benachrichtigungen lassen sich jetzt sehr einfach in der Layoutseite der Anwendung ausgeben. Dafür durchlaufen wir die Liste mit den Benachrichtigungen und geben die Teilansicht, welche als Namen den Klassennamen der Benachrichtigung mit einem vorangestellten Unterstrich hat, aus.

@foreach (var notification in Notifications.From(this.TempData))
{
    @Html.Partial("_" + notification.GetType().Name, notification)
}

Eine Benachrichtigung mit dem Klassenamen "TaskCreatedNotification" würde also eine Teilansicht mit dem Namen "_TaskCreatedNotification" erwarten. Da man nicht immer eine spezielle Benachrichtigung braucht, kann man sich auch eine allgemeine Benachrichtigung implementieren.

public class Notification
{
    private readonly NotificationType type;
    private readonly string text;

    public Notification(NotificationType type, string text)
    {
        this.type = type;
        this.text = text;
    }

    public NotificationType Type
    {
        get { return this.type; }
    }

    public string Text
    {
        get { return this.text; }
    }
}
public static void Notify(this Controller controller, NotificationType type, string text)
{
    Notifications.From(controller.TempData).Add(new Notification(type, text));
}

Anbei die Implementierung in einem MVC-Projekt zum ausprobieren:

MvcNotifications.zip (2,26 mb)

ASP.NET: Virtuelle Projektvorlagen

von Lennart Sonntag, 14. Oktober 2012

Wie verteile ich Komponenten der Benutzeroberfläche (Views, Stylesheets und Javascript) an mehrere ASP.NET Anwendungen? Diese Frage entstand aus der Absicht mehrere ASP.NET MVC Anwendungen mit dem selben Look & Feel zu entwickeln, um so den Eindruck einer einzigen großen Anwendung zu vermitteln.

Das .net Framework nutzt Assemblies um Code zu Verteilen und auch zu Versionieren, diesen Luxus kann man für Komponenten der Benutzeroberfläche normalerweise nicht in Anspruch nehmen. Abhilfe schaffen da zwei Features des .net Frameworks, zum einen kann man jede Datei (somit auch Views, Stylesheets und Javascript) in Assemblies einbinden und zum anderen stellt ASP.NET ein virtuelles Dateisystem bereit, wodurch man die eingebundenen Dateien der ASP.NET Anwendung zur Verfügung stellen kann.

Die Kombination dieser beiden Features habe ich als Projekt auf CodePlex und NuGet hochgeladen. Damit ist es sehr einfach eine virtuelle Projektvorlage, welche Views, Stylesheets und Javascript enthält, zu erstellen. Dazu legt man zuerst eine neue Klassenbibliothek an, welche alle Dateien der Projektvorlage enthalten sollen.

Für jede Datei die in der virtuellen Projektvorlage vorhanden sein soll muss als "Build Action" die Auswahl "Resource" getroffen werden, so wird die Datei in die Assembly eingebunden.

Auf die Klassenbibliothek muss jetzt nur noch aus der Webanwendung verwiesen werden und die virtuelle Projektvorlage muss beim Start der Anwendung registriert werden.

Normalerweise verarbeitet ASP.NET keine CSS- oder JS-Dateien, sondern gibt die Kontrolle an den IIS zurück. Daher müssen wir noch ein Http-Modul registrieren, welches dieses verhindert und ASP.NET dazu veranlasst über das virtuelle Dateisystem auf unsere virtuelle Projektvorlage zuzugreifen.

 

Um die Entwicklung einer Projektvorlage zu vereinfachen gibt es noch die Möglichkeit, sich im Debug-Modus die Dateien aus dem Verzeichnis der Projektvorlage zu holen, so muss man bei kleinen Änderungen an der Projektvorlage diese nicht jedes mal neu kompilieren um die Änderungen zu testen.

Ich hoffe dem einen oder anderen, der vor ähnlichen Problemen steht, kann ich mit diesem Projekt helfen. Es gibt sicher noch viel Optimierungspotenzial an dem Projekt, daher bin ich für weitere Ideen oder Anregungen immer offen.

Ich bin gespannt auf Eure Meinungen.