codefest.at [MS]: 2D Unity Game Tutorial mit Sample Code

Vor dem Sommer haben wir einen Hackathon für Frauen zum Thema “Apps & Games” veranstaltet, in dem wir auch das erste Mal das Thema Gaming angesprochen haben. An diesem Hackathon hat Bernadette Thalhammer von der Sproing Interactive Media GmbH für die Teilnehmerinnen einen Game Development Workshop abgehalten. Eindrücke des Hackathons gibt es natürlich auch online.

Der Sample Code des Unity Projektes aus diesem Workshop ist nun auf GitHub verfügbar. Wenn ihr das Tutorial ausprobieren wollt, so könnt ihr direkt anhand dieser Anleitungendas Spiel nachbauen, das ein Slide Shooter Game darstellt. Falls ihr Unity3D noch  nicht installiert habt, so findet ihr sie hier als Download. Eine Einführung in die 2D Spiele Entwicklung mit Unity findet ihr natürlich auch auf der MVA. Auch ein ganzer JumpStart Kursist hier demnächst geplant.

Um das Hackathon Projekt als Windows Phone oder Windows Store App zu bauen, müsst ihr dieses Projekt von GitHub in der Unity3D IDE öffnen. Dort geht ihr auf File/Build Settings… und wählt eure Platform aus, zb Universal Project, um gleich als Windows Store und Windows Phone App zu deployen.

image

Wenn ihr nach eurer Auswahl auf Build klickt, so könnt ihr ein Verzeichnis wählen/erstellen, in dem eure Visual Studio Solution erstellt wird.

image

Danach ist alles wie gehabt. Ihr öffnet die Solution in Visual Studio und seht dort eure Windows Phone bzw Universal App Projekte, von denen ihr dann die Store Packages zum Upload in den Store erstellen könnt.

Viel Spaß beim Spielen! :)

Paul Mizel: async await und parallel - eine einfache Messung

Es ist nicht immer sinnvoll async und await zu verwenden, auch in einem Parallel-Szenario, für wenige Operationen hat es sogar Nachteile.

Nachmessen hilft.

class Program{

static void Main(string[] args)

{

int runs = 10000;

using (Monitor.Create("Task: "))

{

for (int i = 0; i < runs; i++)

{

Task task = new Task(ProcessDataAsync);

task.Start();

task.Wait();

}

}

using (Monitor.Create("Normal: "))

{

for (int i = 0; i < runs; i++)

{

ProcessData();

}

}

using (Monitor.Create("Parallel Task: "))

{

Parallel.For(0, runs, i =>

{

Task task = new Task(ProcessDataAsync);

task.Start();

task.Wait();

});

}

using (Monitor.Create("Parallel Normal: "))

{

Parallel.For(0, runs, i =>

{

ProcessData();

});

}

Console.ReadKey();    }

static async void ProcessDataAsync()

{

Task<int> task = Task.FromResult(5);

System.Threading.Thread.Sleep(1);

int x = await task;

}

static void ProcessData()

{

System.Threading.Thread.Sleep(1);

}

}

public class Monitor : IDisposable

{

System.Diagnostics.Stopwatch sw;

string prefix;

public Monitor(string prefix)

{

this.prefix = prefix;

sw = System.Diagnostics.Stopwatch.StartNew();

}

public static Monitor Create(string prefix)

{ return new Monitor(prefix); }

public void Dispose()

{ Console.WriteLine(prefix + sw.ElapsedMilliseconds + " ms"); }

}

Martin Hey: noHistory in der Activity und der Seiteneffekt

Normalerweise kann man im savedInstanceState Statusinformationen ablegen, die dann beim Resume der Activity dafür sorgen, dass die Benutzeroberfläche wieder so hergestellt werden kann, wie sie war bevor die App in den Ruhemodus versetzt wurde.


Heute hatte ich das Phänomen, dass im onSaveInstanceState meine Daten in das Bundle geschrieben wurden, beim Fortsetzen der App im onCreate aber immer NULL als savedInstanceState bereitstand, was dafür sorgte, dass sich die Benutzeroberfläche immer zurücksetzte auf den Initialzustand.

Nach einiger Suche kam ich dann auf des Problems Lösung: Ich hatte in der Manifest-Datei der Activity das Flag noHistory="true" gesetzt. Laut Dokumentation hat dies folgenden Effekt:
Whether or not the activity should be removed from the activity stack and finished [...] when the user navigates away from it and it's no longer visible on screen.

[...] 

A value of "true" means that the activity will not leave a historical trace. It will not remain in the activity stack for the task, so the user will not be able to return to it.
Mein Verständnis dieses Flags war, dass dadurch die Activity nicht auf dem Backstack landet. Das funktioniert auch. Allerdings meint "the user will not be able to return to it" auch, dass sämtliche Informationen im Bundle verworfen werden und jedes Resume wie ein Neustart der Activity ist.

Holger Sirtl: Neuerungen in Microsoft Azure: DocumentDB (Preview), Azure Search (Preview), HBase für HDInsight (GA)

Microsoft hat heute einige Neuerungen für die Microsoft Azure Plattform veröffentlicht:

  • Preview des Document-Database-as-a-Service Dienstes DocumentDB
  • Preview des Suchdienstes Azure Search
  • Allgemeine Verfügbarkeit (GA) von Apache HBase für HDInsight

DocumentDB (Preview)

NoSQL Technologien haben sich zur Datenspeicherung in der Cloud fest etabliert. Sie versprechen hohe Skalierbarkeit und flexible Datenspeicherung. Vielen der verfügbaren NoSQL-Angebote fehlen jedoch leistungsfähige Abfragemechanismen und transaktionales Verhalten. Diese Lücke schließt DocumentDB. DocumentDB ist ein Document-Database-as-a-Service Dienst der die Vorteile einer NoSQL Documentendatenbank mit den erweiterten Abfragemechanismen und Transaktionssemantik einer relationalen Datenbank vereint.

Azure DocumentDB unterstützt JSON Dokumente, die nach ihren Propertys durchsucht werden können. Dazu werden Programmierbibliotheken für verschiedene Sprachen und Plattformen – darunter .NET, Node.js, JavaScript und Python – bereitgestellt. Stored Procedures können in JavaScript erstellt werden.

Weitere Informationen zu DocumentDB: Getting started with DocumentDB.

Azure Search (Preview)

Eine Suchfunktion wird praktisch in jeder Webseite benötigt. Der Aufbau einer Such-Infrastruktur kann jedoch sehr aufwändig sein. Es reicht nicht einen öffentlichen Such-Dienst zu nutzen, der in der Regel nur eine gewichtete Volltextsuche bieten kann. Azure Search ist ein vollautomatisch verwalteter Search-as-a-Service Dienst, mit dem Suche in eigene Weseiten integriert werden kann. Dabei können eigene Ranking Profile verwendet werden um Suchergebnisse in Richtung der Geschäftsziele hin zu beeinflussen (z.B. Höherbewertung von Produkten, die eine höhere Marge aufweisen). Azure Search ist hoch-skalierbar und kann auf Lastspitzen reagieren.

Weitere Informationen zu Azure Search: Configure Search in the Azure Preview Portal.

HBase für HDInsight (GA)

In Zusammenarbeit mit Hortonworks wurde mit deren Hilfe bereits die Hadoop-Plattform in Form des HDInsight-Service auf Azure verfügbar gemacht. In diesem Kontext wurde jetzt HBase als Managed Cluster innerhalb von HDInsight verfügbar gemacht. HBase Cluster speichern ihre Daten dabei in Blob Storage.

Weitere Informationen zu HBase für HDInsight: Get started using HBase with Hadoop in HDInsight.

Weitere Informationen

Holger Sirtl: Serie: Eigene Anwendungen auf Microsoft Azure - Teil 2: Virtual Machines

Microsoft Azure bietet zur Ausführung eigener Anwendungen in der Public Cloud vier Optionen: Virtual Machines, Cloud Services, Websites und Mobile Services. Diese Blog-Serie gibt Hinweise zur Entscheidung für die zu einem konkreten Vorhaben beste Alternative, Die Serie ist unterteilt in 7 Teile:

Dieser Teil geht auf Virtual Machines ein. Virtual Machines sind die Ausführungsoption, die wohl die meisten Personen vor Augen haben, die über die Ausführung Ihrer Anwendung in der Cloud nachdenken. Sie stellen das Infrastructure-as-a-Service-Angebot (IaaS) auf Microsoft Azure dar.

Virtual Machines erlauben den Betrieb selbst erstellter oder von Microsoft bereitgestellter virtueller Maschinen auf Microsoft Azure. Diese werden minutengenau abgerechnet. Zur Bereitstellung einer Virtual Machine ist letztlich nur die Festlegung eines VM-Image (hier werden Standard-Hyper-V-Images eingesetzt), auf deren Basis der Bootvorgang ablaufen soll, sowie ein paar wenige Konfigurationsparameter erforderlich:

  • VM-Größe
  • Administrator-Kennung
  • DNS-Name
  • Azure Subscription
  • Die Region des Rechenzentrums, in dem die VM ausgeführt werden soll

Auf die dann in Azure ausgeführten Virtual Machines haben Nutzer vollen Adminstrator-Zugang. Sie können sich z.B. per Remote Desktop auf eine VM einwählen und die Maschine ihren Wünschen entsprechend konfigurieren. Die in den virtuellen Maschinen eingesetzten Festplattenlaufwerke werden im Blob Storage persistiert. Virtual Machines eignen sich deshalb ideal für eine schnelle Migration einer bestehenden On-premise-Anwendung in die Cloud. Prinzipiell können die VMs der lokalen Umgebung in die Cloud übertragen oder quasi 1:1 in der Cloud nachgebaut werden.

Durch die Persistierung der VM-Disks im Blob Storage bleiben – im Gegensatz zu den nicht-persistenten Images der Cloud Services – alle Inhalte erhalten, sollte eine virtuelle Maschine einem Re-Image unterzogen werden (z.B. bei Hardware-Ausfall). Für die Inhalte gelten die gleichen Regeln für Failover (3-fach-Speicherung aller Inhalte, optionale Geo-Replikation in ein entferntes Rechenzentrum) wie für alle anderen Inhalte des Blob Storage. Da von Microsoft Azure Standard-VHDs genutzt werden, können sowohl bestehende VMs aus einer lokalen Hyper-V-Umgebung in die Cloud migriert und als Virtual Machine ausgeführt, als auch der umgekehrte Weg beschritten werden: VHDs können aus Microsoft Azure heruntergeladen und in einer entsprechenden Hyper-V-Umgebung lokal ausgeführt werden.

Als Gast-Betriebssysteme für Virtual Machines werden sowohl verschiedene Windows Server Varianten als auch ausgewählte Linux-Distributionen unterstützt. Ebenfalls unterstützt werden einige Serveranwendungen wie SQL Server, SharePoint Server, BizTalk Server und Active Directory. Durch Kooperation mit Oracle werden auch Anwendungen aus dem Oracle-Technologieportfolio (WebLogic, Java, Oracle DB, …) unterstützt. Es ist möglich, neue Images in einer lokalen Hyper-V-Umgebung zu erzeugen, nach Windwos Azure zu laden und von den Images neue Virtual Machines zu booten. Daneben können auch bereits vorgefertigte mit entsprechender Serversoftware bestückte Images aus einer Gallery (siehe Abb 1) ausgewählt und gestartet werden.

image

Abb 1: Virtual Machine Gallery

Damit ist es möglich, wichtige Teile der Serverumgebungen eines eigenen Rechenzentrums ohne Änderung nach Microsoft Azure zu migrieren. Die minutengenaue Abrechnung macht dieses Ausführungsmodell auch für die Bereitstellung von Test- oder Demo-Umgebungen interessant, wo Infrastruktur nur temporär benötigt wird.
Wie die anderen Ausführungsmodelle können auch Virtual Machines in Kombination mit anderen Azure Services genutzt werden. So kann eine in einer VM ausgeführte Anwendung beispielsweise problemlos Microsoft Azure Storage oder SQL Database nutzen. Besonders interessant ist die Kombination mit dem Virtual Network: Durch die Möglichkeit ein lokale und Cloud-basierte VMs umspannendes virtuelles Netzwerk mit gemeinsamen Ipv4-Adressraum und entsprechenden Routing Tabellen einzurichten, können virtuelle Maschinen flexibel zwischen der Cloud und einem lokalen Rechenzentrum hin- und hergeschoben werden ohne dass dies aus Netzwerksicht Auswirkungen auf die anderen VMs hat.

Die hohe Flexibilität der Virtual Machines kommt allerdings zu dem Preis, dass ein signifikanter Teil der Infrastruktur im Verantwortungsbereich des Nutzers verbleibt, d.h. er muss sich um das Setup und die Wartung der VM-Images kümmern (Patches und Upgrades einspielen).

Gründe für die Wahl von Virtual Machines als Ausführungsumgebung können deshalb sein:

  • Linux wird als Gast-OS für die eigene Anwendung benötigt
  • Es werden administrativer Zugriff und entsprechende Konfigurationsmöglichkeiten benötigt

Gründe für die Wahl einer der anderen Ausführungsoptionen (Cloud Services, Websites oder Mobile Services)  können entsprechend sein:

  • Das Management der Infrastruktur soll vollständig von Azure übernommen werden.
  • Maßnahmen für Failover und High-Availability sollen von Azure automatisiert durchgeführt werden.

Fazit

Die Microsoft Azure Dokumentation enthält einen tabellarischen Überblick über die Möglichkeiten der einzelnen Ausführungsoptionen. Als Fazit kann gezogen werden:

  • Virtual Machines sollten nur dann verwendet werden, wenn es entscheidende Gründe hierfür gibt (es wird ein Feature benötigt, das nur Virtual Machines bieten, z.B. Linux als Gast-OS)
  • Wann immer möglich, sollten die anderen Ausführungsoptionen validiert und ggf. verwendet werden. Sie bieten deutliche (Kosten-)Vorteile im automatisierten Management der Umgebung.

Weitere Informationen

Informationen zu Virtual Machines

Informationen zur allgemeinen Entscheidung für ein Ausführungsmodell

Jürgen Gutsch: Playing around with SignalR 2.1.1 - Teil 2: Die Clientseite

Im ersten Teil habe ich die Serverseite beschrieben. Diesmal geht es um die wesentlich interessantere Clientseite.

Vorbereitung – Das Formular

Als erste habe ich zwei einfache Formulare definiert. Das erste ist ein einfaches An- und Abmeldeformular, das lediglich einen Benutzername erwartet. Neben einer Textbox, beinhaltet das Formular je einen Button zum Anmelden und eines zum Abmelden vom Chat. Wie man sieht nutze ich die vorhanden CSS-Klassen aus Twitter Bootstrap und muss mich nicht groß um das Layout kümmern:

<form class="form-horizontal">
    <fieldset id="loginwindow">
        <legend>Sign-In</legend>

        <div class="form-group">
            <label for="name"
                   class="col-sm-2 control-label">
                User name:
            </label>
            <div class="col-sm-10">
                <input type="text"
                       class="form-control"
                       name="name"
                       id="name"
                       placeholder="User name">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="button"
                        id="signout"
                        class="btn btn-default pull-right"
                        disabled="disabled">Sign-out</button>
                <button type="button"
                        id="signin"
                        class="btn btn-primary pull-right">
                    Sign-in
                </button>
            </div>
        </div>
    </fieldset>
</form>

Das zweite Formular ist das eigentliche Chatfenster. Den Chat gebe ich der Einfachheit halber in einer Textarea aus. Darunter befinden sich eine Textbox zur Eingabe der Chat-Nachrichten und daneben ein Button zum Versenden der Nachricht. Die beiden Formulare sitzen direkt untereinander Optisch durch das Fieldset getrennt:

<form class="form-horizontal">
    <fieldset id="chatwindow"
              disabled="disabled">
        <legend>Chat</legend>

        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                </textarea class="form-control"
                          style="height: 300px;"
                          name="chatarea"
                          id="chatarea">
            </div>
        </div>

        <div class="form-group">
            <label for="name"
                   class="col-sm-2 control-label">
                Your message:
            </label>
            <div class="col-sm-10">
                <input type="text"
                       class="form-control"
                       name="message"
                       id="message"
                       placeholder="Your message">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="button"
                        id="messagesend"
                        class="btn btn-primary pull-right">
                    Send
                </button>
            </div>
        </div>
    </fieldset>
</form>

Auf zum Coden – Das JavaScript

Das war es auch schon auf der HTML-Seite. Schauen wir uns nun mal das JavaScript an. Das erste was getan werden sollte ist, den benötigten Hub zu holen:

var chatter = $.connection.chatter;

Die “connection” wird über die Bibliothel jQuery.signalR bereitgestellt und stellt den Zugriff auf den jeweiligen Hub bereit. Wir erinnern uns an das Attribut über unserem Hub aus dem ersten Teil. Über diesen Namen greifen wir nun darauf zu. Weiter unten sehen wir mehr davon.

Vorerst benötigen wir drei Methoden die unsere Formulare steuern.

Die erste Methode “addMessage” erstellt die komplette Chat-Nachricht, inklusive des Clientseitigen Zeitstempels (Was bringt dem User die Serverzeit? Die Nachrichten werden in diesem Beispiel eh nicht auf dem Server gespeichert, sondern nur durchgeleitet ;) ) Ist die Nachricht komplett, wird sie an den Inhalt der Textarea angehängt:

var addMessage = function (message) {
    var currentdate = new Date();
    var messate = currentdate.getHours() + ":" + currentdate.getMinutes()
    messate += ' ' + message + '\n';
    $('#chatarea').append(messate);
};

var enableChat = function () {
    $('#chatwindow').prop("disabled", false);
    $('#name').prop("disabled", true);
    $('#signin').prop("disabled", true);
    $('#signout').prop("disabled", false);
};

var disableChat = function () {
    $('#chatwindow').prop("disabled", true);
    $('#name').prop("disabled", false);
    $('#signin').prop("disabled", false);
    $('#signout').prop("disabled", true);
    $('#name').val('');
};

Die beiden Methoden “enableChat” und “disableChat” werden aufgerufen, wenn die Anmeldung oder die Abmeldung erfolgreich war und steuern welcher Teil der UI aktiv oder inaktiv ist.

Als nächsten Schritt habe ich, wie auch im Sample, eine “init” Methode geschrieben, mit der die Buttons der Formulare mit Aktionen versehen werden. Hier passiert auch der Aufruf der Serverseitigen Methoden:

var init = function () {

    $('#signin').click(function () {
        var name = $('#name').val();
        if (name.length < 4) {
            alert('username is not valid!');
            return;
        }

        chatter.server
            .signIn($.connection.hub.id, name);
    });

    $('#signout').click(function () {
        var name = $('#name').val();

        chatter.server
            .signOut($.connection.hub.id, name);
    });

    $('#messagesend').click(function () {
        var message = $('#message').val();
        if (message.length < 1) {
            alert('message is not valid!');
            return;
        }

        chatter.server
            .post($.connection.hub.id, message);
        $('#message').val('');
        $('#message').focus();
    });
};

Die Validierung die wir hier sehen, ist nicht wirklich gut, reicht aber für dieses Beispiel voll aus ;)

Über “chatter.server” haben wir nun Zugriff auf die serverseitigen Methoden. In jedem Fall übergeben wir hier die ConnectionId, die sich unter $.connection.hub.id versteckt. Wie auch für die Anmeldung, wird auch bei der Abmeldung der Name übergeben, damit wir eine schöne Begrüßung oder einen Abschiedsnachricht erzeugen können.

Schaut euch im ersten Teil die zugehörigen Server-Methoden an um den Datenfluss nachvollziehen zu können.

“chatter.server.post” schickt nun die eigentliche Chat-Nachricht an den Server, der sie daraufhin an alle Clients sendet.

Wie aber empfängt der Client nun die Nachrichten? Wir Erinnern uns an den serverseitigen Aufruf aus dem ersten Teil:

Clients.All.postMessage(user + "> " + message);

Wir müssen auf der Clientseite – unter anderem – die Methode “postMessage” erstellen und dem clientseitigen “chatter”-Objekt bekannt geben:

$.extend(chatter.client, {
    userAdded: function () {
        enableChat();
    },
    postMessage: function (message) {
        addMessage(message);
    },
    userRemoved: function () {
        disableChat();
    }
});

Wir erzeugen einen “client”-Namespace und fügen die benötigten Methoden ein, die dann wiederum auf die vorhandenen Methoden zugreifen.

That’s it :)

Ich kann nun den Chat laufen lassen und mit zwei verschiedenen Browser testen:

Manfred Steyer: Soft-Delete mit Entity Framework 6.1

Seit Entity Framework 6.1 können Entwickler mit CommandTreeInterceptoren SQL-Anweisungen abfangen und abändern. Im Gegensatz zu den CommandInterceptoren, die bereits mit 6.0 zur Verfügung standen, stellen CommandTreeInterceptoren die SQL-Anweisung nicht in Form eines Strings sondern in Form eines Syntax-Baumes dar. Dies vereinfacht das Abändern der Anweisung. Auf diese Weise lassen sich globale Filter definieren. Ein solcher globaler Filter könnte zum Beispiel festlegen, dass nur Datensätze mit einem bestimmten Status oder nur Datensätze eines bestimmten Mandanten geladen werden. Dazu müsste der Interceptor jeder Abfrage um eine entsprechende Einschränkung erweitern.

Auf der Teched 2014 hat Entity-Framework-Programm-Manager Rowan Miller ein Beispiel präsentiert, in dem er einen CommandTreeInterceptor zur Implementierung von Soft-Deletes nutzt. Hierunter versteht man Fälle, in denen Anwendungen obsolete Datensätze nicht tatsächlich löschen, sondern nur als gelöscht markieren. Den Quellcode dieses Beispiels findet man unter [1]. Da es sich bei Soft-Deletes um eine häufig anzutreffendes Muster im Bereich der Datenbankprogrammierung handelt und Entity Framework hierfür keine Boardmittel bietet, demonstriert dieser Beitrag den Einsatz von CommandTreeInterceptoren anhand von Auszügen dieses Beispiels.

Um den Einsatz von Soft Delete für ausgewählte Entitäten zu aktivieren, sieht das besprochene Beispiel ein Attribut SoftDeleteAttribute vor (siehe nachfolgendes Listing). Damit werden die jeweiligen Entitäten annotiert. Über die Eigenschaft ColumnName gibt der Entwickler den Namen der Spalte, welche Auskunft darüber gibt, ob der Datensatz als gelöscht gilt, an. Standardmäßig wird hierfür der Name IsDeleted angenommen.

Die statische Hilfsmethode GetColumnName nimmt einen EdmType, welcher im Entity Data Model eine Entität repräsentiert, entgegen und liefert den zuvor erwähnten Spaltennamen für diese Entität retour. Sie geht davon aus, dass diese Information unter dem Schlüssel customannotation:SoftDeleteColumnName in den im Model für diesen Typ hinterlegten Metadaten zu finden ist. Damit dies auch der Fall ist, konfiguriert der Entwickler für den verwendeten DbContext innerhalb der Methode OnModelCreating die Konvention AttributeToTableAnnotationConvention:

var conv = 
   new AttributeToTableAnnotationConvention(
       "SoftDeleteColumnName",
        (type, attributes) => attributes.Single().ColumnName);

modelBuilder.Conventions.Add(conv);

Mit dieser Konvention legt der Entwickler fest, dass Entity Framework die Eigenschaft ColumnName des Attributes SoftDeleteAttribute in die Metadaten der Entität aufnehmen soll. Als Schlüssel gibt er hierfür SoftDeleteColumnName an; der zuvor betrachtete Präfix customannotation wird von dieser Konvention standardmäßig vergeben.

public class SoftDeleteAttribute: Attribute
{
    public SoftDeleteAttribute()
    {
        ColumnName = "IsDeleted";
    }

    public string ColumnName { get; set; }

    public static string GetColumnName(EdmType type)
    {
        var prop = type
                    .MetadataProperties
                    .Where(p => 
                        p.Name.EndsWith("customannotation:SoftDeleteColumnName"))
                    .FirstOrDefault();

        string columnName = (prop != null) ? (string) prop.Value : null;

        return columnName;
    }
}

Richtig spannend wird das betrachtete Beispiel, wenn der CommandTreeInterceptor ins Spiel kommt. Diesen findet man im nachfolgenden Listing. Er bietet eine Methode TreeCreated an. Diese führt Entity Framework aus, nachdem es den Syntax-Baum für eine SQL-Anweisung erstellt hat. Die betrachtete Implementierung prüft zunächst, ob TreeCreated für das Store Model ausgeführt wird und somit einen Syntax Baum, aus dem später direkt SQL abgeleitet wird, beinhaltet. Ist dem nicht so, wird die Methode abgebrochen.

Anschließend greift sie auf die Eigenschaft Result des von Entity Framework übergebenen Kontextes zu. Diese Eigenschaft beinhaltet den Syntax-Baum und ist vom abstrakten Typ DbCommandTree. Die hier tatsächlich verwendete Subklasse gibt Auskunft über die Art der zugrunde liegenden SQL-Anweisung. Handelt es sich um ein SELECT kommt die konkrete Subklasse DbQueryCommandTree zum Einsatz. Für den Aufruf einer Stored Procedure oder Stored Function verwendet Entity Framework hingegen das Derivat DbFunctionCommandTree und für DML-Anweisungen (INSERT, UPDATE, DELETE) die abstrakte Klasse DbModificationCommandTree, von der die konkreten Klassen DbInsertCommandTree, DbUpdateCommandTree und DbDeleteCommandTree ableiten. Die Namen sind dabei Programm.

Da das hier behandelte Beispiel jedes SELECT erweitern muss, sodass nur Datensätze, die nicht als gelöscht markiert wurden, geladen werden, prüft es, ob es sich beim Baum um einen DbQueryCommandTree handelt. Ist dem so, wendet es auf den Baum einen SoftDeleteQueryVisitor an, indem sie ihn an dessen Methode Accept übergibt. Dies geht konform mit dem für solche Aufgaben häufig eingesetzten Entwurfs-Muster Visitor (Besucher). Implementierungen dieses Musters durchlaufen die Knoten eines Baums und übergeben diese an eine Komponente, welche als Visitor bezeichnet wird. Der Visitor besucht demnach die einzelnen Knoten. Dieser Visitor kann nun entscheiden, ob er die Daten des erhaltenen Knotens auswertet bzw. den Knoten abändert. Im betrachteten Fall kümmert sich der verwendete Visitor, welcher weiter unten genauer beschrieben wird, um das Hinzufügen der besprochenen Einschränkung.

Das Ergebnis von Accept verpackt die betrachtete Implementierung in einem neuen DbQueryCommandTree. Diesen hinterlegt es in der Eigenschaft Result des Kontextes, was zur Folge hat, dass Entity Framework damit und nicht mit dem ursprünglichen Baum vorliebnimmt.

Die unter [1] zu findende Implementierung prüft auch, ob der an TreeCreated übergebene Syntax-Baum einem DELETE entspricht. In diesem Fall formt es dieses zu einem UPDATE, welches den Datensatz als gelöscht markiert, um.

class CustomCommandTreeInterceptor : IDbCommandTreeInterceptor
{
    public void TreeCreated(
            DbCommandTreeInterceptionContext interceptionContext)
    {
        if (interceptionContext.OriginalResult.DataSpace 
                                          != DataSpace.SSpace) return;

        var tree = interceptionContext.Result as DbQueryCommandTree;

        if (tree != null)
        {
            var newQuery = tree.Query.Accept(new SoftDeleteQueryVisitor());

            interceptionContext.Result = new DbQueryCommandTree(
                tree.MetadataWorkspace,
                tree.DataSpace,
                newQuery);
        }

        var deleteCommand = interceptionContext.OriginalResult 
                                                    as DbDeleteCommandTree;
        if (deleteCommand != null)
        {
            var column = SoftDeleteAttribute.GetColumnName(
                             deleteCommand.Target.VariableType.EdmType);
            if (column != null)
            {

                var setClause =
                    DbExpressionBuilder.SetClause(
                            DbExpressionBuilder.Property(
                                DbExpressionBuilder.Variable(
                                    deleteCommand.Target.VariableType, 
                                    deleteCommand.Target.VariableName),
                                column),
                            DbExpression.FromBoolean(true));

                var update = new DbUpdateCommandTree(
                    deleteCommand.MetadataWorkspace,
                    deleteCommand.DataSpace,
                    deleteCommand.Target,
                    deleteCommand.Predicate,
                    new List { setClause }.AsReadOnly(),
                    null);

                interceptionContext.Result = update;
            }
        }

    }
}

Die Umsetzung des SoftDeleteQueryVisitors findet sich im nachfolgenden Listing. Sie leitet von der Klasse DefaultExpressionVisitor, welche Entity Framework als Basis-Klasse für Visitor-Implementierungen anbietet, ab und überschreibt die Methode Visit. Da es von Visit zahlreiche Überladungen gibt, ist zu betonen, dass es sich hier um jene Überladung von Visit, welche eine DbScanExpression entgegennimmt, handelt. Diese Methode ruft Entity Framework immer dann auf, wenn der jeweils besuchte Knoten das Abfragen von Daten einer Entität repräsentiert.

Die Methode Visit ermittelt mit der zuvor besprochenen Methode GetColumnName die für die betroffene Entität hinterlegte Spalte. Ist dieser Wert null, geht Visit davon aus, dass für die betrachtete Entität keine Soft-Deletes zum Einsatz kommen sollen und delegiert lediglich an die geerbte Basis-Implementierung. Ansonsten erweitert Visit die DbScanExpression um einen Filter, aus dem hervor geht, dass nur Datensätze bei denen die festgelegte Spalte den Wert true hat, zu laden und liefert sie retour.

public class SoftDeleteQueryVisitor : DefaultExpressionVisitor
{
    public override DbExpression Visit(DbScanExpression expression)
    {
        var columnName = 
                SoftDeleteAttribute.GetColumnName(expression.Target.ElementType);

        if (columnName != null)
        {
            var binding = DbExpressionBuilder.Bind(expression);

            return DbExpressionBuilder.Filter(
                binding,
                DbExpressionBuilder.NotEqual(
                    DbExpressionBuilder.Property(
                        DbExpressionBuilder.Variable(
                                binding.VariableType, binding.VariableName),
                        columnName),
                    DbExpression.FromBoolean(true)));
        }
        else
        {
            return base.Visit(expression);
        }
    }
}

Die hinter diesem Beispiel stehende Idee wurde mittlerweile auch von der Community aufgegriffen. Unter [2] findet man beispielsweise ein Projekt, welches das Definieren von globalen Filtern für Entity Framework erlaubt. Es verbirgt die Komplexität der benötigten Interceptoren und Visitatoren vor dem Entwickler, indem er die Möglichkeit bekommt, Filter mit ein paar Zeilen Code zu hinterlegen.

[1] https://github.com/rowanmiller/Demo-TechEd2014

[2] https://github.com/jbogard/EntityFramework.Filters

Fabian Deitelhoff: AntMe! v2: die Ameisen krabbeln wieder

AntMe! Version 2 steht vor der Tür!AntMe! ist ein sehr cooles Stück Software. Es macht einen riesigen Spaß, seine Ameisen zu Programmieren und mit verschiedenen Strategien zu versuchen eine bestimmte Aufgabe auf die beste Art und Weise zu lösen. Entweder vor den bösen Wanzen flüchten oder sie direkt bekämpfen. Und Ressourcen, wie beispielsweise Zucker, wollen auch noch gesammelt werden.

Nach einigen Jahren steht nun AntMe! Version 2 vor der Tür. Allerdings nicht mehr als Nebenbei-Projekt, das immerhin schon seit 2006 besteht, sondern das Team möchte höher hinaus. Dass kann ich sehr gut nachvollziehen, denn das Spiel hat enormes Potenzial.

Die Kampagne

Damit die Version 2 entstehen und das Projekt so wachsen kann wie geplant, ist natürlich Geld notwendig. Zu diesem Zweck gibt es eine Indiegogo-Kampagne, die mit der Crowd zusammen versucht, Geld einzusammeln. Darum geht es auch in diesem Blogpost. Ich möchte auf das wirklich sehr coole Projekt AntMe! und auf die begleitende Kampagne aufmerksam machen. Etwas zu AntMe! und zur Kampagne kann euch am besten Tom Wendel in dem Video auf Indiegogo erklären.

Ich denke, dass macht neugierig :). Unterstützt habe ich das Projekt, weil ich mich freuen würde, wenn die zweite Version noch besser wird als die erste und natürlich auch, weil ich der Meinung bin, dass das Business-Modell eine gute Idee ist und eine Chance verdient hat.

Zum anderen bin ich auch der Meinung, dass Kinder damit hervorragend lernen können, was es heißt zu programmieren und wie sie sich selbst so einem Themenfeld nähern können. Bei meinen VHS-Kursen zum Thema LEGO Mindstorms EV3 merke ich immer wieder, wie schnell Kinder dabei sind, wenn es Spaß macht und wenn es ein Ziel vor Augen gibt. Und eben ein anderes Ziel, als “Hello World” auf dem Bildschirm auszugeben.

Fazit

Da bleibt mir gar nicht viel zu sagen. Cooles Projekt, cooles Team und sehr gute Kampagne. Ich freue mich, meinen Beitrag in Form von ein paar Euros beisteuern zu können, auf dass die nächste Version von AntMe! enstehen kann.

Wenn auch ihr das Projekt unterstützen möchtet, stattet doch einfach der Indiegogo-Kampagne einen Besuch ab.

Jürgen Gutsch: NHibernate 4.0 ist fertig

Es tut sich wieder etwas bei NHibernate :)

Wie Ayende Rahien eben veröffentlicht hat, ist NHibernate 4.0 released und steht auf SourceForge oder per NuGet zum Download bereit.

Die aktuellen Release Notes, sowie die Sourcen findet ihr auf GitHib: https://github.com/nhibernate/nhibernate-core

Somit haben wir noch etwas dass ich mir in der nächsten Zeit genauer anschauen werde :)

ppedv Team Blog: Entity Framework-Datenmodell per Code erstellen

Was kam zuerst? Die relationale Datenbank, das objektorientierte Klassenmodell oder der ORM Mapper?

Die ältere Fraktion, zu der ich zumindest in Zeiteinheiten gehöre, findet sich in RDMBS, Normalisierung und Indizes wieder. Newcomer sehen alles dynamisch, freuen sich über JSON und stecken alles in NoSQL.

Die folgende Schritt-für-Schritt-Anleitung zeigt den sogenannten Code First-Ansatz. Damit legt man die Verantwortung für das Datenbank-Modell in die Hände von Programmierern. Mit Entity Framework und Migrations erstellt sich dann die Datenbank quasi automatisch.

Eigentlich ist es völlig egal, welcher Projekttyp oder Sprache in Visual Studio 2013 gewählt wird. Hier setzen wir ein Webforms VB.NET Projekt ein.

Wer Code First betreibt, sollte sich zuerst mit den Konventionen vertraut machen. Identity-Felder werden mit ID benannt. Am besten nutzen wir den Typ Integer. Foreign Keys erhalten den Tabellennamen und den Zusatz ID als Feldnamen. Mit Attributen nimmt man auf die späteren Feld-Definitionen im SQL Server Einfluss.

Am besten legt man die Klassen in das Model Verzeichnis. Die 1:1 Relation wird über die Eigenschaft in Zeile 22 erstellt. Für 1:n benötigen wir eine List of Property.

   1:  Imports System.ComponentModel.DataAnnotations
   2:   
   3:  Public Class room
   4:      <Key>
   5:      Public Property roomId As Integer
   6:      <MaxLength(50)>
   7:      Public Property roomname As String
   8:      Public Property datum As DateTime
   9:      Public Property isclosed As Boolean
  10:  End Class
  11:   
  12:   
  13:  Public Class chatmessage
  14:      <Key>
  15:      Public Property Id As Integer
  16:      <MaxLength(128)>
  17:      Public Property userId As String
  18:      Public Property roomId As Integer
  19:      Public Property Message As String
  20:      Public Property datum As DateTime
  21:   
  22:      Public Overridable Property room As room
  23:  End Class

 

Zusätzlich benötigen wir mit EF 6 eine vom DBContext abgeleitete Klasse, die wiederum auf die Klassen room und Chatmessage verweist.

   1:  Imports System.Data.Entity
   2:   
   3:  Public Class modellContext
   4:      Inherits DbContext
   5:   
   6:      Public Sub New()
   7:          MyBase.New("name=modellContext")
   8:      End Sub
   9:   
  10:      Public Property chatmessage As System.Data.Entity.DbSet(Of chatmessage)
  11:      Public Property room As System.Data.Entity.DbSet(Of room)
  12:   
  13:  End Class

Als nächstes führen wir in der Visual Studio Nuget Paket Manager Console enable-Migrations mit dem Context aus.

image 

Eine weitere Convention behandelt die Namensgebung des Connection String. Wir müssen diesen in der Web.config ident zur Klasse benennen.

   1:   <connectionStrings>
   2:       <add name="modellContext" 
   3:           connectionString="Data Source=(LocalDb)\v11.0;
   4:  AttachDbFilename=|DataDirectory|\modell1.mdf;Initial Catalog=modell1;
   5:  Integrated Security=True"
   6:        providerName="System.Data.SqlClient" />
   7:    </connectionStrings>

 

Jede Modellklasse fügen wir per add-Migration-Befehl dem Modell hinzu. Die Änderungen in der Datenbank lösen wir per update-Database aus.

image

Ist die Datenbank nicht vorhanden, legen wir sie an.

image

In LINQ Statements selektieren wir deshalb über Relationen hinweg aus den Daten.

   1:  Dim db As New modellContext
   2:  Dim r = db.chatmessage.Where(Function(c) c.room.roomname = "raum1")

Änderungen in der Klasse verteilen wir per add-migration und update Database in der Datenbank. So verlieren wir die Daten nicht. Dazu werden automatisch Migrationsklassen erzeugt, die eine Up und Down-Methode enthalten.

image

Damit gleichen wir auf jedem beliebigen Server jederzeit den Status des SQL Servers ab.

Auf diese Art können Sie Optimierungen der Datenbank ignorieren. Ob Sie einen Datenbank-Admin, der die entsprechende SQL Performance-Optimierung beherrscht, beauftragen oder einen EF-Spezialisten, hängt von vielen Faktoren ab. In jedem Fall bieten wir die passenden Schulungen dafür:

http://www.ppedv.de/schulung/kurse/AdoNetEF_Entity%20Framework_EntityDataModels_EDM_Framework_%204.0_WPF_WCF.aspx

http://www.ppedv.de/schulung/kurse/SQL-Performance-Optimierung-Sicherheit-Indizes-Verwaltung-Komprimierung-Verbesserung.aspx

Holger Sirtl: Serie: Eigene Anwendungen auf Microsoft Azure - Teil 1: Überblick

Die meisten Personen, die sich für das Thema Cloud Computing interessieren, haben zunächst ein Szenario im Blick: die Ausführung einer eigenen Anwendung in der Cloud. Ob nun eine bestehende oder eine neu zu entwickelnde Anwendung: in beiden Fällen kommt man recht schnell an den Punkt an dem auffällt, dass es hierzu in Microsoft Azure – anders als bei einem klassischen Hoster oder vielen anderen Cloud-Anbietern – mehrere Optionen gibt. Microsoft Azure bietet nicht nur das Hosting klassischer virtueller Maschinen im Sinne eines Infrastructure-as-a-Service-Ansatzes, sondern auch speziellere Hosting Varianten, die optimiert sind auf die schnelle Bereitstellung von Web-Anwendungen oder die flexible Skalierung mehrschichtiger Anwendungen. Diese Blog-Serie beschäftigt sich nun mit der Auswahl der für ein bestimmtes Szenario bestgeeigneten Ausführungsmodells. Sie ist unterteilt in

  • Teil 1: Überblick über die Ausführungsoptionen
  • Teil 2: Virtual Machines
  • Teil 3: Cloud Services
  • Teil 4: Websites
  • Teil 5: Mobile Services
  • Teil 6: Auswahl des besten Ausführungsmodells
  • Teil 7: Wechsel des Ausführungsmodells

Folgende Optionen stehen für die Ausführung eigener Anwendungen auf Microsoft Azure zur Verfügung:

Dies klingt zunächst verwirrend, letztlich lässt sich die Frage nach der besten Alternative aber recht schnell beantworten. Hinzu kommt die Möglichkeit, diese Optionen miteinander zu kombinieren. D.h. es ist durchaus möglich, dass Teile einer Anwendung als Website betrieben werden und andere Teile (z.B. die Datenbank) nutzen, die in einer Virtual Machine ausgeführt werden. Darüber hinaus ist ein Wechsel zwischen den Optionen möglich, d.h. man verbaut sich nichts, wenn man mit einer Option (z.B. Websites) beginnt und später auf eine andere Option (z.B. Cloud Services) wechselt.

Die vier Alternativen unterscheiden sich primär dadurch, wie viele Aspekte der Umgebung durch das Ausführungsmodell vorgegeben und damit von Azure automatisiert verwaltet werden (Einspielen von Patches, Updates, Failover-Management etc.) und welche Aspekte durch den Nutzer bestimmt werden können. Je mehr Aspekte bestimmt werden können, desto weniger Aspekte werden von Azure verwaltet. Umgekehrt gilt entsprechend: je mehr von Azure automatisiert verwaltet wird, desto weniger Einfluss auf die Umgebung ist durch den Nutzer möglich. Höchste Automatisierung (dafür geringste Möglichkeiten, die Umgebung zu kontrollieren) bieten Mobile Services. Bei Virtual Machines ist auf der anderen Seite die Möglichkeit, Einfluss auf die Umgebung zu nehmen, am größten, dafür ist der Automatisierungsgrad am kleinsten. Die beiden anderen Alternativen, Cloud Services und Websites, liegen dazwischen. Folgende Tabelle gibt einen Überblick auf die Alternativen und deren Automatisierungsgrad bzw. die Möglichkeiten, Einfluss auf die Umgebung zu nehmen.

  Virtual Machines Cloud
Services
Websites Mobile
Services
Automatisierungsgrad ●● ●●● ●●●●
Einflussmöglichkeiten ●●●● ●●● ●●

Die Tabelle gibt schon den wichtigsten Hinweis: wann immer möglich, sollten Anwendungen als Mobile Service bzw. Websites ausgeführt werden. Dort ist der Automatisierungsgrad und damit die Einsparungen im Vergleich zu einem Eigenbetrieb oder dem Betrieb in einer virtuellen Maschine am höchsten. Nur wenn die Anforderungen bestimmte Konfigurationen der Umgebung erfordern, d.h. die Umgebung stark angepasst werden muss, sollten Virtual Machines zum Einsatz kommen.

Für einige Szenarien können recht einfach erste Empfehlungen für die Ausführungsoption genannt werden:

Szenario Naheliegende
Ausführungsoption
Grund
Hosting einer ASP.NET- oder PHP-basierten Webseite Websites Websites bieten den höchsten Grad an Automatisierung, und die bereitgestellte Umgebung eignet sich sehr gut zur Ausführung von skalierbaren Web-Anwendungen.
Betrieb einer bestehenden Linux-basierten LOB-App Virtual Machines Virtual Machines bieten als einzige Ausführungsoption den Betrieb einer Linux-basierten Umgebung. Diese kann dann individuell konfiguriert werden. Der Nutzer kann sich hierzu als Admin anmelden.
Bereitstellung eines REST-Backends für mobile Anwendungen Mobile Services Mit Mobile Services lassen sich in kürzester Zeit Backends für mobile Anwendungen bereitstellen. Die Dienste können dabei leicht mit Funktionen zur Benutzerauthentifizierung, Push Notifications, Datenspeicherung versehen werden.
Cloud-Anwendung, die auf Ressourcen im lokalen Unternehmensnetzwerk zugreifen soll Cloud Services oder
Virtual Machines
Cloud Services und Virtual Machines bieten die Möglichkeit, über ein virtuelles Netzwerk Verbindungen zu einem lokalen Rechenzentrum herzustellen.

Diese Tabelle gibt nur einen ersten Hinweis auf eine geeignete Alternative. Vor einer konkreten Umsetzung sollte diese noch genauer betrachtet werden. In den weiteren Teilen dieser Blog-Serie sollen die einzelnen Alternativen deshalb genauer vorgestellt werden.

Weitere Informationen

codefest.at [MS]: Kommende JumpStarts auf der Microsoft Virtual Academy: Universal Apps, Game Development mit Unity

In den nächsten Wochen sind einige interessante JumpStarts auf der Microsoft Virtual Academy zu den Themen Universal Apps und Game Development geplant. Wer die JumpStart Serien der MVA nicht kennt: das sind Kurse, in denen in mehreren Modulen ein Thema sehr ausführlich behandelt wird.

Ich habe bereits ein vergangenes JumpStart zu App-Entwicklung für Windows Phone 8.1 besucht und muss sagen, dass diese Serien wirklich sehr gut sind. Was mir besonders gut am JumpStart gefallen hat, war die Tatsache, dass es nebenher auch einen LiveChat gab, bei dem technische Experten, technische Fragen beantwortet haben.

Zu Universal Apps sind in nächster Zeit folgende zwei JumpStarts geplant:

Zu Game Development folgender JumpStart

Ihr könnt euch natürlich auch generell auf der MVA nach anderen Kursen umschauen. Da gibt es jede Menge interessanten Content.

Dirk Primbs [MS]: Me, me, pick me! – A little guide through the web development maze.

My Master degree slowly comes to its end (2 more modules, then my diss.) and in it’s final tech module I’m literally “Programming the Internet” which is also how the course is called.

All this module is about is software engineering for the web using JavaScript, HTML5 and a number of server side frameworks to complete the picture. In parallel I spent the last 8 months catching up on the open source software world. Coming from the client side Microsoft stack with the one and only all-purpose-development-tool (of course that is Visual Studio) and the one and only all-purpose-development-framework (.NET and some flavor of WinJS), this feels like a kid in the candy store.

Suddenly there is a cornucopia of IDEs, editors and libraries at my disposal and the challenge in the beginning was to simply cut through the maze and to get a grip on the many libraries and understand what they offer…

CoolName.js – solutions and functionalities waiting for problems

Clearly, the cool name seem to be half of the job to establish a new library these days and so I was initially drawn between libraries that practially solved the same problems over and over but complemented or competed each other. I’m still confused sometimes but bit by bit I started to find some orientation, so let me share the feeling with you and provide a little info on some of the libs I looked at. Also let me know in the comments if you think there are tools or libraries that I miss out on. Instead of digging into everything, I’ll follow your suggestions and bet my destiny on crowd wisdom :-)

  • Angular.js - Templates, two-way databinding, MVC in a compact fast library. Angular is pretty cool and powerful (and rooted in the Google tech universe which made it one of my first deeper looks)
  • JQuery – This is the all-purpose powerful JavaScript-DOM handling framework pretty much every web developer needs to know. While there have been numerous attempts to solve similar problems it is clearly JQuery who made the race.
  • Ember.js - This is a templating and extension engine that comes with an enourmous amount of functionality. It is built for large, rich and long living applications such as large admin dashboards etc. Ember is moving quite fast which sometimes renders samples found online quite useless for learning. On of it’s strengths is that it gives your code structure and removes quite a bit of boilerplate code, so once familiar with the API it boosts your productivity.
  • JavaScriptMVC - Not all JavaScript frameworks play nice with each other which becomes especially frustrating if that happens with JQuery. In JavaScriptMVC’s case this is no problem as it is built on top of JQuery and aims to extend its scope with buid system, plugin management, testing and more.
  • Underscore .js - This is a collection of 80-something utility functions in one nifty library without extending the core javascript objects or without forcing any specific development style.
  • Backbone.js - This is one of the first MVC frameworks built for JavaScript. It is relatively light weight and tries to stay out of your way for the most. There is quite a fan base out there with an active community supporting the framework. My impression was that the framework requires more implementation work than other frameworks which may be advantage to some and frustrating to others…
  • Mustache - Templates, templates, templates :-) Pretty much the essential MVC framework to some.
  • Polymer – Ok, this  has not been the first project to bring web components to modern browsers but it surely is one of the cooler ones. Also it is moving fast and is getting more productive every build. Features databinding, components for common functionalities and is ready for material design. Responsive and multi-device support is built in as well.

A special mention here deserves the DART language project. It comes with a full stack of web development functionalities and Angular as well as Polymer can be used from that language. It replaces JavaScript as web development language and offers type safety, compiled code and full object orientation which should make it easy for every .NET, Java or web developer to learn. Additionally it comes with it’s own IDE which places it right in the middle between the just finished section and the now following list of Web IDEs:

One tool to rule them all? Not quite.

I mentioned in the beginning that I came from a world where there was pretty much one editor used for everything. While Visual Studio still is a very powerful tool I found it refreshing to make my way to a number of alternatives and by now I feel quite comfortable with some of them. Here is what I tried:

  • Eclipse – hm… let’s just say Eclipse and me will never be  in love with each other. Too bulky, too slow, too patchy. But I tried and it is installed on my machine. Just barely ever started anymore :-) Little sidenote: Have a look at Android Studio if it is Android Dev that you’re after. I liked it better for App development.
  • WebStorm - JetBrains builds a whole family of IDEs and WebStorm really feels quite nice coming from Visual Studio. Decent code completion, extensions, templates… I liked the IDE. That was my first stop.
  • MonoDevelop - Not really for web development, but keep in mind that I started my journey as a .NET Developer. Hence I had a look at mono and tested what it had to offer. Especially since some attempt to write device apps with it too I gave it a look. Feels nice for a VS developer, but since it is not really webby I drifted away quite quickly.
  • Sublime Text – Then I had a look at the favourite coding tools around me and apparently Sublime has a lot of fans. Thus I downloaded and installed it. Boy, I felt like a hacker right away. Sublime surely manages the art to feel productive while still being “just” an editor. On the other hand I had a bit of a hard time to get a decent installation set up that provided me with all the features that I expected in my productivity environment. Conclusion: Still not my tool but substantially more fun to work with than the other tools just mentioned…
  • Atom - After Sublime I toyed around with anumber of similar looking editors. Atom quickly caught my eye. This is a JavaScript-developed IDE developed by Github. All in all it looks quite similar to Sublime and was fast & fun. What turned me off was the rather limited autocompletion. Also the builds I played with were rather instable.
  • Brackets - Ok, this is my current favourite development tool. It is lightweight, written in JavaScript and is for me simply the most productive web development tool I layed my hands on so far. Features such as in-place editing of external stylesheets, live preview in Browser etc. are just topping it for me but what I really love is the flexibility and overall extensibility. Created by Adobe it also supports many interesting features and workflows like integrating Photoshop for instance…
  • Intel XDK – This toolset equips you with all necessary to build cross-platform HTML5 apps. It includes Brackets, Cordova (cross platform middle ware) and support for libraries such as backbone (see above :-) ) out of the box.
  • IDLE - well, this one is admittedly a but odd in that list as it is not a real web dev IDE. Instead it is the Python IDE coming with the typical python installation and was the only IDE I found providing decent code completion. Meanwhile I extended Brackets and Atom to run Python too but the completion always let me revert back to IDLE. Do you have an alternative suggestion for me?

So… do I have favourites in that list? Yep. Currently I really like the ideas in Dart, Polymer and Angular and the DOM sugar provided by JQuery. My favourite IDE by far is Brackets. You should definitely give it a try too! :-)

Picture source: Flickr

The post Me, me, pick me! – A little guide through the web development maze. appeared first on Dirk Primbs Online.

Jürgen Gutsch: Playing around with SignalR 2.1.1 - Teil 1: Die Serverseite

Ich weiß, das Thema SignalR ist schon etwas älter. Umso wichtiger ist es aus meiner Sicht SignalR endlich mal anzuschauen. Seit meiner Selbständigkeit und auch danach, sind einige sehr interessante Themen liegen geblieben, die ich mir aus Zeitgründen nicht anschauen konnte. Eines dieser Themen ist eben auch SignalR, welches (stand heute) in der Version 2.1.1 unter der Apache 2.0 License für Mono und .NET zur Verfügung steht.

Die offizielle Website ist http://signalr.net/, die Dokumentation auf GitHub zu finden. Viele weitere sehr detaillierte Tutorials, Videos und Samples sind allerdings auf http://www.asp.net/signalr zu finden.

Um was geht’s?

SignalR ist im Prinzip ein Client- UND Serverseitiger Wrapper um das WebSocket-Protokoll mit eingebautem Fallback für Clients die WebSockets nicht unterstützen.

Das WebSocket-Protokoll ist ein auf TCP basierendes Netzwerkprotokoll, das entworfen wurde, um eine bidirektionale Verbindung zwischen einer Webanwendung und einem WebSocket-Server bzw. einem Webserver, der auch WebSockets unterstützt, herzustellen.-Protokoll
(http://de.wikipedia.org/wiki/WebSocket)

WebSockets werden heute von nahezu allen modernen Browsern und Web Servern unterstützt

Setup

Ich habe mich entschlossen ein MVC 5 Projekt als Spielwiese zu nutzen und einen kleinen Chat zu realisieren

Das Setup ist kein Hexenwerk. Die nötigen Bibliotheken sind schnell per NuGet eingebunden. Da ich keine Lust hatte erst Dokus zu lesen, habe ich mich entschlossen gleich das Paket mit den SignalR Samples zu installieren:

Install-Package Microsoft.AspNet.SignaR.Sample

Darauf hin habe ich alle nötigen Komponenten im Projekt eingebunden. Eine Readme Datei weist mich darauf hin, dass ich eine Startup Klasse in meinem Projekt hinzufügen muss um SignalR zu initialisieren.

Die Startup-Klasse klingt ganz nach Owin. Was sich dann auch so herausstellt. SignalR wird als Owin-Komponente bereitgestellt. Das ist Klasse. So fängt das an Spaß zu machen :)

Ein letzter Schritt ist nötig, damit SignalR läuft. Wir müssen ein Script-Verweis auf eine Route machen, die von der SignalR Owin Komponente behandelt wird, um die sog. Hubs auf der Clientseite bereitzustellen. Das tue ich in der “scripts”-Sektion direkt auf der Seite auf der mein Chat laufen soll:

@section scripts
{
    <script src="../signalr/hubs"></script>
    @Scripts.Render("~/bundles/chatter")
}

Das Bundle “~/bundles/chatter” bindet die chatter.js ein, mit der ich auf der Clientseite mit SignalR arbeite. Mehr dazu später.

[Update]

In der BundleConfig.cs muss die JavaScript Bibliothek “jquery.signalR” noch eingebaut werden. Das habe ich direkt im Bundle vom jQuery getan:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
            "~/Scripts/jquery-{version}.js",
            "~/Scripts/jquery.signalR-{version}.js"));

[/Update]

Das Sample

Das Beispiel das per NuGet installiert wurde zeigt einen Stock Ticker, ist schön klein und übersichtlich gehalten und läuft auf Anhieb. Die beste Grundlage um mir das eine oder andere abzuschauen.

Aufgerufen wird es über “~/SignalR.Sample/StockTicker.html”

Schaut es euch am besten selber an :)

Auf geht’s

Ich entscheide mich als, den Chat in der gleiche Struktur umzusetzen wie im StockTicker Sample.

Ich fange dafür am besten mit dem sog. “Hub” an. Der Hub definiert die Schnittstelle wie sie vom Client aus aufgerufen werden kann, zudem kann er über den IHubConnectionContext direkt mit den Clients kommunizieren.

[HubName("chatter")]
public class ChatHub : Hub
{
    private readonly Chatter _chatter;

    public ChatHub() :
        this(Chatter.Instance)
    {
    }

    public ChatHub(Chatter chatter)
    {
        _chatter = chatter;
    }

    public void SignIn(string connectionId, string name)
    {
        _chatter.SignIn(connectionId, name);
    }

    public void Post(string connectionId, string post)
    {
        _chatter.Post(connectionId, post);
    }

    public void SignOut(string connectionId, string name)
    {
        _chatter.SignOut(connectionId, name);
    }
}

Das Attribut “HubName” definiert den Hub wie er vom Client aus gesehen wird. Wichtiger ist die Basisklasse “Hub” von der hier geerbt wird. Die eigentliche Arbeit ist dann in der Klasse Chatter die als Singleton implementiert ist. Interessant ist, dass ich die Methodennamen nicht extra auszeichnen muss. Auf der Clientseite kommen Sie dennoch sauber mit Camel-Casing an (also signIn, post, signOut)

Die ConnectionId muss mir der Client explizit mitgeben. Das geht leider nicht aus dem Sample hervor, aber eine kleine Google-Recherche half sofort. Anders als bei einem StockTicker, habe ich es beim Chat mir Usern zu tun die ich erkennen muss. So muss der User der sich einloggt, explizit begrüßt werden, während die anderen Teilnehmer einen Hinweis über einen neuen Teilnehmer bekommen.

Die Klasse “Chatter” ist mit Hilfe vom Typ System.Lazy<> als Singleton angelegt. Singletons habe ich auf diese Art noch nicht umgesetzt, funktioniert aber, sieht gut aus und kann man öfter mal so machen:

private readonly static Lazy<Chatter> _instance = new Lazy<Chatter>(
    () => new Chatter(GlobalHost.ConnectionManager.GetHubContext<ChatHub>().Clients));
public static Chatter Instance
{
    get { return _instance.Value; }
}

Der Chatter bekommt einen IHubConnectionContext<dynamic> injiziert, was die Client API abbildet, denn schließlich soll ich ja auch Methoden auf dem Client aufrufen können. Diesen Context speichere ich in einer Eigenschaft mit dem Namen “Clients”:

private IHubConnectionContext<dynamic> Clients { get; set; }

private Chatter(IHubConnectionContext<dynamic> clients)
{
    Clients = clients;
    Users = new Dictionary<string, string>();
}

Wie das aussieht und wie ich die Teilnehmer beim Login anhand der ConnectioID unterschiedlich behandle, ist hier zu sehen:

public void SignIn(string connectionId, string name)
{
    Users.Add(connectionId, name);
    Clients.Client(connectionId).userAdded();
    Clients.Client(connectionId).postMessage("> ## Hello " + name + " ##");
    Clients.AllExcept(connectionId).postMessage("> ## new user '" + name + "' added ##");
}

Hier ist der Grund für die ConnectionId zu sehen: Nachdem der User hinzugefügt wurde, teile ich diesem User explizit mit, dass er hinzugefügt wurde. Anschießend schreibe ich eine Chat-Nachricht direkt an den neuen User raus und am Ende teile ich allen anderen Teilnehmern mit, dass es einen neuen Teilnehmer gibt.

Eine normale Chatnachricht geht wie folgt an alle Clients raus:

public void Post(string connectionId, string message)
{
    string user;
    if (Users.TryGetValue(connectionId, out user))
    {
        Clients.All.postMessage(user + "> " + message);
    }
}

Existiert der User im Pool, geht die Chatnachricht einfach an alle raus.

Bei Ausloggen gehe ich wieder explizit auf die User ein und behandle den entsprechenden User separat:

public void SignOut(string connectionId, string name)
{
    Users.Remove(connectionId);
    Clients.Client(connectionId).userRemoved();
    Clients.Client(connectionId).postMessage("> ## Goodby " + name + " ##");
    Clients.AllExcept(connectionId).postMessage("> ## user '" + name + "' removed ##");
}

Ralf Westphal: Konstruktivistische Softwareentwicklung für mehr Wandelbarkeit

Code sei ein Mittel, um die Realität abzubilden. Zumindest scheint mir das ein wesentlicher Antrieb hinter der Objektorientierung zu sein. Mit Objekten sollte es endlich möglich sein, Dinge und Verhältnisse der Welt möglichst 1:1 in Code zu fassen. Das ist eine platonische Sichtweise der Welt. Sie geht davon aus, dass es etwas unabhängig von Code gibt, das irgendwie ist. Und dieses So-sein kann

Jürgen Gutsch: CodeLens Indicators for Git in VS 2013 Ultimate Update 3

Nachdem ich gestern endlich mal das Update 3 für Visual Studio 2013 installiert habe, ist mir heute endlich auch aufgefallen, dass die CodeLense Indicators erweitert wurden:

Neu sind an zweiter und dritter Stelle der letzte Änderer und der Zeitpunkt der letzten Änderung, sowie die Anzahl der Änderungen. Diese Angaben stammen in meinem Fall aus Git.

Klickt man auf die zweite oder dritte Stelle so sieht man die die Änderungen mit wunderhübschen, denglischen Commit Messages, Datum, User und kann auch direkt die entsprechende Version in den Editor holen

Ein Maus-Over auf der einzelnen Zeile gibt dabei weitere Informationen preis.

Ein bisschen Recherche hat mich zu einem ausführlichen Blogartikel von Jean-Marc Prieur gebracht: Code Lens for Git in Visual Studio 2013 Ultimate Update 3

Jetzt muss die Git Integration im VS nur noch für große Projekte performanter werden, dann würde ich die nicht immer gleich ausschalten ;)

Kay Giza [MS]: Einladung: Technical Summit 2014 in Berlin im November

Es ist mir eine freude auf das Microsoft Technical Summit 2014, in Berlin im November 2014 aufmerksam zu machen! Denn: Microsoft lädt zum Gipfeltreffen der technischen Experten nach Berlin ein. Top Speaker des Technical Summit 2014 ist sicherlich der neue Microsoft Chief Executive Officer (CEO) Satya Nadella. Microsoft lädt IT-Professionals und Entwickler vom 11. bis 13. November in Berlin zum „Technical Summit 2014“. Die ersten beiden Tage stehen im Zeichen der Konferenz mit ihren insgesamt rund 40 Sessions und Live-Demos, Tag 3 ist... [... mehr auf Giza-Blog.d]


This post is powered by www.Giza-Blog.de | Giza-Blog.de: RSS Feed
© Copyright 2006-2013 Kay Giza. All rights reserved. Legal

ppedv Team Blog: Angular-Listen mit Hash filtern

Beim Stöbern in SPA-Anwendungsfällen bin ich der Idee verfallen, Listen anhand der URL bzw. den enthaltenen Hash-Werten zu filtern. Eine URL setzt sich laut RFC 3986 wie folgt zusammen.

foo://example.com:8042/over/there?name=ferret#nose \_/ \______________/\_________/ \_________/ \__/ | | | | | scheme authority path query fragment | _____________________|__ / \ / \ urn:example:animal:ferret:nose

Der letzte Teil, das Fragment, wird beim HTTP Request vom Browser nicht zum Server übermittelt. Dies macht sich unter anderem Angular.js zu Nutze, um ein clientseitiges Routing der Views durchzuführen. Das ähnelt ASP.NET MVC, ist aber nach dem # Zeichen, das wir hier als Hash Key bezeichnen. So ist es möglich, die Ergebnismenge direkt per Link anzuspringen.

Im folgenden Beispiel filtern wir mit einer Art Navigationsleiste eine Liste. Damit wir den Browser nicht überfordern, geben wir den Hashkey als Parameter an und führen somit AJAX Call Backs zum ASP.NET Web API basierten Service durch.

Der Service liefert Chatnachrichten anhand eines Chatrooms. Das VB.NET Web API Sample decodiert die URL um z.B. Sonderzeichen korrekt zu behandeln.

   1:   Function Getchatmessage(room As String) As IQueryable(Of chatmessage)
   2:       Dim r = HttpUtility.UrlDecode(room)
   3:       Return db.chatmessage.Where(Function(c) c.room.roomname = r)
   4:   End Function

 

Folgende UI bietet dem Benutzer drei Optionen:

image

Die Links werden in der Form ASPX-Seite in der FriendlyUrl Notation ohne Erweiterung, gefolgt vom Hashkey und dem Wert erzeugt.

image

Erste Lektion: Angular fügt nach dem Hashkey einen Slash (Schrägstrich) in die URL im Browser ein, obwohl im HTML Source keiner steht.

image

Ich habe dazu recherchiert und herausgefunden, dass es einen Hashbang Mode, oder HMTL5 Mode, gibt. Der genaue Grund ist mir noch unklar. Später wird ein JavaScript Replace das wieder gerade biegen.

Um die HTML-Inhalte zu erstellen, habe ich eine Server Rendering-Methode gewählt. Hier habe ich auf Webforms gesetzt. Dies ist einfacher und erlaubt auch besseres Caching, also schnellere Ausführung.

Vorbereitend definieren wir eine Angular-App samt dazu gehörigem Controller. Die Anzeige des Hash per Databinding {{}} dient Kontrollzwecken. Das Listview Web Server-Steuerelement binden wir per Model Binding an die Room Liste. Der VB.NET Codebehind Source Code findet sich im nächsten Listing.

Der Name des Rooms wird passend zur URL encodiert. Wenn der Benutzer diesen Link klickt, passiert faktisch nichts, außer dass die URL im Browser um den Hashwert ergänzt wird.

   1:  <body ng-app="App">
   2:      <form id="form1" runat="server">
   3:          <div ng-controller="chatController">
   4:              <div>Hash:{{target}}</div>
   5:              <div>
   6:                  <asp:ListView ID="roomlist" runat="server" 
ItemType="Concorde.room"
   7:                      SelectMethod="roomlist_GetData">
   8:                      <ItemTemplate>
   9:                          <a href='/chat#<%#HttpUtility.UrlEncode(Item.roomname)%>'>
  10:                              <%#Item.roomname%>
  11:                          </a>| 
  12:                  
  13:                      </ItemTemplate>
  14:                  </asp:ListView>

Dies ist der Inhalt der dazu gehörigen aspx.vb Datei. Es kommt ein Entity Framework Code First Model zum Einsatz.

   1:   Public Function roomlist_GetData() As IQueryable(Of room)
   2:          Dim db As New ConcordeContext
   3:          Return db.room
   4:   End Function

 

Nun kommt der spannende Teil, der Angular.js Controller. Dieser führt einen Callback per $http aus und übergibt dabei den Hashwert aus der URL als Parameter. Dabei hilft $location, das per Path (eigentlich sollte es hash() sein) den passenden Wert aus der URL liefert. Nach Aufruf des REST-Services stehen die JSON-Daten in der Variable data (Zeile 20) und werden direkt der Chatmessages-Eigenschaft im $Scope zugewiesen.

Das Besondere an diesem Angular-Beispiel ist, dass ein Watcher (Zeile 5) auf dem Viewmodell gesetzt wird, der die Änderung der URL als Event-Geber nutzt und den Service Call initiiert. Ohne diesen läuft der Controller nur einmal durch.

   1:  angular.module('App', [])
   2:    .controller('chatController',
function ($scope, $http,$location,$window) {
   3:      $scope.chatMessages = [];
   4:      $scope.location = $location;
   5:      $scope.$watch('location.absUrl()', function () {
   6:          $scope.target = $location.path(); 
   7:          $scope.ladeMessages();
   8:      }, true);
   9:      $scope.ladeMessages = function () {
  10:          if ($scope.target != null) { 
var para = $scope.target.replace('/', ''); };
  11:       
  12:          $http(
  13:       {
  14:           method: 'GET',
  15:           url: 'api/chatmessages',
  16:           params: {
  17:               room: para
  18:           }
  19:       })
  20:      .success(function (data, status) {
  21:          $scope.chatMessages =  data;
  22:      })
  23:      };
  24:   
  25:  });
  26:   

Nun fehlt noch der deklarative HTML5 Teil, der entweder eine Meldung für leere Daten oder die Liste anzeigt. Dies ist der einfachste Teil. Der Scope enthält die Liste der ChatMessages, die mit der ng-repeat-Direktive durchlaufen wird. Dies ähnelt einem ASP.NET Repeater Control, nur eben clientseitig.

   1:   <div ng-show="chatMessages.length==0">
   2:                keine Daten...
   3:   </div>
   4:    <div ng-repeat="msg in chatMessages">
   5:                      {{msg.Message}}
   6:   </div>

Holger Schwichtenberg: Satya Nadella kommt zu Microsofts Technology Summit 2014 nach Berlin

Die Anmeldung zu der vom 11. bis 13. November 2014 gehenden Konferenz ist jetzt eröffnet.

Holger Sirtl: Satya Nadella kommt zum Microsoft Technical Summit 2014

Wer heute die Webseite zum Microsoft Technical Summit gesehen hat, hat’s sicher gesehen: Satya Nadella, Microsoft CEO wird da sein und eine Keynote halten!!!

image

Jetzt gibt’s also keine Ausrede mehr… schnell anmelden!

Hier nochmal die wichtigsten Eckdaten

Microsoft Technical Summit

Termin:
11./12. November 2014 (Konferenz)
13. November 2014 (Workshops)

Ort:
Best Western Premier Hotel MOA Berlin
Stephanstrasse 41
10559 Berlin Moabit

Web:
www.technical-summit.de

Ich hoffe, wir sehen uns da!!!

codefest.at [MS]: Visual Studio Online – die Cloud auch für Entwickler

Einleitung

Möglicherweise habt ihr schon den Microsoft Team Foundation Server (TFS) in einem eurer Projekte eingesetzt. Vielleicht nur als reines Source Code Verwaltungstool, oder ihr habt auch mehr davon verwendet, z. B. die Prozessvorlagen für die agile Softwareentwicklung, oder Scrum. Vermutlich habt ihr damit auch Work Items zugewiesen, Bug Tracking verwendet und Builds automatisiert.

Diesen TFS habt ihr vermutlich in einem Windows Server in eurem (Firmen-)Netzwerk installiert. Das Entwicklungsteam verwendet Visual Studio, um sich an den TFS anzuhängen. Das bedeutet, dass die Hardware angeschafft, das Server OS lizenziert und installiert werden musste (bzw. eine VM zur Verfügung gestellt wurde) und jemand eine bestimmte Version des TFS installiert hat. Kurz gesagt, es fallen Kosten an: für die Hardware, die Software und die Wartung des (eigenen) Systems (z. B. Updates des Server OS bzw. des TFS müssen selbst eingespielt werden).

Falls ihr den TFS überhaupt noch nicht in Verwendung hattet, so ist möglicherweise ein anderes Source Code Verwaltungstool, wie z. B. Git, Tortoise, oder Jira im Einsatz. Alle aufgezählten Varianten haben Vorteile, aber auch verschiedene Nachteile.

In einem meiner Entwicklungsteams haben wir eine Menge Source Code und Zeit verloren, da das Infrastruktur-Team geschlampt hat. Wie? Nun ja, trotz mehrmaliger Rückfragen meinerseits, ob es ein funktionierendes Backup unseres Servers gibt, war im Ernstfall leider keines vorhanden. Obwohl diese Anfrage zuvor mehrmals positiv beantwortet worden war…..

Nun…ja….seither verlasse ich mich äußerst ungerne auf Infrastruktur-Teams und sehe mich gerne nach alternativen Lösungen zu dem In-House Hosting unseres Source-Codes um.

Als erste Variante gibt es natürlich den gehosteten TFS. Mehr Informationen findet Ihr z. B. hier:

http://www.discountasp.net/tfs/

Ihr entscheidet euch für eine Version des TFS (2010, 2012, oder 2013) und für die Basic (Source Control und Work Item Tracking), oder die Full Variante (Basic features und mit Sharepoint und Reporting).

Diese Variante hat bestimmt ihren Reiz, ich möchte euch aber eine weitere Möglichkeit erläutern: Visual Studio Online (VS Online).

VS Online – Allgemein

Wieder ein neues Produkt werdet Ihr euch jetzt möglicherweise denken, das ist aber so nicht ganz korrekt. Mit beiden Produkten könnt ihr:

· Euren Source Code in verschiedenen Versionen verwalten
· Work Items verwalten
· Bugs tracken
· Backlogs verwalten

Also im Großen und Ganzen all das, was ein gutes Application Lifecycle Management (ALM) Produkt können sollte.

Wie man anhand dieser Auflistung sehen kann, sind die Core-Funktionalitäten von TFS und VS Online gleich. Eigentlich ist es das selbe Produkt, allerdings mit unterschiedlichen Versionssprüngen und der zugehörigen Updates (VS Online hieß früher auch Team Foundation Service). TFS wird in eigenständigen Versionen ausgeliefert, aktuell 2013, davor 2012 und 2010. Dies kennt ihr z. B. von Visual Studio selbst, oder auch vom SQLServer, oder Office her. Immer, wenn ein neues Release am Markt ist, entscheidet ihr euch diese zu installieren und eure bestehende Software upzugraden (oder eben auch nicht).

VS Online kennt diesen Produktzyklus in dieser Form nicht. Es gibt keine Version 2013, 2012, oder 2010, stattdessen wird VS Online automatisch auf den neuesten Stand gebracht. Schön und gut, aber wer macht dann die Updates? VS Online steht „in der Cloud“ zur Verfügung. Microsoft’s Cloud Lösung heißt Azure und bietet mittlerweile eine Menge an Diensten, einer davon ist eben VS Online.

VS Online – Features

Es gibt zwei verschiedene Varianten von VS Online: Basic und Professional. Gemeinsam ist den beiden, dass keine eigene Infrastruktur, wie z. B. ein eigener Server zur Verfügung gestellt werden muss. Der Source Code liegt in der Cloud und ist von überall – von berechtigten Personen – abrufbar (ohne lästiger VPN Clients auf den Entwickler-Notebooks). Sehen wir uns einmal die beiden Versionen an.

Ich möchte euch zuerst die Features vorstellen, die mich überzeugt haben, mit meinem Entwicklungsteam auf VS Online umzusteigen.

Jeder VS Online Zugang verfügt über

. fünf kostenlose Benutzer (weitere Benutzer sind dann allerdings kostenpflichtig),
· eine unbegrenzte Anzahl von Projekten (im Team, oder „privat“ – also für einen Entwickler),
· gehostete Code-Repositories mit der Team Foundation-Versionskontrolle oder Git in unbegrenzter Größe.

Somit ist sichergestellt, dass auf den Source Code von allen Entwicklern immer und überall zugegriffen werden kann und so jederzeit Source Code eingecheckt werden kann. Sowohl mit einer unbegrenzten Anzahl von Projekten als auch einer unbegrenzten Größe dieser Projekte!

Weitere Vorteile der gebotenen Features für die gemeinsame Entwicklung innerhalb des Teams:

· Über sogenannte Teamräume wird jeder Entwickler über den aktuellen Projektstand informiert.
· Aufgliedern und Planen komplexer Projekte erfolgt mittels der agilen Portfolioverwaltung:

o Erfassen von Product-Backlogs.
o Definition und Verfolgung von Sprints.
o Zuweisen und Tracken von Work-Items.
o Einholen und Nachverfolgen von Feedback für Projektbeteiligte (mit dem Microsoft Feedback Client).

· Erstellen von Testplänen und Test Cases.
· Integriertes Bug-Tracking.
· Verwenden der Auslastungstests (bis zu 15.000 virtuelle Benutzerminuten pro Monat).

Des Weiteren inkludiert VS Online eine Version von Visual Studio Express für das Web, Windows oder Windows Desktop, aber als eingefleischte Entwickler habt ihr vermutlich schon eine der höherwertigeren Desktop Varianten der Visual Studio Editionen installiert. VS Online funktioniert allerdings auch mit Eclipse oder XCode, ist also nicht an Visual Studio gebunden.

All diese aufgezählten Punkte sind bereits in der VS Online – Basic Version enthalten und stehen zur freien Nutzung bereit. Solltet ihr euch mehr Features punkto Projektplanung wünschen, dann solltet ihr einen Blick auf die VS Online Advanced Variante legen, diese kostet allerdings $60,-- pro Benutzer im Monat. Eine VS Online Professional Variante ist ebenfalls erhältlich, diese umfasst ein monatliches Abonnement für die Visual Studio Professional IDE und schlägt mit $ 45,-- zu Buche.

Aber zu Beginn sollte die VS Online Basic Variante durchaus ausreichen, möglicherweise benötigt Ihr mehr Benutzer, dann kostet jeder weitere Benutzer (über die inkludierten 5 hinaus) $ 20,-- im Monat.

Kommen wir aber nun zur Anwendung von VS Online und legen ein Beispielprojekt an und checken auch gleich einmal (vorhandenen) Source Code ein.

Dazu sind folgende Schritte notwendig:

· Anlegen des VS Online Kontos.
· Anlegen eines neuen Projektes.
· Einchecken des lokalen Source Codes.

Drei kleine Schritte, mal sehen, ob es wirklich so einfach ist. In circa 10 Minuten könnt ihr selbst darüber urteilen……legen wir also los, die Zeit läuft!

VS Online – Anwendung

Das VO Online - Konto

Zur Verwendung von VS Online wird ein VS Online-Konto benötigt. Das klappt schnell und problemlos mit dem Browser und folgendem Link: http://go.microsoft.com/fwlink/?LinkId=307137&clcid=0x407

image_thumb1

Nach erfolgreicher Anmeldung ist euer Konto jederzeit unter folgender Adresse im Browser erreichbar: .visualstudio.com">.visualstudio.com">.visualstudio.com">http://<kontoname>.visualstudio.com

Eine zweite Variante steht euch auch noch über das Azure Managementportal zur Verfügung: http://manage.windowsazure.com bzw. https://portal.azure.com/

image_thumb30

Wie auch immer ihr euren VS Online Zugang anlegt, auf jeden Fall seid ihr nun glücklicher Besitzer eines VS Online Zugangs.

Nach erfolgreicher Anmeldung werdet ihr aufgefordert, ein neues Projekt anzulegen. Sehr gut, denn das ist es ja auch, was wir im nächsten Schritt machen wollen. Das ist allerdings nur beim ersten Mal so, nächstes Mal befindet ihr euch im VS Online DashBoard, wo ihr die Zusammenfassung eures Accounts einsehen könnt.

image_thumb32

Anlegen eines neuen Projektes

Ich habe in letzter Zeit an einigen mobilen Projekten mit Xamarin in Visual Studio gearbeitet und eines dieser Projekte würde ich gerne zu VS Online deployen, um damit die die Source Code Verwaltung durchzuführen. Das bedeutet also, dass ich lokal bereits ein Projekt habe, in VS Online existiert dieses aber noch nicht – es muss also angelegt werden, danach dieses VS Online Projekt mit meinem lokalen Verzeichnis verbunden werden, dann kann der Source Code eingecheckt werden. Das klappt natürlich auch umgekehrt, also zuerst das VS Online Projekt erstellen, danach erst in das Codieren einsteigen. Wie auch immer, das VS Online Projekt muss angelegt werden.

Falls ihr gerade euer VS Online Konto erstellt habt, dann seid ihr schon auf der richtigen Eingabemaske. So legt nun ein neues Projekt an, der „New“-Button lädt gerade dazu ein, gedrückt zu werden.

Auf jeden Fall müssen nun ein paar Angaben zu dem Projekt gemacht werden:

  1. Der Name des Projektes ist einzutragen,
  2. optional kann dazu eine Beschreibung erfasst werden.
  3. Als Scrum Master kommt mir das „Microsoft Visual Studio Scrum 2013.3“ Template gerade recht (andere Optionen sind: MSF for Agile Software Development 2013.3 und MSF for CMMI Process Improvement 2013.3).
  4. Als Versions-Kontrolle setze ich auf die „Team Foundation Version Control“, da ich damit jahrelange (gute)Erfahrungen habe, die andere Option wäre Git - SVN wird leider nicht unterstützt.

Wie bereits erwähnt, habe ich das Projekt auf meinem lokalen Rechner, ich habe es also einfach mit den einzugebenden Werten (jaja, wie lange grübelt man normalerweise am Projektnamen…) wie man nachfolgend sehen kann:

image_thumb17

Mit dem „Create Project“ Button ist dieser Schritt auch schon so gut wie abgeschlossen. Den Rest der Arbeit erledigt VS Online, welches das Projekt und den zugehörigen Team Room anlegt und zur Verfügung stellt, wo ihr euch später mit den anderen Teammitgliedern über das Projekt austauschen könnt..

Mit „Navigate to project“ gelangen wir zur Detailansicht, bzw. öffnet sich diese von selbst, wenn ihr das erste Mal ein Projekt angelegt habt.

image_thumb18

Hier ist natürlich noch nicht allzu viel zu sehen, als sehr hilfreich wird sich gleich die rechte obere Ecke erweisen, wenn wir zum nächsten Schritt gelangen.

Mappen und Einchecken des lokalen Source Codes

Bevor Ihr den VS Online Account mit eurem lokalen Projekt verbinden könnt, überlegt bitte noch einmal kurz, ob eure lokale Visual Studio 2013 Installation mit eurem Microsoft Account verbunden ist – gegebenenfalls kontrolliert das bitte, bzw. führt die Anmeldung – rechts oben - im Visual Studio 2013 durch.

image_thumb22

Wenn ihr schon dabei seid, könnt Ihr noch in Visual Studio 2013 kontrollieren, ob Ihr Team Foundation Server als momentanes Source Control plug-in verwendet. Dazu einfach das Menü Tools -> Options und Source Control aufrufen und gegebenenfalls die ComboBox anpassen.

image_thumb25

Nun ist es an der Zeit den VS Online Account mit einem (lokalen) Projekt zu verbinden. Dazu verwendet man am einfachsten den ‚Open in Visual Studio‘ Button im rechten oberen Bereich.

image_thumb11image_thumb14

Sobald dieser gedrückt wird und ihr die Abfrage bestätigt, dass eine lokale Applikation geöffnet werden soll (ich empfehle euch die kleine CheckBox anzuklicken, damit diese Meldung in Zukunft nicht mehr gezeigt wird), öffnet sich auf dem lokalen Rechner Visual Studio 2013. Angezeigt wird der Team Explorer, der darauf wartet, dass das VS Online Projekt mit einem lokalen Projekt gemapped wird.

Dazu führt ihr folgende Schritte durch (in den Bildern unten der Reihe nach dargestellt):

  • Drücken des Links bei der Meldung “configure your workspace”
  • Jetzt muss das VS Online Projekt ($/Azure Informer) auf das lokale Verzeichnis gemappt werden, bei mir liegt der Source Code unter „C:\Development\Mobile\AzureInformer“.
  • Nachdem der “Map & Get” Button gedrückt wurde, ist VS Online mit dem lokalen Projekt verbunden.

image_thumb10image_thumb23image_thumb24

Nachdem diese Schritte erledigt wurden, kann das Projekt unter Source Code-Verwaltung gestellt werden. Spätestens jetzt solltet ihr euer Projekt in Visual Studio 2013 öffnen. Einchecken ist nun keine große Sache mehr, das gelingt mit der rechten Maustaste an eurer Solution im Solution Explorer und der Auswahl von „Add Solution to Source Control…“. Das gleiche Spielchen noch einmal, allerdings wird nun „Check In…“ angewählt.

image_thumb26 image_thumb28

Die Ansicht wechselt wieder auf den „Team Explorer“, jetzt noch schnell ein Kommentar für das Einchecken des Source Codes eingeben, den Check-In Button drücken und der Source Code ist in guten Händen, immer und überall für mein Team und mich erreichbar.

image_thumb19 image_thumb20

Geschafft, der Source Code ist bei VS Online hinterlegt. Die nächsten Schritte wären nun, weitere Team Mitglieder einzutragen, danach Work Items zu erfassen und an das Team zu verteilen. Die faszinierende Reise mit VS Online kann für mein Team und mich beginnen!

Zusammenfassung

Ich durfte in meinem Arbeitsleben bisher 3 Entwicklungsteams leiten und ich hätte mir jedes Mal die unproblematische Möglichkeit der Kollaboration innerhalb des Teams, sowie die jederzeitige Verfügbarkeit des Source Codes von jedem Ort der Welt gewünscht. VS Online macht es möglich eine unlimitierte Anzahl von Projekten mit unlimitierter Größe zu verwalten. Für Entwicklerteams mit bis zu 5 Leuten ohne jeglicher Kosten. Microsoft ist hier wieder ein hervorragendes Stück Software gelungen, einfach verpackt, ready to use for everyone!


Berndt Hamböck ist seit 2007 MCT, darüber hinaus befasst er sich mit Lösungen für komplexe Anwendungsszenarien mit den neuesten Microsoft Technologien. Die Erfahrungen aus der Projektarbeit gibt er in Vorträgen und Trainings weiter und begleitet Entwicklerteams in Softwareunternehmen bei Projekten im Microsoft Umfeld.

„Das ist ein Gastbeitrag. Die Meinung des Autors muss sich nicht mit jener von Microsoft decken. Durch den Artikel ergeben sich keinerlei Handlungsempfehlungen. Microsoft übernimmt keine Gewähr für die Richtigkeit oder Vollständigkeit der Angaben.“

Sven Hubert: New feature for AIT Apply Company Policy: include and exlude projects

Coding guidelines are very useful and should be enforced wherever possible. The free tool AIT Apply Company Policy (ACP), which we already presented in another blog entry, can help here. But there might be some guidelines or rules that should be applied to only some projects or to all except some projects. This is now possible with the new version of AIT Apply Company Policy, which is available in the download section.

For example one could create an ACP package that will be applied to all projects, but for all test projects the documentation should not be created. Then the respective section in the CompanyPolicy.config could look like this:

<Documentation exclude="*.Test"> 
    <Configuration Name="Debug" enabled="true" /> 
    <Configuration Name="Release" enabled="true" />    
    <Configuration Name="Staging" enabled="true" /> 
</Documentation>

The exclude attribute determines that in all projects ending with “.Test” the documentation will not be created.

In another scenario one could create an ACP package which should be applied only to test projects, e.g. specific rules for the static code analysis, and one has to make sure that this package can really be applied only to test projects. This is possible using the following entry:

<StaticCodeAnalysis includeOnly="*.Test"> 
    <Configuration Name="Debug" enabled="true" ruleSet="AIT.ruleset" /> 
    <Configuration Name="Release" enabled="true" ruleSet="AIT.ruleset" />     
    <Configuration Name="Staging" enabled="true" ruleSet="AIT.ruleset"/> 
</StaticCodeAnalysis>

Here the includeOnly attribute defines that the rules for the static code analysis is applied only to projects ending with “.Test”.

Furthermore it is possible to combine both of these attributes. This way, one can apply rules e.g. only to projects whose name contains “Infrastructure” but does not end with “.Test”.

New feature for AIT Apply Company Policy: include and exlude projects is a post from: AIT Blog

ppedv Team Blog: Windows Tipp - Wochentag in der Startleiste anzeigen

So mancher mag sich zuweilen die Frage stellen: Kann Windows auch den Wochentag in der Startleiste darstellen? Selbst wenn man sich diese Frage noch nie gestellt hat: wer diese Einstellung bei jemandem sieht, ist oft sehr angetan. Die meisten Benutzer möchten dann wissen, wie sie dies auch auf ihrem Computer einstellen können.

So wird's gemacht:

Die Einstellung vornehmen

Drücken Sie die Windows-Taste + R und geben "intl.cpl" ein, gefolgt von OK, danach wählen Sie Weitere Einstellungen… und den Reiter Datum.

clip_image001

Anpassung der Datumsdarstellung

Sie möchten, dass der Wochentag ausgeschrieben sein soll, dann geben Sie in das Feld Datum (kurz) statt "TT.MM.JJJ" "TTTT, TT.MM.JJJJ" ein.

clip_image002

Unterhalb der Felder stehen Erläuterungen zur Bedeutung der Buchstaben und deren Auswirkungen auf die Anzeige.

clip_image003

Bestätigen Sie die Einstellungen mit OK und der Wochentag erscheint, wie gewünscht, unten in der Startleiste.

clip_image005

Fertig

Jürgen Gutsch: Agile Bodensee Konferenz am 01. und 02 Oktober 2014

Auch auf der diesjährigen Agile Bodensee Konferenz bin ich wieder dabei. Dieses mal – am 1. Oktober – mit einem Workshop mit dem Titel “TDD Extreme

Was sich dahinter verbirgt? Vor allem provokante Aussagen meinerseits und um das Thema TDD die ich versuche anhand von Beispielen und Übungen zu Beweisen ;)

Interessiert? Dann schreibt doch einfach eine Twitter-PM an @sharpcms oder eine Nachricht per Facebook an juergen.gutsch mit dem Stichwort “TDD@abkon”. Ihr erhaltet dann einen Rabattcode mit dem ihr 10% Rabatt auf ALLE Ticket-Kategorien bekommt und könnt so etwas günstiger an dem Workshop teilnehmen :)

Weitere Informationen zur Agile Bodensee Konferenz 2014 und vor allem die komplette Agenda über die zwei Tage erhaltet ihr direkt auf der Website: www.agile-bodensee.com

ppedv Team Blog: Windows 8.1 ohne Microsoft-Konto installieren

Manche Benutzer verwenden ein lokales Benutzerkonto, damit keine Daten bei Microsoft gespeichert werden. Beim Update auf Windows 8.1 müssen diese während der Installation ein Microsoft-Konto anlegen. Es gibt dennoch eine Möglichkeit, die Registrierung zu umgehen. Sie müssen nicht, wie suggeriert, ein neues Konto anlegen.

Wie Sie dabei vorgehen, lesen Sie hier.

Update starten:

Das Update auf Windows 8.1 ist im Windows Store zu finden. Mit der „Windows-Taste“ gelangen Sie auf die Kacheloberfläche. Klicken Sie hier auf Store, dann erscheint die Kachel Kostenloses Update auf Windows 8.1.

image

Unter Umständen erscheint die Meldung, dass Sie Updates installieren müssen.

Die verborgene Einstellung auswählen:

Jetzt wird das Update heruntergeladen, der Computer startet neu, danach bestätigen Sie wie üblich die Lizenzbedingungen und klicken dann auf Express-Einstellungen verwenden.

Wenn „Melden Sie sich bei Ihrem Microsoft-Konto an“ erscheint, klicken Sie unterhalb auf die nahe unsichtbare Zeile Neues Konto erstellen und auf Mit einem vorhandenen Konto fortfahren.

image

Sie lassen alles Weitere durchlaufen und installieren.

Das ist alles, so klappt es!

Golo Roden: Konsole & …: Rekursion

Die Fähigkeit einer Funktion in JavaScript, sich rekursiv aufrufen zu können, scheint nichts Besonderes zu sein. Dennoch gibt es dabei ein paar Aspekte zu beachten, insbesondere im Hinblick auf die kommende Version der Sprache: ECMAScript 6.

Karsten Kempe: TFS loves Git: Pull Requests

Der Pull Request ist ein Mechanismus, mit den Entwickler andere Teammitglieder über die Fertigstellung eines Features informieren, zu einem Review auffordern oder zur Zustimmung für die Aufnahme in einen integrierten Source Code Stand bitten können. Dieser Workflow kommt in Open Source Plattformen wie GitHub oder Bitbucket stark zum Einsatz und war bislang ein vermisstes Feature im TFS und Visual Studio Online. Seit ein paar Wochen gibt es diesen Mechanismus jetzt auch für Git Projekte in Visual Studio Online und bald auch im TFS on-prem.

Ein Entwickler entwickelt ein Feature in einem dedizierten Branch auf einem lokalen Repository. Sobald er seinem Team eine Version zur Verfügung stellen will, pusht der Entwickler den Branch in ein öffentliches Repository in Visual Studio Online. Dort kann er dann einen Pull-Request absetzen und das Team zum Review auffordern. Das Team wird daraufhin den Code untersuchen, darüber diskutieren und kommentieren. Am Ende wird der bereitgestellte Code von einem Verantwortlichen aus dem öffentlichen Feature Repository in das Master Repository überführt. Wenn die Entwicklung des Features komplett abgeschlossen ist, wird das öffentliche Repository gelöscht.

TFS Git Pull Requests

Abbildung 1: Pull Request Workflow

In folgendem Video könnt Ihr Euch ansehen, wie dieser Vorgang in Visual Studio Online funktioniert.

Fazit:

Pull-Requests erleichtern die Zusammenarbeit in weit verteilten Teams, in denen oftmals nur isoliertes Arbeiten möglich und meistens auch gewünscht ist. Damit der integrierte Master-Stand nicht zerstört wird, setzen viele Open Source Communities auf diesen Mechanismus. Dadurch wird die Code-Qualität des Master Repositories stabilisiert und die Qualität des ganzen Teams verbessert.

Jürgen Gutsch: Geplanter Umzug meines Blogs

Im Zuge des Umbaus meiner eigenen Website, habe ich mich dazu entschlossen, auch meinen Blog umzuziehen. Nicht weil das System auf dem Community Server von ASP.NET Zone schlecht wäre, sondern eher deshalb, weil ich mein Blog enger in meine Website integrieren möchte. In den vergangenen Monaten wurde die Website wieder immer mehr eine persönliche Portfolio Seite und das Blog soll der hauptsächliche Content-Lieferant der Website werden.

Auch vorher hatte ich bereits die Idee, dass ich mein Blog mehr in meine Kontrolle holen möchte. Allerdings läuft das bisherige System gut und stabil und es gab keinen zwingenden Grund für einen Umzug. Dennoch hatte ich mir einige vorhandene Systeme angeschaut, die mir aber alle zu umfangreich sind, um sie in meine Website zu integrieren. In vielen Fällen fehlte mir jedoch die MetaWeblog API um das Blog per Windows Live Writer zu bedienen, den ich immer noch sehr gerne verwende. (Tipps und Hinweise zu modernen Blog APIs und modernen Authoring-Tools nehme ich hier sehr gerne entgegen.) Sehr gerne schreibe ich morgens oder Abends offline im Zug um die Posts dann später zu veröffentlichen.

Bis ich nun ein wirklich passendes System finde, tendiere ich dazu ein kleines Blog-Framework zu schreiben, dass ich beliebig in jedes ASP.NET Projekt integrieren kann. Für den Anfang soll der SimpleObjectStore die Persistierung übernehmen. Da für dieses Tool beliebige DataProvider bereitgestellt werden können, kann das Framework dann auch bei Bedarf auf eine SQL Database gehen. Ich für meinen Teil werde den DataProvider für den Azure Table Storage verwenden, da die Website selber auf einer Azure Website gehosted wird.

Ziel ist es eine Bibliothek bereitzustellen, welche die nötigen Controller und Models bereitstellt. Die zugehörigen Views muss dann jeder Nutzer dieser Bibliothek selber bereitstellen:

Controller:

  • BlogController
    • Für Artikel-Listen und Kommentare
  • MetaWeblog Controller
    • Für den Windows Live Writer
    • ggf. per API Controller
  • BlogML Controller
    • Import/Export
  • RSS Controller
    • per API Controller

Models:

  • BlogArticleList
  • BlogArticle
  • Comment
  • Tag

Das wird wohl in den nächsten Monaten meine Beschäftigung neben der Arbeit und Familie sein. Mal sehen wie weit ich damit gehe.

Warum selber machen?

Na, um zu lernen. :) In den letzten Monaten sind interessante Neuerungen zu ASP.NET herausgekommen, die ich natürlich gerne genauer anschauen und umsetzen möchte.

Auch hier gilt: Für Vorschläge zu einer alternativen leichtgewichtigen Lösung bin ich immer zu haben.

codefest.at [MS]: V-Play -- Cross-Plattform 2D Spiele-Engine

Spiele-Entwickler kennen Sie wahrscheinlich schon: die österreichische Game Engine V-Playermöglicht die Erstellung von 2D Spielen, die man dann für verschiedene Plattformen deployen kann. Der Gründer von V-Play, Christian Feldbacher, hat schon beim letzten Mobile Developer After-Workdie Engine vorgestellt und demonstriert, wie man damit entwickeln kann.

Die gute Nachricht ist, dass es seit letzter Woche nun auch Support für die Windows Runtimegibt. Das heißt, Spiele, die ihr mit der Engine erstellt, könnt ihr nun auch als Windows Phone und Windows Store Apps deployen. Eine detaillierte Anleitung, wie ihr das machen könnt, findet ihr auf dem V-Play Blog.

Die V-Play Engine gibt es als 14-tätige Trial-Version gratis als Download. Probiert es mal mit einem ersten Spiel aus. Wenn ihr auf dem Geschmack gekommen seid, so könnt ihr in den nächsten Wochen noch interessante Infos zum Thema Gaming auf diesem Blog erwarten.

Ralf Westphal: Warnung vor dem Microservice – Versuch einer Definition

Services sind wieder im Trend. Jetzt unter der Bezeichnung Microservice oder kurz: µService. Das empfinde ich grundsätzlich als Fortschritt. Schon vor einer “Moore-Periode” :-) (also 18 Monaten) habe ich das als konsequente Entwicklung beschrieben unter dem Titel “Software als Web of Services”. Und noch weiter zurück, im Jahr 2005, hatte ich mir in einer Artikelserie unter der Überschrift “

Dirk Primbs [MS]: The zombie apocalypse

“Daddy, why do you always say that the Zombie apocalypse will come and why don’t we prepare for it?”
This question coming from our youngest recently reminded us to flag our pop culture humour more clearly, especially when joking about the potential end of the world.

Zombies are quite in fashion these days. I’m myself a huge fan of “The Walking Dead”, the series _and_ the original comic preceding it. I also watched World War Z, read through the Zombie Survival Guide and I really love the idea to be stranded with my family on a deserted island with tropical fruits growing all around me and a fully equipped yet autarc mansion in the middle of it when it happens.

This (and the tendency to creepy humour which my wife and I share) leads us to referencing zombies every now and then and making fun of the sort “don’t throw away this broken [whatever], what if the zombie apocalypse strikes and you’re in need of a deadly weapon?” or like “in case of the Z.A. we’ll barricade in the children’s rooms. The zombies never make it through that mess without a guide”. Turns out our children wonder how much truth is in the fiction (or alternatively wonder if adults really can believe in such a crazy szenario).

The fact of the matter is that I loved the theme from very early on. A book that I read ages ago and of which I can’t recall the title phantasized that all adults are whiped off the earth by some strange virus and books of that kind were on my reading lists ever since…

Just to name a few:
The Stand
I am legend (must read!)
World War Z (as mentioned)

I guess what fascinated me most was the question how we could hope to strive if no foundation exists anymore. Heck, I’m not even knowledgable enough to repair my shoes, let alone pull something off as a full scale farm (without the help of experienced farmers that is). Truth is, I’m not skilled in anything really useful. I can program, I can create online videos and podcasts, I studied psychology and business administration to some degree and I know how to navigate inside large tech corporations… I’d look into a brisk post-apocalyptic future indeed.

And if you look closely then you’ll discover that in our extremely specialized world almost no one knows enough about the processes around us to restart something remotely resembling civilization, or, to stay at a smaller scale, at least a comfortable living for a few selected survivors.

Since it makes a fascinating thought experiment though – what is necessary to enable mankind to restart quickly – a scholar found the time to write a book on it. (Yep, I’m reading a lot :-))

The Knowledge starts with the assumption that earth has been ripped of 70+% of humans and the survivors need to restart. This means basic knowledge of machinery, medicine, agriculture, etc. is in short supply and the book takes a stab to provide a fascinating and educating overview. I’ll have to admit after reading through my last book – How to create a mind (Ray Kurzweil) – it is quite a shock to get thrown back from envisioning humankinds next evolutionary step to basic survival but, boy, it is fun!

To circle back to the intro: I’ll stash that book for the certain zombie apocalypse, right next to my fully charged laptop, just in case anyone needs either a programmer or someone who simply read a lot, after humankind has been whiped out :-)

Picture credit

The post The zombie apocalypse appeared first on Dirk Primbs Online.

Fabian Deitelhoff: dotnetpro: Screencasts der Rubrik “Frameworks” jetzt online verfügbar

Vor einiger Zeit war das Team der dotnetpro so freundlich, die Screencasts zur Rubrik “Frameworks” auch online zur Verfügung zu stellen. Dass freut mich sehr, ist es ab jetzt doch um einiges einfacher, sich die Videos anzuschauen.

Verlinkt sind die einzelnen Screencasts immer beim jeweiligen Artikel im Online-Portal. Beispielsweise hier für den Artikel “Geschwindigkeitsrausch”. Dafür ist allerdings ein Abo und ein Login auf der Webseite erforderlich. Abbildung 1 zeigt einen Screenshot des eingebetteten Videos.

Abb. 1: Eingebetteter Screencast auf der dotnetpro Webseite.

Abb. 1: Eingebetteter Screencast auf der dotnetpro Webseite.

Zusätzlich besteht die Möglichkeit, jeden Screencast als WMV- oder MP4-Datei herunterzuladen. Wer also bis jetzt keine Lust auf den Datenträger hatte, der jeder Ausgabe beiliegt, kann sich die Screencasts nun auch online ansehen.

Und wie immer gilt: ich freue mich über konstruktives Feedback jeder Art!

Sven Hubert: ALM kompakt: Prüfung eines Work Item Feldes auf ein bestimmtes Textmuster

Bei der Anpassung von Process Templates kann es vorkommen, dass die Möglichkeiten von AllowedValues oder SuggestedValues (siehe All FIELD XML elements reference in der MSDN) nicht ausreichend sind. Wenn man z.B. die freie Texteingabe ermöglichen möchte, diese jedoch einem bestimmten Muster folgen soll. Ein einfaches Beispiel dafür ist die Eingabe einer MAC-Adresse.

Das MATCH-Element

Man könnte also auf die Idee kommen, eine Feldvalidierung mittels regulärer Ausdrücke durchzuführen. Die Konfigurierbarkeit von TFS Process Templates sieht hierfür eine eingeschränkte Variante vor: Das MATCH Element. Dieses ermöglicht eine sehr einfache Musterdefinition. Es wird nach folgender Syntax verwendet:

<MATCH pattern="patternValue" for="userGroupName" not="userGroupName" />

Laut MSDN sind folgende Pattern Values möglich:

  • “A” represents an alphabetical character.
  • “N” represents a numeric character.
  • “X” represents any alphanumeric character.

(siehe Online-Dokumentation in der MSDN)

Das Beispiel der MAC-Adresse lässt sich in der Work Item Type Definition konfigurieren, wie in Abbildung 1 dargestellt.

Abbildung 1: MATCH Element für eine MAC-Adresse

Abbildung 1: MATCH Element für eine MAC-Adresse

Für den Anwender der Work Items äußert es sich so, dass eine Hinweismeldung angezeigt wird, wenn der eingegebene Wert nicht definierten Textmuster entspricht (siehe Abbildung 2).

Abbildung 2: Verstoß gegen das Textmuster

Abbildung 2: Verstoß gegen das Textmuster

Einschränkungen

Wie vorher beschrieben, bietet das MATCH-Element eine sehr einfache Möglichkeit der Musterdefinition. Von “echten” regulären Ausdrücken ist dies weit entfernt. Wenn man beispielsweise prüfen möchte, ob ein Testfeld ein bestimmtes Präfix hat, reicht diese Möglichkeit bereits nicht mehr aus. Eine weitere Einschränkung ist der Feldtyp, auf den das MATCH-Element anwendbar ist. Es ist ausschließlich für die Verwendung mit String-Feldern vorgesehen. Da sich insbesondere für Beschreibungen die HTML-Felder immer größerer Beliebtheit erfreuen, lassen sich diese Felder mit dem MATCH-Element ebenfalls nicht überprüfen.

Erweiterungen

Wer weitergehende Prüfungen der Feldinhalte benötigt, muss sich wohl mit der TFS API auseinandersetzen. Eine Möglichkeit in einer standardisierten Form Erweiterungen für den TFS bereitzustellen, die serverseitig geprüft werden, bietet TFS ASAP. Mit dieser Plattform lassen sich Regeln ereignisbasiert (z.B. mit dem Speichern eines Work Items) sowie zeitgesteuert (z.B. einmal stündlich) ausführen. Dabei bietet sie bereits bewährte Mechanismen zur Integration serverseitiger Erweiterungen in den TFS. Im Falle der erweiterten Prüfung auf Textmuster mit regulären Ausdrücken könnte man beispielsweise eine E-Mail an den Verursacher versenden lassen oder die Änderung sogar wieder rückgängig machen. Mehr Informationen zu TFS ASAP sowie den Bezug einer Testlizenz gibt es unter http://www.tfsasap.com

ALM kompakt: Prüfung eines Work Item Feldes auf ein bestimmtes Textmuster is a post from: AIT Blog

ppedv Team Blog: Mehr Infos während Laufzeit oder Debug einer Web-Anwendung

Wer mit Visual Studio eine ASP.NET Anwendung schreibt, nutzt in der Regel den Debugger. Man kann aber auch Informationen über den Fluss in der Console ausgeben, sowohl server- als auch clientseitig.

Die Idee kam mir, während ich mit VB.NET Timer Code geschrieben habe und das Ticking beobachten wollte, ohne Breakpoints zu setzen. ASP.NET Servercode einfach mit

   1:   Debug.WriteLine("tick...")

Und schon tickt's im Visual Studio Output Window.

image

Mit JavaScript und diversen Frameworks wird das Thema noch schwieriger, weil Breakpoints manchmal in unüberschaubaren Code-Konstrukten enden. Auch hier kann man Log Messages ausgeben lassen und diese in den Developertools von Chrome oder IE mit F12 betrachten. Wer noch ein Alert verwendet, sollte schnellstens umstellen.

   1:    <script>
   2:          var myVar = setInterval(function () { myTimer() }, 1000);
   3:   
   4:          function myTimer() {
   5:              console.warn("tick..");
   6:              console.log("tick...");
   7:              
   8:          }
   9:      </script>

 

Im Internet Explorer 11:

image

dasselbe in Chrome:

image

Es existiert auch noch eine Methode Console.error mit dann rot gefärbter Ausgabe.

ppedv Team Blog: Auswertung zum StoragePool-Benchmark

Dies ist ein Update zu meinem vorherigen Beitrag über die Storage-Pools im Windows Server 2012 R2

http://blog.ppedv.de/post/2014/08/13/windows-server-2012-r2-storage-pools-mit-ssd-tiering.aspx

Ich habe noch ein paar weitere Tests bezüglich der Storage-Pools gemacht und diese in einer Tabelle ausgewertet:

Benchmark-Ergebnisse

 

Zusammenfassend kann man hier nun also sehen:

  • In den lesenden Disziplinen ist ein “echtes” RAID0 mittels RAID-Controller und den beiden SSDs am schnellsten
  • In den schreibenden Disziplinen ist der Storage-Pool mit einem Simple-Laufwerk am LSI-Controller am besten – dabei auch deutlich schneller als das controllereigene RAID0 von LSI und HP mit den SSDs
  • Der direkte Vergleich zwischen den Storage-Pools am HP-Controller und am LSI-Controller geht erstaunlicherweise zu Gunsten des LSI-Controllers aus und dies auch durchweg, obwohl der LSI-Controller (im Gegensatz zum HP-Controller) über keinen eigenen Cache verfügt (mit aktiviertem BBWC würde der HP-Controller wohl beim Schreiben noch deutlich besser werden)
  • Geht es um Datenredundanz (hier also RAID1 o.ä.), dann ist der Storage-Pool im Mirror-Modus mit der Kombination HDD plus SSD am besten!
  • Ein Storage-Pool mit 2 HDDs im Mirror-Mode ist fast genau so gut (oder genau so schlecht) wie die RAID1-Implementierung des HP- oder des LSI-Controllers

ppedv Team Blog: Microsoft Azure: Wartungsarbeiten in der Region Westeuropa

An diesem Wochenende führt Microsoft Wartungsarbeiten an der Netzwerkhardware in den Rechenzentren der Region Westeuropa durch. Dabei wird es zu Reboots der virtuellen Maschinen kommen, die zwischen 30 und 45 Minuten dauern können. Betroffen davon sind Instanzen von virtuellen Maschinen und Clouddiensten. Die Wartungsarbeiten finden am Freitag ab 20 Uhr und am Samstag ab 20 Uhr statt. An einem Tag sind die virtuellen Maschinen betroffen, während am nächsten Tag die Clouddienste betroffen sind.

Wie Microsoft am Freitag Abend bekannt gab, werden die Wartungsarbeiten für die Region Nordeuropa am kommenden Wochenende (22./23.08) zu den selben Zeiten durchgeführt.

Martin Hey: Attribute in Metadaten prüfen

Heute wurde mir eine gute Frage zu einem Problem gestellt, das ich bisher als trivial abgetan habe: Wie ermittle ich in ASP.NET für eine Eigenschaft des Models, ob dort ein bestimmtes Attribut gesetzt ist? Solche Attribute (insbesondere die vom Typ ValidationAttribute) werden ja verwendet, um Eingabevalidierung vorzunehmen.


Einstiegspunkt soll eine ExtensionMethod auf HtmlHelper sein, wie man sie in ASP.NET häufig findet und die einfach nur einen Text in der Html-Seite ausgeben soll.
public static MvcHtmlString RequiredMark<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression)
{
    var required = expression.IsRequired();
    return new MvcHtmlString((!required ? "kein " : string.Empty) + "Pflichtfeld");
}
Spannender Teil daran ist jetzt die schon verwendete ExtensionMethod IsRequired, die für die eigentliche Magie zuständig ist. Diese ist auch noch recht trivial: Sie prüft die Eingabe und ruft die noch zu erstellende Methode HasAttribute auf, die dann die eigentliche Prüfung auf das gesuchte Attribute durchführt:
private static bool IsRequired<T, V>(this Expression<Func<T, V>> expression)
{
    var memberExpression = expression.Body as MemberExpression;
    if (memberExpression == null)
        throw new InvalidOperationException("Expression must be a member expression");

    return HasAttribute(memberExpression.Member, typeof(RequiredAttribute));
}
Auch diese Methode ist recht einfach implementiert - schließlich gibt es in der Klasse Attribute eine statische Methode IsDefined, die dafür verwendet werden kann:
private static bool HasAttribute([NotNull] MemberInfo memberInfo, [NotNull] Type attributeType)
{
    if (memberInfo == null)
    {
        throw new ArgumentNullException();
    }

    var isDefinedOnMember = Attribute.IsDefined(memberInfo, attributeType);

    return isDefinedOnMember;
}
Funktioniert super ..... Funktioniert super und deswegen hören hier die meisten Lösungsvorschläge in einschlägigen Foren auch schon auf.... Funktioniert super, so lange man das Attribut direkt auf dem Model definiert. Allerdings gibt es auch die Möglichkeit, Metadatentypen zu definieren, die dann die Attribute beinhalten. Das ist immer dann sinnvoll, wenn das eigentliche Modell automatisch generiert wird - aus einem Designer oder aus einem T4-Template.

Schauen wir uns ein Beispiel an:
public class MyViewModel
{
    [Required]
    public string Name { get; set; }
}
Dafür funktioniert die bisher erstellte Lösung. Aber bei dem folgenden Beispiel schlägt unsere Prüfung fehl:
[MetadataType(typeof(MyViewModelMetaData))]
public class MyViewModel
{
    public string Name { get; set; }
}

public class MyViewModelMetaData
{
    [Required]
    public string Name { get; set; }
}

Wie kann das Problem gelöst werden? Ganz einfach - zusätzlich zu der schon erstellten Prüfung auf direkt gesetzte Attribute muss nun noch dem Metadatenattribut auf dem Typ gefolgt werden und in diesem Typ geprüft werden welche Attribute auf dem gleichnamigen Member gesetzt sind:
private static bool HasAttribute([NotNull] MemberInfo memberInfo, [NotNull] Type attributeType)
{
    if (memberInfo == null)
    {
        throw new ArgumentNullException();
    }

    // hier prüfe ich direkt gesetzte Attribute
    var isDefinedOnMember = Attribute.IsDefined(memberInfo, attributeType);
    if (isDefinedOnMember)
    {
        return true;
    }

    // jetzt wird noch der Metadatentyp geprüft
    var type = GetMetadataType(memberInfo);
    if (type == null)
    {
        return false;
    }

           
    return type.GetProperties().Any(prop => prop.Name.Equals(memberInfo.Name, StringComparison.OrdinalIgnoreCase) && Attribute.IsDefined(prop, attributeType));
}
Nun liefert die erstellte Methode auch in diesem Fall korrekte Ergebnisse.

Happy coding.

codefest.at [MS]: Visual Studio 14 CTP 2 in Azure - Virtuelle Computer einfach erstellen

Da ich noch auf das Gehäuse für meinen neuen Hyper-V PC warte, ich aber unbedingt Visual Studio 14 CTP2 ausprobieren wollte, stand ich kurzfristig vor einem Dilemma. Ich könnte natürlich mein Entwickler-Notebook missbrauchen, aber für eine CTP möchte ich mir die Arbeit, die dann vermutlich auf mich wartet, um wieder produktiv zu sein, nicht wirklich antun.

Des Weiteren ist ein ATX Unternehmen einer meiner Auftraggeber - der leider noch kein Windows 8/8.1 im Einsatz hat – bei dem das Interesse an Windows Phone 8/8.1 und Windows Store Applikationen aber vorhanden, bzw. sehr groß ist, wofür aber eben Windows 8/8.1 im Einsatz sein sollte. Tja, was tun, eine kleine Ewigkeit hat sich Ratlosigkeit breit gemacht…….bis…ja, bis mir eine wirklich gute Idee gekommen ist.

Zum Glück kommt mir nämlich wieder einmal Microsofts Cloud Lösung – Azure - zu Hilfe (das ist wirklich nicht das erste Mal, aber das werdet Ihr in weiteren Blog Einträgen bestimmt noch nachlesen können), genauer gesagt, die VMs, die bereits fix und fertig zur Verfügung stehen und auf eine Verwendung unsererseits nur warten.

Und genau das ist die Lösung meines momentanen Problems: Das risikolose Testen der neuen Visual Studio Version und das Entwickeln für den Windows Store in der Cloud. Also, nichts wie ran an das Aufsetzen eines virtuellen Computers.

Einrichten der VM mit VS 14 CTP 2

Mit einer bestehenden Azure Subscription sind die Anzahl der Schritte überschaubar, die man braucht, um an eine VM mit VS 14 CTP 2 zu gelangen. Da ich eine MSDN-Subscription mein Eigen nennen darf, kann ich auch jedes Monat Azure im Wert von €150,-- dank Microsoft kostenfrei nutzen.

Die Schritte, die notwendig sind kurz zusammengefasst:

1. Anmelden am Management Portal unter https://manage.windowsazure.com 
2. Anlegen eines virtuellen Computers
3. Konfiguration des virtuellen Computers
4. Start des virtuellen Computers
5. Verbinden mit Remote Desktop

Klingt relativ einfach - ist es auch - wie wir gleich sehen werden.

Anmelden im Portal

Nehmt den Browser eurer Wahl und navigiert zu https://manage.windowsazure.com. Dort meldet Ihr euch mit eurer Microsoft ID und dem Passwort an, danach landet Ihr (wie gewohnt) im Management Portal.

image

Nach der Anmeldung wollen wir den virtuellen Computer mit Visual Studio 14 CTP 2 anlegen.

Virtuellen Computer anlegen

Wählt nun auf der linken Seite ‚virtuelle Computer‘ an und klickt auf ‚virtuellen Computer erstellen‘.

image

In dem neuen Fenster wählt Ihr nun ‚aus Katalog‘ aus.

image

Es öffnet sich ein Fenster, wo alle vorhandenen virtuellen Maschinen aufgelistet sind, die Ihr installieren könnt. Wir sind auf der Suche nach dem Visual Studio 14 CTP 2 Image, dazu habe ich in der Suchleiste das Suchkriterium ‚visual studio‘ eingegeben, dementsprechend wird die Liste der verfügbaren Images eingeschränkt. Voila, Visual Studio Professional 14 CTP 2 steht an erster Stelle.

image

Dieses Image habe ich angewählt und danach den image Button gedrückt um die VM zu konfigurieren, oder besser gesagt, konfigurieren zu lassen. Ach, wie schön ist es doch, Arbeit delegieren zu können…..

Konfiguration des virtuellen Computers

Die Konfiguration ist eine recht einfache Sache - geschieht in drei einfachen Schritten.

Im ersten Schritt sollte man vorsichtig sein, hier ist folgendes einzugeben:

· Der Name des virtuellen Computers. Unter diesem Namen (plus der Erweiterung .cloudapp.net) ist später derselbe über Remote Desktop erreichbar. Der Name muss weltweit eindeutig sein und ist später nicht mehr änderbar.

· Die zweite Auswahl betrifft die Art und Größe der zugrunde liegenden Hardware. Je stärker, umso mehr Kosten fallen pro Monat an. Ich habe den Vorschlag auf A1 zurück gesetzt, das bedeutet 1 Core mit 1.75 GB RAM und (maximale) Kosten von €45,-- pro Monat (dazu aber später noch etwas mehr).

Im zweiten Schritt kann die Region des virtuellen Computers angepasst werden. Diesen habe ich auf Westeuropa geändert. Besondere Beachtung sollte man den Ports widmen, diese werden später zur Herstellung der Verbindung benötigt.

imageimage

Im abschließenden dritten Schritt erkennt Ihr die rechtlichen Bestimmungen von Microsoft an, danach kann es auch schon losgehen.

image

Unser Job ist getan, jetzt sind wir nur noch wenige Minuten davon entfernt, unseren virtuellen Computer auszuführen.

Start des virtuellen Computers

Nach dem Klick auf image wird der virtuelle Computer angelegt, was in der Statusanzeige sehr schön ersichtlich ist.

image

Nach einigen Minuten ist der virtuelle Computer bereit, die Statusanzeige wechselt auf ‚wird ausgeführt‘.

image

Das war es auch schon. Jetzt werden wir uns noch mit Remote Desktop an den soeben erstellten virtuellen Computer verbinden.

Verbinden mit Remote Desktop

Auf meinem lokalen Notebook starte ich Remote Desktop und stelle eine Verbindung zu meinem vorhin angelegten virtuellen Computer her.

imageimage

Das dauert ein paar Sekunden, danach kann ich Visual Studio 14 CTP 2 starten und gleich einmal auf meine Person aktivieren.

image

Voila, einem ersten Test von Visual Studio 14 CTP 2 steht nun nichts mehr im Wege – und das ganz ohne eigenes Risiko eine (bestehende) Installation durch die CTP unbrauchbar zu machen….

Kosten der VM

Das Ganze hat natürlich auch seinen Preis. Ich habe das einmal herausgesucht, Ihr könnt das gerne selbst kontrollieren unter: http://azure.microsoft.com/en-us/pricing/details/virtual-machines/

image

Die Kosten von €45,-- pro Monat sind  für die gebotene Leistung an sich schon eine feine Sache. Wenn ich diesen virtuellen Computer aber gerade nicht benötige, kann ich diesen jederzeit im Management Portal herunterfahren, um Kosten zu sparen.

Stoppen der virtuellen Maschine

Mittlerweile wird von Microsoft eine minutengenaue Abrechnung durchgeführt und gestoppte VMs produzieren keinerlei Kosten. Das Herunterfahren ist ganz einfach mit dem Button imageim Management Portal zu bewerkstelligen.

image

Das bedeutet, dass es sich durchaus lohnt, virtuellen Maschinen im Azure Management Portal herunterzufahren, denn damit lassen sich die Gesamtkosten für die Infrastruktur verringern. Viele Server müssen nämlich nur während der regulären Bürozeiten im Betrieb sein und können über Nacht beendet werden. Ähnlich verhält es sich natürlich mit der hier vorgestellten Entwickler VM, diese kann zu Zeiten, wo der Entwickler sich seinen wohl verdienten Schlaf gönnt, heruntergefahren werden.

Azure SDK 2.4 und Azure VMs in VS 2013

Mit der neuen Version 2.4 des Azure SDKs (und dem Update 3 von Visual Studio 2013) ist es nun möglich, den virtuellen Computer direkt in Visual Studio 2013 zu konfigurieren. Die zuvor erstellte VM wird im Server Explorer im Azure/Virtual Machines Knoten aufgelistet.

imageimage

Starten, Stoppen, Konfigurieren und sogar Debuggen ist schon länger möglich, der „Configure…“ Menüeintrag ist allerdings neu und öffnet ein neues Fenster mit zahlreichen Einstellungsmöglichkeiten.

image

Perfekt, so muss man nicht in das Azure Portal wechseln, wenn man Einstellungen kontrollieren, oder anpassen möchte. Ich frage mich gerade ernsthaft, ob ich meinen neuen, gerade bestellten Server nicht gleich wieder zurück schicken soll…..

Zusammenfassung

Ich denke Microsoft hat eine sehr elegante und auch kostengünstige Lösung für Entwicklungsteams geschaffen, um „schnell einmal etwas auszuprobieren“ – wie etwa Beta Versionen, neue Major Releases, oder einfach nur vorgefertigte virtuelle Computer, die ein bestimmtes Thema abdecken, an dem man gerade interessiert ist (z. B. BI mit dem SQLServer 2014).

Als kleine Randnotiz möchte ich noch anfügen, dass ich parallel zur Erstellung des oben beschriebenen virtuellen Computers auf meinem Notebook das Update 3 für Visual Studio 2013 installiert habe. Es war ein knappes Rennen, der virtuelle Computer mit Visual Studio 14 CTP 2 war aber um einige Minuten schneller verfügbar. Ich kann nur sagen: Echt beeindruckend!


Berndt Hamböck ist seit 2007 MCT, darüber hinaus befasst er sich mit Lösungen für komplexe Anwendungsszenarien mit den neuesten Microsoft Technologien. Die Erfahrungen aus der Projektarbeit gibt er in Vorträgen und Trainings weiter und begleitet Entwicklerteams in Softwareunternehmen bei Projekten im Microsoft Umfeld.

„Das ist ein Gastbeitrag. Die Meinung des Autors muss sich nicht mit jener von Microsoft decken. Durch den Artikel ergeben sich keinerlei Handlungsempfehlungen. Microsoft übernimmt keine Gewähr für die Richtigkeit oder Vollständigkeit der Angaben.“

Ralf Westphal: Software systematisch wachsen lassen

Mir gefällt die Metapher von der “wachsenden Software”. Ein schöner bildlicher Gegenentwurf zur Hausbaumetapher. Aber bisher hat mir dabei immer etwas gefehlt. Wie funktioniert denn das mit dem Wachsen genau? Software wächst ja nicht von allein, sondern durch unseren Eingriff von außen. Das Buch “Growing Object-Oriented Software Guided by Tests” (GOOS) hat versucht, diesen Wachstumsprozess, nein,

ppedv Team Blog: CRUD mit Angular und ASP.NET Web API

Es gibt schon eine Reihe von Blogeinträgen, die sich mit Angular, dem Controller, Listen, Suche und dem Sortieren beschäftigen. Auch wie man einen REST Service erstellt, auf Basis von Web API, habe ich bereits beschrieben. Schon etwas länger liegt ein fertiges Create, Read, Update und Delete-Beispiel auf meiner Festplatte. Allerdings muss klar gesagt werden, dass dies mit hohen Risiken verbunden ist. Eine transparente API für z.B. das Löschen von Datensätzen wird irgendwann immer missbraucht. Schutz kann nur Verschlüsselung, Authentifizierung und ein zusätzliches Token-System bieten. Ganz generell sehe ich erhebliche Risken bei einem reinen SPA Ansatz. Shawn Wildermuth schreibt dazu “I dont believe in SPA”.

Trotzdem möchte ich rein akademisch ein End to End-Beispiel zeigen. Daten aus der Northwind SQL Server Datenbank werden über eine ASP.NET Web API als REST-Service zur Verfügung gestellt. Ein HTML5 basiertes UI lädt mit Hilfe von Angular die Daten und bindet sie dem MVx Pattern folgend. Ebenso werden die Events im Viewmodel erstellt und an Buttons gebunden.

Das UI könnte aus der Feder des Lada Tiger Designers stammen: es ist zweckmäßig schlicht. Im oberen Bereich kann ein neuer Customer erzeugt werden. Darunter findet sich eine Liste. Eine Reihe kann in einen Edit-Modus versetzt werden.

image

Zuerst wird ein Entity Model aus der Datenbank generiert und danach per Scaffolding ein neuer Web API Controller aus dem Modell. Schon mehrfach beschrieben. Der so erzeugte VB.NET Code bedarf keiner Änderungen.

   1:  Imports System.Data
   2:  Imports System.Data.Entity
   3:  Imports System.Data.Entity.Infrastructure
   4:  Imports System.Linq
   5:  Imports System.Net
   6:  Imports System.Net.Http
   7:  Imports System.Web.Http
   8:  Imports System.Web.Http.Description
   9:  Imports Angular1Learn
  10:  Imports System.Web.Http.OData
  11:   
  12:  Namespace Controllers
  13:      Public Class CustomersController
  14:          Inherits ApiController
  15:   
  16:          Private db As New NorthwindEntities
  17:   
  18:          ' GET: api/Customers
  19:   
  20:          Function GetCustomers() As IQueryable(Of Customers)
  21:              Return db.Customers
  22:          End Function
  23:   
  24:          ' GET: api/Customers/5
  25:          <ResponseType(GetType(Customers))>
  26:          Function GetCustomers(ByVal id As String) As IHttpActionResult
  27:              Dim customers As Customers = db.Customers.Find(id)
  28:              If IsNothing(customers) Then
  29:                  Return NotFound()
  30:              End If
  31:   
  32:              Return Ok(customers)
  33:          End Function
  34:   
  35:          ' PUT: api/Customers/5
  36:          <ResponseType(GetType(Void))>
  37:          Function PutCustomers(ByVal id As String, ByVal customers As Customers) As IHttpActionResult
  38:              If Not ModelState.IsValid Then
  39:                  Return BadRequest(ModelState)
  40:              End If
  41:   
  42:              If Not id = customers.CustomerID Then
  43:                  Return BadRequest()
  44:              End If
  45:   
  46:              db.Entry(customers).State = EntityState.Modified
  47:   
  48:              Try
  49:                  db.SaveChanges()
  50:              Catch ex As DbUpdateConcurrencyException
  51:                  If Not (CustomersExists(id)) Then
  52:                      Return NotFound()
  53:                  Else
  54:                      Throw
  55:                  End If
  56:              End Try
  57:   
  58:              Return StatusCode(HttpStatusCode.NoContent)
  59:          End Function
  60:   
  61:          ' POST: api/Customers
  62:          <ResponseType(GetType(Customers))>
  63:          Function PostCustomers(ByVal customers As Customers) As IHttpActionResult
  64:              If Not ModelState.IsValid Then
  65:                  Return BadRequest(ModelState)
  66:              End If
  67:   
  68:              db.Customers.Add(customers)
  69:   
  70:              Try
  71:                  db.SaveChanges()
  72:              Catch ex As DbUpdateException
  73:                  If (CustomersExists(customers.CustomerID)) Then
  74:                      Return Conflict()
  75:                  Else
  76:                      Throw
  77:                  End If
  78:              End Try
  79:   
  80:              Return CreatedAtRoute("DefaultApi", New With {.id = customers.CustomerID}, customers)
  81:          End Function
  82:   
  83:          ' DELETE: api/Customers/5
  84:          <ResponseType(GetType(Customers))>
  85:          Function DeleteCustomers(ByVal id As String) As IHttpActionResult
  86:              Dim customers As Customers = db.Customers.Find(id)
  87:              If IsNothing(customers) Then
  88:                  Return NotFound()
  89:              End If
  90:   
  91:              db.Customers.Remove(customers)
  92:              db.SaveChanges()
  93:   
  94:              Return Ok(customers)
  95:          End Function
  96:   
  97:          Protected Overrides Sub Dispose(ByVal disposing As Boolean)
  98:              If (disposing) Then
  99:                  db.Dispose()
 100:              End If
 101:              MyBase.Dispose(disposing)
 102:          End Sub
 103:   
 104:          Private Function CustomersExists(ByVal id As String) As Boolean
 105:              Return db.Customers.Count(Function(e) e.CustomerID = id) > 0
 106:          End Function
 107:      End Class
 108:  End Namespace

 

Mit dem $http Service, der per Dependency Injection in den Controller injiziert wird, wird ein GET auf die REST URL abgesetzt. Im Erfolgsfall reicht eine direkte Zuweisung der Rückgabe an das Customers Array.

Hier wird eine Sucess und eine Error-Methode verwendet. In der Angular-Dokumentation wird dies als Promise bezeichnet. Technisch sind das Objekte, die Callback Methoden besitzen, die asynchron aufgerufen werden.

   1:  var url = 'api/Customers/';
   2:  angular.module('kunden2App', [])
   3:  .controller('CRUDController', function ($scope, $http) {
   4:      $scope.customers = [];
   5:       $http.get(url).success(function (data) {
   6:          $scope.customers = data;
   7:      })
   8:      .error(function (data) {
   9:          $scope.error = "An Error has occured while loading posts! " + data.ExceptionMessage;
  10:      });
  11:  });
  12:   

Mit ähnlicher Taktik wird als nächstes ein Datensatz gelöscht, hier mit der ID des Customers als Parameter in der URL. Ebenso wird eine Success und Error-Methode angelegt.

Allerdings muss nach dem Löschvorgang der Datensatz auch aus dem lokalen Viewmodel im Browser entfernt werden, genauer gesagt, aus allen Browsern, die diese Liste aktuell anzeigen. Wir wollen aber beim Machbaren bleiben. Nach einigen Tests mit unterschiedlichen Varianten wird das ganz klassische JavaScript verwendet, um die Liste im Scope zu durchlaufen und die ID des Customers zu vergleichen. Ist sie ident, hat der dazugehörige Customer im Array nichts mehr zu suchen.

   1:   $scope.delcustomer = function () {
   2:          var currentCustomer = this.customer;
   3:          $http.delete(url + currentCustomer.CustomerID).success(function (data) {
   4:              alert("gelöscht")
   5:              //foreach faktor x langsamer http://jsperf.com/angular-foreach-vs-native-for-loop/3
   6:              for (i = $scope.customers.length - 1; i >= 0; i--){
   7:                  if ($scope.customers[i].CustomerID === currentCustomer.CustomerID) {
   8:                      $scope.customers.splice(i, 1);
   9:                      return false;
  10:                  }
  11:   
  12:              }
  13:            
  14:          }).error(function (data) {
  15:              $scope.error = "Fehler " + data.ExceptionMessage;
  16:          });
  17:      };

 

Ich bin kein Freund von multifunktionalen Grids im Browser, aber die Menschheit ist Excel gewohnt und möchte in der Liste direkt editieren können. Dazu muss aber ein bzw. mehrere INPUT-Elemente dynamisch ein bzw. ausgeblendet werden. Die DataGrid-Darstellung benötigt einen Edit Modus, der als Property dem ViewModel hinzugefügt wird, hier benannt als addMode. Das Gleiche gilt für die Anzeige des Add Modus.

Der REST Service erwartet ein HTTP PUT Kommando mit der CustomerID als Key und dem kompletten Customer Objekt als Daten. Nach erfolgreichem Speichern wird der Modus umgeschalten und damit alle Felder sozusagen in Labels dargestellt.

   1:  angular.module('kunden2App', [])
   2:  .controller('CRUDController', function ($scope, $http) {
   3:      $scope.customers = [];
   4:      $scope.addMode = false;
   5:      $scope.toggleEdit = function () {
   6:          this.customer.editMode = !this.customer.editMode;
   7:      };
   8:      $scope.toggleAdd = function () {
   9:          $scope.addMode = !$scope.addMode;
  10:      };
  11:   
  12:      $scope.save = function () {
  13:          var cust = this.customer;
  14:          $http.put(url + cust.CustomerID,cust).success(function (data) {
  15:              cust.editMode = false;
  16:          }).error(function (data) {
  17:              $scope.error = "Fehler " + data.ExceptionMessage;
  18:          });
  19:      };

 

Außerdem werden andere Buttons eingeblendet.

image

Das Neuanlegen eines Datensatzes funktioniert auf Angular-Seite fast identisch, lediglich ein HTTP-Post ohne explizite ID, aber mit dem kompletten Customer-Objekt, wird übermittelt.

   1:  $scope.add = function () {
   2:       $http.post(url, this.newcustomer).success(function (data) {
   3:              $scope.addMode = false;
   4:              $scope.customers.push(data);
   5:          }).error(function (data) {
   6:              $scope.error = "Fehler " + data.ExceptionMessage;
   7:          });
   8:      };

 

Am Ende muss dem $Scope Customer Array noch der Kunde hinzugefügt werden, um ihn auch sichtbar zu haben.

image

Fehlt lediglich noch der HTML5 View. Die Events werden per ng-click an das Viewmodell bzw. die passenden Methoden gebunden. Dabei wird das Customer-Objekt als Parameter übergeben. Mit ng-hide wird das Ein- bzw. Ausblenden von Teilen der UI bezüglich des Viewmodell-Status sichergestellt. Das alles klappt mit der Angular-Zwei-Wege-Datenbindung per ng-model Attribut oder {{}} sehr einfach,

   1:    <body ng-app="kunden2App">
   2:          <div ng-controller="CRUDController">
   3:              <h2>Customers</h2>
   4:              <strong>{{ error }}</strong>
   5:            
   6:              <p ng-hide="addMode"><a ng-click="toggleAdd()" href="">Neu</a></p>
   7:   
   8:              <form name="Form1" ng-show="addMode">
   9:                  Name<input type="text" ng-model="newcustomer.CompanyName" required />
  10:                  CustomerID<input type="text" ng-model="newcustomer.CustomerID" required maxlength="5"/>
  11:                  <br />
  12:   
  13:                  <input type="submit" value="Add" ng-click="add()" ng-disabled="!Form1.$valid" />
  14:                  <input type="button" value="Cancel" ng-click="toggleAdd()" />
  15:   
  16:              </form>
  17:              <hr />
  18:   
  19:             Name Suchen <input type="text" ng-model="search.CompanyName" />
  20:              <table >
  21:                  <tr>
  22:                      <th>#</th>
  23:                      <th> <a href="" ng-click="reverse=!reverse;order('CompanyName', reverse)">Name <img ng-src="img/down{{reverse}}.gif"&lt;/a></</th>
  24:                      <th></th>
  25:                  </tr>
  26:               
  27:                  </tr>
  28:                  <tr ng-repeat="customer in customers | filter:search | orderBy:'CustomerID':reverse" >
  29:                      <td><strong ng-hide="customer.editMode">{{ customer.CustomerID }}</strong></td>
  30:                      <td>
  31:                          <p ng-hide="customer.editMode">{{ customer.CompanyName }}</p>
  32:                          <p ng-show="customer.editMode">
  33:                              <input type="text" ng-model="customer.CompanyName" />
  34:                          </p>
  35:                      </td>
  36:                      <td></td>
  37:                      <td>
  38:                          <p ng-hide="customer.editMode">
  39:                              <a ng-click="toggleEdit(customer)" href="">Edit</a> |
  40:                              <a ng-click="delcustomer(customer)" href="">Delete</a>
  41:                          </p>
  42:                          <p ng-show="customer.editMode">
  43:                              <a ng-click="save(customer)" href="">Speichern</a> |
  44:                              <a ng-click="toggleEdit(customer)" href="">Cancel</a>
  45:                          </p>
  46:                      </td>
  47:                  </tr>
  48:              </table>
  49:    

codefest.at [MS]: SIGGRAPH 2014 Report

Zurzeit findet im kanadischen Vancouver mit der 41. Ausgabe der ACM SIGGRAPH (International Conference on Computer Graphics and Interactive Techniques) eine der bedeutendsten wissenschaftlichen Konferenzen zum Thema Grafik, Animation und Gaming statt. 

Ich bin vor Ort und werde somit live für euch die wichtigsten Trends zusammenfassen. Da die Exibition erst kürzlich gestartet ist mache ich den Anfang mit einem Report aus der "Emerging Technologies Hall" in welcher Universitäten und Forschungsteams aus aller Herren Länder ihre neuesten Forschungsergebnisse präsentieren, wobei ich mich aufgrund der großen Zahl an vorgestellten Projekten auf die meiner Meinung nach wichtigsten beschränken muss.

Den Anfang machen wir mit der ETH Zürich (Disney Research), welche eine neue Methode zur Kommunikation vorstellt. LEDs bieten die Eigenschaft dass sie Lichtsignale nicht nur aussenden sonder auch empfangen können. Diesen Effekt machen sich die Wissenschaftler zu nutze, in dem sie mehrere LEDs in unglaublich kurzer Zeit sowohl als Lichtquelle als auch Lichtsensor arbeiten lassen. Dem menschlichen Betrachter fallen diese Änderungen nicht auf, für ihn leuchten die LEDs permanent. In Wahrheit nutzen sie die kurzen Empfangsphasen dazu, sich gegenseitig Nachrichten auszutauschen. Ein potentielles Einsatzgebiet hierfür ist etwa interaktives Spielzeug. 

Viele Projekte widmen sich 3D Displays ohne Brillen. Beim Spheree von der University of British Columbia beleuchten mehrere Projektoren eine Art Globus von innen - der Betrachter kann sich stufenlos um ihn herumbewegen und dreidimensionale Objekte erkunden. 

CYBERITH verspricht ein realistisches First-Person Gesamterlebnis

Gamer unter euch dürfte vor allem Cyberith interessieren - das Kickstarter Projekt aus Deutschland hat mit seinem dreidimensionalen Bewegungskäfig bereits sein Ziel erreicht und wird laut den Betreibern wohl um weniger als 1000 Euros erhältlich sein. Dann wird sich zeigen ob das Produkt seinen Einzug ins Wohnzimmer findet. Das Herumlaufen funktioniert an sich blendend, trotzdem fühlte sich die Bewegung aufgrund des Beschleunigungsausgleichs nicht zwingend natürlich an, hier zählt wohl der Trainingscharakter - man wird einige Zeit brauchen um einen Shooter einen Abend lang ohne Muskelkater zu bewältigen. 

Eines der Highlights ist neben dem Lumiconsense, einem von Microsoft Research geförderten Bildsensor der JKU Linz, dem ich bereits einen Beitrag gewidmet habe, der Bird Simulator. Virtual Reality Brille auf einem mechanischen Flugeingabegerät vermitteln dem Spieler ein vollständiges Vogelerlebnis - Flügelschlag und vom Ventilator gesteuerter Gegenwind inklusive. 

Der Bird Simulator in Aktion

In der ersten Halle der #SIGGRAPH2014 befanden sich außerdem eine Reihe von Kunstprojekten aus dem Video und Audiobereich. Zum Abschluss muss ich euch noch vom größten jemals geschossenen Bild berichten. Von diesem von den Konferenzbesuchern gestalteten Mandala aus Essenszutaten werden über sechshunderttausend HDR Bilder geschossen - wie viel Speicher das finale Bild benötigt steht noch nicht fest, Schätzungen gehen von mehr als 3 Terrabyte aus. Und das wars auch schon wieder mit dem ersten Teil meines Liveberichts, morgen werde ich mich für euch auf die Exibition begeben.

Mehrere Kameras schießen mehrmals pro Sekunde Teile des Trillion-Pixel Fotos

ppedv Team Blog: Windows 7/8 Tipp – Ungebetene Gäste aussperren

Hat man als Benutzer den Verdacht, jemand versucht sich am eigenen Rechner anzumelden, gibt es für einen solchen Fall eine entsprechende Abhilfe. Leider erlaubt Windows beliebig viele Anmeldeversuche, potentielle Angreifer können es also problemlos mehrmals probieren. Mit der nachfolgend beschriebenen Anleitung sperren Sie die Anmeldung für 30 Minuten, wenn eine bestimmte Anzahl misslungener Versuche erreicht worden ist.

So öffnen Sie die Eingabeaufforderung:

  • in Windows 7 drücken Sie die Windows-Taste und tippen cmd ein, anschließend mit der rechten Maustaste auf cmd.exe, dann auf Als Administrator ausführen und Ja.
  • In Windows 8 drücken Sie die Windows-Taste + X, klicken auf Eingabeaufforderung (Administrator) und Ja.

Sperrung festlegen:

Hierzu geben Sie folgenden Befehl ein: net accounts /lockoutthreshold:3 und Enter

Hinweis: „3“ steht für die Anzahl falscher Anmeldungen

Windows meldet anschließend „Der Befehl wurde erfolgreich ausgeführt“. Ab jetzt wird der Rechner für 30 Minuten gesperrt, sofern die Eingabe drei Mal falsch erfolgt.

 

clip_image002

 

Sperrung aufheben:

Hierzu geben Sie folgenden Befehl ein: net accounts /lockoutthreshold:0

 

clip_image004

Das ist alles, fertig!

Viel Spaß damit

Holger Sirtl: FTP-Zugriff auf Microsoft Azure Blob Storage via Cloud Service

Vor knapp 2 Jahren habe ich in einem Blog Artikel beschrieben wie sich mit Hilfe einer auf CodePlex bereitgestellten FTP to Azure Blob Storage Bridge ein FTP-Zugriff auf Microsoft Azure Blob Storage realisieren lässt. Die Architektur dieser Lösung war wie folgt:

image

Abb 1: Architektur der FTP-Bridge-Lösung

Die in einer Cloud Service Worker Role betriebene Bridge fungiert als Mittler zwischen einem FTP-Client, der die Bridge über Port 21 anspricht und dem Blob Storage, der die Daten hält.

Problem einer veralteten Worker Role Konfiguration

Seit besagtem Blog Artikel hat sich in Microsoft Azure einiges getan, und wenngleich man heute FTP-Zugriff auf Blob Storage ggf. anders implementieren würde (z.B. über eine Virtual Machine, in der ein IIS entsprechend konfiguriert wird), ist es doch eine funktionierende Lösung. Leider setzten die in der Bridge-Lösung verwendeten Konfigurationsdateien ein heute nicht mehr unterstütztes VM-Image für die Worker Role voraus. Deshalb lässt sich die Lösung heute so nicht mehr betreiben.

Aktualisierung der Worker Role Konfiguration

In ein paar wenigen Schritten lässt sich die Blob Storage Bridge allerdings in eine neue, aktuelle Visual Studio Solution übertragen, von wo aus sie dann in eine aktuelle Worker Role deployt werden kann.

Voraussetzungen

Folgende Softwarepakete müssen auf dem Rechner installiert sein:

Darüber hinaus ist ein Microsoft Azure Account erforderlich.

Anlegen eines Storage Accounts

Das Vorgehen hierzu ist identisch zu dem im ursprünglichen Blog Artikel beschriebenen.

Erstellen einer aktuellen Visual Studio Solution

Zum Erstellen einer aktuellen Visual Studio Solution, die auf aktuelle Worker Role VMs deployt werden kann führen Sie folgende Schritte durch:

  1. Öffnen Sie Visual Studio 2013 und wählen Sie den Menüpunkt File/New/Project…
  2. Wählen Sie als Projektvorlage Templates/Visual Studio C#/Cloud/Azure Cloud Service.
     
    image
     
  3. Fügen Sie dem Cloud Service eine Worker Role hinzu und benennen Sie diese mit FTPServerRole.
     
    image
     
  4. Wechseln Sie in den Windows Explorer. Kopieren Sie aus der Visual Studio Solution der FTP to Azure Blob Storage Bridge das Verzeichnis AzureFtpServer in das Verzeichnis der in Schritt 2 angelegten Cloud Service Solution (also “neben” das Verzeichnis FTPServerRole).
  5. Fügen Sie das AzureFtpServer-Projekt der Visual Studio Solution hinzu. Wählen Sie in Visual Studio im Solution Explorer im Kontextmenü (Klick mit der rechten Maustaste auf die Solution) den Eintrag Add/Existing Project… und wählen Sie im Verzeichnis AzureFtpServer die Projektdatei AzureFtpServer.csproj. Die Solution sollte danach drei Projekte enthalten: Das Cloud Service Projekt, die Worker Role und das Ftp-Server-Projekt.
     
    image
  6. Damit die Worker Role den Ftp-Server nutzen kann, fügen Sie in der Worker Role eine Referenz auf den Ftp-Server ein. Klicken Sie in der Worker Role im Eintrag References im Kontextmenü auf Add Reference… Wählen Sie unter Solution/Projects das AzureFtpServer-Projekt und bestätigen Sie mit OK.
     
    image
     
  7. Implementieren Sie nun die Logik der Worker Role. Im Wesentlichen ist dies eine Kopie des Codes, der bereits in der Visual Studio Solution der FTP to Azure Blob Storage Bridge in der dortigen Worker Role enthalten war.
     
    Fügen Sie folgende using-Statements in die Datei WorkerRole.cs: 

    using AzureFtpServer.Azure;
    using AzureFtpServer.Ftp;
    using AzureFtpServer.Provider;
    Definieren Sie in der Klasse Worker Role eine private Variable für den Ftp-Server:
    private FtpServer _server;
    Implementieren Sie die Methode OnStart() wie folgt:
    public override bool OnStart()
    {
    // Set the maximum number of concurrent connections
    ServicePointManager.DefaultConnectionLimit = 12;

    // For information on handling configuration changes
    // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
    RoleEnvironment.Changing += RoleEnvironmentChanging;

    if (_server == null)
    _server = new FtpServer(new AzureFileSystemFactory());

    _server.NewConnection += ServerNewConnection;

    bool result = base.OnStart();

    Trace.TraceInformation("FTPServerRole has been started");

    return result;
    }
    Implementieren Sie die Methode ServerNewConnection() wie folgt:
    static void ServerNewConnection(int nId)
    {
    Trace.WriteLine(String.Format("Connection {0} accepted", nId), "Connection");
    }
    Implementieren Sie die Methode RoleEnvironmentChanging() wie folgt:
    private static void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
    {
    // If a configuration setting is changing
    if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
    {
    // Set e.Cancel to true to restart this role instance
    e.Cancel = true;
    }
    }
    Implementieren Sie die Methode RunAsync() wie folgt:
    private async Task RunAsync(CancellationToken cancellationToken)
    {
    while (!cancellationToken.IsCancellationRequested)
    {
    Trace.TraceInformation("Working");
    if (_server.Started)
    {
    await Task.Delay(1000);
    //Trace.WriteLine("Server is alive.", "Information");
    }
    else
    {
    _server.Start();
    Trace.WriteLine("Server starting.", "Control");
    }
    }
    }

Damit ist die Implementierung abgeschlossen. Was fehlt, sind die Konfigurationsparameter sowie die Definition der für Ftp benötigten Endpunkte.

Setzen der Konfigurationsparameter

Klicken Sie nun im Solution Explorer auf die FTPServerRole und wechseln Sie bei den Einstellungen in den Reiter Settings. Fügen Sie dort die einzelnen Settings wie sie in meinem ursprünglichen Blog Artikel beschrieben sind, hinzu. Klicken Sie jeweils auf Add Setting, wählen den Namen und die zugehörigen Werte. Nach Fertigstellung sollte die Seite wie folgt aussehen:

image

Definieren der benötigten Endpunkte

Wechseln Sie in den Reiter Endpoints und konfigurieren Sie dort die beiden benötigten Endpunkte. Das Ergebnis sollte wie folgt aussehen:

image

Damit ist die eigentliche Implementierung abgeschlossen. Das Ganze kann im Azure Emulator getestet werden. An dieser Stelle soll gleich mit dem Deploment nach Microsoft Azure weiter gemacht werden.

Deloyment der FTP-Bridge-Lösung in einen Cloud Service Container

Aus Visual Studio heraus kann nun via Publish-Befehl (aus dem Kontextmenü der Solution) das Deployment-Paket (eine CSPKG- und eine CSCFG-Datei) erstellt werden, das dann entsprechend der Beschreibung in meinem  ursprünglichen Blog Artikel in Microsoft Azure deployt werden kann.

Alternativ kann aus Visual Studio heraus direkt das Deployment vorgenommen werden. Führen Sie hierzu folgende Schritte aus:

  1. Klicken Sie mit der rechten Maustaste auf das Cloud Service Projekt und wählen im Kontextmenü den Eintrag Publish.
  2. Wählen Sie zunächst die Azure-Subscription, in die der Cloud Service installiert werden soll (bzw. konfigurieren Sie zunächst die Subscription).
     
    image
     
  3. Wählen Sie einen Namen und eine Region, in der der Cloud Service bereitgestellt werden soll.

    image
     
  4. Bestätigen Sie die Eingaben mit Publish.

Daraufhin installiert Visual Studio die FTP-Bridge in einen Microsoft Azure Cloud Service.

Zugriff über einen FTP-Client

Das Vorgehen hierzu ist identisch zu dem im ursprünglichen Blog Artikel beschriebenen.

Weitere Informationen

ppedv Team Blog: Windows Server 2012 R2: Storage Pools mit SSD-Tiering

Seit dem Windows Server 2012 beherrschen die Microsoft-Server-Systeme die Möglichkeit, so genannte “Storage Pools” (Speicherpools) zu bilden. Dabei handelt es sich um einen Zusammenschluss verschiedener lokal angebundener oder als LUN eingebundener Datenträger, z.B. via SAS, SATA oder auch USB. Bei den LUNs stehen iSCSI und FiberChannel zur Verfügung.

Die grundsätzliche Idee ist hier, eine Art Storage abzubilden, quasi eine “Storage-Virtualisierung”. Aus einem gebildeten Storage-Pool können anschließend logische Laufwerke, sogenannte “Speicherplätze” (Storage Spaces), gebildet werden. Dabei kann die Organisation des Speichers gewählt werden. Zur Verfügung stehen “Simple” (eine Art RAID0, keine Datensicherheit, aber eine Erhöhung des Durchsatzes durch die gleichzeitige Nutzung aller beteiligter Festplatten), “Mirror” (Eine Art RAID1 mit einfacher oder doppelter Spiegelung der Blöcke um ein Erhalten der Daten auch bei Ausfall einer Festplatte sicherzustellen) und “Parity” (Funktioniert wie RAID5; Paritätsdaten, die ein Wiederherstellen der Daten bei Ausfall einer Festplatte möglich machen, werden über alle beteiligten Datenträger verteilt). Dabei spielen Größe, Hersteller, Bus-Typ und Co. der Festplatten nahezu keine Rolle – ein Faktor, der die Storage Pools deutlich von klassischen RAID-Controllern unterscheidet.

spool7b2

Ein weiterer Faktor, der Storage-Pools von üblichen “lokalen” Speichertechnologien abgrenzt, ist die Möglichkeit, nachträglich Festplatten hinzuzufügen oder durch größere auszutauschen, um den zur Verfügung stehenden Speicherplatz zu erhöhen.

Seit dem zweiten Release des Server 2012 wird diese Technologie noch erweitert: Der Windows Server 2012 R2 beherrscht das sogenannte “SSD-Tiering” (Speicherebenen). Hierbei werden klassische HDDs und SSDs gemeinsam in einem Pool genutzt und die häufig gelesenen Daten auf die SSD verschoben, die seltener genutzten Daten bleiben auf der HDD. Alternativ kann man SSDs auch als Write-Back-Cache einsetzen.

spool6b

(Eine Anleitung, wie das genau eingerichtet werden kann, werde ich in Kürze ebenfalls veröffentlichen.)

Diese Möglichkeit – sowie Speicherpools insgesamt – sind in meinen Augen vor allem für kleinere und mittlere IT-Landschaften interessant, in denen keine “ausgewachsenen” SANs zum Einsatz kommen (können). Daher war für mich interessant, wie gut diese Technologie funktioniert und welche Geschwindigkeitsvorteile hierbei erzielt werden können. Daher habe ich diverse Test-Messungen unternommen, welche ich nun hier auswerten möchte. Zum Einsatz kam ein Fujitsu-Siemens-Server mit einem 4-Kern-Xeon-Prozessor und 8GB RAM, dazu 2 SATA-Festplatten von Western Digital und 2 SATA-SSDs von Crucial, jeweils mit etwa 250GB Speicher.

Zuerst habe ich die Festplatten einzeln getestet, um Vergleichswerte zu haben:

CrystalDiskMark_Pool_einzelne_HDD CrystalDiskMark_Pool_einzelne_SSD
hdtach_einzelne_HDD hdtach_einzelne_SSD

Hier ist natürlich zu erkennen, dass die SSD (rechts) deutlich schneller als die HDD (links) ist – und zwar in allen Disziplinen.

Weiterhin habe ich den Server-eigenen LSI RAID-Controller getestet (jeweils im RAID0, links 2x HDD, rechts 2x SSD):

CrystalDiskMark_2xHDD_RAID0_Controller CrystalDiskMark_2xSSD_RAID0_Controller
hdtach_2xHDD_RAID0_Controller hdtach_2xSSD_RAID0_Controller

Beim Lesen schafft der Controller sogar etwa doppelt so schnelle Werte – beim Schreiben brechen die Werte dafür dann recht ordentlich ein, der Betrieb ist also langsamer als eine einzelne Platte!

Und nun im direkten Vergleich ein Betrieb via Storage-Pool im “Simple”-Modus (links) und im “Mirror”-Modus (rechts):

CrystalDiskMark_Pool_mitSSD_Tearing_RAID0 CrystalDiskMark_Pool_mitSSD_Tearing_RAID1
hdtach_Pool_mitSSD_Tearing_RAID0 hdtach_Pool_mitSSD_Tearing_RAID1

Hier sieht man zunächst (CrystalDiskMark) etwa folgende Ergebnisse:

- Im Simple-Modus erreicht der Pool fast die Lese-Raten des RAID0 aus 2x SSD am Controller, übertrifft die Schreibraten aber deutlich

- Auch bei den wahlfreien Zugriffen sind durchweg bessere Werte zu sehen als beim RAID0 oder den einzelnen Platten

- Beim Mirror-Modus sind die Leseraten in etwa so wie beim Simple-Modus, beim Schreiben dafür aber nur etwa halb so hoch

- Insgesamt ist der Mirror-Modus aber besser als die beiden SSDs im RAID0 des Controllers

Wenn man nun aber noch HD Tach mit betrachtet, dann sieht man recht deutlich, dass die hohen Raten nur anfänglich erreicht werden (nämlich bis zu der Stelle, an der zwischen den SSDs und den HDDs gewechselt wird, hier etwa bei der Hälfte. Dennoch sind die Daten im “HDD-Bereich” recht gut!

Ich denke diese Ergebnisse zeigen, dass die Technologie zu hohen Geschwindigkeiten fähig ist, die selbst mit (zumindest einfacheren) RAID-Controllern nicht erreicht werden. Ich werde zeitnah noch eine tabellarische Gegenüberstellung der Werte ausarbeiten.

In diesem Beitrag habe ich weitere Tests und eine Auswertung in Tabellenform veröffentlicht: http://blog.ppedv.de/post/2014/08/15/Auswertung-zum-StoragePool-Benchmark.aspx  

ppedv Team Blog: HTML Input mit Bootstrap Edit Template umranden per Angular

Wer umfangreiche Formulare für den Webbrowser erstellt, wird sich bald wünschen weniger Code tippen zu müssen. Ein HTML Input wird mit Attributen versehen, einer Fehlermeldung, einem Label und einigen Klassen.

   1:  <div class="form-group">
   2:      <label class="col-xs-2 control-label" for="text1">Label</label>
   3:      <div class="col-xs-10">
   4:          <input type="text" id="text1" class="form-control" />
   5:          <span class="help-block">Fehlermeldung</span>
   6:      </div>
   7:  </div>

 

Tippen möchte ich aber nur etwas in der Form

 
   1:  <input type="text" id="text1" label="Name:" 
fehlermeldung="bitte füllen" required />

 

Der HTML Code außen rum soll sich automatisch daraus generieren. Ein Anwendungsfall für eine Angular.js Direktive. Das folgende Beispiel ist also der Prototyp zum Prototyp einer zukünftigen SPA Anwendung.

image

Dazu wird eine Angular App im HTML Code deklariert, samt zugehörigem Controller.

   1:  <body ng-app="App">
   2:      <div ng-controller="ExampleController">
   3:          <div formulargruppe data-label="Firmenname" 
data-fehlermeldung="Da muss was rein">
   4:              <input type="text" required name="feld1" 
ng-model="Customer.CompanyName"
   5:                      placeholder="Firma"/>
   6:          </div>
   7:      </div>

Wer sehr korrekt sein will, setzt ein data- vor die Eigenschaftsattribute wie fehlermeldung oder label. Es geht auch ohne. In Zeile 3 wird die Direktive Formulargruppe eingebunden. Auf keinen Fall in Direktiven einen Bindestrich im Namen verwenden, da dieser intern per Konvention entfernt wird.

Direktiven würde ich mit Behaviours aus XAML vergleichen. Damit lassen sich einem UI Element neue Eigenschaften, Visualisierung und Events zuordnen.

Das Ziel ist um jedes bestehende INPUT-Element eine Bootstrap-passende Formatierung zu legen und die Attribute aus dem INPUT weiter zu verwenden.

Die Direktive formulargruppe liefert mit einer Art Konstruktormethode Daten zurück. Mit restrict A ist die Nutzung nur als Attribut zulässig. Transclude ersetzt das bestehende DIV (Zeile 3 obiges Listing) mit dem Inhalt aus dem Template (Zeile 10 folgendes Listing). Das Input Element wandert dann an die Stelle ng-transclude, aus dem HTML Template.

Der besondere Gag ist die Datenbindung an einen lokalen Scope. Nicht zu verwechseln mit dem $Scope aus dem Viewmodel. Die Attribute label und Fehlermeldung und deren Werte aus der HTML-Seite (Zeile 3), werden durch de Zuweisung scrope: zu Eigenschaften. Diese können dann in Zeile 11 und 14 im Template frei gebunden werden. Das erinnert ein wenig an die ContentTemplates aus XAML und die Bindinglogik.

   1:     <script src="Scripts/angular.js"></script>
   2:      <script>
   3:          angular.module('App', [])
   4:           .directive('formulargruppe', function () {
   5:               return {
   6:                   restrict: 'A',
   7:                   transclude: true,
   8:                   replace: true,
   9:                   scope: { label: '@', fehlermeldung: '@' },
  10:                   template: '<div class="form-group">' +
  11:           '<label class="col-xs-2 control-label" for="text1">
{{label}}</label>' +
  12:           '<div class="col-xs-10">' +
  13:           ' <div ng-transclude ></div>' +
  14:           ' <span class="help-block">{{fehlermeldung}}</span> </div></div>',
  15:                              }
  16:   
  17:               }
  18:           })
  19:          .controller('ExampleController', ['$scope', function ($scope) {
  20:          ...
  21:          }]);

 

Das bleibt ein nicht unerhebliches Problem. Bootstrap braucht im Input-Element, für die runden Ecken, eine CSS Klasse form-control. Man könnte diese Klasse im Ausgangs-HTML-Code definieren, schöner wäre aber ein Automatismus über die Direktive. Allerdings ist im HTML Template kein INPUT vorhanden.

Genau für diesen Zweck, nämlich per Logik, das Template zu manipulieren, wurde die Link-Eigenschaft geschaffen. Im folgenden JavaScript Code wird das erste und einzige INPUT-Element selektiert. Dieses muss in einen Angular-Elementtyp umgewandelt werden, um die Jquery-Methode addClass nutzen zu können.

   1:  link: function (scope, element, attrs {
   2:          var input1 = element[0].querySelector("input");
   3:          angular.element(input1).addClass('form-control');

 

Letztendlich noch ein Blick auf den erzeugten HTML Code. Es fällt auf, dass ein zusätziches DIV um das INPUT Element gerendert wird. Erkennbar am Attribut ng-transclude. In meinen Tests mit allen möglichen Varianten Direktive als Element oder Attribut wurde auch ein  <span class="ng-scope">hannes</span> eingefügt.

   1:  <div ng-transclude="">
   2:            
   3:    <input name="feld1" class="ng-scope ng-pristine ng-untouched 
   4:  form-control ng-invalid ng-invalid-required" required=""
   5:   type="text" placeholder="Firma" 
   6:  ng-model="Customer.CompanyName">
   7:   
   8:  </div>

Dies ist nur der Anfang für ein vollständiges Angular-Formular mit Validierung und Bootstrap Design. Gezeigt wurde der Einsatz einer Direktive mit HTML Template und Binding. Mehr lernen Sie in meinem ppedv Angular Workshop auf der #ADCX.

codefest.at [MS]: Visual Studio 2013 Update 3 (2013.3) RTM - August 4

Ganz rasch, ganz frisch: Visual Studio 2013 Update 3 (2013.3) RTM - August 4 ist verfügbar! Nebenbei ist heute auch ein großer Microsoft Patchday August updates for Windows 8.1 and Windows Server 2012 R2. Also viel zu aktualisieren… Das zuvor erwartete “Windows 8.1 Update 2” wird es nicht geben, stattdessen kommen – wie gewohnt - viele kleine Updates: Patches. Neue Features (wie etwa das neue alte Startmenu, welches auf Build 2014 gezeigt wurde) kommt dann wohl erst mit “Treshold”…

Das Update kann direkt aus VS installiert werden…

image

…oder hier per Web-Installer oder als ISO bezogen werden, siehe Download. Das ISO ist satte 4GB groß.

image

Einige Neuerungen von VS 2013 Update 3 auf einen Blick zusammengefasst finden sich im Visual Studio Blog:

Visual Studio 2013 Update 3 (2013.3) RTM - August 4

image

Viel Spaß mit den Neuerungen!

ppedv Team Blog: Windows zeitgesteuert herunterfahren

Sie wollen längst nach Hause, der Rechner ist jedoch noch nicht fertig mit der Arbeit. Dateien werden noch kopiert oder Inhalte heruntergeladen. Sie wollen, anstatt zu warten, dass der Rechner z.B. in 20 Min automatisch herunterfährt.

Mit einer kleinen Textdatei sorgen Sie dafür, dass Ihr Rechner, so wie Sie es wollen, zukünftig selbstständig herunterfährt.

Das sind die nötigen Schritte:

Schritt 1: Dokument erstellen:

Sie drücken die Tastenkombination „Windows-Taste“ + „R“, tippen Notepad ein und bestätigen mit OK.

clip_image001

Geben Sie nun folgenden Text ein:

@echo off

set /p eingabe="Minuten bis zum Herunterfahren:"

set /a sekunden=%eingabe%*60

shutdown /s /t %sekunden%

exit

image

Danach klicken Sie auf Datei, Speichern unter und wählen einen Speicherort aus (am besten auf dem Desktop) und benennen die Datei als Herunterfahren.cmd und speichern diese ab.

Schritt 2: Timer einstellen:

Um Ihren PC herunterzufahren, klicken Sie doppelt auf die eben auf dem Desktop gespeicherte Datei Herunterfahren.cmd. Im Dialogfenster geben Sie die Zeit in Minuten ein, wann der PC herunterfahren soll und bestätigen die Eingabe mit Enter.

clip_image003

Der sog. Countdown beginnt sofort und läuft auch weiter, auch wenn Sie das Fenster schließen. Nach Ablauf der Zeit fährt der PC herunter.

clip_image005

Viel Spaß damit

Holger Sirtl: Microsoft Azure Caching - welchen Service soll ich nehmen?

Wer für seine Azure-basierte Anwendung einen Caching Service nutzen möchte wird nach Studium der entsprechenden MSDN-Seiten möglicherweise etwas verunsichert bleiben. So gibt es in Microsoft Azure (Stand August 2014) sage und schreibe vier Alternativen für die Umsetzung von Caching:

Hinweise zur Auswahl des geeigneten Azure Cache Service finden sich auf der MSDN-Seite Which Azure Cache offering is right for me?

Ohne das Ergebnis der Empfehlungen komplett vorweg nehmen zu wollen, lässt sich daraus ableiten:

  1. Wann immer möglich (insbesondere bei neuen Projekten) sollte Azure Redis Cache als Cache verwendet werden.
  2. Sofern Redis nicht möglich ist, sollte vom Shared Cache kurzfristig (bis 01.09.2014) zum Managed Cache Service migriert werden.
  3. Für Cloud Services sind sowohl der Redis Cache als auch der In-Role-Cache sinnvoll.

Azure Redis Cache

Azure Redis Cache basiert auf dem Open Source Redis Cache Framework. Dieser wird von Microsoft verwaltet auf Azure bereitgestellt und von beliebigen Azure Anwendungen (Websites, Cloud Services, Virtual Machines) heraus zugreifbar. Redis Cache (Preview) ist in zwei Ausbaustufen verfügbar: Basic (ein Knoten, verschiedene Größen) und Standard (zwei Knoten (Master/Slave), mehrere Größen, 99,9% SLA). Während die anderen Cache Services nur einfache Schlüssel-Wert-Paare verwalten können, kann der Redis Cache auch mit Datenstrukturen wie Strings, Hashes, Listen, Sets und Sortierte Sets umgehen. Darüber hinaus unterstützt er Transaktionen, Pub/Sub-Pattern, Lua Scripting und Schlüssel mit begrenzter Lebensdauer.

Weitere Informationen zum Redis Cache unter:

Managed Cache Service

Der Managed Cache Service ist ein zentral bereitgestellter Cache Service, der – anders als der In-Role-Cache – von Cloud Services, Websites und Virtual Machines heraus zugänglich ist. Er basiert auf der AppFabric Cache Engine in Azure. Der Managed Cache wird in drei Ausbaustufen, die sich in Größenoptionen und einigen Funktionen unterscheiden (z.B. Notifications) angeboten: Basic, Standard und Premium. Das Anlegen eines Managed Cache Service ist derzeit (August 2014) nur über PowerShell möglich.

Weitere Informationen zum Managed Cache Service:

In-Role Cache

Dieser Cache läuft innerhalb von Cloud Service Rollen. Hierzu können entwicklerseitig entweder dedizierte Cache Rollen definiert werden, bei denen die gesamte Leistung der Rolleninstanzen für den Cache reserviert wird (dedicated), oder anteilig Leistung regulärer Web oder Worker Rollen für den Cache reserviert werden (co-located). Sofern eine Umkonfiguration des Cache erforderlich ist, muss der Cloud Service neu deployt werden. Durch die flexible Bereitstellung von Rollen und Instanzen sind quasi beliebige Cache-Größen möglich. Der In-Role Cache kann nur innerhalb von Cloud Services genutzt werden.

Weitere Informationen zum In-Role Cache:

Shared Cache

Dies ist der erste, in Microsoft Azure (damals noch Windows Azure genannt) angebotene Caching-Dienst. Dieser stellt an zentraler Stelle Caching-Funktionalität für Key-Value-Paare bereit. Nachdem dieser Cache als Multi-Mandanten-Dienst implementiert war (d.h. mehrere Azure Kunden sind zwar durch die Plattform voneinander getrennt, teilen sich aber die gleichen Ressourcen), kann die Performanz variieren (abhängig davon wie das Zugriffsverhalten der einzelnen Kunden ist).

Der Shared Cache wird am 01.09.2014 eingestellt. Kunden, die diesen Dienst nutzen, müssen ihre Anwendungen bis dahin auf einen der anderen Caching-Dienste migriert haben. Informationen hierzu:

Zusammenfassung

Folgende Tabelle gibt einen schnellen Überblick über die Caching Alternativen in Microsoft Azure:

Caching Service Eigenschaften Roadmap
Azure Redis Cache
  • Zentral bereitgestellt
  • Nutzbar von Websites, Cloud Services, Vitual Machines
  • Ablage von Schlüssel-Wert-Paaren, wobei Schlüssel Datenstrukturen wie Strings, Hashes, Listen, Sets und Sortierte Sets enthalten können
  • Unterstützung von Transaktionen, Pub/Sub, Notifications, Lua Scripting
  • Wählbare Lebensdauer von Schlüsseln
Empfehlung für alle neuen Projekte mit Caching Bedarf.
Managed Cache
  • Zentral bereitgestellt
  • Nutzbar von Websites, Cloud Services, Vitual Machines
  • Ablage von Schlüssel-Wert-Paaren
 
In-Role Cache
  • Caching-Funktion wird in Cloud Service Rollen bereitgestellt
  • Nutzbar nur aus Cloud Services.
  • Ablage von Schlüssel-Wert-Paaren
 
Shared Cache
  • Zentral bereitgestellt
  • Multi-Mandanten-Umgebung
  • Nutzbar von Websites, Cloud Services, Virtual Machines
  • Ablage von Schlüssel-Wert-Paaren
Wird am 01.09.2014 eingestellt.

Weitere Informationen

Sven Hubert: Neues Feature für AIT Apply Company Policy: Projekte ausschließen und einbeziehen

Entwicklungsrichtlinien sind sinnvoll und sollten nach Möglichkeit durchgesetzt werden. Dabei hilft das kostenlose Tool AIT Apply Company Policy (ACP), welches wir schon in einem anderen Beitrag vorgestellt haben. Allerdings gibt es vielleicht manche Richtlinien, die nur auf ganz bestimmte oder gerade auf bestimmte Projekte nicht angewandt werden sollen. Dies ist mit der neuen Version von AIT Apply Company Policy möglich, welche im Downloadbereich zur Verfügung steht.

Zum Beispiel könnte man ein ACP-Paket erstellen, was auf alle Projekte angewandt wird, nur die Dokumentation soll in Testprojekten nicht erstellt werden. Dann könnte der entsprechende Abschnitt in der CompanyPolicy.config so aussehen:

<Documentation exclude="*.Test"> 
    <Configuration Name="Debug" enabled="true" /> 
    <Configuration Name="Release" enabled="true" />    
    <Configuration Name="Staging" enabled="true" /> 
</Documentation>

Das exclude-Attribut bestimmt, dass in allen Projekten, die auf “.Test” enden, nicht die Dokumentation erstellt wird.

Es ist auch denkbar, dass man ein ACP-Paket erstellt, welches nur für Testprojekte gelten soll, z. B. bestimmte Regeln für die statische Codeanalyse, und man möchte sicherstellen, dass dieses Paket auch wirklich nur auf Testprojekte angewandt werden kann. Dies ist mit folgendem Eintrag möglich:

<StaticCodeAnalysis includeOnly="*.Test"> 
    <Configuration Name="Debug" enabled="true" ruleSet="AIT.ruleset" /> 
    <Configuration Name="Release" enabled="true" ruleSet="AIT.ruleset" />     
    <Configuration Name="Staging" enabled="true" ruleSet="AIT.ruleset"/> 
</StaticCodeAnalysis>

Das includeOnly-Attribut definiert hier, dass die Regeln für die statische Codeanalyse nur auf Projekte angewandt werden, welche auf “.Test” enden.

Darüber hinaus ist es möglich, diese beiden Attribute zu kombinieren. Damit kann man z. B. Regeln nur auf Projekte anwenden, die “Infrastructure” im Namen haben aber nicht auf “.Test” enden.

Neues Feature für AIT Apply Company Policy: Projekte ausschließen und einbeziehen is a post from: AIT Blog

Christian Giesswein: Roslyn Live - Roslyn in der Cloud

Letztens wollte ich die neuen Features von Roslyn ausprobieren, und damit meinte ich die neusten, von neuen Features wie zum Beispiel den „Null Propagation Operator“ der mit C# 6.0 kommen wird. Dieses Feature ist leider nicht in der Preview von Microsoft enthalten. Ich könnte nun natürlich mir den Quellcode von Roslyn herunterladen, Compilieren und in der Roslyn-Hive installieren, jedoch ist dies relativ viel Aufwand. Dementsprechend kam ich auf die Idee – Warum nicht eine kleine Website bauen die dies übernimmt? Gesagt,.. getan,… erledigt! Damit habe ich http://roslynlive.azurewebsites.net ins Leben gerufen. Dabei wird die neuste Version von Roslyn verwendet (vom 04. August also knappe 9 Tage alt) und man kann dort die Features sauber ausprobieren. Nachdem in meinen bisherigen Sessions und Vorträgen zu diesem Thema immer wieder die Frage aufgetaucht ist, wie denn der IL Code dafür aussehen würde, habe ich diesen gleich mitausgewertet um damit zu sehen was der Compiler denn daraus macht.

Der Compiler in der Cloud...

Damit kann man natürlich wahnsinnig schnell mal eben die Sprachfeatures von C# 6.0 ausprobieren und sieht auch den IL Code davon.
Persönlich finde ich gerade das neue Null-Propagating Operator Feature doch recht nützlich wenn man es mal verwendet.

Falls dazu wer Fragen hat, oder es nützlich findet aber es fehlt einem ein Feature würde es mich freuen wenn ich dazu eine kurze Mail an mail@giesswein-apps.at erhalt
oder per Twitter an @giessweinweb.

friends header

bloggers headline

links header

 
Don't contact us via this (fleischfalle@alphasierrapapa.com) email address.