Holger Schwichtenberg: Global Unique Identifier in .NET, C# und Visual Basic formatieren

Auch wenn im .NET Framework GUIDs nicht mehr zur Identifikation von Schnittstellen und Klassen zum Einsatz kommen, haben diese 128 Bit langen Zahlen weiterhin dort viele Einsatzgebiete. Eine GUID ist zwischen 32 und 68 Zeichen lang – je nach Formatierung.

Golo Roden: Einführung in Node.js, Folge 1: Node.js installieren

Die Installation von Node.js scheint auf den ersten Blick ein Selbstläufer zu sein. Doch was, wenn man mehrere Versionen von Node.js parallel installieren und zwischen diesen wechseln möchte?

AIT: Neu in Visual Studio und TFS "15" / 2017: C# 7 – Teil 1

Mit der Offenlegung des C#-Compilers können neue C#-Features bereits heute verwendet werden. Da dieser Prozess jedoch aufwändig und nicht unbedingt geeignet für ein produktives Umfeld ist, gibt es mit C# 7 wieder ein Abbild des aktuellen Stands. Dabei wird C# 7 zusammen mit Visual Studio 2017 ausgerollt. Da eine Beschreibung aller Features von C# 7 den Rahmen eines Blog Posts sprengen würde, gibt es hier den ersten Teil.

Binary literals

Mit Binary literals wird eine Möglichkeit geboten, um Binärzahlen im Code besser darzustellen. Dies ist vor allem nützlich für jeden, der hardwarenah in C# programmiert.

Beispiel

In diesem Beispiel soll die Zahl 8 als Binärformat dargestellt werden, zum einen über die neue Technik und zum anderen im Vergleich, wie es bereits heute funktioniert. In jedem der dargestellten Fälle wird am Ende in der Variablen EnableFlag die Zahl 8 stehen.

// Integer representation
public const int EnableFlag = 8;

// Shift representation
public const int EnableFlag = 1 << 3;

// Convert representation
public const int EnableFlag = Convert.ToInt32("1000", 2);

// Binary literal representation (C#7)
public const int EnableFlag = 0b1000;

Digit separators

Mit der neuen Binärdarstellung geht ein weiteres Problem einher. Was, wenn längere Binärzahlen oder z.B. große Dezimalzahlen dargestellt werden sollen. Ein Trennzeichen z.B. für Tausenderstellen oder Halbbytes, um die Zahlen besser lesbar zu machen, würde die Lesbarkeit verbessern. Auch hier bietet C# 7 eine interessante Neuerung.

Das Trennzeichen wurde auf den Unterstrich _ festgelegt. Mit diesem ist es möglich, beliebige Zahlenwerte zu trennen. Dabei kann es beliebig oft wiederholt werden (siehe Beispiel SpecialNumber) und wird später beim Kompilieren einfach ignoriert. Zu Bedenken gilt: Das Trennzeichen kann nur zwischen Ziffern stehen und nicht zwischen Sonderzeichen (z.B. der Dezimalpunkt oder am Anfang oder am Ende einer Zahl).

Beispiel

public const int EnableFlag = 0b0000_1000;
public const decimal IntervalInMilliseconds = 1_000_000.500_50;
public const int WhiteColor = 0xFF_FF_FF;
public const decimal SpecialNumber = 10___543__245_123.500_241;

Ref locals

Vielen C#-Entwicklern dürfte ref von Methoden-Parametern bekannt vorkommen. Durch dieses Keyword können Parameter als Referenz statt als Wert an eine Methode übergeben werden.

Ref locals ermöglicht es nun, eine Referenz auf eine Variable zu deklarieren. Wird die lokale Referenz angepasst, so verändert sich damit auch der Ursprungswert. Ref locals ergeben alleine wenig Sinn, mit dem nächsten Feature in der Liste (ref returns) wird der Anwendungsfall hierfür deutlich klarer.

Beispiel

int var1 = 5;
ref int refVar = ref var1;
refVar = 15; // var = 15

int var2 = 5;
var refVar2 = var2;
refVar2 = 15; // var2 = 5;

Ref returns

Eine Referenz als Parameter übergeben gibt es bereits, was noch fehlt ist als Rückgabewert einer Funktion eine Referenz statt eines Werts zu definieren. Dieses fehlende Feature wird nun auch in C# 7 abgedeckt.

Als Vorteil ergibt sich, dass der Rückgabe nicht kopiert werden muss, sondern eine Referenz zurückgegeben wird. Besonders bei großen Strukturen ergibt sich hier ein großer Performance- und Speichervorteil. Zusätzlich kann der Rückgabewert bearbeitet werden, wodurch sich der Ursprungswert verändert.

Beispiel

ref int Max(ref int x, ref int y)
{
   if (x > y)
      return ref x;
   else
      return ref y;
}

int a = 5;
int b = 10;
ref int max = ref Max(ref a, ref b);
max = 0; // b = 0

Local functions

Lokale Funktionen bieten die Möglichkeit, innerhalb einer Funktion eine weitere Funktion zu definieren. Was heute schon über die Func- und Action-Klassen möglich ist, kann nun auch direkt als lokale Funktion deklariert werden.

Durch die Nutzung von lokalen Funktionen ergeben sich mehrere Vorteile:

  1. ref und out Parameter können nun in lokalen Funktionen verwendet werden
  2. Beim Anlegen einer Action oder Func wird ein Objekt auf dem Heap allokiert. Dies passiert bei einer lokalen Funktion nicht. Diese wird durch den Compiler entweder in eine statische oder in eine Klassen-Methode umgewandelt, je nachdem ob Konstrukte der Klasse verwendet wurden.
  3. Werden Variablen außerhalb der Funktion verwendet (im Beispiel wäre das offsetX), so generiert der C#-Compiler im Falle einer Func oder Action eine separate Klasse mit einem Feld pro verwendeter Variablen. Bei einer lokalen Funktion wird jedoch ein struct, also ein Value Type, generiert. Dadurch wird kein Speicher auf dem Heap benötigt und es gibt auch keine Bedenken bei parallelem Zugriff.

Beispiel

int Compute()
{
   int offsetX = 5;

   var addOffset = new Func<int, int>(x => x + offsetX);
   addOffset(5); // 10

   int AddOffset(int x) => x + offsetX;
   AddOffset(5); // 10
} 

Tuple

Wer mehr als einen Rückgabewert benötigt oder eine Sammlung an Daten erstellen wollte, die zu kurzlebig für eine eigene Klasse sind, musste entweder auf out-Parameter oder eine Tuple-Klasse zurückgreifen.

Die Tuple-Klasse gibt es seit dem .NET Framework 4. In dieser kann eine beliebige Kombination an Daten abgelegt werden. Das Problem an der Tuple-Klasse ist, dass die zugewiesenen Properties keine sprechenden Namen haben. Diese werden mit Item1 bis ItemN abgerufen.

Das Tuple-Feature in C# 7 ermöglicht es nun, benannte Tuples zu erstellen und führt hierzu sogar eine eigenen Syntax ein.

Zu Bedenken gibt es hier nur, dass Tuple kurzlebig und klein sein sollten, da die Syntax den Code doch recht schnell unleserlich macht. Alles andere sollte in eine eigene Klasse oder Struktur ausgelagert werden.

Beispiel

(int count, decimal sum) Compute(IEnumerable<int> items)
{
   var result = new (int count, decimal sum) { count = 0, sum = 0 };
   foreach (var item in items)
   {
      result.count++;
      result.sum += item;
   }
}

(int c, decimal s) x = Compute(new[] { 1, 2, 3, 4, 5 });
Console.WriteLine($"count = {c}, sum = {x.s}"); // count = 5, sum = 15

Out Parameter

Wer eine Funktion mit Out-Parametern verwendet (das beste Beispiel ist die TryParse-Methode), der musste sich zuerst mit einer Variablendeklaration herumschlagen, bevor man die Funktion verwenden konnte. Doch C# 7 bietet nun Abhilfe, indem man diese Variablendeklaration direkt mit dem Out-Parameter verbinden kann.

Beispiel

if (int.TryParse("500", out int cost))
   Console.WriteLine(cost); // 500

Persönlich freue ich mich bereits auf Features wie Local Functions, Tuples und Out Parameter, da der Anwendungsfall hierfür doch recht häufig vorkommt. Die anderen Features sind zwar nicht unwichtig, hier ist die Häufigkeit der Anwendung aber eher gering.

Im nächsten Teil soll auf die weiteren Feature wie Pattern Matching, Throw Expressions, Expression bodied members und Generalized async return types eingegangen werden. Da sich Visual Studio zum Zeitpunkt des Blogpost noch in der RC-Version befindet, können unter Umständen bestimmte C# 7 Features nicht in der finalen Version enthalten sein.

Marco Scheel: Links for 2017-01-14 [del.icio.us]

Alexander Schmidt: WPF und MVVM richtig einsetzen – Teil 4

Converter und Messenger

Marco Scheel: Links for 2017-01-12 [del.icio.us]

  • Microsoft Office 365 Activation Hassles « Tim Anderson's ITWriting
    Imagine you are a customer of Microsoft’s Office 365 service, including a subscription to the Office desktop applications like Word, Excel and Outlook. One day you click on the shortcut for Word, but instead of opening, it just shows a “Starting” splash screen which never progresses. via Pocket
  • Updating File Management for SharePoint Modern Doc... - Microsoft Tech Community
    Continuing our rollout of copying and moving files between SharePoint and OneDrive, we’re announcing the ongoing expansion of this capability to allow copying files within SharePoint Team Sites, from one Team Site to another; from Team Sites back to OneDrive for Business; and from OneDrive for Bu via
  • Dirt Showdown für Steam aktuell kostenlos erhältlich
    Bei Humble Bundle verschenkt man aktuell das Steam-Spiel Dirt Showdown für Windows, MacOS und Linux / SteamOS. via Pocket
  • BigBlue Akku-Handwärmer ausprobiert
    Kurz vor Weihnachten machte sich leichte Panik breit. Das passende Geschenk für die Liebste sollte gefunden werden. Grobes Thema in diesem Jahr: Wärme. Beim Thema Wärme gibt es ja jede Menge Produkte, die man verschenken kann. via Pocket

Marco Scheel: Links for 2017-01-11 [del.icio.us]

Golo Roden: Asynchrone Auftragsverarbeitung in Webdiensten

Eine Message-Queue lässt sich dazu verwenden, Aufgaben an verschiedene Instanzen eines Dienstes zu verteilen. Doch was, wenn man den Aufwand für eine Message-Queue scheut? Wie wäre es, einen solchen Dispatcher stattdessen auf Basis einer Datenbank zu implementieren?

Marco Scheel: Links for 2017-01-10 [del.icio.us]

  • 302 Found
    These are by no means the exhaustive list of items mentioned but you get the gist of the conversation. Hmmm, that table looks pretty much “Even Stevens” to me on functionality yet almost everyone I have spoken to has, a.) Used Yammer, b.) disliked it and c.) will not use it again. via Pocket
  • Twitter
    It's here! Document Generation action for Nintex on-premises. Generate PDFs, PPTs, excel files and more. owl.li/YbxV306XvQj pic.twitter. via Pocket
  • SharePoint Server 2016 patching using side-by-side functionality explained - Stefan Goßner
    The nature of zero downtime patching is that - during patching - some servers in the farm are already on a higher patch level while other servers are still on the previous patch level. via Pocket
  • 302 Found
    Microsoft Teams is currently still in Preview, but it was announced that it will be generally available by the end of Q1 2017. Microsoft Teams is available in the Office 365 Premium and Essentials (no Office install) plans. via Pocket
  • Modern Workplace Webcast
    In this episode, learn how to improve collaboration and communication in multi-generational teams. via Pocket
  • Azure AD Connect: Single Sign-on | Microsoft Docs
    Single sign on is an option that can be enabled in Azure Active Directory Connect with either Password hash synchronization or Pass-through authentication. via Pocket

Marco Scheel: Links for 2017-01-09 [del.icio.us]

Karsten Kempe: Screencast: Visual Studio – Effizienz auf allen Plattformen

Ich möchte mal wieder eine Aufzeichnung mit Euch teilen, die auf dem Microsoft Technical Summit 2016 in Darmstadt entstanden ist. Dort habe ich gemeinsam mit meinem geschätzten Kollegen Daniel Meixner über die Neuerungen in der Visual Studio Produktfamilie gesprochen. Visual Studio 2017, Visual Studio for Mac, Team Foundation Server 2017 und viele, viele Features…

MSDN Team Blog AT [MS]: Was Vornamen über uns verraten – Eine Spurensuche in Azure Machine Learning Studio

Wer bereits in irgendeiner Art und Weise mit Online-Formularen zu tun gehabt hat, kennt vielleicht die Situation: Sobald Daten abgefragt werden, die nicht unmittelbar verifiziert werden, geben User oftmals falsche Informationen ein. Aus Sicht der Benutzer verständlich, ist doch ein Formular meist nur lästiges Mittel zum Zweck um zum eigentlich gewünschten Ergebnis zu kommen, aus Sicht des Bearbeiters hinter dem Schreibtisch jedoch ärgerlich, immerhin hat dieser oftmals einen konkreten Grund warum er gewisse Daten abfragt, der durch falschen Input torpediert wird. Während eMail-Adressen noch relativ leicht verifiziert werden können, ist dies bei Adressen bereits schwieriger, ist doch eine (laufend zu aktualisierende) Adressdatenbank notwendig die – möchte man seinen Dienst oder sein Produkt global zur Verfügung stellen – noch dazu für viele Länder funktionieren muss. Ganz verzichtet wird bei den meisten Online-Services auf eine Prüfung des Vornamens, immerhin existieren derart viele verschiedene Namen in unterschiedlichen Schreibweisen, dass es relativ aufwendig ist, eine Namensdatenbank zu erstellen und zu warten, speziell, wenn sie global ausgelegt ist.

Wenn konventionelle Methoden nicht weiterhelfen, wird schnell der Ruf nach einer der aktuell stark forcierten Lieblingsproblemlösungsmethode der IT laut: Machine Learning! Die Frage die sich stellt ist: Lassen sich mit Machine Learning gewisse Strukturen in Namen erlernen, sodass es dem Computer möglich ist, zwischen einem konventionellen Vornamen und zufällig zusammengewürfelten Zeichenketten zu unterscheiden? Kann man auch einen Schritt weitergehen und eventuell noch mehr Informationen aus einem Vornamen lesen, etwa ob dieser eher Männern oder Frauen zugeordnet wird, aus welchem Sprachraum er stammt und ob sein Träger möglicherweise älter oder jünger ist? Die Antwort vorweg: Man kann (bis zu einem gewissen Grad) und mit Azure Machine Learning Studio geht das auch relativ schnell und unkompliziert.

Modelle trainieren und auswerten

Die Demo eines in Azure Machine Learning Studio implementierten “Name Analyzer” gibt es hier: http://inqubu.com/nameanalyzer. Das Frontend wurde in Visual Studio 2015 mit AngularJS,  jQuery und C3.js entwickelt, das Backend basiert auf Azure API Management (um CORS-Probleme zu verhindern) und die als Webservice zur Verfügung gestellten, in Azure Machine Learning Studio trainierten Modelle.

nameanalyzer

Gibt man einen Vornamen in das Suchfeld ein und drückt “Analyze”, wird eine REST-API aufgerufen, die Wahrscheinlichkeiten dafür zurückgibt, ob der Name real oder erfunden ist, ob er eher männlich oder weiblich ist und ob er aus dem deutschen, englischen, italienischen, französischen, iberischen, slawischen, arabischen, afrikanischen oder asiatischem Raum stammen könnte. Die Modelle für diese Vorhersage können sehr schnell und einfach in Azure Machine Learning Studio erstellt werden. Azure Machine Learning Studio (AMLS) ist eine Drag&Drop-Oberfläche, über die Daten hochgeladen, Modelle trainiert und daraus REST-Webservices erstellt werden können. Es ist erstaunlich wenig Aufwand notwendig um vorherzusagen, ob ein Name männlich oder weiblich ist, folgender Ablauf genügt dazu:

mls_screenshot

Das Experiment besteht aus mehreren miteinander verbundenen Modulen. An der Spitze sieht man eine direkt in AMLS hochgeladene CSV-Datei, die Namen als unabhängig und das Geschlecht (m,f) als abhängig Variable beinhaltet (einen Namensdatensatz um die Demo nachbauen zu können gibt es hier). Im nächsten Modul wird ein Python-Script ausgeführt, das die Namen in einzelne Buchstaben aufspaltet und auf eine Länge von maximal 10 normiert. Der Input, um unser Modell zu trainieren sieht damit wie folgt aus:

mls_names

Wie man sieht, beinhaltet die Eingabe nur kategoriale Variablen. Das limitiert in gewisser Weise die Modelle, die für das Training verwenden können. Es gäbe die Möglichkeit, den Input numerisch zu kodieren um die Namen auch für zB Neuronale Netze verwertbar zu machen (eine der einfachsten Methoden dazu wäre One-Hot encoding), allerdings versuchen wir das Modell bewusst einfach und verständlich zu halten und wählen daher Two-class Boosted Decision Trees als Trainingsmethode. Das Grundprinzip hinter Decision Trees ist, dass aus den Eingabedaten ein Baum erstellt wird, der von der Wurzel beginnend durchlaufen wird und eine Vielzahl an Verzweigungen beinhaltet. An jeder Verzweigung (split) wird eine Frage gestellt (zB.: Ist der erste Buchstabe ein A?) und entsprechend der Antwort folgt man der passenden Verzweigung bis man an einen “Blattknoten” (leaf node) gelangt – der Blattknoten beinhaltet die Klassifizierung (also zB.: Name ist männlich).
Bei “Boosted Decision Trees” wird nun nicht nur ein Baum sondern mehrere erstellt, wobei zunächst der erste Baum durchlaufen und überprüft wird, ob die Vorhersage korrekt ist (ob also weibliche Namen tatsächlich als weiblich vorhergesagt werden). Liegt der Baum falsch, wird ein zweiter Baum durchlaufen, der die Fehler des vorherigen Baums korrigiert. Der Clou ist, dass die Trainingsdaten derart modifiziert werden, sodass die Attribute, die im vorherigen Baum zu einer falschen Klassifizierung geführt haben, im nächsten Baum stärker gewichtet werden (das ist übrigens der Unterschied zu “Decision Forrests” bei der mehrere Bäume unabhängig voneinander eine Vorhersage angeben und der gewichtete Durchschnitt aller Bäume als Resultat zurückgegeben wird). Man kann in AMLS übrigens praktisch alle Ausgaben visualisieren, indem man auf den Output-Knoten klickt und “Visualize” auswählt – so lässt sich verdeutlichen, wie unser Baum tatsächlich aussieht.

 

mls_visualizemls_treeDas vorletzte Modul “Score Model” verlangt als Input ein trainiertes Modell und Testdaten. Testdaten sind genauso strukturiert wie unsere Trainingsdaten, beinhaltet aber andere Namen. Der Sinn dahinter ist, dass man feststellen möchte, wie gut das Modell das Geschlecht von Namen vorhersagt, die es zuvor noch nie gesehen hat (genau das zeichnet Machine Learning aus). Würde unser Modell sehr gut für unsere Trainingsdaten aber nicht für andere Namen funktionieren, spricht man von “overfitting” (auch “overtraining” genannt) – das Modell passt sich also zu genau an die Struktur der Trainingsdaten an, generalisiert aber nicht. Insbesondere Decision Trees neigen zu “overfitting” – um das zu verhindern, gibt es verschiedene Techniken die je nach Machine Learning Methode unterschiedlich sind. Bei Entscheidungsbäumen kann man zB die Tiefe des Baumes (vom Wurzel- bis zum Blattknoten) einschränken – das verhindert, dass unser Baum zu detailliert wird, hat aber den Nachteil, dass die Vorhersagegenauigkeit (“accuracy”) sinkt. In AMLS stehen für jedes Modell eine Vielzahl an Parameter zur Verfügung, die man abändern kann um die Güte des Modells zu erhöhen, man spricht hierbei auch von “Hyperparameter Optimization”.

Das letzte Modul beinhaltet schließlich die Evaluierung. Hier wird visualisiert, wie “gut” unser Modell ist, wie genau also die Vorhersagen getroffen werden.

mls_evaluation

Eine beliebte Evaluierungsvisualisierung binärer Klassifizierungsprobleme ist eine ROC-Kurve (Receiver Operating Characteristic). Die ROC-Kurve stellt die vom Decision Tree richtig klassifizierten Daten (True Positive Rate) den falsch klassifizierten (False Positive Rate) gegenüber. Liegt unsere Kurve genau auf der grau eingezeichneten Diagonalen, bedeutet das, dass unser Modell für jeden richtig klassifizierten Namen auch jeweils einen falsch klassifiziert hat – das entspricht also einer Trefferquote von 50% und ist damit nicht besser als Zufall. Unser Modell ist etwas klüger: Steigert man die True Positive Rate (geht man also auf der Kurve von links unten nach oben), steigt zwar auch die Anzahl der falsch klassifizierten Namen, jedoch bedeutend langsamer als die Anzahl der richtig zugeordneten Daten. Unser Geschlechtsklassifikator hat 373 unserer Männernamen aus den Testdaten korrekt als männlich eingestuft und 365 korrekt als weiblich. 97 Namen wurden als Männernamen eingestuft obwohl sie Frauennamen sind, 70 als Frauennamen obwohl sie männlich sind, das entspricht einer Genauigkeit (“Accuracy“) von 81,5%: (373+365)/(373+70+97+365). “Precision” gibt an, wie viele der vom Modell als “männlich” identifizierten Namen auch tatsächlich männlich sind, nämlich 373/(373+97) = 79,4%. “Recall” stellt die richtig als männlich eingestuften Namen den insgesamt vorhandenen männlichen Namen gegenüber: 373/(373+70) = 84,2%. Der “F1 Score” schlussendlich ist das Harmonische Mittel aus Precision und Recall. Es errechnet sich aus 2*Precision*Recall/(Precision + Recall) und entspricht in unserem Beispiel daher 2*0,842*0,794/(0,842+0,794) = 81,7%.

Generell gilt, dass jedes Modell nur so gut ist wie die zugrunde liegenden Daten. Für das Training des “Name Analyzer” wurden insgesamt rund 5.000 verschiedene Namen verwendet – und hierbei nicht aus jedem Kulturkreis. Indische Namen etwa fehlen gänzlich, weshalb zum Beispiel der Name “Satya” als “weiblich” klassifiziert wird. Der Modell hat durch viele Namen aus dem deutschen, italienischen oder spanischen Sprachraum gelernt, dass Namen, die auf “a” enden sehr oft weiblich sind. Wie der Entscheidungsbaum klassifiziert, lässt sich klar verdeutlichen, wenn man den Namen “Donald” eingibt – dieser wird richtigerweise als männlich und aus dem englischen Raum kommend eingestuft. Ändert man den Namen zu “Donaldo”, wird dieser als männlich und “Iberisch” klassifiziert. Ändert man ihn abermals auf “Donalda” ab, ändert sich das Geschlecht auf weiblich, der Sprachraum auf Englisch. Offensichtlich ist die Endung “o” nicht nur stark ausschlaggebend für die männliche Klassierung sondern auch für den Herkunftsraum (es gibt deutlich mehr Namen die auf “o” enden in Spanien oder Portugal als im angloamerikanischen Raum) während die Endung “a” vom Modell im Hinblick auf die Herkunft als wenige relevant erachtet wird, weshalb die ursprüngliche Zuordnung (Donald = Englisch) beibehalten wird.

Vom Modell zum Webservice

Ein Modell in AMLS ist schön und gut, praktisch nützlich ist es aber nur, wenn wir es auch direkt in einer Applikation verwenden können. Glücklicherweise nimmt uns AMLS einen großen Teil der Arbeit an, denn mit einem Klick auf “Set up as webservice” in der unteren Menüleiste kann aus dem Experiment sehr schnell ein Webservice generiert werden ohne selbst ein Backend schreiben zu müssen. AMLS generiert dazu nicht nur eine API sondern stellt auch gleich Beispielcode in C#, Python und R bereit.

mls_restapi

Etwas komplizierter wird die Sache, wenn man via JavaScript die API nutzen möchte, hier verhindert die Same-Origin-Policy den direkten Zugriff. Da das Backend von Azure verwaltet wird und man daher keinen direkten Zugriff auf den Access-Control-Allow-Origin response headers hat, muss man den Umweg via Azure API Management nehmen. Dieses Video von Josh Twist erklärt kurz und bündig, wie hier vorzugehen ist.

Abschließend ist zu erwähnen, dass auch Machine Learning kein Allheilmittel zur Eingabevalidierung ist. Zwar würde unser Modell verhindern, dass Zeichenketten wie “usfdiwb” oder “Vogelhaus” als Vornamen durchgehen, wenn sich ein User namens Peter allerdings als Michael ausgibt, würde die Fake-Name-Erkennung logischerweise nicht anschlagen. Nicht zu unterschätzen ist jedoch die Außenwirkung eines solchen Services, zeigt sie doch dem User, dass das Unternehmen offensichtlich innovative Technologien einsetzt um ihre Dienste “smart” zu machen. Vorsicht und ein gewisser Toleranzspielraum ist dennoch geboten, ein als falsch klassifizierter richtiger Name könnte Benutzer unnötigerweise vergraulen – hier sollte jedenfalls mehr Zeit aufgewendet werden um False-Positives des Modells möglichst gering zu halten.
Durchwegs interessant könnte auch die nachträgliche automatisierte Geschlechter-Klassifizierung in einer Datenbank sein, wenn zwar die Vornamen, nicht aber das Geschlecht erhoben wurden. Typischerweise würde man hier einen “confidence threshold” definieren, ab der die Klassifizierung automatisch stattfindet (zB 90%). Ist die “confidence” für einen Namen zu gering (das Modell sich also zu unsicher) wird der Name entweder nicht klassifiziert oder zu manuellen Bearbeitung weitergeleitet.

Marco Scheel: Links for 2017-01-08 [del.icio.us]

  • Dependency Injection with .NET Core - csharp.christiannagel.com
    Dependency injection is built-in with .NET Core. Microsoft.Extensions.DependencyInjection is a framework that is an essential part for ASP.NET Core, but can be used with other application types such as console applications, WPF, UWP, and also Xamarin. via Pocket

Marco Scheel: Links for 2017-01-07 [del.icio.us]

MSDN Team Blog AT [MS]: Ist Geek the new Sexy?

Die Zeit rast vorbei und schon wieder ist das neue Jahr ein paar Tage alt. Damit sind es nur noch zwei Wochen bis zur nächsten Microsoft Tech Conference.

Das folgende trifft auf Euch zu?

  • Ihr liebt die neuesten Technologien?
  • Ihr wünscht Euch technische Vorträge?
  • Marketing Slides findet Ihr zwar schön aber viel lieber seht Ihr Live-Demos?
  • Ihr seid auf der Suche nach qualitativen Updates zu einem Weihnachtlichen-Spezial-Preis?

Ihr sagt JA, JA, JA und nochmals JA?

Dann meldet Euch  jetzt an zur:

Microsoft Tech Conference

Jetzt heißt es also schnell handeln um sich noch eines der begehrten Tickets zu sichern! Am 19. Jänner ist es zu spät!

Die Trainer- und Vortragenden rund um die Tech Conf haben sich auf jeden Fall schon mal eingegrooved und arbeiten für Euch an mehreren Dutzend Vorträgen von Windows Server 2016 bis hin zu Sharepoint 2016 und Office 365!

Für IT-Professionals und Infrastruktur-Experten stehen Vorträge und Hands-on Trainings zu Themen wie Industrialisierung 4.0, Windows Server 2016, Security, Exchange 2016, Skype4Business, Mobility Management, SharePoint 2016 in der Agenda – und natürlich beleuchten wir auch Chancen und Möglichkeiten von Lösungen in den Bereichen Public-Private-Hybrid Cloud, Microsoft Azure, Office 365, System Center, Big Data, SQL Server und mehr.

Software-Entwickler werden hingegen mit Sessions zu Themen wie .NET, ASP.NET, Azure Development und SharePoint voll auf ihre Kosten kommen.

Die einzelnen Sessions findet Ihr auf www.techconference.at

Die Microsoft Tech Conference bietet Euch den perfekten Start in das neue Jahr. Zum Preis von nur € 399.- erhaltet Ihr perfekte Tech Sessions zum absoluten Senationspreis! Also schnell anmelden bevor alle Plätze weg sind!

MSDN Team Blog AT [MS]: Dynamics 365 Trainings

dynamics-365-business-apps-in-the-cloud-1024x557Die Microsoft Partner wachsen immer mehr zusammen und es kommen verhäuft Anfragen zu Dynamics 365 und AppSource. AppSource ist ein Online Store mit verschiedenen Lösungen die speziell für Ihre Branche entwickelt wurden und mit den Produkten eingesetzt werden können, die Sie bereits nutzen, beispielsweise mit Microsoft Azure, Dynamics 365, Power BI und/oder Office 365.

Lesen Sie hier mehr über AppSource.

Wir bieten daher nun auch Technische Presales- und Bereitstellungsdienste für diverse Dynamics 365 Trainings ab Jänner bis Juni 2017 an.

Hier ein übersichtlicher One-Pager und eine Detailsicht über die Einführungskurse, laufenden Services & Advanced Workloads für Dynamics 365 Trainingsmöglichkeiten:

MSDN Team Blog AT [MS]: Wie Du gratis die Microsoft Build 2017 sehen kannst

Gerwald hat ja schon Anfang Dezember geschrieben, dass die Microsoft Build 2017 heuer vom 10. bis 12 Mai in Seattle stattfinden wird.

Noch hat der  Kartenverkauf nicht begonnen, aber ich bin mir sicher dass die Build auch heuer wieder rasend schnell ausverkauft sein wird. Die Hotels vor Ort füllen sich auf jeden Fall schon.,

Für alle die nicht persönlich zur Build fliegen können bringen wir daher die Build nach Österreich. Es gibt also auch heuer wieder die Möglichkeit in Österreich quasi live dabei zu sein

Komm doch auch Du zu einem unserer beliebten Keynotestreamings!!

Die Teilnahme ist kostenlos. Daher melde Dich noch heute an, denn auch hier sind die Plätze begrenzt!

Und für alle die es schon gar nicht mehr bis zur Build erwarten können: Hier noch ein kleines Video zur Einstimmung:

Viel Spaß!!

PS: Wer jetzt schon sicher weiß, dass er auf jeden Fall zur Build fliegen möchte schickt mir vor dem 19. Jänner ein E-Mail an Gerhard.Goeschl@Microsoft.com.

MSDN Team Blog AT [MS]: Wie man seine nativen cross-Platform Entwicklungskenntnisse für mobile Betriebssysteme verbessern kann: Die Xamarin Show

In der Xamarin Show geht es um native cross-Platform Entwicklung für mobile Betriebssysteme wie iOS, Android, macOS und Windows und zwar mit Xamarin (no na Smile )

Experten diskutieren regelmäßig wie man mobile Apps baut, SDKs integriert, mobile Apps erweitert, was es an Neuigkeiten zu Xamarin gibt und noch vieles mehr.

Ihr könnt @JamesMontemagno auf Twitter auch Vorschläge für zukünftige Ausgaben der #XamarinShow senden. Was möchtet Ihr denn dort gerne sehen??

Hier ein paar Kostproben:

bzw: The Xamarin Show 8- Microsoft Graph with Simon Jäger

 

Bei dieser Gelegenheit sei auch nochmals auf die Xamarin Webcast Serie vom Sommer verwiesen.

Neben den “normalen” Ausgaben der Xamarin Show, gibt es mit den Snack Packs auch kurze 10 Minuten Videos zum “drüberstreuen”:

Hier noch ein paar weiterführende Links:

Apropos DevOps: Am 25 und 26. Jänner findet bei Microsoft Österreich ein kostenloses 2 tägiges Mobile DevOps Training statt.

PS: Nur zur Erinnerung: Xamarin ist ohne Zusatzkosten für alle Visual Studio Kunden verfügbar!

Code-Inside Blog: GitHub API: Create or update files

This blogpost covers a pretty basic GitHub topic: Creating and updating content on GitHub. Of course, there are many ways to do it - e.g. you could do the full Git-ceremony and it would work with all Git hosts, but in my case I just wanted to target the offical GitHub API.

Prerequisite: A GitHub User, Repo and Token

To use this code you will need write access to a GitHub repository and you should have a valid GitHub token.

Code

The most simple way to communicate with the GitHub API is by using the Octokit SDK (from GitHub).

Description: Inside the try-block we try to get the target file, if it is already committed in the repo the API will return the last commit SHA.

With this SHA it is possible to create a new commit to do the actual update.

If the file was not found, we create the file. I’m not a huge fan of this try/catch block, but didn’t found any other way to check if the file is comitted or not (please give me a hint if this is wrong ;))

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Octokit;

namespace CreateOrUpdateGitHubFile
{
    class Program
    {
        static void Main(string[] args)
        {
            Task.Run(async () =>
            {
                var ghClient = new GitHubClient(new ProductHeaderValue("Octokit-Test"));
                ghClient.Credentials = new Credentials("ACCESS-TOKEN");

                // github variables
                var owner = "OWNER";
                var repo = "REPO";
                var branch = "BRANCH";

                var targetFile = "_data/test.txt";

                try
                {
                    // try to get the file (and with the file the last commit sha)
                    var existingFile = await ghClient.Repository.Content.GetAllContentsByRef(owner, repo, targetFile, branch);

                    // update the file
                    var updateChangeSet = await ghClient.Repository.Content.UpdateFile(owner, repo, targetFile,
                       new UpdateFileRequest("API File update", "Hello Universe! " + DateTime.UtcNow, existingFile.First().Sha, branch));
                }
                catch (Octokit.NotFoundException)
                {
                    // if file is not found, create it
                    var createChangeSet = await ghClient.Repository.Content.CreateFile(owner,repo, targetFile, new CreateFileRequest("API File creation", "Hello Universe! " + DateTime.UtcNow, branch));
                }

                
                
            }).Wait();
        }
    }
}

The demo code is also available on GitHub.

Hope this helps.

MSDN Team Blog AT [MS]: MIT DER CLOUD IN DIE ZUKUNFT

isv-go-bigDie Vorteile der Cloud wurden in anerkannten Studien deutlich bewiesen. Für viele Firmen sind heutzutage Faktoren wie Skalierbarkeit, Kostenersparnis, regelmäßige Sicherung der Daten, Mobilität und vieles mehr wichtig, um eine wettbewerbsfähige Position am Markt zu erlangen und diese dann auch langfristig zu behalten.

Wir möchten Sie herzlichst dazu einladen diese Vorteile zu erfahren und mit uns gemeinsam verschiedene Einsatzszenarien in der Cloud zu besprechen. Wenn Sie als Unternehmen Anwendungen entwickelt haben, die Cloud-fähig gemacht werden sollen, bieten wir Ihnen die folgenden kostenlosen Möglichkeiten an:

 

    1. Mit der Cloud in die Zukunft-Workshop
      Datum: 23. Februar 2017
      Zeit: 9:00 bis 12:30 Uhr
      Ort: Microsoft Office, Am Euro Platz 3, 1120 Wien

      In diesem Vortrag zeigen wir Ihnen, wie Sie mit der Cloud ihr eigenes Business aufbauen können. Wir stellen Ihnen Microsoft Azure als Cloud Plattform für die digitale Transformation vor. Hierbei zeigen wir anhand von praktischen Beispielen wie Microsoft Azure Ihnen hilft Ihre Anwendungen noch innovativer zu gestalten. Gleichzeitig behalten ISVs (Independent Software Vendors) und Softwarehersteller weiterhin Offenheit in ihren Entwicklungsentscheidungen und gewinnen zusätzlich an Sicherheit.

    2. Technische Beratung mit einem Cloud Experten
      Datum: nach Vereinbarung mit dem Experten
      Zeit/Dauer: 1 Stunde
      Ort: Microsoft Office Wien oder Skype Call

      Besprechen Sie die Möglichkeiten mit einem unserer technischen Cloud Experten Ihre Anwendung in die Cloud zu migrieren. Diese Beratung ist für kleinere Applikationen angedacht.

    3. Acceleration Lab
      Datum: 28.02. + 01.03., 28. + 29.03., 16. + 17.05.2017
      Zeit: 2 Tage, jeweils von 9:00 bis 17:30 Uhr
      Ort: Microsoft Office, Am Euro Platz 3, 1120 Wien

      Nutzen Sie die Expertise unserer technischen Spezialisten um gemeinsam mit Ihren Entwicklern in einem dieser Workshops Ihre Proof of Concept Applikation in die Cloud zu heben. Nach den 2 Tagen haben Sie erste Hands-On Erfahrung mit Microsoft Azure und einen besseren Einblick den Aufwand für eine vollständige Migration Ihrer Applikation zu schätzen. Diese Workshops eignen sich am Besten für Unternehmen mit größeren Applikationen.

 

Wenn Sie Ihr Business in die Microsoft Cloud bringen wollen, bewerben Sie sich jetzt bei uns für die genannten Möglichkeiten. Beschreiben Sie Ihre Lösung kurz und bündig in einem E-Mail und senden Sie diese an die folgende Adresse: ISVat@microsoft.com. Die Teilnehmeranzahl ist limitiert. Wir wählen anhand der Applikationsbeschreibungen aus und geben sobald wie möglich Bescheid.

Holger Sirtl: Azure News on Friday – in eigener Sache

In den vergangenen Jahren gab es hier regelmäßig zum Wochenende Neuigkeiten zu Microsoft Azure. Die große Leserzahl und positive Resonanz haben mich immer gefreut. Nachdem ich zur Erstellung der News leider noch keine automatisierten Prozess aufsetzen konnte, waren nach dem zunehmenden Innovationstempo bei Azure die Aufwände zur Erstellung der Nachrichtenseite doch deutlich gestiegen. Da ich den erforderlichen Zeitaufwand nicht mehr erbringen kann, habe ich beschlossen, mit dem neuen Jahr die Serie einzustellen.

Für Azure-Interessierte gibt es allerdings eine sehr gute Alternative, um sich mit Neuigkeiten, Infos zu Videos, Whitepapers und Tools rund um Azure zu versorgen: den

Azure InfoHub

Dieser listet in deutlich höherer Frequenz alles Neue und Wissenswerte zu Azure, zudem Links zu Videos usw. auf. Letztlich war dieser auch Basis für meine wöchentlichen News-Posts.

Über konstruktives Feedback, Ideen und Wünsche zu weiteren Inhalten freue ich mich natürlich.

Norbert Eder: Ziele 2017

Ich finde es wichtig, Ziele zu haben, an denen man arbeitet. Nach meinem Rückblick 2016 werde ich in diesem Beitrag meine Ziele für 2017 grob beschreiben. Diese Ziele setze ich mir privat, beruflich führe ich eine eigene Liste.

  • In der Softwareentwicklung werden im kommenden Jahr wohl die Themen IoT und große Datenmengen recht interessant. Generell möchte ich auch wieder mehr über Softwareentwicklung bloggen, besonders mit Code. Ich überlege auch, den einen oder anderen Fachartikel zu schreiben.
  • In der Fotografie möchte ich weiteres Know-how beim Portrait-Shooten und der nachfolgenden Bearbeitung aufbauen. Dazu bedarf es einer Verbesserung im Umgang mit Adobe Lightroom und ordentliche Grundlagen mit Adobe Photoshop. Wenn es sich irgendwie ausgeht, möchte ich gerne den einen oder anderen Workshop, zur Vertiefung in ausgesuchten Themenbereichen, besuchen.
  • Die Website hat bereits einen neuen Anstrich erhalten, will aber noch weiter verbessert werden. Generell möchte ich den neun Bereich Unterwegs aufmotzen. Darin werden Berichte von Städten, deren Sehenswürdigkeiten und von Lokalen und Restaurants zu sehen sein. Eventuell auch die eine oder andere kulinarische Empfehlung.
  • Sportlich möchte ich natürlich eine Steigerung erreichen. Das Mindeste ist ein Gleichbleiben der Aktivitäten.
  • Auch 2017 sollen wieder einige Fachbücher zur persönlichen Weiterbildung gelesen werden. Mehr als 2016.

Welche Ziele nimmst du dir für das kommende Jahr vor?

The post Ziele 2017 appeared first on Norbert Eder.

Code-Inside Blog: DbProviderFactories: Write database agnostic ADO.NET code

Recently I needed to write a module that needs to connect to a wide range of SQL-DBs, e.g. MySQL, MS SQL, Oracle etc.

Problem: Most providers will use their concret classes

If you look at the C# example on the MySQL dev page you will see the MsSql-Namespace and classes:

MySql.Data.MySqlClient.MySqlConnection conn;
string myConnectionString;

myConnectionString = "server=127.0.0.1;uid=root;" +
    "pwd=12345;database=test;";

try
{
    conn = new MySql.Data.MySqlClient.MySqlConnection();
    conn.ConnectionString = myConnectionString;
    conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show(ex.Message);
}

The same classes will probably not work for a MS SQL database.

“Solution”: Use the DbProviderFactories

For example if you install the MySql-NuGet package you will also get this little enhancement to you app.config:

<system.data>
  <DbProviderFactories>
    <remove invariant="MySql.Data.MySqlClient" />
    <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
  </DbProviderFactories>
</system.data>

Now we can get a reference to the MySql client via the DbProviderFactories:

using System;
using System.Data;
using System.Data.Common;

namespace DbProviderFactoryStuff
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("All registered DbProviderFactories:");
                var allFactoryClasses = DbProviderFactories.GetFactoryClasses();

                foreach (DataRow row in allFactoryClasses.Rows)
                {
                    Console.WriteLine(row[0] + ": " + row[2]);
                }

                Console.WriteLine();
                Console.WriteLine("Try to access a MySql DB:");

                DbProviderFactory dbf = DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
                using (DbConnection dbcn = dbf.CreateConnection())
                {
                    dbcn.ConnectionString = "Server=localhost;Database=testdb;Uid=root;Pwd=Pass1word;";
                    dbcn.Open();
                    using (DbCommand dbcmd = dbcn.CreateCommand())
                    {
                        dbcmd.CommandType = CommandType.Text;
                        dbcmd.CommandText = "SHOW TABLES;";

                        // parameter...
                        //var foo = dbcmd.CreateParameter();
                        //foo.ParameterName = "...";
                        //foo.Value = "...";

                        using (DbDataReader dbrdr = dbcmd.ExecuteReader())
                        {
                            while (dbrdr.Read())
                            {
                                Console.WriteLine(dbrdr[0]);
                            }
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
            }

            Console.ReadLine();

        }
    }
}

The most important line is this one:

DbProviderFactory dbf = DbProviderFactories.GetFactory("MySql.Data.MySqlClient");

Now with the DbProviderFactory from the MySql client we can access the MySql database without using any MySql-specific classes.

There are a couple of “in-built” db providers registered, like the MS SQL provider or ODBC stuff.

The above code will output something like this:

All registered DbProviderFactories:
Odbc Data Provider: System.Data.Odbc
OleDb Data Provider: System.Data.OleDb
OracleClient Data Provider: System.Data.OracleClient
SqlClient Data Provider: System.Data.SqlClient
Microsoft SQL Server Compact Data Provider 4.0: System.Data.SqlServerCe.4.0
MySQL Data Provider: MySql.Data.MySqlClient

Other solutions

Of course there are other solutions - some OR-Mapper like the EntityFramework have a provider model which might also work, but this one here is a pretty basic approach.

SQL Commands

The tricky bit here is that you need to make sure that your SQL commands work on your database - this is not a silver bullet, it just lets you connect and execute SQL commands to any ‘registered’ database.

The full demo code is also available on GitHub.

Hope this helps.

Fabian Deitelhoff: WordPress MIME Typen anpassen

In einer Standard-Installation von WordPress gibt es die Möglichkeit, verschiedene Dateitypen hochzuladen. Welche Dateitypen das sind, wird in WordPress durch einen Filter geregelt. Häufig reichen die vorgegebenen Dateitypen aber nicht aus. So war es vor einiger Zeit auf diesem Blog, da ich auch Dateien des LEGO Mindstorms Education EV3 hochladen möchte, die WordPress in der Standard-Konfiguration natürlich nicht kennt. Erfreulicherweise ist das Anpassen dieser sogenannten MIME Typen sehr einfach.

MIME Typen hinzufügen

Der Filter trägt den Namen upload_mimes und kann durch eine eigene Funktion erweitert werden. Diese Funktion wird anschließend immer dann aufgerufen, wenn eine Datei hochgeladen wird und WordPress ermitteln möchte, welche MIME Typen unterstützt werden. Das folgende Listing zeigt die Funktion, wie ich sie auch in diesem Blog im Einsatz habe.

add_filter('upload_mimes', 'add_custom_mime_types');

function add_custom_mime_types($mimes){
    return array_merge($mimes,array (
        'ev3b' => 'application/octet-stream',
        'ev3'  => 'application/octet-stream'
    ));
}

Hinzugefügt wird ein Filter mit der zugehörigen Funktion add_custom_mime_types. Diese Funktion bekommt mit dem Parameter $mimes die aktuellen schon vorhandenen MIME Typen reingereicht. Das ermöglicht es uns, die vorhandenen MIME Typen um eigene zu erweitern, ohne bei jedem Aufruf eigenhändig eine vollständige Liste aufbauen zu müssen, die auch die eigentlich schon bekannten MIME Typen erneut enthält. Durch das Listing werden also nur die Dateiendungen ev3b und ev3 hinzugefügt.

Diese Funktion muss in die Datei functions.php eures aktiven Designs (Themes). Ich habe mir angewöhnt, für solche Zwecke eine zusätzliche Datei zu erstellen, in denen diese Anpassungen gespeichert sind. In nennen die Datei Erweiterungen bzw. Englisch extensions.php.

MIME Typ herausfinden

Es gibt zahlreiche Tools, um den MIME Typ einer Datei herauszufinden. Das ist nützlich, wenn nicht ganz klar ist, welcher Typ zu welcher Datei gehört. Ich nutze häufig Online-Tools wie zum Beispiel http://mime.ritey.com/. Dort können Dateien hochgeladen werden und die Webseite zeigt den MIME Typ an. Natürlich sind solche Online-Tools nur dann sinnvoll, wenn die hochgeladenen Dateien nicht sicherheitskritisch oder sonstwie relevant sind, da natürlich nicht klar ist, was auf der Gegenseite nach der Prüfung mit der Datei passiert.

Auf diese Weise lassen sich schnell und unkompliziert die erlaubten MIME Typen der aktuellen WordPress-Installation erweitern. Unter Umständen kann es auch sein, dass euer eingesetzten Design (Theme) eine Funktion bereithält, mit der diese MIME Typen komfortabel über eine Oberfläche konfiguriert werden können. Dann entfällt der oben gezeigte manuelle Aufwand.

Norbert Eder: WordPress Debug-Mode aktivieren

Oft kommt es ja nicht vor, dass WordPress einen 500 Internal Server Error liefert. Wenn dann aber mal doch, dann bricht der Stress aus. Wo liegt ein Logfile? Was ist schief gegangen?

Trial and Error

In den meisten Fällen ist ein Plugin dran Schuld, gerne in Verbindung mit einem Caching. Viele Seiten im Internet raten daher, für Testzwecke, den Plugin-Ordner umzubenennen. Auch Anleitungen, wie man Plugin für Plugin durchtesten kann, welches nun das böse ist.

Das ist mühsam und dauert natürlich ewig. Das muss schneller gehen.

Debug-Mode aktivieren

Die eindeutig bessere und schnellere Variante ist den Debug-Mode zu aktivieren. Dieser ist standardmäßig deaktiviert, kann jedoch mit folgenden Einträgen in der Datei wp-config.php aktiviert werden:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

Der erste Eintrag ist in der Regel in der wp-config-php schon zu finden. Fehlende Einträge sind zu erweitern.

WP_DEBUG dient generell der (De)Aktivierung des Debug-Modes. Aktiviert man WP_DEBUG_LOG wird ins Verzeichnis wp-content eine Datei namens error.log geschrieben. Hierbei ist darauf zu achten, dass Schreibvorgänge in dieses Verzeichnis erlaubt sind. Mittels WP_DEBUG_DISPLAY kann gesteuert werden, ob Debug-Meldungen via HTML ausgegeben werden sollen.

Damit sollte es in der Regel relativ schnell möglich sein, den Übeltäter zu finden und zu deaktivieren.

The post WordPress Debug-Mode aktivieren appeared first on Norbert Eder.

Norbert Eder: Warum auskommentierter Sourcecode im Source Control nichts zu suchen hat

Wer im Team arbeitet stößt unweigerlich auf auskommentierten Sourcecode. Dieser entsteht aus unterschiedlichsten Gründen. Manchmal wird etwas getestet. Ein anderes Mal bleibt er als Erinnerungsstütze während der Neuimplementierung. Hin und wieder vergisst man den auskommentierten Code schlichtweg zu löschen und manche haben einfach nur Angst davor.

Nichts von all dem rechtfertigt allerdings auskommentierten Code im Source Control. Meinen “Unmut” darüber hatte ich via Twitter kundgetan:

Neben zahlreichen Zustimmungen gab es natürlich auch einige Stimmen, die das überhaupt nicht so sehen und auskommentierten Sourcecode im Source Control als legitimes Mittel während einer Feature- oder Test-Implementierung hinstellen. Genau dazu möchte ich einige Worte loswerden.

Kontext

Zuerst möchte ich allerdings ein wenig Kontext herstellen. Einzelne Entwickler handhaben es gerne so, dass sie ihren täglichen (oder von mir aus auch stündlichen) Stand ins Source Control (eventuell auch als Feature-Branch) committen. Da geht es dann oft um das Thema Backup oder aber einfach nur um den Zugriff von unterschiedlichen Geräten aus. Viele der von mir genannten Punkte mögen für diesen Fall nicht zwingend relevant sein, da ich mich insbesondere auf Entwicklungsteams beziehe. Ebenfalls spreche ich nicht von Repositories in denen POCs oder Tests abgelegt werden, sondern eine RL-Anwendung.

Kommentare in Featurebranches

Natürlich kann man die Arbeit an einem Feature oder das Austesten von unterschiedlichen Varianten als Anlass nehmen, je nach Belieben Sourcecode auszukommentieren und im Source Control zu hinterlegen. Möglicherweise könnte man das sogar damit argumentieren, dass man ja der einzige aus dem Team ist, der damit arbeitet.

Tatsächlich ist das ganz schlechter Stil. Ein Feature (das einen eigenen Feature-Branch verlangt) ist hoffentlich in viele kleine Tasks zerlegt, die einzeln und unabhängig voneinander abgehandelt werden können. Ist ein Punkt umgesetzt bzw. funktionstüchtig, wird aufgeräumt und dann die Änderung an den Server übergeben.

Dabei wird das Aufräumen nicht prokrastiniert, sondern sofort erledigt. Alles was aufgeschoben wird, wird in der Regel nicht erledigt. Man lässt ja auch runter, bevor man das WC verlässt.

Werden unterschiedliche Möglichkeiten getestet, empfiehlt sich, dies in Form eines eigenständigen Tests zu machen. Losgelöst vom eigentlichen Produkt – gerne auch mit eigenen Builds. Das beste Ergebnis wird übernommen – und zwar sauber.

Source Control als Archiv

Wurden auszutauschende Codestellen identifiziert, behelfen sich manche Softwareentwickler, indem dieser auskommentiert und darunter der neue Code geschrieben wird. Der alte bleibt quasi als Gedankenstütze vorhanden. Dagegen ist nichts einzuwenden. Das ist für die eigentliche Implementierung sehr hilfreich, eine Übernahme des auskommentierten Codes ist allerdings wenig zielführend, denn er ist in der Historie ersichtlich und kann auch jederzeit wiederhergestellt werden.

Frühere Implementierungen können im Source Control ausfindig gemacht werden.

Tritt an dieser Stelle ein Problem auf, wird man einen Blick auf die Historie werfen und kann so dieses ausmachen bzw. gegebenenfalls wieder den alten Code aktivieren. Funktioniert alles wie es soll, bedarf es auch des alten Codes nicht mehr.

Appell ans Qualitätsbewusstsein

Natürlich kann es schon mal vorkommen, dass man die eine oder andere Zeile auskommentierten Code vergisst wegzuräumen. Vielleicht ist es manchmal auch wirklich gerade doof und man hat keine Lust nochmals über den Code zu gehen und zu prüfen, ob man die Stellen auch tatsächlich sauber verlässt. Im Endeffekt ist es aber ein Zeichen der Professionalität, dass man genau das tut.

Aufgeräumter Code steht für Professionalität.

Was denken wir denn von anderen Handwerkern, die ihre Behelfe nicht wegräumen oder die Baustelle schlimmer hinterlassen als sie sie aufgefunden haben?

Bewahre die Übersichtlichkeit

Schon mal ein Buch im Laden gekauft, aufgeschlagen und auskommentierte Absätze und dergleichen gefunden? Nein? Genau, das könnte der geneigte Leser niemals flüssig lesen. Innerhalb kürzester Zeit wird das Buch zur Seite gelegt oder zurückgebracht.

Wir Softwareentwickler verbringen die meiste Zeit mit Lesen von Sourcecode. Je leichter uns das gemacht wird und umso weniger uns von den wirklich wichtigen Stellen Code ablenken, desto konzentrierter und produktiver können wir arbeiten. Zudem sinken die Fehlerrate und der Mehraufwand.

Multiplikator Team

Ein Team verstärkt Verhaltensweisen. Das macht auch vor dem Auskommentieren von Sourcecode nicht halt. Wenn dies der Großteil des Teams praktiziert, dann sieht der Source innerhalb kürzester Zeit wie eine Müllhalde aus. Arbeiten macht damit keinen Spaß mehr und statt aufzuräumen werden manche kreativ und verwenden z.B. Regions um das einigermaßen lesbar zu bekommen. Das kann nun wirklich nicht das Ziel sein.

In der Regel gibt es den einen oder anderen im Team, der als unbemerktes Heinzelmännchen jeden auskommentierten Sourcecode wegwirft, damit das nicht vollkommen ausartet.

Es mag durchaus sein, dass die Arbeitsweise einzelner Entwickler auskommentierten Sourcecode im Source Control erlaubt oder sogar erfordert. Im Grunde ist man gewillt ihm das selbst zu überlassen, wenn er doch alleine arbeitet. Irgendwann arbeitet aber auch dieser Entwickler mit anderen zusammen, legt diese Arbeitsweise (aus Gewohnheit) aber nicht ab. Da kann man sich ausrechnen wohin das führt.

Keine Kommentare mehr im Sourcecode?

Dieser Beitrag ist kein Appell an die Kommentarlosigkeit innerhalb des Sourcecodes. Kommentare sind ein hilfreiches Mittel um an den relevanten Stellen ein Warum zu erklären oder auf eine Besonderheit hinzuweisen. Die Grundvoraussetzung ist natürlich die Pflege derselben.

Wird die Kommentarfunktion allerdings zum Deaktivieren oder Archivieren von Sourcecode verwendet, dann wird diese Funktionalität schlicht missbraucht. Das geht anders.

Wie ist deine Meinung zu diesem Thema?

The post Warum auskommentierter Sourcecode im Source Control nichts zu suchen hat appeared first on Norbert Eder.

Johannes Renatus: File Nesting Addon für Visual Studio und Angular

Wenn man sich an den offiziellen Guide oder die Angular CLI hält, dann wird es sehr schnell sehr unübersichtlich in den einzelnen Verzeichnissen für eine Angular Anwendung. Denn zu den meisten TypeScript Dateien gibt es noch die passende HTML, Style oder Testdatei. Schon bei einfachen Verzeichnissen kann das ganze im Explorer bereits folgendermaßen aussehen. Oft […]

Norbert Eder: Rückblick 2016

Gerade noch habe ich den Rückblick 2015 geschrieben und muss es jetzt schon für das Jahr 2016 tun – auch schon bald eine Tradition. Nun gut, nicht trödeln, los geht’s. Der Vollständigkeit halber sei auf meine Ziele 2016 verwiesen.

Softwareentwicklung

Nach meinem Engagement für WPF war ich jahrelang hauptsächlich im Web-Bereich unterwegs. Im letzten Jahr hat sich das sehr stark verändert. Zwar beschäftige ich mich immer noch stark damit, allerdings hat sich hier einiges in die Bereiche Desktop, Kommunikationsprotokolle und vor allem SQL Server ausgedehnt.

Natürlich hat es auch wieder zahlreiche Erweiterungen in meinem Nodejs-Modul trello gegeben.

In meinen Zielen hatte ich die Veröffentlichung eines Projekts für März vorgesehen. Leider hatte ich keine Zeit bzw. ergab sich ein weit wichtigeres Projekt, welches aber nicht für die Öffentlichkeit gedacht ist.

Arbeitsweise und Kollaboration

Nach wie vor setze ich Todoist ein und bin wirklich begeistert. Dieses Tool hilft mir, meine Aufgaben im Überblick zu behalten. Hatte ich voriges Jahr zu diesem Zeitpunkt bereits 620 abgeschlossene Tasks, sind es nun fast 2500.

Für das Sammeln und Kategorisieren von Informationen verwende ich nach wie vor Microsoft OneNote, da es für mich einfach das beste Tool seiner Art ist.

Auch 2016 ging ohne meinen Moleskine nichts. Mittlerweile findet sich schon ein ganzer Stapel der kleinen Notizbücher in meinem Schrank. Am liebsten sind mir nämlich diese hier. Viele können das vielleicht nicht nachvollziehen, aber in “alten Gedanken” zu blättern ist schon etwas ganz Besonderes.

Hatte ich in der Kommunikation in den Jahren zuvor hauptsächlich Skype eingesetzt, gab es 2016 eine starke Verlagerung hin zu mehr persönlichem Kontakt (inklusive regulärer Telefonie).

Fotografie

Der fotomontag war ein regelmäßiger Bestandteil im vergangenen Jahr. Schon das zweite Jahr gab es wirklich jeden Montag ein neues Foto. Wie ich zum 100. fotomontag schon geschrieben habe, hilft mir dieses Projekt sehr bei meiner Weiterentwicklung. Die mir für 2016 auferlegte Einschränkung hat sich als wenig zielführend erwiesen und wurde von mir – wie Interessierte bemerkt haben – recht früh abgebrochen.

Vorgenommen hatte ich mir auch 2-3 Portrait-Shootings. Zwei habe ich geschafft. Ich bin mit beiden nicht ganz zufrieden, da fehlt noch ganz viel Erfahrung beim Shooten und besonders bei der Nachbearbeitung.

Ganz besonders Spaß haben meine Fotoreisen gemacht. Gleich zu Beginn des Jahres war ich in Triest, im Mai dann auf Sizilien, im Sommer in Luzern und Anfang November in Bratislava. Dabei habe ich vieles entdeckt und natürlich auch festgehalten. Dabei habe ich viele schöne Plätze entdeckt und hoffe natürlich, den einen oder anderen wieder einmal zu besuchen.

Blog

Viele Jahre ohne Design-Update hat es auf meiner Website noch nicht gegeben. 2016 war aber eines (das muss ich übrigens schnell ändern). Eigentlich wollte ich noch mehr bloggen, habe es dann aber zeitlich nicht geschafft, da mich der Job dann doch ziemlich in Beschlag nimmt. Durch die regelmäßigen Posts zum Thema Fotografie und dann doch einigen Entwicklungs-Posts, die sehr gut ankamen, konnte ich meine Kennzahlen deutlich steigern. Ich blogge zwar nicht für Statistiken, dennoch freut es mich sehr, wenn meine Website an Reichweite gewinnt.

Interessanterweise wurde das Thema WPF sehr häufig nachgefragt.

Allgemeine Statistiken

Metrik Veränderung
Aufrufe +26%
Besucher +34%
Beiträge -4%

Top 5 neue Beiträge 2016

Top 5 Beiträge 2016

Viele der älteren, aber noch immer aktuellen, Beiträge wurden von mir aufgemotzt und aktualisiert.

Bücher

Ich hatte mir für 2016 weit mehr Bücher zu lesen vorgenommen (12, um genau zu sein, die eigentlich nur 10 waren), als ich schlussendlich geschafft habe (nämlich 5, davon nur eines aus der ursprünglichen Liste). Einige sind es dann aber doch geworden (Belletristik nicht mitgezählt). Hier die Auflistung (Links führen zu Amazon):

Mein Leseplan ist öffentlich einsehbar.

Sport

Auch der Sport kam nicht zu kurz. Regelmäßiges Radfahren und die schon im Jahr zuvor betriebenen BWT-Übungen haben mich begleitet. Wenn man den Großteil seiner Arbeitszeit sitzt, geht es auch nicht anders. Die angestrebten Verbesserungen habe ich nicht geschafft (kaum eine Veränderung zum Vorjahr).

Fazit

2016 war ein schweres Jahr mit zahlreichen Höhepunkten, aber auch vielen schwierigen Phasen. Ich konnte viel lernen und habe jede Menge neuer Erfahrungen gemacht. Im Allgemeinen bin ich mit dem vergangenen Jahr (soweit es mich betrifft) ganz zufrieden. Die Liste für das kommende Jahr ist allerdings eine sehr lange – muss ja etwas weiter gehen :)

The post Rückblick 2016 appeared first on Norbert Eder.

Norbert Eder: Microsoft MVP Reconnect

Na was ist denn heute mit der Post gekommen? Seht selbst:

Microsoft MVP Reconnect

Microsoft MVP Reconnect Willkommensgeschenk

Herzlichen Dank an Microsoft. Nicht nur für das Willkommensgeschenk, sondern auch für das MVP Reconnect Programm.

MVP Reconnect is a program designed to provide our former MVPs with the opportunity to remain connected, recognized and engaged following the end of their award period.

The post Microsoft MVP Reconnect appeared first on Norbert Eder.

Golo Roden: npm-Module lizenzieren

Das Veröffentlichen eines Moduls auf npm allein genügt nicht, um es anderen zur Verfügung zu stellen. Es gilt zusätzlich, eine Lizenz auszuwählen und sie in der Datei package.json auszuweisen. Was ist dabei zu beachten?

Norbert Eder: Why no Buildserver?

Wenn man in einschlägigen Kreisen unterwegs ist, dann wird über das Thema Buildserver kaum noch gesprochen. Vielleicht kommen seltene Randthemen zur Sprache, das war es dann aber im Grunde schon wieder. Die meisten haben das für sich schon gelöst. Ist ja auch wirklich schon ein alter Hut.

Bei Unterhaltungen mit weniger Community-affinen Entwicklern, oder wenn die Arbeit im Unternehmen Überhand nimmt, sieht das dann mitunter anders aus. Unglaublich viele haben keinen Buildserver im Einsatz, ja sind sich teilweise nicht sicher, wofür diese gut sind oder welchen Nutzen sie daraus ziehen sollten.

In manchen Fällen muss auch der Aufwand der Konfiguration und Pflege für das Fehlen einer entsprechenden Infrastruktur herhalten. Mitunter werden Buildserver schon auch mal als neumodisches Zeug abgehandelt.

Vorteile eines Buildservers

Die Anzahl an Vorteilen eines Buildservers sind nicht enden wollend. Nachfolgend möchte ich die für mich wichtigsten Vorteile aufzählen und näher beschreiben.

  • Gegenprüfung der Funktionstüchtigkeit auf einem anderen Rechner
    “It compiles on my machine” kennen wir doch alle. Auf einem anderen Computer geht dann plötzlich gar nichts mehr, weil eine Abhängigkeit nicht installiert ist oder nicht alle Dateien im Source Control hinterlegt bzw. aktuell sind.

  • Zeitgesteuertes Erstellen von Builds
    In regelmäßigen Abständen wird ein Build vom aktuellen Stand (oder auch mehreren) erstellt und dabei überprüft, ob er kompilierbar ist.

  • Anwenden von definierten Regeln auf jede Änderung
    Überprüfungen durch die Ausführung von Unit-/Integrationstests und weiteren Prüfungen, die die Funktionstüchtigkeit garantieren sollen.
  • Erzeugen von Releases
    Alle Releases werden nach einer bestimmten Vorgabe immer gleich erstellt. Durch spezielle Prüfungen (Durchlaufen von Unit Tests etc.) können Grundvoraussetzungen für ein erfolgreiches Release überprüft werden. Es kann nicht passieren, dass essentielle Schritte vergessen werden.
  • Automatisches Bespielen von unterschiedlichsten Testsystemen
    Nächtliches Bespielen von Testsystemen, damit diese aktuell gehalten werden, Migrationsszenarien durchgespielt werden können usw.
  • Einheitliche Ausführung
    Builds werden immer auf dieselbe Art und Weise ausgeführt, d.h. Eigenheiten bzw. besondere Konfigurationen von Entwickler-Rechnern fallen in der Regel schnell auf.

Sicherlich lassen sich weitere Vorteile finden, ich denke jedoch, dass die genannten durchaus ausreichend sind.

Aufwand und Pflege

Es bedeutet Aufwand, einen Buildserver zu betreiben. Eine Installation ist nicht ausreichend. Zuerst bedarf es eines Plans. Hierzu sollten (mindestens) folgende Fragen gestellt (und beantwortet) werden:

  • Welche Builds werden benötigt? (Debug-Build, Release-Build, etc.)
  • Wann sollen die Builds ausgeführt werden? (Checkin, Hourly, Nightly, etc.)
  • Welche Builds müssen was tun? (Compile, Ausführen der Tests, Cleanup, Setup erstellen, etc.)
  • Wie wird mit den Buildartefakten umgegangen? (Retention Policy)

Wenn das alles geklärt ist, muss ein Buildserver inklusive aller notwendigen Software her. Danach kann man an die Erstellung der Builds und der notwendigen Scripts gehen. Das kostet natürlich Zeit und muss auch aktuell gehalten werden.

Dafür ist es ein schönes Gefühl, wenn das alles läuft, man seine erste Änderung ins Source Control überträgt und ein Checkin-Build startet, am Server kompiliert, alle Tests durchläuft und einem zurückmeldet, dass alles in Ordnung ist.

Es gibt viele Buildserver da draußen in der weiten Welt, ich für meinen Teil setze seit Jahren auf Jenkins und bin mit ihm immer gut gefahren. Einmal installiert, können Updates (Jenkins selbst als auch Plugins) sehr schnell eingespielt werden.

Einheitliche Release-Policy

Gerade in kleineren Teams und Unternehmen kommt es gerne einmal vor, dass Releases am Entwicklerrechner gemacht und ausgeliefert werden. Das mag besonders agil oder flexibel erscheinen, ist aber oft die Grundlage für zahlreiche Probleme:

  • Änderungen finden den Weg ins Source Control nicht, wurden aber in ein Release gepackt und ausgeliefert. Diese Änderungen gehen bei einem etwaigen Update unweigerlich verloren. Daraus resultierende Probleme können nicht nachvollzogen werden.
  • Das Setzen der Versionsnummern erfolgt durch einen Release Build. Dadurch wird dies immer einheitlich durchgeführt und es kann auch nicht passieren, dass zwei Auslieferungen dieselbe Versionsnummer tragen.

Ein Buildserver alleine löst dieses Thema nicht, es muss auch organisatorisch entsprechende Regeln geben. Problemfälle können hierdurch jedoch stark minimiert werden.

Ausgelieferte Versionen rekonstruieren

Wenn die Software in vielen unterschiedlichen Versionen bei vielen Kunden im Einsatz ist, dann muss man jederzeit den dortigen Softwarestand rekonstruieren können. Durch einen Buildserver und dezidierten Release-Builds können versionierte/ausgelieferte Stände mit einem Label/Tag automatisch versehen werden. Damit sind alle Stände/Versionen sehr einfach rekonstruierbar.

Eine gute Idee ist auch das Schreiben und Verpacken einer RevisionInfo-Datei in ein Setup. Dadurch können bei Bedarf entsprechende Informationen vom Kunden eingeholt und so der ausgelieferte Stand einfach wiederhergestellt werden (so beispielsweise das Taggen schief ging). Diese Datei kann eine einfache Datei sein und beispielsweise folgende Informationen enthalten:

  • Commit-Hash/-Id
  • Build-Name
  • Build-Datum

Mit diesen Informationen kann der jeweilige Stand problemlos gefunden werden.

Fazit

Gerade im Enterprise-Umfeld gestalten sich Anwendungen immer komplexer. Mitunter sind viele Schritte notwendig, um ein Release zu erstellen, oder ein Testsystem zu bespielen. Oftmals fehlt überhaupt ein automatisierter Testdurchlauf. All das ist mit einem Buildsystem gut zu automatisieren und hilft Zeit zu sparen und gewährleistet, dass immer dieselben Schritte angewandt werden. Wer in diese Richtung noch nichts investiert hat, sollte spätestens jetzt damit starten.

Solltest du Jenkins einsetzen, findest du hier den einen oder anderen Jenkins-Tipp.

The post Why no Buildserver? appeared first on Norbert Eder.

Martin Hey: Goodbye Techblog

Ich habe immer gerne gebloggt, war das doch für mich ein Weg, mein Wissen zu teilen. Und oft genug habe ich beim Suchen nach Lösungen für Probleme meine eigenen Posts gefunden und so gemerkt, dass ich das gleiche Problem schon mal hatte - ein bisschen Eigennutz war also dabei und ich habe ihn auch als private Wissenssammlung mit Indizierung durch Google verwendet. 


Aber in den letzten beiden Jahren ist immer weniger Zeit fürs Bloggen geblieben (6 Posts in 2016 ist nicht viel) und auch die Themen mit denen ich mich beschäftige verändern sich - so bin ich zwar noch an Entwickler-Themen dran, aber oft genug sind da auch eher betriebswirtschaftliche Themen die mich umtreiben.

Ich werde auch weiterhin aktiv in der Entwickler-Community bleiben und an anderer Stelle sicher weiter bloggen. Nur dieser eher privat betriebene Blog wird zum Ende des Jahres 2016 gelöscht.

Angelehnt an den allerersten Post aus 2007: goodbye world

Holger Schwichtenberg: Eine VM in einer VM betreiben

In Windows 10 und Windows Server 2016 unterstützt Microsoft auch "Nested Virtualization". Das heißt, es ist möglich, in einem Hyper-V-Gastbetriebssystem wieder einen Hyper-V-Host mit untergeordneten Gästen zu betreiben.

Norbert Eder: Jenkins: Build-Id zurücksetzen

In manchen Fällen ist es wünschenswert, die Build-Id eines Builds zurückzusetzen oder mit einem bestimmten Wert zu starten (beispielsweise bei einem Wechsel des System, nach Tests etc.).

Am schnellsten geht wohl das Erstellen eines neuen Builds auf Basis des bereits existierenden. Der alte kann danach gelöscht werden.

Es gibt allerdings auch eine Alternative.

Unter Jenkins verwalten / Skript Konsole ist folgendes Script auszuführen:

def jobName = "Name des Builds"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().each { it.delete() }

Damit werden alle Builddurchläufe gelöscht. In manchen Fällen bleiben jedoch noch Verweise im Verzeichnis builds\[jobname] übrig. Diese sind mit der Buildnummer angegeben und müssen gelöscht werden.

Schlussendlich ist in der Datei %ProgramFiles(x86)%\Jenkins\Jobs\[jobname]\nextBuildNumber die nächste Build-Nummer einzutragen. Möchte man von vorne beginnen, dann ist hier eine 1einzutragen. Dieser Schritt kann auch mit Hilfe des Next Build Number Plugins vorgenommen werden.

The post Jenkins: Build-Id zurücksetzen appeared first on Norbert Eder.

Holger Sirtl: Azure News on Friday (KW50/16)

Auch diese Woche gab’s wieder viele Nachrichten zur Microsoft Azure Plattform. Stets aktuelle News, Videos, Tools, MVA-Kurse, und vieles mehr zu Azure auf dem Azure Infohub unter http://aka.ms/azureinfohub.

Hier sind nähere Infos dazu…

Aktuelle Neuigkeiten

Datum Nachricht
15.12. Release of SDK 2.4.145 and Runtime 5.4.145 for Windows
Azure Service Fabric mit neuem SDK 2.4.145 und neuer Runtime 5.4.145 für Windows
14.12. #AzureAD Certificate Based Authentication is Generally Available!
Zertifikatsbasierte Authentifizierung via Azure AD allgemein verfügbar
13.12. General availability: Azure IoT Gateway SDK
Azure IoT Gateway SDK jetzt allgemein verfügbar
12.12. General availability: Azure IoT Hub device management
Azure IoT Hub Device Management jetzt allgemein verfügbar

Neue Kurse in der MVA

Datum Nachricht
12.12. Monitoring Your Hybrid Environment with OMS Security
Neuer kostenloser MVA Kurs zur Überwachung hybrider Umgebungen mit der Operations Management Suite (OMS) in Azure

Neue Videos

Datum Nachricht Video
15.12. Introducing Azure Analysis Services
Überblick über Azure Analysis Services
14.12. Exploring our newest sample app, BikeSharing360
Überblick über BikeSharing360 – Demo App mit Web Apps, Azure Functions, Mobile Apps, Cognitive Services etc.
14.12. Interactive Spark on Azure
Interactive Spark on Azure
09.12. Introducing Apache Kafka on Azure HDInsight
Neu: Apache Kafka auf Azure HDInsight – hier ein Überblick
07.12. Getting Started with Azure Analysis Services
Schneller Überblick über Azure Analysis Services

Albert Weinert: ASP.NET Core: Alle Cookies nur noch per HTTPS ausliefern

Möchte man bei ASP.NET Core seine Cookie z.B. nur über HTTPS ausliefern oder
vor dem Zugriff vor JavaScript schützen. So kann man bei dem entsprechenden
Cookie die Properties Secure und HttpOnly setzen. Bei jedem
einzelnem Cookie, oder bei den Optionen für entsprechenden Middlewares.

Jedoch ist die Aufwand, und man weiss vielleicht nicht unbedingt welche
Middleware auch mal eben tempörare oder andere Cookies erzeugt.

Dies können z.B. im Falle der ASP.NET Security Middlewares schonmal einige sein.

Abhilfe schafft hier die CookiePolicyMiddlware von ASP.NET Core.

Diese findet sich im NuGet Paket Microsoft.AspNetCore.CookiePolicy. Dies muss
man seinem Projekt hinzufügen, dann kann in der Startup-Klasse der Anwendung
einfach die Middleware konfiguriert werden.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)  
{
    if (env.IsDevelopment()) {
        app.UseCookiePolicy(new CookiePolicyOptions
        {
            Secure = CookieSecurePolicy.Always,
            HttpOnly = HttpOnlyPolicy.Always,
            OnAppendCookie = context =>
            {
                context.CookieOptions.Expires = DateTimeOffset.Now.AddMinutes(10);
            }
        }); 
    }
}

Dies sollte natürlich vor allem geschehen was Cookie erzeugt.

Die CookiePolicy hat die Properties Secure und HttpOnly, sowie jeweils
eine Callback Funktion für beim hinzufügen und entfernen von Cookies.

Norbert Eder: Robocopy und Exit codes in Buildumgebungen

Bis dato hatte ich Robocopy in automatisierten Builds noch nicht verwendet, copy tat, was ich brauchte. Nun habe ich erweiterte Anforderungen und bin deswegen auf Robocopy umgestiegen. Gescheiterte Builds zeigten schnell auf, dass Robocopy wohl unterschiedlichste Exit codes einsetzt und diese behandelt werden müssen, möchte man einen durchlaufenden Build haben.

Robocopy Exit codes

Folgende Exit codes stellt Robocopy zur Verfügung (siehe auch Return codes that are used by Robocopy:

Value Description
0 No files were copied. No failure was encountered. No files were mismatched. The files already exist in the destination directory; therefore, the copy operation was skipped.
1 All files were copied successfully.
2 There are some additional files in the destination directory that are not present in the source directory. No files were copied.
3 Some files were copied. Additional files were present. No failure was encountered.
5 Some files were copied. Some files were mismatched. No failure was encountered.
6 Additional files and mismatched files exist. No files were copied and no failures were encountered. This means that the files already exist in the destination directory.
7 Files were copied, a file mismatch was present, and additional files were present.
8 Several files did not copy.

Alle Werte größer 8 deuten jedenfalls auf mindestens einen aufgetretenen Fehler hin. Bei einem Wert von 16 ist ein ernsthafter Fehler aufgetreten. Dabei wurden keine Dateien kopiert.

Exit codes im Batch behandeln

Da also auch nach erfolgreichem Kopiervorgang Exit codes größer 0 geliefert werden, sind diese in einem Batch-Aufruf extra zu behandeln. Wie dies funktioniert zeigt nachfolgendes Beispiel:

robocopy sourceDir targetDir /E /XC /XN /XO /NP

IF %ERRORLEVEL% LSS 8 goto finish
EXIT /B 1

:finish
EXIT /B 0

Hierbei wird für alle Robocopy Exit codes die kleiner als 8 sind, der Exit code 0 zurück geliefert, andernfalls 1. Darauf kann nun im Build Rücksicht genommen werden.

Gutes Gelingen!

The post Robocopy und Exit codes in Buildumgebungen appeared first on Norbert Eder.

AIT: Neu in Visual Studio und TFS "15" / 2017: Package Management

Um eigene Softwareware Paket innerhalb der Firma zu verteilen war bisher eine separate Lösung notwendig, wie zum Beispiel ein NuGet Server. Die Einrichtung war zwar kein Hexenwerk, brachte dennoch Aufwände mit sich. Dies ist seit dem Team Foundation Server 2017 nicht mehr notwendig. Der TFS 2017 bringt ab sofort seine eigene, wenn auch kostenpflichtige Paket Verwaltung mit, welche es erlaubt NuGet oder npm Pakete im TFS oder VSTS zu veröffentlichen und zu nutzen. Im VSTS gibt es bereits eine Unterstützung für npm Pakete während die on-premise Variante des TFS npm erst später durch ein Update unterstützen wird.

Die Paket Verwaltung ist eine Extension und kann im Marketplace für den TFS erworben werden. Ähnlich zu dem VSTS ist diese Erweiterung für die ersten 5 Nutzer des VSTS kostenfrei.

clip_image002

Abbildung 1: Package Feeds im VSTS

Analog zu einem NuGet Server arbeitet der TFS mit Feeds, in dem die Pakete abgelegt werden können. Im Visual Studio können diese direkt konsumiert werden. Um einen neuen Feed anzulegen gibt es in der Weboberfläche unter Build & Release einen neuen Punkt Packages (siehe Abbildung 1). Hier können die verfügbaren Feeds verwaltet werden.

clip_image003

Abbildung 2: Connect Button zum Feed

Um sich mit einem Feed in Visual Studio zu verbinden und deren Pakete zu nutzen gibt es extra den „Connect to feed“-Button (siehe Abbildung 2). Dieser öffnet ein Popup (siehe Abbildung 3), welches die URL zum Feed enthält.

clip_image005

Abbildung 3: Feed Url

Im Visual Studio unter Options kann im NuGet Package Manager (siehe Abbildung 4) die URL bei den Package Sources eingetragen und für den Feed einen Namen angegeben werden.

clip_image007

Abbildung 4: Package Source im Visual Studio

Ab jetzt steht der NuGet Feed in allen Projekten zur Verfügung. Im Nuget Package Manager kann unter Package Source der neue Feed ausgewählt und die darin enthaltenen Pakete installiert werden (siehe Abbildung 5).

clip_image009

Abbildung 5: Nuget Packege Manager im Visual Studio

Fazit: Microsoft hat einen weiteren wichtigen Schritt unternommen, um den Softwareentwicklungsprozess mit dem TFS noch weiter zu automatisieren. Eigene Komponenten können automatisch über den Buildprozess zu NuGet Paketen gepackt und direkt in der Paket Verwaltung des TFS über einen Feed veröffentlicht werden. Dabei erfindet Microsoft das Rad nicht neu: Bisher war dies auch möglich, jedoch wurde dafür einen extra Server benötigt . Abschließend ist zu sagen, dass in jedem Fall die Kosten der Bereitstellung eines eigenen Package Servers gegen die Kosten der Paket Verwaltungs-Extension von Microsoft abgewogen werden sollten

MSDN Team Blog AT [MS]: kostenloses Mobile DevOps Training (25. und 26.01.2017)

kostenloses Mobile DevOps Training (24. und 25.11.)

Am 25 und 26. Jänner findet bei Microsoft Österreich ein kostenloses 2 tägiges Mobile DevOps Training statt.

Wir zeigen agile mobile App Entwickliung mit Visual Studio, Xamarin & Microsoft Azure. Das Training wird in deutscher Sprache abgehalten.

Jetzt zum Mobile DevOps Training am 25. und 26.01. anmelden!!

Software-Engineering-Methoden haben sich in den letzten Jahren drastisch verändert. Agile Praktiken, DevOps, Cloud Computing, Open Source und ähnliche Entwicklungen haben ihre Wirksamkeit bewiesen. Microsoft Plattformen für Software-Entwicklung und Cloud Computing haben ebenfalls diese Konzepte angenommen und sind ihrem Bereich an der Spitze in cross-Plattform und mobile App-Entwicklung.

In diesem zweitägigen Kurs lernst du wie mobile Software Entwicklung mit Microsoft Tools und Sprachen arbeitet.

Auf Basis eines durchgängigen Beispieles lernst Du:

  • Einrichten einer Entwicklungsumgebung für eine mobile Anwendung mit den neuesten Versionen von Visual Studio und Visual Studio Team Services
  • eine einfache Android App mit Xamarin zu entwickeln,
  • von den neuesten Entwicklungen in der Visual Studio C#-IDE (z.B. PerfTips, live code Analyse, CodeLense, Diagnose-Tools, etc..) zu profitieren
  • die Visual Studio Team Services zu verwenden um Deine Qualitätssicherungs-Prozesse zu automatisieren
  • Deine Tests mit der Xamarin Test Cloud auf über 2.000 echten Geräten zu automatisieren
  • die Bereitstellung mit Visual Studio-Release-Management zu automatisieren und
  • aussagekräftige Berichte und Feedback von Deinen Benutzern in der HockeyApp zu sammeln

Tag 1:

  • Microsoft Developer Plattform und mobile Entwicklung
  • Mobile Anwendungen mit Xamarin erstellen
  • Wie Visual Studio Team Services und mobile App-Entwicklung zusammen funktionieren
    (Build, Release-Management, kontinuierliche Bereitstellung usw.).

Tag 2:

  • Automatisierte Tests mit der Xamarin Test Cloud
  • Integration von HockeyApp für Absturz-Berichterstattung und Benutzer-Feedback
  • Bereichern Deiner Mobilanwendung mit Cloud-Services

Wichtige Voraussetzung: Du benötigst Deinen EIGENEN LAPTOP für die praktischen Übungseinheiten!

Weitere Details hier herunterladen: https://1drv.ms/w/s! AqM7MHvEOS1jipcxNNyLyvxqsIH37w

Jetzt zum Mobile DevOps Training am 25. und 26.11. anmelden!!

Eure Trainer sind:

Rainer Stropek Roman Schacherl
Rainer Stropek, MVP Roman Schacherl, MVP

Norbert Eder: Jenkins: Builds mit Groovy-Scripts aufpeppen

Seit einigen Jahren setze ich nun auf Jenkins und bin seit jeher sehr glücklich mit diesem System. Durch die zahlreich verfügbaren Plugins kann man Builds unheimlich schnell konfigurieren. Mit steigenden Anforderungen, die über allgemeine Ansätze hinaus gehen, muss man jedoch selbst Hand anlegen. Eine gute Möglichkeit dazu bieten Groovy-Scripts.

Was ist Groovy?

Dazu sagt die Groovy-Webiste:

Apache Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.

Jenkins und Groovy

Jenkins bietet über die Skript-Konsole (siehe Jenkins-Verwaltung) die Möglichkeit Groovy-Scripts auszuführen. Dazu muss allerdings Groovy installiert sein, auch in der Global Tool Configuration ist der Pfad zu konfigurieren.

Mit dem Groovy-Plugin können Groovy-Scripts auch innerhalb eines Builds ausgeführt werden. Hierzu stehen zwei Varianten zur Verfügung:

  • Groovy Scripts
  • System Groovy Scripts

Während normale Groovy Scripts in einer eigenen JVM auf dem Slave ausgeführt werden, der den Build ausführt, laufen die System Groovy Scripts innerhalb der Jenkins JVM. So haben sie Zugriff auf die Jenkins API und Informationen des Builds können ausgelesen werden. In vielen Fällen ist eine Manipulation derselben ebenfalls möglich.

Als ganz einfaches Beispiel kann der Name des Builds angepasst werden. Im Standard wird #Buildnummer verwendet. In vielen Fällen möchte man aber eine andere Notation um zusätzliche Informationen darin zu kodieren. Diese könnte als Beispiel so aussehen: 1.0.0.1-DEV-20161212-1800 und entspricht dem ersten DEV-Build inkl. Datumsinformation. Und so sieht das Script dazu aus:

import java.text.SimpleDateFormat;

def sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
def version = "1.0.0.";
def type = "DEV";
def build_date = sdf.format(build.getTime());

def build_id = build.properties.environment.BUILD_NUMBER.toString();

def version_number_formatted = version + build_id + "-" + type + "-" + build_date;

build.displayName = version_number_formatted;

Nun möchte man so generierte Informationen in Build-Variablen setzen, um sie eventuell in anderen Plugins abrufen zu können. Hierzu habe ich den Artikel Programmatically set Jenkins build variables gefunden. Im Gegensatz zu vielen anderen Lösungen, die man über die Suchmaschine seiner Wahl findet, funktioniert diese auch. Erreicht wird dies durch nachfolgenden Code:

import hudson.EnvVars
import hudson.model.*

def build_number = Job.getVariable("BUILD_NUMBER")
def branch_name  = Job.getVariable("GIT_BRANCH")

def build_branch = "${build_number}-${branch_name}"

Job.setVariable("BUILD_BRANCH", build_branch)

class Job {

    static def getVariable(String key) {
        def config = new HashMap()
        def thr = Thread.currentThread()
        def build = thr?.executable
        def envVarsMap = build.parent.builds[0].properties.get("envVars")
        config.putAll(envVarsMap)
        return config.get(key)
    }

    static def setVariable(String key, String value) {
        def build = Thread.currentThread().executable
        def action = new VariableInjectionAction(key, value)
        build.addAction(action)
        build.getEnvironment()
    }
}

class VariableInjectionAction implements EnvironmentContributingAction {

    private String key
    private String value

    public VariableInjectionAction(String key, String value) {
        this.key = key
        this.value = value
    }

    public void buildEnvVars(AbstractBuild build, EnvVars envVars) {

        if (envVars != null && key != null && value != null) {
            envVars.put(key, value);
        }
    }

    public String getDisplayName() {
        return "VariableInjectionAction";
    }

    public String getIconFileName() {
        return null;
    }

    public String getUrlName() {
        return null;
    }
}

Groovy als Post-Build Action ausführen

Standardmäßig können in der Post-Build Action keine Shell- und Script-Tasks ausgeführt werden. Wer das benötigt, installiert sich das Hudson Post build task-Plugin. Dieses ermöglicht die Ausführung von Groovy Commands und Scripts (auch System Scripts). Zuvor gesetzte Variablen können natürlich an dieser Stelle verwendet werden.

Zudem hat man die Möglichkeit, die Scripts nur dann ausführen zu lassen, wenn der Build durchgelaufen ist.

Fazit

Wer das Buildsystem ausreizen möchte, hat mehrere Möglichkeiten. Parametrisierte Shell-Scripts/Commands sind eine mögliche Variante. Weit angenehmer empfinde ich jedoch Groovy-Scripts, da durch die System Scripts auf die Jenkins-API zugegriffen werden kann. Grundlegende Java-Kenntnisse werden allerdings empfohlen.

The post Jenkins: Builds mit Groovy-Scripts aufpeppen appeared first on Norbert Eder.

Holger Sirtl: Azure News on Friday (KW49/16)

Auch diese Woche gab’s wieder viele Nachrichten zur Microsoft Azure Plattform. Stets aktuelle News, Videos, Tools, MVA-Kurse, und vieles mehr zu Azure auf dem Azure Infohub unter http://aka.ms/azureinfohub. Hier sind nähere Infos dazu…

Aktuelle Neuigkeiten

Datum Nachricht
05.12. #AzureAD PowerShell V2.0 is now GA
Azure AD PowerShell ist jetzt allgemein verfügbar
02.12. New Quickstart experience for App Service Web App
Neue Quickstart Optionen für den Azure App Service – vorinstallierbare Frameworks für Web Apps und Co.
01.12. App Service Continuous Delivery Preview
Continuous Delivery beim Aufbau und Betrieb Azure App Service basierter Anwendungen
01.12. Running Azure Functions Locally with the CLI and VS Code
Azure Functions können jetzt auch lokal entwickelt und getestet werden

Neue Kurse in der MVA

Datum Nachricht
02.12. Azure DocumentDB: Planet-Scale NoSQL
Kostenloser MVA-Kurs zu Azure DocumentDB – voll-automatiserte NoSQL Datenbank auf Microsoft Azure
02.12. Web and Data Application Development with Visual Studio 2017 and Azure
MVA-Kurs zur Entwicklung Web- und Daten-basierter Apps – SQL Database, Docker, Azure Search, Application Insights…

Neue Videos

Datum Nachricht Video
09.12. Introducing Apache Kafka on Azure HDInsight
Neu: Apache Kafka auf Azure HDInsight – hier ein Überblick
07.12. Getting Started with Azure Analysis Services
Schneller Überblick über Azure Analysis Services
02.12. Intro to Azure Site Recovery
Kurzeinführung in Azure Site Recovery – Disaster Recovery und Failover in Azure
02.12. Azure DocumentDB Elastic Scale – Partitioning
Neue Azure Friday Folge mit den Möglichkeiten zu Elastic Scale und Partitioning in Azure Document
02.12. Get started with Microsoft Cognitive Services
Schnelleinstieg in Cognitive Services

Jürgen Gutsch: A small library to support the CQS pattern.

The last years, I loved to use the Command and Query Segregation pattern. Using this pattern in every new project, requires to have the same infrastructure classes in this projects. This is why I started to create a small and reusable library, which now supports ASP.NET Core and is written to match .NET Standard 1.6.

About that CQS

The idea behind CQS is to separate the query part (the read part / fetching-the-data-part) from the command part (the write part / doing-things-with-the-data-part). This enables you to optimize both parts in different ways. You are able to split the data flow into different optimized pipes.

From my perspective, the other most important benefit of it is, that this approach enforce you, to split your business logic into pretty small peaces of code. This is because each command and each query only does one single thing:

  • fetching a specific set of data
  • executing a specific command

E. g. if you press a button, you probably want to save some data. You will create a SaveDataCommand with the data to save in it. You'll pass that command to the CommandDispatcher and this guy will delegate the command to the right CommandHandler, which is just responsible to save that specific data to the database, or what ever you want to do with that data. You think you'll also add a log entry with the same command? No problem: Just create another CommandHandler using the same command. With this approach you'll have two small components, one to save the data and another one to add a log entry, which are completely independent and can be tested separately.

What about fetching the data? Just create a "Query" with the data used as a filter criteria. Pass the Query to the QueryProcessor, which delegates the Query to the right QueryHandler. in this QueryHandler, you are able to select the data from the data source, map it to the result you expect and return it back.

Sounds easy? It really is as easy.

Each Handler, both the QuerHandlers and the CommandHandlers, are isolated peaces of code, if you use Dependency Injection in it. This means unit tests are as easy as the implementation itself.

What is inside the library?

This library contains a CommandDispatcher and a QueryProcessor to delegate commands and queries to the right handlers. The library helps you to write your own commands and queries, as well as your own command handlers and query handlers. There are two main NameSpaces inside the library: Command and Query

The Command part contains the CommandDispatcher, an ICommand interface and two more interfaces to define command handlers (ICommandHandler<in TCommand>) and async command handlers (IAsyncCommandHandler<in TCommand>):

The CommandDispatcher interface looks like this:

public interface ICommandDispatcher
{
    void DispatchCommand<TCommand>(TCommand command) where TCommand : ICommand;
    Task DispatchCommandAsync<TCommand>(TCommand command) where TCommand : ICommand;
}

The Query part contains the QueryProcessor, a generic IQuery, which defines the result in the generic argument and two different QueryHandlers. It also contains two more interfaces to define query handlers (IHandleQuery<in TQuery, TResult>) and async query handlers (IHandleQueryAsync<in TQuery, TResult>)

public interface IQueryProcessor
    {
        TResult Process<TResult>(IQuery<TResult> query);
        Task<TResult> ProcessAsync<TResult>(IQuery<TResult> query);
    }

Using the library

For the following examples, I'll reuse the speaker database I already used in previous blog posts.

After you installed the library using Nuget, you need to register the the QueryProcessor and the CommandDispatcher to the dependency injection. You can do it manually in the ConfigureSerices method or just by using AddCqsEngine()

public void ConfigureServices(IServiceCollection services)
{
	services.AddMvc(),

	services.AddCqsEngine();

	services.AddQueryHandlers();
	services.AddCommandHandlers();
}

The methods AddQueryHandlers and AddCommandHandlers are just methods to encapsulate the registrtion of your Handlers, and are propably written by you as a user of this library. The method could look like this:

public static IServiceCollection AddQueryHandlers(this IServiceCollection services)
{
	services.AddTransient<IHandleQueryAsync<AllSpeakersQuery, IEnumerable<Speaker>>, SpeakerQueryHandler>();
	services.AddTransient<IHandleQueryAsync<SpeakerByIdQuery, Speaker>, SpeakerQueryHandler>();

	services.AddTransient<IHandleQueryAsync<AllEventsQuery, IEnumerable<Event>>, EventQueryHandler>();
	services.AddTransient<IHandleQueryAsync<SingleEventByIdQuery, Event>, EventQueryHandler>();

	services.AddTransient<IHandleQueryAsync<AllUsergroupsQuery, IEnumerable<Usergroup>>, UsergroupQueryHandler>();
	services.AddTransient<IHandleQueryAsync<SingleUsergroupByIdQuery, Usergroup>, UsergroupQueryHandler>();

	services.AddTransient<IHandleQueryAsync<AllNewslettersQuery, IEnumerable<Newsletter>>, NewsletterQueryHandler>();
	services.AddTransient<IHandleQueryAsync<SingleNewsletterByIdQuery, Newsletter>, NewsletterQueryHandler>();
	
	return services;
}

Usually you will place this method near you handlers.

The method AddCqsEngine is overloaded to add your QueryHandlers and yor CommandHandlers to the dependnecy injection. There is no real magic behind that method. It is just to group the additional dependencies:

services.AddCqsEngine(s =>
	{
		s.AddQueryHandlers();
		s.AddCommandHandlers();
	});

The parameter s is the same Seervicecollection as the one in the ConfigureServices method.

This library makes heavily use of dependency injection and uses the IServiceProvider, which is used and provided in ASP.NET Core. If you replace the built in DI container with different one, you should ensure that the IServiceProvider is implemented and registered with that container.

Query the data

Getting all the speakers out of the storage is a pretty small example. I just need to create a small class called AllSpeakersQuery and to implement the generic interface IQuery:

public class AllSpeakersQuery : IQuery<IEnumerable<Speaker>>
{
}

The generic argument of the IQuery interface defines the value we want to retrieve from the storage. In this case it is a IEnumerable of speakers.

Querying a single speaker looks like this:

public class SpeakerByIdQuery : IQuery<Speaker>
{
    public SingleSpeakerByIdQuery(Guid id)
    {
        Id = id;
    }

    public Guid Id { get; private set; }
}

The query contains the speakers Id and defines the return value of a single Speaker.

Once you got the QueryProcessor from the dependency injection, you just need to pass the queries to it and retrieve the data:

// sync
var speaker = _queryProcessor.Process(new SpeakerByIdQuery(speakerId));
// async
var speakers = await _queryProcessor.ProcessAsync(new AllSpeakersQuery());

Now let's have a look into the QueryHandlers, which are called by the QueryProcessor. This handlers will contain your business logic. This are small classes, implementing the IHandleQuery<in TQuery, TResult> interface or the IHandleQueryAsync<in TQuery, TResult> interface, where TQuery is a IQuery<TResult>. This class usually retrieves a data source via dependency injection and an Execute or ExecuteAsync method, with the specific Query as argument:

public class AllSpeakersQueryHandler :
    IHandleQuery<AllSpeakersQuery, IEnumerable<Speaker>>
{
    private readonly ITableClient _tableClient;

    public SpeakerQueryHandler(ITableClient tableClient)
    {
        _tableClient = tableClient;
    }

    public Task<IEnumerable<Speaker>> Execute(AllSpeakersQuery query)
    {
        var result = _tableClient.GetItemsOf<Speaker>();
        return result;
    }
}

public class SpeakerByIdQueryQueryHandler :
    IHandleQueryAsync<SpeakerByIdQuery, Speaker>
{
    private readonly ITableClient _tableClient;

    public SpeakerQueryHandler(ITableClient tableClient)
    {
        _tableClient = tableClient;
    }
    
    public async Task<Speaker> ExecuteAsync(SpeakerByIdQuery query)
    {
        var result = await _tableClient.GetItemOf<Speaker>(query.Id);
        return result;
    }
}

Sometimes I handle multiple queries in a single class, this is possible by just implementing multiple IHandleQuery interfaces. I would propose to do this only, if you have really small Execute methods.

Executing Commands

Let's have a quick look into the commands too.

Let's assume we need to create a new speaker and we need to update a speakers email address. To do this we need to define two specific commands

public class AddSpeakerCommand : ICommand
{
    AddSpeakerCommand(Speaker speaker)
    {
        Speaker = speaker;
    }

    public Speaker Speaker { get; private set; }
]

public class UpdateSpeakersEmailCommand : ICommand
{
    UpdateSpeakersEmailCommand(int speakerId, string email)
    {
        SpeakerId = speakerId;
        Email = email;
    }

    public int SpeakerId { get; private set; }

    public string Email { get; private set; }
}

As equal to the queries, the commands need to be passed to the CommandDispatcher, which is registered in the DI container.

// sync
_commandDispatcher.DispatchCommand(new AddSpeakerCommand(myNewSpeaker));
// async
await _commandDispatcher.DispatchCommandasync(new UpdateSpeakersEmailCommand(speakerId, newEmail));

The CommandHandlers are small classes which are implementing the ICommandHandler or the IAsyncCommandHandler where TCommand is a ICommand. Thise handlers contain a Handle or a HandleAync method with the specific Command as argument. As equal to the query part, you usually will also get a data source from the dependency injection:

public class AddSpeakerCommandHandler : ICommandHandler<AddSpeakerCommand>
{
	private readonly ITableClient _tableClient;

	public AddSpeakerCommandHandler(ITableClient tableClient)
	{
		_tableClient = tableClient;
	}

	public void Handle(AddSpeakerCommand command)
	{
		_tableClient.SaveItemOf<Speaker>(command.Speaker);
	}
}

Command validation

What about validatig the commands? Sometimes it is needed to check authorization or to validate the command values before executing the commands. You can do the checks inside the handlers, but this is not always a good idea. This increases the size and the complexity of the handlers and the validation logic is not reusable like this.

This is why the CommandDispatcher supports precondition checks. As equal to the command handlers, you just need to write command preconditions (ICommandPrecondition<in TCommand>) od async command preconditions (ICommandPrecondition<in TCommand>). This interfaces contain a Chack or ChackAsync method which will be executed before the command handlers are executed. You can hava as many preconditions as you want for a single command. If you register the preconditions to the DI container, the command dispatcher will find and execute them:

public class ValidateChangeUsersNameCommandPrecondition : ICommandPrecondition<ChangeUsersNameCommand>
{
    public void Check(ChangeUsersNameCommand command)
    {
        if (command.UserId == Guid.Empty)
        {
            throw new ArgumentException("UserId cannot be empty");
        }
        if (String.IsNullOrWhiteSpace(command.Name))
        {
            throw new ArgumentNullException("Name cannot be null");
        }
    }
}

In case of errors, the command dispatcher will throw an AggregateException with all the possible exceptions in it.

Conclusion

The whole speaker database application is built like this: Using handlers to create small components, which are handling queries to fetch data or which are executing commands to do something with the data.

What do you think? Does it make sense to you? Would it be useful for your projects? Please drop some lines and tell me about your opinion :)

This library is hosted on GitHub in the "develop" branch. I would be happy about any type contribution on GitHub. Feel free to try id out and let me know about issues, tips and improvements :)

AIT: Dependency Manager available as OpenSource on GitHub

Today we proudly announce that the sources of AIT Dependency Manager have been published under Microsoft Public License on GitHub. ghlogo

dmflogoLast year we started open sourcing some of our tools. We continued publishing sources on GitHub this year and eventually open sourced our AIT Dependency Manager.

Feel free to use the source under the formerly mentioned license. However, we continue providing binaries on our website for download.

We are looking forward four your feedback as well as contributions.

MSDN Team Blog AT [MS]: Microsoft //build 2017

 

Microsoft hat die //build 2017 vom 10. bis 12 Mai in Seattle angekündigt!

Wer hat Interesse an einem Ticket für die Microsoft //build 2017? Die Teilnahmegebühr (+ individuelle Reisekosten) sind von den Teilnehmern zu tragen.  Bitte an der kurzen Umfrage teilnehmen (für eine geringe Anzahl an Interessenten haben wir eventuell ein interessantes Angebot)!

Christian Binder [MS]: Hands-on Workshop – Apps entwickeln für Microsoft Surface Hub

Wann:

14.12.2016 – Nur noch 3 Plätze sind verfügbar! Wer kurzfristig Zeit hat kann an dem Workshop im neuen Microsoft Technology Center in München teilnehmen.

Wo:

Microsoft Technology Center
Walter-Gropius-Str. 5
80807 München

Kosten: Keine

Anmeldung: Wir freuen uns auf Ihre verbindliche Anmeldung

Agenda:

  • Vorstellung Einsatzmöglichkeiten und Funktionen Microsoft Surface Hub
  • Grundlagen zur Entwicklung mit der Microsoft Universal Windows Plattform
  • Grundlagen zur Programmierung mit Surface Hub Features wie z.B. Stiftbedienung
  • Hands-On Lab: Entwicklung einer Beispielanwendung für den Surface Hub
  • Deployment-Strategien für Surface Hub Apps

Mehr Infos:

Microsoft Surface Hub ist die neue Plattform für modernste Zusammenarbeit und Apps für große Bildschirme. Realisieren Sie Lösungen, die Teams in Ihrem Unternehmen lieben werden und nutzen Sie dabei das volle Potenzial des Surface Hub. In diesem Workshop lernen Sie, wie Sie Anwendungen für den Surface Hub entwickeln und bereitstellen können.

Die Workshops richten sich an Unternehmen und Personen, die eigene Lösungen für Surface Hub unter Ausnutzung der spezifischen Funktionen erstellen wollen.

David Tielke: Materialien meiner Sessions und Workshops auf der DDC 2016

Da ist sie schon wieder vorbei, die .NET Developer Conference in Köln. An den insgesamt drei Tagen plus zusätzlichem Workshoptag, durfte ich mit einer Session zu .NET Core sowie zwei Workshops zu "Moderne Softwareentwicklung" sowie "Softwarequalität" teilnehmen. An dieser Stelle möchte ich mich noch einmal bei dem Veranstalter und natürlich auch allen Teilnehmern meiner Workshops und Sessions bedanken. Wie versprochen gibt es hier nun alle Inhalte zum Download. Ich freue mich auf die DDC 2017, welche vom 28.11.2017 bis 30.11.2017 stattfinden wird.


Das für die Workshopinhalte benötigte Passwort wurde während den Workshops bekannt gegeben und kann notfalls per Mail direkt bei mir erfragt werden.

Links
Workshop Softwarequalität
Workshop Moderne Softwareentwicklung
Session .NET Core

Stefan Henneken: IEC 61131-3 – The ‘Command’ Pattern

A command can be run on a function block by calling a method. Function block A calls a method of function block B. So far, so good, but how can such “commands” be exchanged flexibly between several function blocks. The command pattern provides an interesting approach.

A small example from the home automation should help us at this. Suppose we have several FBs which represent each a device or an actuator. Each device has an individual set of commands which provide different functions.

Pic01

A further function block should display 8-button keypad. This keypad contains 8 buttons which correspond to single functionalities (commands) of the devices. The necessary commands are called in the devices via positive edge at the corresponding input.

FUNCTION_BLOCK PUBLIC FB_SwitchPanel
VAR_INPUT
  arrSwitch : ARRAY [1..8] OF BOOL;
END_VAR
VAR
  fbLamp : FB_Lamp;
  fbSocket : FB_Socket;
  fbAirConditioning : FB_AirConditioning;
  fbCDPlayer : FB_CDPlayer;
  arrRtrig : ARRAY [1..8] OF R_TRIG;
END_VAR

arrRtrig[1](CLK := arrSwitch[1]);
IF arrRtrig[1].Q THEN
  fbSocket.On();
END_IF

arrRtrig[2](CLK := arrSwitch[2]);
IF arrRtrig[2].Q THEN
  fbSocket.Off();
END_IF

arrRtrig[3](CLK := arrSwitch[3]);
IF arrRtrig[3].Q THEN
  fbLamp.SetLevel(100);
END_IF

arrRtrig[4](CLK := arrSwitch[4]);
IF arrRtrig[4].Q THEN
  fbLamp.SetLevel(0);
END_IF

arrRtrig[5](CLK := arrSwitch[5]);
IF arrRtrig[5].Q THEN
  fbAirConditioning.Activate();
  fbAirConditioning.SetTemperature(20.0);
END_IF

arrRtrig[6](CLK := arrSwitch[6]);
IF arrRtrig[6].Q THEN
  fbAirConditioning.Activate();
  fbAirConditioning.SetTemperature(17.5);
END_IF

arrRtrig[7](CLK := arrSwitch[7]);
IF arrRtrig[7].Q THEN
  fbCDPlayer.SetVolume(40);
  fbCDPlayer.SetTrack(1);
  fbCDPlayer.Start();
END_IF

arrRtrig[8](CLK := arrSwitch[8]);
IF arrRtrig[8].Q THEN
  fbCDPlayer.Stop();
END_IF

Regarding flexibility, this outline is rather suboptimal. Why?

Unflexible. There is a fixed assignment between FB_SwitchPanel and the single devices (FB_Lamp, FB_Socket, FB_CDPlayer und FB_AirConditioning). If, for example, FB_Socket has to be replaced with a second FB_Lamp, it is necessary to adapt the implementation of FB_SwitchPanel.

Missing reusability. If the buttons 3 and 4 have to serve for controlling the CD player, the necessary sequence of methods calls has to be programmed anew.

Undynamic. The 8-button keypad was implemented as a function block. As long as all key fields have the same key assignments, this approach is executable. But what if the key assignments have to be different? An individual function block has to be programmed or, instead of function blocks, programs should be used.

Definition of the Command Pattern

The solution of the problem is to introduce a software layer which is inserted between the keypad and the devices. This layer encapsulates each single command (with a command FB) and contains all relevant method calls to perform an action on the device. Thus, the 8-button keypad sees only these commands and contains no further references to the corresponding devices.

The command pattern defines three layers:

Invoker FBs of this layer trigger the required command. The invoker, the 8-button keypad FB_SwitchPanel in our example, doesn’t know the command receiver. But it knows how a command is started.
Receiver These are the FBs which represent the corresponding receiver of the commands: FB_Socket, FB_Lamp, …
Commands Each command is represented by a FB. This FB contains a reference to the receiver. Furthermore, these commands have a method to activate the command. If this method is called, the command FB knows, which methods have to be executed on the receiver to achieve the desired effect.

Let us take a close look at the command FB.

A command FB encapsulates an assignment by containing a set of actions for a certain receiver. For this purpose, the actions and the reference of the receiver are combined into one FB. Via any method (e.g., Execute()), the command FB ensures that the proper actions are executed on the receiver. The invoker doesn’t see from the exterior, which actions these actually are. It only knows, that when it calls the method Invoke(), all required steps are performed.

Commands

Below is the implementation for the command FB to run the ON command on the FB_Socket:

FUNCTION_BLOCK PUBLIC FB_SocketOnCommand
VAR
  refSocket : REFERENCE TO FB_Socket;
END_VAR

The variable refSocket contains the reference to the instance of the block FB_Socket, i.e. the receiver of the command. The reference is set via the method FB_init.

METHOD FB_init : BOOL
VAR_INPUT
  bInitRetains : BOOL;
  bInCopyCode : BOOL;
  refNewSocket : REFERENCE TO FB_Socket;
END_VAR

IF (__ISVALIDREF(refNewSocket)) THEN
  THIS^.refSocket REF= refNewSocket;
ELSE
  THIS^.refSocket REF= 0;
END_IF

The method Execute() runs the required action on FB_Socket:

METHOD Execute
IF (__ISVALIDREF(THIS^.refSocket)) THEN
  THIS^.refSocket.On();
END_IF

Depending on the receiver, this method can be also composed of several actions. Thus, the following method calls are necessary to begin playing a CD:

METHOD Execute
IF (__ISVALIDREF(THIS^.refCDPlayer)) THEN
  THIS^.refCDPlayer.SetVolume(40);
  THIS^.refCDPlayer.SetTrack(1);
  THIS^.refCDPlayer.Start();
END_IF

Since all command FBs in our example provide the method Execute() to run the command, this method is standardised by the interface I_Command. Each command FB has to implement this interface.

Invoker

The 8-button keypad (FB_SwitchPanel) should only get the information, which command FBs have to be used. The details of the command FBs doesn’t have to be known. FB_SwitchPanel knows only 8 variables that are of type I_Command. If a positive edge on a button is detected, the command FB calls the method Invoke() via the interface I_Command.

FUNCTION_BLOCK PUBLIC FB_SwitchPanel
VAR_INPUT
  arrSwitch : ARRAY [1..8] OF BOOL;
END_VAR
VAR
  aiCommand : ARRAY [1..8] OF I_Command;
  arrRtrig : ARRAY [1..8] OF R_TRIG;
  nIndex : INT;
END_VAR

FOR nIndex := 1 TO 8 DO
  arrRtrig[nIndex](CLK := arrSwitch[nIndex]);
  IF arrRtrig[nIndex].Q THEN
    IF (aiCommand[nIndex]  0) THEN
      aiCommand[nIndex].Execute();
    END_IF
  END_IF
END_FOR

Prior to this, the required command FB is assigned to the single buttons using the method SetCommand(). Thus, FB_SwitchPanel is universally applicable.

METHOD PUBLIC SetCommand : BOOL
VAR_INPUT
  nPosition : INT;
  iCommand : I_Command;
END_VAR

IF ((nPosition >= 1) AND (nPosition <= 8) AND (iCommand  0)) THEN
  THIS^.aiCommand[nPosition] := iCommand;
END_IF

The invoker FB_SwitchPanel doesn’t know the receiver. It sees only the interface I_Command with its method Execute() 8 times.

Receiver

The FBs which map a receiver doesn’t have to be adapted. A command FB can execute the required actions with the help of the corresponding methods or inputs.

Application

Below is a small example of a program, which combines an application from the three software layers shown above:

PROGRAM MAIN
VAR
  // Invoker
  fbSwitchPanel                 : FB_SwitchPanel;
     
  // Receiver
  fbSocket                      : FB_Socket;
  refSocket                     : REFERENCE TO FB_Socket := fbSocket;   
  fbLamp                        : FB_Lamp;
  refLamp                       : REFERENCE TO FB_Lamp := fbLamp;   
  fbAirConditioning             : FB_AirConditioning;
  refAirConditioning            : REFERENCE TO FB_AirConditioning := fbAirConditioning;
  fbCDPlayer                    : FB_CDPlayer;
  refCDPlayer                   : REFERENCE TO FB_CDPlayer := fbCDPlayer;
 
  // Commands
  fbSocketOnCommand             : FB_SocketOnCommand(refSocket);
  fbSocketOffCommand            : FB_SocketOffCommand(refSocket);
  fbLampSetLevel100Command      : FB_LampSetLevelCommand(refLamp, 100);
  fbLampSetLevel0Command        : FB_LampSetLevelCommand(refLamp, 0);
  fbAirConComfortCommand        : FB_AirConComfortCommand(refAirConditioning);
  fbAirConStandbyCommand        : FB_AirConStandbyCommand(refAirConditioning);  
  fbMusicPlayCommand            : FB_MusicPlayCommand(refCDPlayer);
  fbMusicStopCommand            : FB_MusicStopCommand(refCDPlayer);
 
  bInit                         : BOOL;
END_VAR
 
IF (NOT bInit) THEN
  fbSwitchPanel.SetCommand(1, fbSocketOnCommand);
  fbSwitchPanel.SetCommand(2, fbSocketOffCommand);
  fbSwitchPanel.SetCommand(3, fbLampSetLevel100Command);
  fbSwitchPanel.SetCommand(4, fbLampSetLevel0Command);
  fbSwitchPanel.SetCommand(5, fbAirConComfortCommand);
  fbSwitchPanel.SetCommand(6, fbAirConStandbyCommand);
  fbSwitchPanel.SetCommand(7, fbMusicPlayCommand);
  fbSwitchPanel.SetCommand(8, fbMusicStopCommand);
  bInit := TRUE;
ELSE
  fbSwitchPanel();  
END_IF

An instance of FB_SwitchPanel is created for 8 keys (invoker).

Likewise, an instance is declared per each device (receiver). Moreover, a reference of each instance is required.

When declaring the command FBs, the created references are passed to FB_init. If necessary, further parameters can be also transferred here. Thus, the command to set lighting has a parameter for the control value variable.

In this example, the single command FBs can be assigned to the 8 buttons with the method SetCommand(). The method expects the key numbers (1…8) as a first parameter, and an FB, which implements the interface I_Command, as a second parameter.

The resulting benefits are quite convincing:

Decoupling. Invoker and receiver are decoupled from each other. As a consequence, FB_SwitchPanel can be designed generically. The method SetCommand() provides possibility to adapt the assignment of the keys during runtime.

Expandability. Any command FB can be added. Even if FB_SwitchPanel is provided by a library, a programmer can define any command FB and use it with FB_SwitchPanel, without the need for adapting the library. Because the additional command FBs implement the interface I_Command, they can be used by FB_SwitchPanel.

Sample 1 (TwinCAT 3.1.4020)

UML class diagram

UML

All the commandos implement the interface I_Command.

The invoker has references to the commands via the interface I_Command and executes these commands if required.

One command calls all the required methods of the receiver.

MAIN sets out a link between the single commands and the receiver.

Extensions

The command pattern can be very easily expanded with further functions.

Macro command

Especially interesting is the possibility to combine any commands with one another and encapsulate in a command object. One speaks here of so-called macro commands.

A macro command has an array of commands. Up to four command FBs can be defined in this example. Since each command FB implements the interface I_Command, the commands can be stored in an array of type ARRAY [1…4] OF I_Command.

FUNCTION_BLOCK PUBLIC FB_RoomOffCommand IMPLEMENTS I_Command
VAR
  aiCommands    : ARRAY [1..4] OF I_Command;
END_VAR

The single command FBs are piped to the macro command via the method FB_init().

METHOD FB_init : BOOL
VAR_INPUT
  bInitRetains  : BOOL;
  bInCopyCode   : BOOL;
  iCommand01    : I_Command;
  iCommand02    : I_Command;
  iCommand03    : I_Command;
  iCommand04    : I_Command;
END_VAR
 
THIS^.aiCommand[1] := 0;
THIS^.aiCommand[2] := 0;
THIS^.aiCommand[3] := 0;
THIS^.aiCommand[4] := 0;
IF (iCommand01  0) THEN
  THIS^.aiCommand[1] := iCommand01;
END_IF
IF (iCommand02  0) THEN
  THIS^.aiCommand[2] := iCommand02;
END_IF
IF (iCommand03  0) THEN
  THIS^.aiCommand[3] := iCommand03;
END_IF
IF (iCommand04  0) THEN
  THIS^.aiCommand[4] := iCommand04;
END_IF

When executing the method Execute(), iteration over the array is performed and Execute() is called for each command. Thus, several commands can be executed all at once with the single Execute() of the macro command.

METHOD Execute
VAR
  nIndex  : INT;
END_VAR
 
FOR nIndex := 1 TO 4 DO
  IF (THIS^.aiCommands[nIndex]  0) THEN
    THIS^.aiCommands[nIndex].Execute();
  END_IF
END_FOR

When declaring the macro command, the four command FBs are passed in MAIN. Since the macro command is a command FB itself (it implements the interface I_Command), it can be assigned to a button in the 8-button keypad.

PROGRAM MAIN
VAR
  ...
  fbRoomOffCommand     : FB_RoomOffCommand(fbSocketOffCommand,
                                           fbLampSetLevel0Command,
                                           fbAirConStandbyCommand,
                                           fbMusicStopCommand);
  ...
END_VAR
 
IF (NOT bInit) THEN
  ...
  fbSwitchPanel.SetCommand(8, fbRoomOffCommand);
  ...
ELSE
  fbSwitchPanel();  
END_IF

Another option would be a method which passes single command FBs to the macro command. The implementation would be comparable with the method SetCommand() of the 8-button keypad. Thus, a scene controller could be implemented, with which the user can himself allocate the commands to a scene over an interactive user interface.

Sample 2 (TwinCAT 3.1.4020)

Undo functionality

A further possible feature is a cancellation function. The 8-button keypad gets a further input which undoes the last executed command. For this purpose, the interface I_Command is extended by the method Undo().

UML2

This method contains the inversion of the execute method. If a socket is switched on with the execute method, it is switched off again in the same command FB with the undo method.

FUNCTION_BLOCK PUBLIC FB_SocketOffCommand IMPLEMENTS I_Command
VAR
  refSocket : REFERENCE TO FB_Socket;
END_VAR
 
METHOD Execute
IF (__ISVALIDREF(THIS^.refSocket)) THEN
  THIS^.refSocket.Off();
END_IF
 
METHOD Undo
IF (__ISVALIDREF(THIS^.refSocket)) THEN
  THIS^.refSocket.On();
END_IF

The implementation of the undo method for setting the lamp brightness is somewhat more complex. In this case, the command FB has to be expanded with a memory. Before setting a new regulating variable via the method Execute(), the previous regulating variable is stored. When calling, the undo method uses this value to restore the previous regulating variable.

FUNCTION_BLOCK PUBLIC FB_LampSetLevelCommand IMPLEMENTS I_Command
VAR
  refLamp        : REFERENCE TO FB_Lamp;
  byNewLevel     : BYTE;
  byLastLevel    : BYTE := 255;
END_VAR
 
METHOD Execute
IF (__ISVALIDREF(THIS^.refLamp)) THEN
  THIS^.byLastLevel := THIS^.refLamp.Level; 
  THIS^.refLamp.SetLevel(THIS^.byNewLevel);
END_IF
 
METHOD Undo
IF (__ISVALIDREF(THIS^.refLamp)) THEN
  IF (THIS^.byLastLevel  255) THEN
    THIS^.refLamp.SetLevel(THIS^.byLastLevel);
  END_IF
END_IF

After the command FBs were expanded with a undo method, the 8-button keypad must also be adjusted.

FUNCTION_BLOCK PUBLIC FB_SwitchPanel
VAR_INPUT
  bUndo         : BOOL;
  arrSwitch     : ARRAY [1..8] OF BOOL;
END_VAR
VAR
  aiCommand     : ARRAY [1..8] OF I_Command; 
  arrRtrig      : ARRAY [1..8] OF R_TRIG;
  iLastCommand  : I_Command;
  fbRtrigUndo   : R_TRIG;
  nIndex        : INT;
END_VAR
 
FOR nIndex := 1 TO 8 DO
  arrRtrig[nIndex](CLK := arrSwitch[nIndex]);
  IF arrRtrig[nIndex].Q THEN
    IF (aiCommand[nIndex]  0) THEN
      aiCommand[nIndex].Execute();
      iLastCommand := aiCommand[nIndex];
    END_IF
  END_IF
END_FOR
 
fbRtrigUndo(CLK := bUndo);
IF fbRtrigUndo.Q THEN
  IF (iLastCommand  0) THEN
    iLastCommand.Undo();
  END_IF
END_IF

In line 19, the last executed command is stored temporarily. When activating the undo function, this command can be used and the undo method is executed (line 27). The details of the inversion of a command are implemented in the command FB. The 8-button keypad refers to the single commands only via the interface I_Command.

Sample 3 (TwinCAT 3.1.4020)

Logging of commands

Since each command FB implements the interface I_Command, each command can be stored in a variable of type I_Command. For example, the undo functionality would make use of it. If this variable is replaced with a buffer, we get an opportunity to log the commands. The analysis and the diagnosis of an equipment can be facilitated in this way.

Summary

The central idea of the command pattern is decoupling of the invoker and the receiver by means of command objects.

•    A developer can add new command FBs without adapting the code of the invoker (8-button keypad).
•    The assignment of the commands to the invoker can be performed dynamically during runtime.
•    Command FBs can be reused at various points. Thus, code redundancy is prevented.
•    Commands can be made “intelligent”. In this way, macro commands and undo commands can be implemented.


Johannes Renatus: Angular 2 mit webpack 2 mit ts, less, sass Loader für Anfänger in Visual Studio 2015 (Webpack Version – Beta 27)

Wäre die Welt nicht schön, wenn man sich nur mit Angular 2 beschäftigen könnte und nicht noch über das Deployment für den Live Betrieb nachdenken muss. Denn dann wäre die Standardinstallation von Angular 2 mit SystemJs völlig ausreichend. Wenn man allerdings seine erste kleine Angular 2 Anwendung erstellt hat, dann merkt man schnell das man […]

Jürgen Gutsch: Contributing to OSS projects on GitHub using fork and upstream

Intro

Some days ago, Damien Bowden wrote a pretty cool post about, how to contribute to an open source software project hosted on GitHub, like the AspLabs. He uses Git Extensions in his great and pretty detailed post. Also a nice fact about this post is, that he uses a AspLabs as the demo project. Because we both worked on that on the hackathon at the MVP Summit 2016, together with Glen Condron and Andrew Stanton-Nurse from the ASP.NET Team.

At that Hackathon we worked on the HealthChecks for ASP.NET Core. The HealthChecks can be used to check the heath state of dependent sub systems in an e. g. micro service environment, or in any other environment where you need to know the health of depending systems. A depending systems could be a SQL Server, an Azure Storage service, the Hard drive, a Web-/REST-Service, or anything else you need to run your application. Using the HealthChecks you are able to do something, if a service is not available or unhealthy.

BTW: The HealthChecks are mentioned by Damian Edwards in this ASP.NET Community Standup: https://youtu.be/hjwT0av9gzU?list=PL0M0zPgJ3HSftTAAHttA3JQU4vOjXFquF

Because Damien Bowden also worked on that project, my idea was to do the same post. So asked him to "fork" the original post, but use the Git CLI in the console instead of Git Extensions. Because this is a fork, some original words are used in this post ;)

Why using the console? Because I'm a console junkie since a few years and from my perspective, no Git UI is as good as the simple and clean Git CLI :) Anyway, feel free to use the tool that fits your needs. Maybe someone will write the same post using SourceTree or using the Visual Studio Git integration. ;)

As a result this post is a also simple guideline on how you could contribute to OSS projects hosted on GitHub using fork and upstream. This is even not the only way to do it. In this demo I'm going to use the console and the basic git commands. As same as Damien did, I'll also use the aspnet/AspLabs project from Microsoft as the target Repository.

True words by Damien: So you have something to contribute, cool, that’s the hard part.

Setup your fork

Before you can make your contribution, you need to create a fork of the repository where you want to make your contribution. Open the project on GitHub, and click the "Fork" button in the top right corner.

Now clone your forked repository. Click the "Clone and download" button and copy the clone URL to the clipboard.

Open a console and cd to the location where you want to place your projects. It is c:\git\ in my case. Write git clone followed by the URL to the repository and press enter.

Now you have a local master branch and also a server master branch (remote) of your forked repository. The next step is to configure the remote upstream branch to the original repository. This is required to synchronize with the parent repository, as you might not be the only person contributing to the repository. This is done by adding another remote to that git repository. On GitHub copy the clone URL the the original repository aspnet/AspLabs. Go back to the console and type git remote add upstream followed by the URL of the original repository:

To check if anything is done right, type git remote -v, to see all existing remotes. It should look like this:

Now you can pull from the upstream repository. You pull the latest changes from the upstream/master branch to your local master branch. Due to this you should NEVER work on your master branch. Then you can also configure your git to rebase the local master with the upstream master if preferred.

Start working on the code

Once you have pulled from the upstream, you can push to your remote master, i. e. the forked master. Just to mention it again, NEVER WORK ON YOUR LOCAL FORKED MASTER, and you will save yourself hassle.

Now you’re ready to work. Create a new branch. A good recommendation is to use the following pattern for naming:

<gitHub username>/<reason-for-the-branch>

Here’s an example:

JuergenGutsch/add-healthcheck-groups

By using your GitHub username, it makes it easier for the person reviewing the pull request.

To create that branch in the console, use the git checkout -b command followed by the branch name. This creates the branch and checks it out immediately:

Creating pull requests

When your work is finished on the branch, you need to push your branch to your remote repository by calling git push Now you are ready to create a pull request. Go to your repository on GitHub, select your branch and and click on the "Compare & pull request" button:

Check if the working branch and the target branch are fine. The target branch is usually the master of the upstream repo.

NOTE: If your branch was created from an older master commit than the actual master on the parent, you need to pull from the upstream and rebase your branch to the latest commit. This is easy as you do not work on the local master. Or update your local master with the latest changes from the upstream, push it to your remote and merge your local master into your feature branch.

If you are contributing to any Microsoft repository, you will need to sign an electronic contribution license agreement before you can contribute. This is pretty easy and done in a few minutes.

If you are working together with a maintainer of the repository, or your pull request is the result of an issue, you could add a comment with the GitHub name of the person that will review and merge, so that he or she will be notified that you are ready. They will receive a notification on GitHub as soon as you save the pull request.

Add a meaningful description. Tell the reviewer what they need to know about your changes. and save the pull request.

Now just wait and fix the issues as required. Once the pull request is merged, you need to pull from the upstream on your local forked repository and rebase if necessary to continue with you next pull request.

And who knows, you might even get a coin from Microsoft. ;)

The console I use

I often get the question what type console I use. I have four consoles installed on my machine, in addition to the cmd.exe and PowerShell. I also installed the bash for Windows. But my favorite console is the Cmder, which is a pretty nice ConEmu implementation. I like this console because it is easy to use, easy to customize and it has a nice color theme too.

Thanks

Thanks to Andrew Stanton-Nurse for his tips. Thanks to Glen Condron for the reviews. thanks Damien Bowden for the original blog post ;)

I'd also be happy for tips from anyone on how to improve this guideline.

Golo Roden: Dokumentation schreiben in 30 Minuten

Eine gute Dokumentation ist äußerst wertvoll, trotzdem scheuen die meisten Entwickler den Aufwand, sie zu schreiben. Dabei muss das Entwerfen einer guten Dokumentation weder langwierig noch aufwendig sein. 30 Minuten genügen in der Regel vollkommen.

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