codefest.at [MS]: Neues im Office 365 Developer Podcast

Office 365 ist eine Developer Plattform. Als Einstieg in die Entwicklung stellt Microsoft die http://dev.office.com/ Website bereit. Neben den umfangreichen Informationen für den optimalen Start und vielen Demos gibt es auch eine weitere aktuelle Bezugsquelle, die wenig Developern bekannt ist: den Office 365 Developer Podcast. Davon gibt es nun die 100.te Ausgabe!

image

Software-Entwickler finden im Office Dev Center den Einstieg in das Office Development.

Das Office 365 Dev Team bei Microsoft feiert nun den 100.ten Podcast – und zwar mit prominenten Gästen!

Episode 100 with Corporate Vice President Jeff Teper on Future of SharePoint—Office 365 Developer Podcast

image

Hier sprechen Coding-Guru Richard diZerega und Andrew Coates, die Jeff Teper, Corporate Vice President of SharePoint and OneDrive, als Gast begrüßen dürfen. Unter anderem ist auch Jeremy Thake mit dabei, der vorige Produzent des Office 365 Developer Podcasts.

Viel Spaß mit den Podcasts und der Jubiläumsausgabe des Office 365 Developer Podcasts!

Sven Hubert: New release of TFS ASAP for TFS 2015 Update 3

We are proud to present the new release of our TFS Automated Servicing and Administration Platform (TFS ASAP). Besides some minor bug fixes, this version supports update 3 of Microsoft Team Foundation Server 2015. In addition, we improved the usability of the Global Lists Editor.

Administering global lists in TFS is not straight forward. Out of the box, this can only be achieved by using command line or the TFS Power Tools. Both ways require the user to be member of the Project Collection Administrators group. Thus, the number of users who can maintain global lists and their entries are very limited. To remove this limitation TFS ASAP provides the Global Lists Editor, a web based administration platform.

Global List

Within this web page, global lists can be created, updated and deleted. By sorting the global lists and its entries alphabeticaly it should now be easier to find the items you are looking for. New entries are always added on top of the list until the next page load. There is also the option to enable users who are not in the Project Collection Administrators group to maintain global lists by creating a dedicated TFS group. For detailed information about this feature please refer to our user manual (chapter 6).

The installer (Build 14.30.16202.1) can be downloaded here and for further information please visit www.tfsasap.com. If you don’t have a licence key, you can request a trial at support@tfsasap.com.

Marco Scheel: Links for 2016-07-21 [del.icio.us]

  • Object moved
    Last month, we announced an updated approach to the transition of mobile and desktop apps from Visual Studio Application Insights to HockeyApp. To recap that announcement: any existing Mobile and Desktop apps will now have a linked HockeyApp app. via Pocket
  • Microsoft to support Stack Overflow Documentation for Microsoft developers - MSPoweruser
    Microsoft today announced partnership with Stack Overflow to support Stack Overflow Documentation for Microsoft developers. Stack Overflow Documentation is a new community-curated, example-focused developer documentation, based on the principles of Stack Overflow. via Pocket

codefest.at [MS]: Willkommen bei Microsoft AppSource

Die Art und Weise, wie wir heute Software und Services verwenden hat sich geändert. Heutzutage sind wir gewohnt, Apps rasch und einfach zu finden, zu installieren, anzusehen und zu verwenden. Um dieses Konzept auch im Business-Bereich umsetzen zu können, sind moderne Apps und eine entsprechende Infrastruktur erforderlich. Der neue AppSource Store macht dies möglich.

Der AppSource Store läuft ganz unter dem Motto “Find the right app for your business needs - Get solutions tailored to your industry that work with the products you already use”. Hier werden Lösungen für die Bereiche Microsoft Dynamics, Power BI, Office 365 und Azure gelistet.

Der AppSource Store steht unter https://appsource.microsoft.com bereit.

image

Der AppSource Store wird im Artikel Turning business process into business advantage for organizations everywhere unter blogs.microsoft.com vorgestellt.

AppSource kann nach Lösungen nach Kategorien, Branchen und Produkten gefiltert werden, wie etwa hier in diesem Beispiel.

image

 

Für Software-Entwickler ist diese Plattform interessant, um eigene Lösungen hier anzubieten.

image

Es sind nur wenige Felder auszufüllen, nämlich das Unternehmen, Kontaktinfos und eine kurze App-Beschreibung. Relevant ist natürlich auch die Art der App/Lösung:

image

Das wars auch schon. Nach dem Submit folgt eine kurze Info, dass sich Microsoft melden wird, um Details über die Lösung zu erfragen: “Thanks for telling us about your app! We’ll reach out to you with next steps soon”.

Wir sehen uns im AppSource Store…

Marco Scheel: Links for 2016-07-20 [del.icio.us]

Uli Armbruster: Should I stay or should I go: Wechselmotive analyisieren

In unserem Video, welches sich an Bewerber für die co-IT.eu GmbH richtet, sprechen wir das Thema Wechselgründe an. Die folgende Linksammlung soll euch bei eurer Entscheidung helfen.

 

 

Wir werden die Liste kontinuierlich erweitern, sofern wir gut Artikel finden. Der geneigte Leser kann gerne weitere Vorschläge einreichen oder von seinen Erfahrungen berichten.


Einsortiert unter:German, Links, Misc Tagged: Gehalt, Retrospektive, Stellenausschreibung

Sven Hubert: WiX Toolset Teil 5: Access denied! – Permissions setzen leicht gemacht

Herzlich willkommen zum fünften Teil der WiX-Blog-Serie. Jeder, der im Alltag mit Computern arbeitet, kommt irgendwann an einen Punkt, an dem Administratoren-Rechte auf dem System sehr hilfreich wären, um ein Problem schnell und unkompliziert zu lösen. Aus Sicht des IT-Supports wäre das gleichzusetzen mit absoluter Anarchie. Jeder macht was er will, keiner macht was er soll, aber alle machen mit. Beschränkungen stellen in der Regel sicher, dass nur diejenigen, die ganz genau wissen, was sie tun, tiefere Eingriffe in ein bestehendes System durchführen können. Dies gewährleistet einen konsistenten Zustand des Gesamt-Systems.

Trotzdem müssen auch Anwendern in bestimmten Bereichen weitreichende Rechte eingeräumt werden. Eine installierte Anwendung, die vom angemeldeten Nutzer zwar gesehen, aber nicht ausgeführt werden darf, kann auch nicht die Arbeitsleistung verbessern. Eine Anwendung, die eine Datei-basierte Datenbank benutzt, auf welcher der Anwender aber keine Schreib-Rechte hat, wird keine Daten persistieren können. Berechtigungen müssen also schon vor der ersten Ausführung einer Anwendung gesetzt werden. Am besten schon während der Installation. Dazu sind während der Installation zwar temporäre Administrations-Rechte nötig, diese werden bei vielen Firmen im Verteilungskonzept einer Software aber berücksichtigt. Wie sieht die Rechte-Vergabe mit Hilfe von WiX also aus?

Um das zu beantworten muss unterschieden werden zwischen drei zur Verfügung stehenden Elementen. Die Elemente Permission, PermissionEx und util:PermissionEx haben alle das gleiche Ziel: Berechtigungen setzen. Sie verfolgen jedoch verschiedene Wege um ans Ziel zu kommen.

Das Element PermissionEx ist ein mit WiX mitgeliefertes Element zum Schreiben von Berechtigungen. Es besitzt zwei Attribute: eine ID und einen SDDL-String (Security Descriptor Definition Language). Dieses Element ist nur für Installationsprojekte, die auf MSI 5.0 aufbauen verfügbar. Über den SDDL-String werden die genauen Berechtigungen des übergeordneten Elementes bestimmt. Denn eines haben alle Permission Elemente geminsam: Sie müssen stets einem anderen Element zugeordnet werden. Dies kann ein CreateFolder, ein File oder ein RegistryKey/Value Element sein. Somit werden die Berechtigungen auf einem Element gesetzt, das einem Component, und damit einem DirectoryRef-Element zugeordnet ist. Die Arbeit mit SDDL-Strings ist jedoch etwas gewöhnungsbedürftig und benötigt Einarbeitung, daher ist das PermissionEx-Element nicht für den Einstieg geeignet und soll hier nicht weiter betrachtet werden. Mehr Informationen über die Handhabung der SDDL-Strings findet man bei MSDN oder in verschiedenen Tutorials.

Das ebenfalls im Standard-WiX-Paket enthaltene Permission-Element kann mehrere Attribute beinhalten. Hier werden einzelne Berechtigungen über einzelne Attribute erteilt oder verweigert. Anders als das PermissionEx-Element, muss auch der User und die Domain des Users über ein Attribut definiert werden. Hierbei wird deutlich, dass ein Element auch mehrere Permission, beziehungsweise PermissionEx Elemente beinhalten kann, um unterschiedlichen Benutzern verschiedene Rechte-Sets zuzuweisen. Hierbei ist jedoch zu beachten, dass durch das Permission-Element, alle ACLs (Access Control List) überschrieben werden und somit nur noch die definierten Rechte-Sets gelten. Dies birgt bei unbedachtem Einsatz die Gefahr, sich selbst auszusperren. Im folgenden Beispiel gelten nach der Installation ausschließlich die definierten Rechte-Sets:

18-07-2016 15-54-24

Das letzte Element, das util:PermissionEx Element, ist kein Bestandteil des eigentlichen WiX-Pakets. Es ist in der Util-Extension enthalten und kann durch xmlns:util=“http://schemas.microsoft.com/wix/UtilExtension“ in den Installer eingebunden werden. Im Großen und Ganzen ähnelt das util:PermissionEx-Element dem mitgelieferten Permission-Element des WiX-Pakets. Der größte Unterschied ist jedoch, dass durch das util:PermissionEx-Element die ACLs nicht überschrieben, sondern modifiziert werden. Somit bleiben bestehende Berechtigungen, wie etwa der volle Zugriff für Administratoren, unberührt. Ein weiterer Vorteil des util:PermissionEx Elementes ist, dass ohne weiteres Zutun alle Unterordner die gleichen Berechtigungen wie der definierte Ordner erhalten.

Im Falle von Permission und util:PermissionEx werden Permissions einzeln als Attribut vergeben. Das Attribut Read setzt beispielsweise die Lese-Rechte des angegebenen Nutzers. Darüber hinaus existieren noch allgemeinere Rechte-Sammlungen. Neben GenericAll, was alle Rechte beinhaltet, gibt es noch GenericRead oder GenericWrite. Diese beinhalten verschiedene Rechte, die zum Lesen beziehungsweise Schreiben benötigt werden. Diese können nicht einzeln verboten werden, da sie implizit auch das Recht Synchronize beinhalten. Somit würde eine Anfrage für GenericRead fehlschlagen wenn GenericWrite verboten ist. Es wird daher empfohlen, explizit nur mit dem Erlauben von Rechten zu arbeiten, um solche impliziten Verkettungen auszuschließen.

Ein weiteres Pflicht-Attribut ist der User. Damit wird der Nutzer, für den die Berechtigung gesetzt werden soll, bestimmt. Dabei sind bestimmte Schlüsselwörter bereits vorhanden. Everyone, Administrators und Users werden auf jedem System erkannt. Darüber hinaus können weitere Benutzer beziehungsweise Gruppen angegeben werden. Dazu kann über das Domain-Attribut auch die entsprechende Domain  angegeben werden. Dies führt jedoch dazu, dass Installer an ein bestimmtes System angepasst werden müssen. Für interne Software einer Firma ist dies irrelevant, da nur das eigene System unterstützt werden muss. Falls das Zielsystem aber unbekannt ist, sollten nur die obigen allgemein erkannten Schlüsselwörter genutzt werden. Wesentlich einfacher kann dabei die Verwendung von Properties sein, die in Custom Actions mit den entsprechenden Werten gefüllt werden. Im folgenden Beispiel bleiben die bestehenden Rechte des Systems erhalten und werden entsprechend angepasst:

18-07-2016 15-50-29

Ausblick

Zu guter Letzt besteht natürlich immer die Möglichkeit, spezielle Wünsche über Custom Actions umzusetzen. Mit den Custom Actions sind dem Entwickler kaum noch Grenzen gesetzt, welche Vorgänge und Anpassungen während einer Installation durchgeführt werden sollen. Wie das aussieht, wird im nächsten Teil der WiX-Blog-Serie beleuchtet.

Uli Armbruster: Tools for Developers Session vom NET Open Space 2016

Zur Session „Tools & Practices for Developers“ habe ich mir Notizen gemacht. Wie versprochen findet ihr hier aufgelistet die genannten Tools. Ich habe nicht alle aufgeschrieben, also postet gerne weitere, wenn euch eines fehlt.

Mein Antrieb hinter der Session war der, dass ich meine tägliche Arbeit versuche so weit es geht zu optimieren und automatisieren. Wenn ich pro Tag 10 Minuten einsparen kann,was z.B. alleine durch TotalCommander möglich ist, so ergibt sich pro Jahr eine freigewordene Zeit von 43,5h.

 

Keepass Plugins

meine Keepass Plugins

Wenn ihr noch wichtige Tools aus eurer täglichen Arbeit nicht aufgelistet findet, dann schreibt mir und ich füge sie hinzu.

 

 

 


Einsortiert unter:German, Links, Misc Tagged: Community, Open Space

Marco Scheel: Links for 2016-07-17 [del.icio.us]

codefest.at [MS]: Microsoft Cognitive Services Emotion API Teil 4

Neben der Face-API habe ich kürzlich die Emotion API der Microsoft Cognitive Services ausprobiert. Beide Services basieren auf Machine Learning und interpretieren Gesichter aus Fotos (bzw. auch aus Videos). Während die Face API Basisinformationen über ein Gesicht liefern, versucht die Emotion API den Gesichtsausdruck von erkannten Gesichtern in Zahlen zu fassen. Die Emotion API beurteilt einen Ausdruck in verschiedenen Kategorien und liefert Wahrscheinlichkeiten retour. Das Ganze sieht dann so aus…

Der Startpunkt für die Emotion API ist https://www.microsoft.com/cognitive-services/en-us/emotion-api und die Documentation.

Auch hierfür gibt es ein Tutorial Get Started with Emotion API in C#, auf GitHub steht das Microsoft/Cognitive-Emotion-Windows Projekt zum Download bereit. Die Repo enthält die Windows Client Library und ein Beispiel mit einer Windows-App.

Build…

Allerdings ist für Windows SDK for the Microsoft Emotion API etwas Handarbeit nötig, um das Projekt zum Laufen zu bekommen. Das Projekt SampleUserControlLibrary muss extra geladen und in die Solution eingebunden werden. Dann lädt man noch in der NuGet Console das Paket Install-Package Microsoft.ProjectOxford.Emotion und fügt die Reference zum SampleUserControlLibrary in das EmotionAPI-WPF_Samples Project hinzu. Dann klappts auch mit dem Compile.

Ausprobieren

Nachdem diese technischen Voraussetzungen erfüllt sind, und die Solution ge-build-et werden kann, kann der Start der WPF App erfolgen. Das Demo startet mit der erforderlichen Key-Aufforderung.

image

Hier wird also zunächst der eigene “Emotion-Preview” Key benötigt. Diesen erhält man von https://www.microsoft.com/cognitive-services/en-us/subscriptions. Der kostenfrei Key kann für 30,000 transactions per month und 20-mal pro Minute verwendet werden. Diesen kopiert man und trägt in hier in das Subscription Key Feld ein und klickt auf Save Key. Damit wird der eigene Key auf die eigene Festplatte gespeichert und steht für die Zukunft in dieser App bereit.

Detect emotion using a stream

Beim Fortsetzen kann nun ein Bild oder ein Video ausgewählt werden. Ich habe diesmal ein Bild von mir verwendet, das nicht so neutral wie jenes von der Face API ist, sondern wo ich mir ein Lächeln abgerungen habe. Hinweis: In den Nutzungsbedingungen steht auch klar, dass Personen im Bild damit einverstanden sein müssen, dass das Bild hier verwendet wird… Gut, ich bin einverstanden.

Das Ergebnis sieht hier, mit der Emotion API, wie folgt aus:

image

Die Ergebnisse im Detail:

[17:17:44.959642]: EmotionServiceClient is created
[17:17:44.985143]: Calling EmotionServiceClient.RecognizeAsync()...
[17:17:46.279940]: Detection Result:
[17:17:46.282933]: Emotion[0]
[17:17:46.285444]:   .FaceRectangle = left: 122, top: 49, width: 53, height: 53
[17:17:46.287934]:   Anger    : 0.0003246186
[17:17:46.289450]:   Contempt : 0.002541366
[17:17:46.290972]:   Disgust  : 0.003764645
[17:17:46.297973]:   Fear     : 8.104636E-07
[17:17:46.299971]:   Happiness: 0.7857869
[17:17:46.302971]:   Neutral  : 0.2070151
[17:17:46.304972]:   Sadness  : 7.317301E-05
[17:17:46.307971]:   Surprise  : 0.0004933038

Man sieht hier also die erkannte Wahrscheinlichkeiten in verschiedenen Kategorien (Anger, Contempt, Disgust, Fear, Happiness, Neutral, Sadness, Surprise). Die Kategorien mit der höchsten Wahrscheinlichkeit werden neben dem Foto zusammengefasst. In meinem Beispiel sind das Happiness mit 78%, gefolgt von Neutral mit 20% und Disgust mit 0,3%. Witzig, 0,3% “Abscheu” hätte ich nicht interpretiert, allerdings ist das in diesem Beispiel auch völlig vernachlässigbar. Alle anderen Faktoren (wie Geringschätzung, Angst, Traurigkeit) werden von der Emotion API mit einer noch geringeren Wahrscheinlichkeit bewertet.

Technisch gesehen erfolgt das Ermitteln der Emotionen wie folgt.

image

…hier folgt dann die UploadAndDetectEmotions Methode mit dem Client (SDK) in DetectEmotionUsingStreamPage.xaml.cs. Diese erzeugt den Client mit dem Subscription Key und lädt das Bild in das Service.

image

…und die Ausgabe dieses Szenarios aus dem Beispiel durch Durchlaufen der emotionResult-Collection.

image

Weitere Szenarien funktionieren nach demselben Prinzip.

Detect emotion using a URL

Die zweite Option “Detect emotion using a URL” macht dasselbe, nur dass eben ein Bild-URL verwendet werden kann.

image

Wenn das Bild nicht entspricht (wie in meinem Fall), zeigt die API mögliche Ursachen an:

No emotion is detected. This might be due to:

  • image is too small to detect faces
  • no faces are in the images
  • faces poses make it difficult to detect emotions
  • or other factors

Mein Versuchsbild von der URL ist nur 150 Pixel breit und viel zu pixelig, um für brauchbare Ergebnisse verwendet zu werden. Verständlich, wenn sich die API dann beschwert.

Detect emotion using a video

Hierbei muss das Videofile als .mp4, .mov oder .wmv File auf der Festplatte vorliegen. Dieses wird nach der Auswahl zur Analyse an die Emotion API upgeloadet. Das Ergebnis wird in EmotionDetectionUsingVideoPage.xaml.cs von der async-Methode emotionServiceClient.GetOperationResultAsync(videoOperation) geliefert.

image

Ein Video wird in verschiedene Sequenzen zerlegt und analysiert. Das dauert natürlich je nach Video einige Zeit… mein Beispielvideo war zwar nur etwa 14 Sekunden lang, der Upload und die Analyse dauerte rund 3 Minuten.

image

Das Ergebnis der Videoanalyse zeigt die “Top 3 Emotions”. In diesem Video habe ich viele unterschiedliche Gesichtsausdrücke ausprobiert, von happy, über erstaunt bis neutral. Mein Ergebnis sah dann so aus:

image

Die Top 3 Kategorien meines Kurzvideos waren Neutral (51%), Erfreut (46%) und Verärgert (0,5%).
Mein Ausdruck für “überrascht” scheint wohl in Happiness aufgegangen zu sein. Winking smile

Hier der JSON-Output des ersten Gesichtsausdrucks (offensichtlich der Ausdruck “Happy”, visualisiert mit jsonvisualizer.com):

SNAGHTML11bc727

Aus dem Array werden dann die Top 3 Ausdrücke ausgegeben. So kann dann durch die Ergebnisse gelaufen werden und diese weiterverwendet werden.

Fazit

Die Emotion API stellt neben der Face API ein weiteres, cooles Cloud Service aus den Microsoft Cognitive Services dar. Bei Bildern funktionierte die Erkennung in meinem Beispielen ziemlich gut. Bei Videos ist das schwerer zu beurteilen und nachzuvollziehen. Auf jeden Fall sind beide Services für mich sehr beeindruckend. In zukünftiger Software (auch abseits von Spaß-Apps) wird es bestimmt Anwendungsfälle geben - mir fallen hier neben Überwachungsaspekten vor allem Beispiele in Bezug auf Menschen mit Behinderungen ein -, wo der Einsatz und die Bewertung der Gesichtserkennung Sinn macht.

Somit meine Empfehlung: Eine coole Sache. Am besten einmal die Beispiele selbst ausprobieren und damit experimentieren!

 

Quicklinks zu den vorigen Teilen dieser Serie über Cognitive Services:

Marco Scheel: Links for 2016-07-16 [del.icio.us]

codefest.at [MS]: Microsoft Cognitive Services Teil 3

In den ersten beiden Teilen über die Microsoft Cognitive Services ging es um die Face-API.Die Cognitive Services sind jedoch sehr umfangreich und bieten eine ganze Reihe von interessanten Beispielen, welche die Verwendung demonstrieren.

Viele Beispiele für die Microsoft Cognitive Services sind auf der SDKs & Samples SDKs & Samples Website aufgelistet.

image

Viele Samples liegen auf GitHub oder können direkt von dort bezogen werden. Bitte nicht vergessen, dass für die einzelnen Services ein eigener API-Key erforderlich ist, der von https://www.microsoft.com/cognitive-services/en-us/subscriptions bezogen und verwaltet werden kann. Die Liste kann nach Plattform und API gefiltert werden.

Ein Service, das wahrscheinlich oft in eigenen Apps/Webapps genutzt werden kann, ist das Microsoft Bot Framework: “Your bots — wherever your users are talking.”. In diesem Sinne ist ein “Bot” etwas Gutes. Er soll Benutzern Hilfestellung durch natürliche Fragen und Antworten geben. Der Startpunkt für Bots ist https://dev.botframework.com/.

image

Zum Entwickeln eigener Bots steht das Bot Framework Developer Portal bereit. Hier können eigene Bots registriert und konfiguriert werden, gewünschte Channels gewählt werden und der Bot im Bot Directory veröffentlicht werden. Alle so registrierten Bots sind auto-configured umd mit Skype und dem Web zu funktionieren.

Hinweis: Das Microsoft Bot Framework wurde bei der BUILD Conference vorgestellt. Mittlerweile, rund 3 Monate später, gibt es hier bereits Neuerungen und es liegt bereits die API V3 vor: Upgrade your bot to V3.

Viel Spaß beim Ausprobieren der Services!

Marco Scheel: Links for 2016-07-15 [del.icio.us]

Martin Richter: Samsung S4 (I9500 und I9295) mit Android 5.01 stürzen ab, wenn man die Google Kontoeinstellungen bearbeiten will

Vor über 2 Monaten fing es an. Nach irgend einem Update konnte ich auf einmal die Kontoeinstellungen meines Google Accounts auf meinem Samsung S4 Active mit Android 5.01 nicht mehr erreichen. Einstellungen -> Konten -> Google und Crash, Anwendung wird angehalten.

Relativ schnell fand ich Leidensgenossen im Netz, denen es genauso geht. Der häufigste Kommentar der Experten war: „Warten auf ein neues Google-Play-Store Update“. Andere setzten tatsächlich ihr Handy zurück und machten die wildesten Klimmzüge. Resultat war: Nach dem nächsten Update lief es wieder nicht.

Bis dato war es mir erstmal egal, aber jetzt wollte ich doch eine Einstellung ändern. Also noch mal gegoogelt und gleich in mehreren Threads einen simplen Workaround gefunden, wie man doch an sein Konto kommt und den Tipp möchte ich Euch auch gerne zukommen lassen:

  • Einfach Gallerie App öffnen
  • Einstellungen auswählen
  • Und da findet man auch das verwendete Google Konto.

Hier stürzt nichts ab und man kann die entsprechenden Einstellungen vornehmen.

Siehe unter anderem hier und auch hier.


Copyright © 2010 Martin Richter
Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.
(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)

codefest.at [MS]: Microsoft Cognitive Services Face API Teil 2

In Teil 1 ging es um das Erstellen einer einfachen App, um Gesichter auf Fotos mit der Face-API zu erkennen. Nun geht es darum, mehr über die Gesichter zu erfahren…

Ich habe das Beispiel aus dem Tutorial Get Started with Face API in C# etwas erweitert. Hier sehen wir das bisherige Ergebnis mit einer Person (mir) und dem erkannten Gesichtsfeld auf dem Foto. Sehen wir uns an, was die Face-API noch alles kann und welche Daten sie uns für eigene Apps liefern kann…

image_thumb[10]

Dazu habe ich das Sample (Code siehe hier) mit den Infos von der Face-API - How to Detect Faces in Image erweitert und mit demselben Bild (und weiteren, s.u.) experimentiert.

Somit habe ich einfach das verwendete Bild erneut mit FaceAttributes an das Service gesendet:

faceServiceClient.DetectAsync(s, returnFaceLandmarks: true, returnFaceAttributes: requiredFaceAttributes)

Der Screenshot zeigt die möglichen Attribute (Age, Gender, Smile, FacialHair, HeadPose, Glasses).

image_thumb[18]

Das Ergebnis und die erkannten Merkmale sind beeindruckend… von Alter, Geschlecht, Brillenträger-Info bis zum Smile-Faktor mit einer Wahrscheinlichkeit (0 bis 1 = 100%). Cool, oder?

image_thumb[22]

Schöner wird das Ganze, wenn man die Ergebnisse serialisiert und so ausgeben lässt:

var json = JsonConvert.SerializeObject(face);

image

Beim Erforschen entdeckt man weitere interessante Details… etwa in FacialHair, ob ein Bart, Schnurrbart oder Kotletten erkannt wurden.

Geliefert werden auch die X und Y-Position der wichtigsten Gesichtsmerkmale im Bild (FaceLandmarks). Das kann hilfreich für das Erkennen von Gesichtsausdrücken und für die Steuerung der eigenen App sein.

image

Diese Eigenschaften sind hier visualisiert.

image

…sowie die Haltung des Kopfes. In meinem Beispiel ist Pitch 0 Grad, Roll –1.8 Grad und Yaw +1 Grad. Die Person im Bild oben hat den Kopf ganz leicht nach links geneigt.

image

Die folgende Grafik aus dem Glossar und Infos aus Face API - V1.0 helfen, die Werte zu verstehen.

image

Natürlich habe ich auch mit weiteren Beispielbildern experimentiert. Bei einem Bild eines (grinsenden = 93% Wahrscheinlichkeit) Brillenträges (ReadingGlasses) hat das auch brav funktioniert…

image

Ebenso hat mein Versuch mit einem Bild von Martina gut geklappt… Winking smile

image_thumb[43]

image

Natürlich musste ich auch ein (spätes) Foto von Elvis Presley ausprobieren… es wäre wegen den Kotletten. Viel mehr Sideburns geht bei dem Foto (das ich aus Copryright Gründen hier nicht poste) eigentlich nicht, aber – you get the idea - die Sideburns werden erkannt: 0.2 und Beard 0.3. Das Alter…hm auch Elvis war mal jung…

image

Zugegeben, ich bin von diesem Service recht beeindruckt. Wie in Teil 1 erwähnt, muss die Qualität der Bilder, die Auflösung, die Lichtverhältnisse und die Konstellation der Personen für eine korrekte Erkennung natürlich ausreichen. Bei meinen Versuchen erkannte die Face-API – bei guter Bildqualität - recht zuverlässig Daten aus den Fotos. Umgekehrt gab es auch Fotos, wo gar keine Gesichter erkannt wurden.

Die Face-API liegt derzeit (siehe Endpoint https://api.projectoxford.ai/face/v1.0/detect) als Version 1.0 vor. Offensichtlich wird für die Public-Demo http://how-old.net/ eine ältere Version verwendet, diese liefert teilweise unterschiedliche Ergebnisse. Zum Herumspielen ist die Website aber allemal gut. Aus meiner Sicht liefert das eigene V1 Demo jedoch bessere Ergebnisse. Wichtig ist auch der Gesichtsausdruck. Je neutraler (Stichwort Passfoto), desto genauer ist auch die Altersermittlung.

Manche Cognitive Services können in eigenen Applikationen durchaus Sinn machen. Die Verwendung (der Face-API) ist denkbar einfach. Alleine die Möglichkeit solche Funktionen einfach zu benutzen (und nicht selbst entwickeln oder zukaufen zu müssen), beflügeln Gedanken zur Integration in eigene Software-Lösungen.

Die Spielwiese ist eröffnet! Viel Spaß beim Erforschen der Microsoft Cognitive Services!

In Teil 3 gibts dann noch Hinweise für weitere Beispiele.

Kay Giza [MS]: Visual Studio Code 1.3 - Tabs, Extensions View und mehr Neuigkeiten

Visual Studio Code (VSCode) hat mir Version 1.3 einige entscheidende Verbesserungen und Highlights erhalten. In diesem Blogeintrag möchte ich einige der Neuigkeiten vorstellen. Eine... [... mehr in diesem Blogeintrag auf Giza-Blog.de]


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

codefest.at [MS]: Microsoft Cognitive Services Face API Teil 1

Die Art und Weise, wie wir in Zukunft Computer bedienen werden, wird sich ändern. Neben den gewohnten Mechanismen mit Tastatur, Maus, Touch und Spracheingabe wird Software zunehmend intelligenter und besser auf den User eingehen und die Kommunikation mit der Maschine vereinfachen.

Zu diesem Zweck forschen Software-Entwickler daran, Machine Learning zu verbessern und Services bereitzustellen, welche APIs zur Konsumentation von Logik in eigene Apps erlauben.

Microsoft hat kürzlich die Cognitive Services vorgestellt, die mehr als zwanzig (!) verschiedene Cloud-Services zur Integration in eigene Apps anbieten. Der Projektname lautete übrigens “Project Oxford”. Die Cognitive Services sind derzeit noch in Preview und die Endpoints und Libraries heißen auch noch “Project Oxford”.

Die Website https://www.microsoft.com/cognitive-services zeigt alle verfügbaren Services.

image

Ich habe mir ein einfaches Service herausgepickt, um dieses selbst einmal auszuprobieren, nämlich die Face-API aus der Vision-Kategorie.

image

Der Startpunkt ist Face-API Webseite.
Die Face-API Dokumentation liefert den Überblick und weitere Links zu Beispielen.

Das Tutorial Get Started with Face API in C# zeigt die ersten Schritte zum Ausprobieren. Los gehts!

Als Voraussetzung ist für jedes Service ein (derzeit kostenfreier) API Key erforderlich. Dieser kann unter https://www.microsoft.com/cognitive-services/en-us/sign-up mit einem Microsoft Account (MSA) angefordert werden.

Die Verwaltung der Keys erfolgt unter https://www.microsoft.com/cognitive-services/en-us/subscriptions.

image

In meinem Fall benötige ich das “Face-Preview” Service. Hier muss der Key für die Face-API angezeigt werden (ein Key ist ausreichend) und hier können die Keys verwaltet werden.

Noch ein Wort zu den Preisen: Diese richten sich nach dem Service und der Nutzung. Soweit ich gesehen habe, sind alle Services bis zu einem Volumen von 5,000 transactions per month kostenfrei! Die aktuellen Preise sind unter Preview pricing ersichtlich.

image

Damit können wir das Demoprojekt starten. Zunächst wird in Schritt 1 mit Visual Studio ein neues WPF Projekt angelegt und in Schritt 2 mit dem NuGet Package Manager das Paket Newtonsoft.Json installiert.

Die Cognitive Services sind per HTTPS Request gegen den entsprechenden Cloud-Endpoint aufrufbar. Dieser lautet (siehe Face API - V1.0):

https://api.projectoxford.ai/face/v1.0/detect[?returnFaceId][&returnFaceLandmarks][&returnFaceAttributes]

Für die .NET Plattform gibt es zur einfacheren Nutzung Client Libraries, um die Web-Requests einzukapseln und um das Service bequemer zu verwenden. In Schritt 3 wird nun die Client-Library “Microsoft.Project Oxford.Face” über NuGet wie folgt bezogen.

image

Danach werden die Libraries zu MainWindow.xaml.cs hinzugefügt:

using Microsoft.ProjectOxford.Face;
using Microsoft.ProjectOxford.Face.Contract;

…und ein Interface mit dem eigenen Subscription Key (aus der eigenen Subscription von oben) in der MainWindow class erstellt:

private readonly IFaceServiceClient faceServiceClient = new FaceServiceClient("Your subscription key");

Das wars schon mit den ersten Vorbereitungen für das App-Framework. Nun geht es um den eigentlichen Code zur Verwendung der Face-API.

Wir verwenden die Face-Detect API um ein Bild direkt upzuloaden. Der Link führt direkt zur Dokumentation des Endpoints. Für asynchrone Methoden kann die DetectAsync methode des FaceServiceClient verwendet werden. Jedes retournierte Gesicht enthält ein Rechteck um die Position im Foto zu markieren, das mit Face Attributes ergänzt ist. In Schritt 4 wird der FaceServiceClient verwendet.

In Schritt 5 des Tutorials wird die ButtonClick Methode async und das Ergebnis ausgewertet. Dabei wird pro erkanntem Gesicht ein rotes Rechteck über die Position gezeichnet. Dazu habe ich ein Schwarz/Weiß-Foto von mir verwendet, das Beispiel zeigt den Output.

image

Sehr schön. Das Beispiel klappt und markiert das erkannte Gesicht auf dem Foto. In meinem Beispiel besteht das Array faceRects aus nur einem Face.

Die Qualität der Bilder muss natürlich ausreichend sein. Auch Gruppenfotos (hier ein Schnappschuss der Audience vom letzten Microsoft Community Open Day in München) liefern beeindruckende Ergebnisse.

image

In Teil 2 interessieren mich jedoch noch weitere Details und was die Face-API so alles erkennen und liefern kann…

Marco Scheel: Links for 2016-07-13 [del.icio.us]

Manfred Steyer: Slides and Sample from my talk about the newest new Router in Angular 2 at @angular_berlin in July 2017

Please find below the slides and the sample from my talk about the newest new Router in Angular 2 that I did at @angular_berlin in July 2017.

The samples show:

  • How to configure the router
  • How to create hierarchical routes
  • How to use Aux-Routes
  • How to use Guards, e. g. for Authentication 
  • How to use modern Auth with OAuth2 und OIDC using my npm-package angular2-ouath2

The slides give an outlook to the upcomming lazy-loading features.


Downloads

Christian Giesswein: Developer Week 2016 - Ein Rückblick

Schön war sie, die #dwx16.. und auch schon ein paar Wochen her.
Leider kam ich noch nicht dazu ein paar Worte über diese Konferenz zu verlieren.

Die Developer Week 2016 fand wieder in Nürnberg im Konferenzzentrum statt und ist im .NET Umfeld, im deutschsprachigen Bereich eine der größten Konferenzen mit fast 2000 Teilnehmern. Als Entwickler hat man auf dieser Konferenz glaub ich die Qual der Wahl welchen Vortrag man denn nun besuchen möchte.
Für mich war es als Sprecher eine recht stressige aber sehr schöne Zeit, schließlich war ich mit 4,5 Vorträgen auf der Konferenz vertreten.

Am Montag gleich das erste, spannende Thema "Datenbindung Deluxe – Deep Dive in das Binding von WPF" wo der Saal platzend voll war, sogar vor der Bühne noch Leute im Schneidersitz saßen - als Sprecher immer ein gutes Gefühl und auch die Gespräche im Anschluss zeigten ein hohes Interesse an dem Thema.

Weiter ging es am Montagnachmittag gleich mit "Modulares UI - MVVM mit Prism 6" wo in rasanten 60 Minuten die Grundprinzipien von PRISM erläutert wurde und eine Kleine Basisanwendung mit PRISM entwickelt wurde. Wie üblich bei all meinen Vorträgen, zu 99% mit Visual Studio statt mit Powerpoint - Praxis pur!

Am Dienstag begann der Tag dann etwas ruhiger, da war am Nachmittag dann eine zweistündige "DevSession" zum Thema "Entity Framework und WPF" statt, wo es um die Best Practices im Umgang von Entity Framework MIT WPF ging. Also Erfahrungen womit zwei Technologien zusammengefasst wurden.

Der letzte Tag, am Mittwoch, fing dann bereits in der Früh mit "Visual Studio 2015 Extensions leichtgemacht" an, wo es um das Entwickeln von eigenen Erweiterungen für Visual Studio 2015 ging. Obwohl das Thema sicherlich nicht das gängigste ist, haben sich auch hier sehr viele Teilnehmer eingefunden um in der Früh sich mal über das Thema zu informieren. Dabei kam am Ende eine kleine Erweiterung raus, die "mal eben schnell" von mehreren Projekten in der Solution die .NET Version verändert.

Ging ich aus diesem Vortrag noch raus mit dem Gefühl *puh,.. das war’s* sprangen mein geschätzter Kollege David Tielke und ich für eine Ersatzsession am Nachmittag ein.
Dabei haben wir uns das Thema "Back to the Future - Eine Zeitreise - von C# 1.0 bis 7.0" eine knackige aber sehr unterhaltsame Session zum Thema C# überlegt.
Ich glaube nach dieser Session ist wohl jeder mit sehr guter Laune und einem Lächeln zur Abschlusskeynote von Scott Hanselman gegangen.

Persönlich bleibt mir die Developer Week 2016 in Nürnberg sehr gut in Erinnerung, viele Sprecher als auch Teilnehmer kennt man mittlerweile von den .NET Konferenzen die das ganze Jahr über so vergehen und man geht mit sehr viel neuen Input nach Hause.

Alle Codebeispiele sind auf GitHub veröffentlich und können dort heruntergeladen werden: https://github.com/softwaretirol/conferences
Ich freue mich auf jeden Fall auf eine Developer Week 2017 und hoffe, dass auch die Konferenz wieder so gelungen wird wie die vergangene.

 

Die Unterlagen:

Marco Scheel: Links for 2016-07-12 [del.icio.us]

  • Jerry Nixon on Windows: Understanding TargetDeviceFamily
    If you are like me, you might spelunk from time to time in the bowels of your application's manifest file. But, "why?", you might ask, "Isn't everything in the manifest revealed in the graphical editor in Visual Studio?" Oh, you poor child. Allow me to enlighten you on this one: No. via Pocket
  • Understanding SOME of the Pratfalls and Pitfalls of Sharing in a Collaborative World | Marc D Anderson's Blog
    Digital content sharing with SharePoint is both a tremendously useful set of features and also a set of capabilities fraught with peril - depending on the type of content and the knowledge level of the person doing the sharing. via Pocket
  • How to get Pikachu as your starter in Pokémon Go | Polygon
    This may be the coolest, and most annoying, thing we’ve learned about Pokémon Go thus far. The game sets you up with a choice between one of three starter Pokémon: Charmander, Squirtle and Bulbasaur. via Pocket
  • SharePoint Patches
    Title Product Build Prerequisite Type Known Issues Downloads Patch Notes SharePoint Foundation 2010 SharePoint Foundation 2010 14.0.4762.1000 IsRTM RM 0 SharePoint Server 2010 SharePoint Server 2010 14.0.4762.1000 IsRTM RM 0 Project Server 2010 Project Server 2010 14.0.4762. via Pocket

codefest.at [MS]: TypeScript 2.0 Beta ist da

Das Microsoft TypeScript Entwicklungsteam war fleißig und hat gestern im MSDN Blog die TypeScript 2.0 Beta-Version angekündigt, siehe Announcing TypeScript 2.0 Beta.

Neuerungen in TypeScript Version 2 sind unter anderem Non-nullable Types, Easier Module Declarations, Control flow based type analysis, The never type, Read-only properties and index signatures, Glob support in tsconfig.json, Wildcard character in module names, Support for UMD module definitions und vieles mehr. Im Detail gibt es die Neuerungen im GitHub Wiki von Typescript nachzulesen:

What's new in TypeScript 2.0

Für alle jene, die neu in TypeScript sind, steht die https://www.typescriptlang.org/ Website bereit.

image

TypeScript wird auf GitHub entwickelt. Der TypeScript compiler selbst ist in TypeScript geschrieben und kann in jedem JavaScript Host laufen. Das Projekt kann hier angesehen werden: Follow the GitHub project.

Für das erste Hands-On mit der Beta-Version, lädt man TypeScript 2.0 Beta for Visual Studio 2015 – dies erfordert Visual Studio 2015 Update 3. Alternativ lädt man dies über den Node.js Package Manager

npm install -g typescript@beta

Kompiliert wird mit tsc helloworld.ts

Den Überblick und die Ankündigung gibts hier.

Viel Spaß beim Testen und Erforschen der neuen TypeScript 2.0 Beta-Version!

Jürgen Gutsch: Working with user secrets in ASP.​NET Core applications.

In the past there was a study about critical data in GitHub projects. They wrote a crawler to find passwords, user names and other secret stuff in projects on GitHub. And they found a lot of such data in public projects, even in projects of huge companies, which should pretty much care about security.

the most of this credentials are stored in config files. For sure, you need to configure the access to a database somewhere, you also need to configure the credentials to storages, mail servers, ftp, what ever. In many cases this credentials are used for development, with lot more rights than the production credentials.

Fact is: Secret information shouldn't be pushed to any public source code repository. Even better: not pushed to any source code repository.

But what is the solution? How should we tell our app where to get this secret information?

On Azure, you are able to configure your settings directly in the application settings of your web app. This overrides the settings of your config file. It doesn't matter if it's a web.config or an appsettings.json.

But we can't do the same on the local development machine. There is no configuration like this. How and where do we save secret credentials?

With .Core, there is something similar now. There is a SecretManager tool, provided by the .NET Core SDK (Microsoft.Extensions.SecretManager.Tools), which you can access with the dotnet CLI.

This tool stores your secrets locally on your machine. This is not a high secure password manager like keypass. It is not really high secure, but on your development machine, it provides the possibility NOT to store your secrets in a config file inside your project. And this is the important thing here.

To use the SecretManager tool, you need to add that tool in the "Tools" section of your project.json, like this:

"Microsoft.Extensions.SecretManager.Tools": {
  "version": "1.0.0-preview2-final",
  "imports": "portable-net45+win8+dnxcore50"
},

Be sure you have a userSecretsId in your project.json. With this ID the SecretManager tool assigns the user secrets to your app:

"userSecretsId": "aspnet-UserSecretDemo-79c563d8-751d-48e5-a5b1-d0ec19e5d2b0",

If you create a new ASP.NET Core project with Visual Studio, the SecretManager tool is already added.

Now you just need to access your secrets inside your app. In a new Visual Studio project, this should also already done and look like this:

public Startup(IHostingEnvironment env)
{
    _hostingEnvironment = env;

    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

    if (env.IsDevelopment())
    {
        // For more details on using the user secret store see 
        // http://go.microsoft.com/fwlink/?LinkID=532709
        builder.AddUserSecrets();

        // This will push telemetry data through Application 
        // Insights pipeline faster, allowing you to view results 
        // immediately.
        builder.AddApplicationInsightsSettings(developerMode: true);
    }

    builder.AddEnvironmentVariables();
    Configuration = builder.Build();
}

If not arr a NuGet reference to Microsoft.Extensions.Configuration.UserSecrets 1.0.0 in your project.json and add builder.AddUserSecrets(); as shown here.

The Extension Method AddUserSecrets() loads the secret information of that project into the ConfigurationBuilder. If the keys of the secrets are equal to the keys in the previously defined appsettings.json, the app settings will be overwritten.

If this all is done you are able to use the tool to store new secrets:

dotnet user-secrets set key value

If you create a separate section in your appsettings.config as equal to the existing settings, you need to combine the user secret key with the sections name and the settings name, separated by a colon.

I created settings like this:

"AppSettings": {
    "MySecretKey": "Hallo from AppSettings",
    "MyTopSecretKey": "Hallo from AppSettings"
},

To overwrite the keys with the values from the SecretManager tool, I need to create entries like this:

dotnet user-secrets set AppSettings:MySecretKey "Hello from UserSecretStore"
dotnet user-secrets set AppSettings:MyTopSecretKey "Hello from UserSecretStore"

BTW: to override existing keys with new values, just call set the secret again with the same key and the new value.

This way to handle secret data works pretty fine for me.

The SecretManager tool knows three more commands:

  • dotnet user-secrets clear: removes all secrets from the store
  • dotnet user-secrets list: shows you all existing keys
  • dotnet user-secrets remove <key>: removes the specific key

Just type dotnet user-secrets --help to see more information about the existing commands.

If you need to handle some more secrets in your project, it possibly makes sense to create a small batch file to add the keys, or to share the settings with build and test environments. But never ever push this file to the source code repository ;)

Code-Inside Blog: CAKE: Building solutions with C# & Roslyn

x

CAKE - C# Make

  • A DSL for build tasks (e.g. build following projects, copy stuff, deploy stuff etc.)
  • It’s just C# code that gets compiled via Roslyn
  • Active community, OSS & written in C#
  • You can get CAKE via NuGet
  • Before we begin you might want to check out the actual website of CAKE
  • Cross Platform support

Our goal: Building, running tests, package NuGet Packages etc.

I already did a couple of MSBuild and FAKE related blogposts, so if you are interested on these topics as well go ahead (some are quite old, there is a high chance that some pieces might not apply anymore):

Ok… now back to CAKE.

Let’s start with the basics: Building

I created a pretty simple WPF app and followed these instructions.

The build.cake script

My script is a simplified version of this build script:

// ARGUMENTS
var target = Argument("target", "Default");

// TASKS
Task("Restore-NuGet-Packages")
    .Does(() =>
{
    NuGetRestore("CakeExampleWithWpf.sln");
});

Task("Build")
    .IsDependentOn("Restore-NuGet-Packages")
    .Does(() =>
{
      MSBuild("CakeExampleWithWpf.sln", settings =>
        settings.SetConfiguration("Release"));

});

// TASK TARGETS
Task("Default").IsDependentOn("Build");

// EXECUTION
RunTarget(target);

If you know FAKE or MSBuild, this is more or less the same structure. You define tasks, which may depend on other tasks. At the end you invoke one task and the dependency chain will do its work.

Invoke build.cake

The “build.ps1” will invoke “tools/cake.exe” with the input file “build.cake”.

“build.ps1” is just a helper. This Powershell script will download nuget.exe and download the CAKE NuGet-Package and extract it under a /tools folder. If you don’t have problems with binary files in your source control, you don’t need this Powershell script.

Our first CAKE script!

The output is very well formatted and should explain the mechanics behind it good enough:

Time Elapsed 00:00:02.86
Finished executing task: Build

========================================
Default
========================================
Executing task: Default
Finished executing task: Default

Task                          Duration
--------------------------------------------------
Restore-NuGet-Packages        00:00:00.5192250
Build                         00:00:03.1315658
Default                       00:00:00.0113019
--------------------------------------------------
Total:                        00:00:03.6620927

The first steps are pretty easy and it’s much easier than MSBuild and feels good if you know C#.

The super simple intro code can be found on GitHub.

Jürgen Gutsch: How web development changed for me over the last 20 years

The web changed pretty fast within the last 20 years. More and more logic moves from the server side to the client side. More complex JavaScript needs to be written on the client side. And something freaky things happened the last years: JavaScript was moving to the server and Web technology was moving to the desktop. That is nothing new, but who was thinking about that 20 years ago?

The web changed, but also my technology stack. It seems my stack changed back to the roots. 20 years ago, I started with HTML and JavaScript, moving forward to classic ASP using VBScript. In 2001 I started playing around with ASP.NET and VB.NET and used it in in production until the end of 2006. In 2007 I started writing ASP.NET using C#. HTML and JavaScript was still involved, but more or less wrapped in third party controls and jQuery was an alias for JavaScript that time. All about JavaScript was just jQuery. ASP.NET WebForms felled pretty huge and not really flexible, but it worked. Later - in 2010 - I also did many stuff with SilverLight, WinForms, WPF.

ASP.NET MVC came up and the web stuff starts to feel little more naturally again, than ASP.NET WebForms. From an ASP.NET developer perspective, the web changed back to get better, more clean, more flexible, more lightweight and even more naturally.

But there was something new coming up. Things from outside the ASP.NET world. Strong JavaScript libraries, like KnockOut, Backbone and later on Angular and React. The First Single Page Application frameworks (sorry, I don't wanted to mention the crappy ASP.NET Ajax thing...) came up, and the UI logic moves from the server to the client. (Well, we did a pretty cool SPA back in 2005, but we didn't thought about to create a framework out of it.)

NodeJS change the world again, by using JavaScript on the server. You just need two different languages (HTML and JavaScript) to create cool web applications. I didn't really care about NodeJS, except using it in the back, because some tools are based on it. Maybe that was a mistake, who knows... ;)

Now we got ASP.NET Core, which feels a lot more naturally than the classic ASP.NET MVC.

Naturally in this case means, it feels almost the same as writing classic ASP. It means using the stateless web and working with the stateless web, instead of trying to fix it. Working with the Request and Response more directly, than with the classic ASP.NET MVC and even more than in ASP.NET WebForms. It doesn't mean to write the same unstructured, crappy shit than with classic ASP. ;)

Since we got the pretty cool client side JavaScript frameworks and simplified, minimalistic server side frameworks, the server part was reduced to just serve static files and to serve data over RESTish services.

This is the time where it makes sense to have a deeper look into TypeScript. Until now it didn't makes sense to me. I was writing JavaScript for around 20 years, more and less complex scripts, but I never wrote so much JavaScript within a single project, than as I started using AngularJS last years. Angular2 also was the reason to have a deep look into TypeScript, 'cause now it is completely written in Typescript. And it makes absolutely sense to use it.

A few weeks ago I started the first real NodeJS project. A desktop application which uses NodeJS to provide a high flexible scripting run-time for the users. NodeJS provides the functionality and the UI to the users. All written in TypeScript, instead of plain JavaScript. Why? Because TypeScript has a lot of unexpected benefits:

  • You are still able to write JavaScript ;)
  • It helps you to write small modules and structured code
  • it helps you to write NodeJS compatible modules
  • In general you don't need to write all the JavaScript overhead code for every module
  • You will just focus on the features you need to write

This is why TypeScript got a great benefit to me. Sure a typed language is also useful in many cases, but - working with JS for 20 years - I also like the flexibility of the implicit typed JavaScript and I'm pretty familiar with it. that means, from my perspective the Good thing about TypeScript is, I am still able to write implicit typed code in TypeScript and to use the flexibility of JavaScript. This is why I wrote "You are still able to write JavaScript"

The web technology changed, my technology stack changed and the tooling changed. All the stuff goes more lightweight, even the tools. The console comes back and the IDEs changed back to the roots: Just being text editors with some benefits like syntax highlighting and IntelliSense. Currently I prefer to use the "Swiss army knife" Visual Studio Code or Adobe Brackets, depending on the type of project. Both are starting pretty fast and include nice features.

Using that light weight IDEs is pure fun. Everything is fast, because the machines resource could be used by the apps I need to develop, instead by the IDE I need to use to develop the apps. This makes development a lot faster.

Starting the IDE today means, starting cmder (my favorite console on windows). changing to the project folder, starting a console command to watch the typescript files, to compile after save. Starting another console to use the tools like NPM, gulp, typings, dotnet CLI, NodeJS, and so on. Starting my favorite light weight editor to write some code. :)

codefest.at [MS]: SQL Server Hands-on Online Workshops auf Channel 9

Der Sommer ist ja auch Urlaubszeit und somit – zumindest für mich – eine gute Zeit für Weiterbildung. Aus diesem Grund möchte ich auf eine neue Channel 9 Serie zum Thema Praktisches Wissen zu SQL Server hinweisen.

In kurzen Clips wird jede Menge technisches Know-how rund um die Arbeit mit SQL Server vermittelt. Neu ist, dass Ihr die Leistungsoptimierungstechniken – LIVE – gleich selbst ausprobieren könnt. Wie ist das möglich? Das SQLTest Toolsimuliert die verschiedenen Performanceengpässe; mit ein paar Klicks seid Ihr dabei, ohne umständlich VMs herunterladen zu müssen!

Themen sind unter anderem: Daten-Komprimierung, Ressourcenverwaltung, In-Memory OLTP, sowie AlwaysOn Availability Groups. Die Grundlage ist wie immer praktische Leistungsoptimierung, erarbeitet anhand von realen Kundenproblemen, damit Ihr das volle Leistungspotential von SQL Server erfahren und nutzen könnt.

Happy Learning…

Jürgen Gutsch: Writing blog posts using Pretzel

Until yet I wrote more than 30 blog posts with Pretzel and it works pretty well. From my current perspective it was a good decision, to do this huge change, to move to that pretty cool and lightweight system.

I'm using MarkdownPad 2 to write the posts. Writing goes much easier. The process is now simplified and publishing is almost automated. I also added my blog CSS to that editor to have a nice preview.

The process of writing and publishing new posts goes like this:

  1. Creating a new draft article and save it in the _drafts folder
  2. Working on that draft
  3. Move the finished article to the _posts folder
  4. Commit and push that post to GitHub
  5. Around 30 seconds later the post is published on Azure

This process allows me to write offline in the train, while traveling to the Office in Basel. This is the most important thing to me.

The other big change, was switching to English. I now get more readers and feedback from around the world. Now the most readers are from the US, UK, India and Russia. But also from the other European countries, Australia, Middle East (and Cluj in Romania).

Maybe I lost some readers from the German speaking Area (Germany, Switzerland and Austria) who liked to read my posts in German (I need to find a good translation service to integrate) and I got some more from around the world.

Writing feels good in both, English and in the MarkdownPad :) From my perspective it was a good decision to change the blog system and even the language.

to learn more about Pretzel, have look into my previous post about using pretzel.

Sven Hubert: WiX Toolset Teil 4: Manuell starten war gestern – Autostart und Conditions

In diesem Teil der WiX-Blog-Serie steht das Thema Autostart im Fokus. Die zwei größten Anwendungsfälle für diese Funktion sind das Starten eines benötigten Services im Hintergrund, sowie eine Komfortfunktion um Programme, die man während der Arbeit benötigt, nicht mehr manuell starten zu müssen. Dazu wird im Laufe einer Installation oft gefragt, ob das installierte Programm beim Systemstart direkt mit ausgeführt werden soll. Wie diese Funktion über einen WiX Installer umgesetzt werden kann, soll im Folgenden beschrieben werden.

Um die Auswahl zu ermöglichen, wird zwischen dem aus Teil zwei der WiX Toolset Blogserie bekannten EULA-Dialog und dem Verifizierungs-Dialog ein weiterer Installationsschritt eingebaut, in dem ausgewählt werden kann, ob bestimmte Funktionen aktiviert werden sollen. In diesem Fall betrifft es das Erstellen des Desktop-Icons sowie das Ausführen der Anwendung beim Systemstart. Der Dialog enthält außer zwei Checkboxen und den bekannten Buttons Back, Next und Cancel keine weitere Logik:

clip_image002[4]

clip_image004[4]

 

Besonders wichtig sind die beiden Controls AutomaticStartup und DesktopCreation. Sie referenzieren jeweils ein Property, welches zusätzlich angelegt werden muss. Um die Übersicht zu behalten, wird empfohlen alle anfallenden Properties in ein eigenes Fragment auszulagern. Im Beispiel wird das Property in dem Fragment angelegt, in dem es von einer Komponente benutzt wird. Innerhalb des DesktopShortcut-Component-Elements wird daraufhin ein zusätzliches Element Condition gelegt, das den Wert der entsprechenden Property überprüft. Das Ergebnis wird im folgenden Screenshot dargestellt:

clip_image006[4]

Dass eine Anwendung beim Systemstart ausgeführt wird, lässt sich auf zwei Arten erreichen: Man kann eine Verknüpfung im StartupFolder von Windows anlegen, oder einen Eintrag in der Registry vornehmen. Der einfachste Weg ist dabei das Hinzufügen einer Verknüpfung in den StartupFolder. Dazu wird der Directory-Struktur der Knoten StartupFolder hinzugefügt, unter dem anschließend ein weiterer Shortcut angelegt wird. Diese Variante bietet zum einen den Charme, sehr simpel zu sein. Des Weiteren kann der Nutzer jederzeit selbstständig ohne größere Komplikationen die Verknüpfung aus dem StartupFolder löschen und somit das Ausführen beim Systemstart verhindern. Ein weiterer Punkt ist die Tatsache, dass der Verknüpfung im StartupFolder Parameter übergeben werden können, die den Programmstart beeinflussen.

clip_image008[4]

Eine weitere Variante, um die Anwendung beim Systemstart auszuführen, ist ein Eintrag in der Registry unter Software \Microsoft\Windows\CurrentVersion\Run. Besonderes Augenmerk sollte darauf auf das Root-Attribut des RegistryValue-Elementes gelegt werden. Dieses Attribut gibt an, ob die Anwendung für die Maschine, also unabhängig vom Nutzer, oder ob sie erst nach der Anmeldung eines bestimmten Nutzers gestartet werden soll. Der Registry-Eintrag zeigt dabei auf die ausführbare Datei im Installationsverzeichnis. Da sich ein Condition-Element stets auf das gesamte Component-Element bezieht, werden für das Setzen des Autostarts über die Registry zwei Component-Elemente benötigt. Dabei enthält die erste Komponente die ausführbare Datei und die zweite das RegistryValue, sowie das Condition-Element zur Überprüfung, ob der Nutzer einen Autostart möchte. Die zweite Komponente wird somit nur installiert, wenn die Condition zutrifft.

clip_image010[4]

Stefan Henneken: IEC 61131-3: Arrays mit variabler Länge

Bei der Deklaration von Arrays musste bisher immer eine konstante Größe angegeben werden. Ab der 3rd Edition der IEC 61131-3 können Arrays mit einer variablen Länge deklariert werden. Funktionen lassen sich dadurch deutlich generischer anlegen als bisher.

Zwar können für die Arraygrenzen auch Variablen benutzt werden, diese Variablen müssen aber als Konstanten deklariert werden. Eine Anpassung der Arraygrenzen zur Laufzeit ist somit nicht möglich.

PROGRAM MAIN
VAR
  arrData             : ARRAY[1..ARRAY_UPPER_BOUND] OF INT;
END_VAR
VAR CONSTANT
  ARRAY_UPPER_BOUND   : INT := 10;	
END_VAR

Gerade wenn Arrays als Parameter an Funktionen oder Funktionsblöcken übergeben werden, stellen feste Arraygrenzen eine unangenehme Limitierung dar. Ist diese nicht hinnehmbar, musste bisher auf Pointerarithmetik gewechselt werden, mit allem Nachteilen. Hier ein einfaches Beispiel, welches die Summe eines eindimensionalen Arrays von LREAL-Variablen berechnet.

FUNCTION F_CalcSum1DimArrayOldSchool : LREAL
VAR_INPUT
  pData           : POINTER TO LREAL;
  nSize           : UDINT;
END_VAR
VAR
  pDataIndex      : POINTER TO LREAL;
  nUpperIndex     : UDINT;
  nIndex          : UDINT;
END_VAR

F_CalcSum1DimArrayOldSchool := 0;
nUpperIndex := nSize / SIZEOF(pDataIndex^);
IF (nUpperIndex > 0) THEN
  FOR nIndex := 0 TO (nUpperIndex - 1) DO
    pDataIndex := pData + (nIndex * SIZEOF(pDataIndex^));
    F_CalcSum1DimArrayOldSchool := F_CalcSum1DimArrayOldSchool + pDataIndex^;	
  END_FOR
END_IF

Die Funktion kann für die Addition beliebiger LREAL-Arrays genutzt werden. Sie ist unabhängig von der Anzahl der Elemente und von der oberen und unteren Arraygrenze.

PROGRAM MAIN
VAR
  array01    : ARRAY[2..8] OF LREAL := [16.1, 34.1, 4.1, 43.1, 35.1, 2.1, 65.1];
  lrSum01    : LREAL;
	
  array02    : ARRAY[-1..2] OF LREAL := [16.1, 34.1, 9.1, 13.1];
  lrSum02    : LREAL;
	
  array03    : ARRAY[-3..-1] OF LREAL := [16.1, 34.1, 8.1];
  lrSum03    : LREAL;
END_VAR
lrSum01 := F_CalcSum1DimArrayOldSchool(ADR(array01), SIZEOF(array01));
lrSum02 := F_CalcSum1DimArrayOldSchool(ADR(array02), SIZEOF(array02));
lrSum03 := F_CalcSum1DimArrayOldSchool(ADR(array03), SIZEOF(array03));

Beispiel 1 (TwinCAT 3.1.4020)

Allerdings hat diese Lösung einige Nachteile. Zum einen eben die Tatsache das Pointerarithmetik benutzt werden muss. Der Quellcode der Funktion wird schon bei relativ einfachen Aufgaben recht komplex. Zum anderen muss an die Funktion auch eine Größen- bzw. Längenangabe übergeben werden. Bei dem Aufruf muss also sichergestellt werden, das der Pointer auf das Array und die Längenangabe übereinstimmen.

Seit der 3rd Edition der IEC 61131-3 können Arrays auch mit variabler Arraygrenze definiert werden. Statt der Arraygrenze, wird ein ’*’ angegeben:

arrData   : ARRAY[*] OF LREAL;

Wird die Funktion aufgerufen, so muss das übergebene Array konstante Arraygrenzen besitzen. In der Funktion kann über die Funktionen LOWER_BOUND und UPPER_BOUND die jeweilige obere- und untere Arraygrenze abgefragt werden.

Derzeit können Arrays mit variabler Länge nur an VAR_IN_OUT Variablen von Funktionen, Funktionsblöcken und Methoden übergeben werden (bleibt zu hoffen, dass in Zukunft auch VAR_INPUT und VAR_OUTPUT Variablen unterstützt werden).

Hier das angepasste Beispiele:

FUNCTION F_CalcSum1DimArray : LREAL
VAR_IN_OUT
  arrData    : ARRAY[*] OF LREAL;
END_VAR
VAR
  nIndex     : DINT;
END_VAR
F_CalcSum1DimArray := 0;
FOR nIndex := LOWER_BOUND(arrData, 1) TO UPPER_BOUND(arrData, 1) DO
  F_CalcSum1DimArray := F_CalcSum1DimArray + arrData[nIndex];
END_FOR

Die Funktion erwartet als Eingangsparameter nur noch ein Array von LREAL-Werten. Die Anzahl der Array-Elemente ist variabel. Mit LOWER_BOUND und UPPER_BOUND kann eine Iteration über das gesamte Array durchgeführt werden. Der Quellcode ist deutlich lesbarer als im ersten Beispiel.

PROGRAM MAIN
VAR
  array01    : ARRAY[2..8] OF LREAL := [16.1, 34.1, 4.1, 43.1, 35.1, 2.1, 65.1];
  lrSum01    : LREAL;
	
  array02    : ARRAY[-1..2] OF LREAL := [16.1, 34.1, 9.1, 13.1];
  lrSum02    : LREAL;
	
  array03    : ARRAY[-3..-1] OF LREAL := [16.1, 34.1, 8.1];
  lrSum03    : LREAL;
END_VAR
lrSum01 := F_CalcSum1DimArray(array01);
lrSum02 := F_CalcSum1DimArray(array02);
lrSum03 := F_CalcSum1DimArray(array03);

Beispiel 2 (TwinCAT 3.1.4020)

Auch werden mehrdimensionale Arrays unterstützt. Bei der Deklaration müssen alle Dimensionen als variabel angelegt werden:

arrData    : ARRAY[*, *, *] OF LREAL;

Der zweite Parameter von UPPER_BOUND und LOWER_BOUND gibt die Dimension an, von der die jeweilige Arraygrenze ermittelt werden soll.

FUNCTION F_CalcSum3DimArray : LREAL
VAR_IN_OUT
   arrData      : ARRAY[*, *, *] OF LREAL;
END_VAR
VAR
   nIndex1, nIndex2, nIndex3  : DINT;
END_VAR
F_CalcSum3DimArray := 0;
FOR nIndex1 := LOWER_BOUND(arrData, 1) TO UPPER_BOUND(arrData, 1) DO
  FOR nIndex2 := LOWER_BOUND(arrData, 2) TO UPPER_BOUND(arrData, 2) DO
    FOR nIndex3 := LOWER_BOUND(arrData, 3) TO UPPER_BOUND(arrData, 3) DO
      F_CalcSum3DimArray := F_CalcSum3DimArray + arrData[nIndex1, nIndex2, nIndex3];
    END_FOR
  END_FOR
END_FOR

Bei dem Aufruf kann ein beliebiges dreidimensionales Array von LREAL-Werten an die Funktion übergeben werden.

PROGRAM MAIN
VAR
  array01    : ARRAY[1..2, 3..4, 5..6] OF LREAL := [16.1, 34.1, 4.1, 43.1, 35.1, 2.1, 65.1, 16.1];
  lrSum01    : LREAL;
END_VAR
lrSum01 := F_CalcSum3DimArray(array01);

Beispiel 3 (TwinCAT 3.1.4020)

Somit lassen sich auch komplexere Aufgaben flexibel umsetzen ohne das auf Pointerarithmetik zurückgegriffen werden muss.

Dieses soll zum Schluss an einem Funktionsblock gezeigt werden, der zwei Matrizen miteinander multipliziert. Die Größen der Matrizen sind variabel:

METHOD PUBLIC Multiplication : BOOL
VAR_IN_OUT
  arrayA     : ARRAY[*, *] OF DINT;
  arrayB     : ARRAY[*, *] OF DINT;
  arrayX     : ARRAY[*, *] OF DINT;	
END_VAR
VAR
  nIndex1, nIndex2, nIndex3, nIndex4   : DINT;
END_VAR;
FOR nIndex1 := LOWER_BOUND(arrayA, 1) TO UPPER_BOUND(arrayA, 1) DO
  FOR nIndex2 := LOWER_BOUND(arrayB, 2) TO UPPER_BOUND(arrayB, 2) DO
    nIndex4 := 0;
    FOR nIndex3 := LOWER_BOUND(arrayA, 2) TO UPPER_BOUND(arrayA, 2) DO
      nIndex4 := nIndex4 + arrayA[nIndex1, nIndex3] * arrayB[nIndex3, nIndex2];
    END_FOR;
    arrayX[nIndex1, nIndex2] := nIndex4;
  END_FOR;
END_FOR;

Die Methode kann mit unterschiedlich großen Arrays aufgerufen werden.

PROGRAM MAIN
VAR
  fbMatrix     : FB_Matrix;
  arrayA1      : ARRAY[1..2, 1..2] OF DINT := [1, 2, 3, 4];
  arrayB1      : ARRAY[1..2, 1..2] OF DINT := [5, 6, 7, 8];
  arrayX1      : ARRAY[1..2, 1..2] OF DINT;
	
  arrayA2      : ARRAY[1..3, 1..3] OF DINT := [1, 2, 3, 4, 5, 6, 7, 8, 9];
  arrayB2      : ARRAY[1..3, 1..3] OF DINT := [5, 6, 7, 8, 10, 11, 12, 13, 14];
  arrayX2      : ARRAY[1..3, 1..3] OF DINT;				
END_VAR
fbMatrix.Multiplication(arrayA1, arrayB1, arrayX1);
fbMatrix.Multiplication(arrayA2, arrayB2, arrayX2);

Beispiel 4 (TwinCAT 3.1.4020)


codefest.at [MS]: Einladung zum Visual Studio MeetUp

 

Die ppedv und die Microsoft Österreich laden Euch herzlich zum Visual Studio User Group MeetUp am 14.Juli ein, mit anschließendem Rooftop BBQ. 

Was erwartet Euch dort?

=> Windows Server 2016 als Nano Server

=> Xamarin und Visual Studio für Cross-Plattform Entwicklung

 

Terminplan:

17:00 Uhr

Opening Hannes 

17:15 Uhr

Ein Blick unter die (Grill)haube: Windows Server 2016 Kleiner gehts nicht: Der neue Nano Server.
Stefan Ober 

17:15 Uhr

Knackig & Cross (Plattform) Entwicklung mit Visual Studio 

Visual Studio bietet mit Xamarin eine kostenlose Cross-Plattform-Entwicklungsumgebung, die es ermöglicht, native Apps für unterschiedliche Plattformen wie iOs, Android oder Windows zu schreiben. 
Hannes Preishuber

18:00 Uhr

Offizielle Übergabe EM Tippspiel Computerwelt 3D Google CardBoards Dr Weiss, Computerwelt 

ab 18:30 Uhr

Rooftop BBQ Party und Networking (open end)

 

Veranstaltungsort: Märzstraße 1 (Wien) im 1. Dachgeschoss

 

 

Jürgen Gutsch: How to continuously deploy a ASP.​NET Core 1.0 web app to Microsoft Azure

We started the first real world project with ASP.NET Core RC2 a month ago and we learned a lot of new stuff around ASP.NET Core

  • Continuous Deployment to an Azure Web App
  • Token based authentication with Angular2
  • Setup Angular2 & TypeScript in a ASP.NET Core project
  • Entity Framework Core setup and initial database seeding

In this post, I'm going to show you how we setup a continuous deployment stuff for a ASP.NET Core 1.0 project, without tackling TypeScript and Angular2. Please Remember: The tooling around .NET Core and ASP.NET Core is still in "preview" and will definitely change until RTM. I'll try to keep this post up-to-date. I wont use the direct deployment to an Azure Web App from a git repository because of some reasons, I [mentioned in a previous post] .

I will write some more lines about the other learned stuff in one of the next posts.

Let's start with the build

Building is the easiest part of the entire deployment process. To build a ASP.NET Core 1.0, solution you are able to use MSBuild.exe. Just pass the solution file to MSBuild and it will build all projects in the solution.

The *.xproj files use specific targets, which will wrap and use the dotnet CLI. You are also able to use the dotnet CLI directly. Just call dotnet build for each project, or just simpler: call dotnet build in the solution folder and the tools will recursively go threw all sub-folders, to look for project.json files and build all the projects in the right build order.

Usually I define an output path to build all the projects into a specific folder. This makes it a lot easier for the next step:

Test the code

Some months ago, I wrote about unit testing DNX libraries (Xunit, NUnit). This didn't really change in .NET Core 1.0. Depending on the Test Framework, a test library could be a console application, which can be called directly. In other cases the test runner is called, which gets the test libraries passed as arguments. We use NUnit to create our unit tests, which doesn't provide a separate runner yet for .NET Core. All of the test libraries are console apps and will build to a .exe file. So we are searching the build output folder for our test libraries and call them one by one. We also pass the test output file name to that libraries, to get detailed test results.

This is pretty much all to run the unit tests.

Throw it to the clouds

Deployment was a little more tricky. But we learned how to do it, from the Visual Studio output. If you do a manual publish with Visual Studio, the output window will tell you how the deployment needs to be done. This are just two steps:

###1. publish to a specific folder using the "dotnet publish" command We are calling dotnet publish with this arguments:

Shell.Exec("dotnet", "publish \"" + webPath + "\" --framework net461 --output \"" + 
    publishFolder + "\" --configuration " + buildConf, ".");
  • webPath contains the path to the web project which needs to be deployed
  • publishFolder is the publish target folder
  • buildConf defines the Debug or Release build (we build with Debug in dev environments)

###2. use msdeploy.exe to publish the complete publish folder to a remote machine. The remote machine in our case, is an instance of an Azure Web App, but could also be any other target machine. msdeploy.exe is not a new tool, but is still working, even with ASP.NET Core 1.0.

So we just need to call msdeploy.exe like this:

Shell.Exec(msdeploy, "-source:contentPath=\"" + publishFolder + "\" -dest:contentPath=" + 
    publishWebName + ",ComputerName=" + computerName + ",UserName=" + username + 
    ",Password=" + publishPassword + ",IncludeAcls='False',AuthType='Basic' -verb:sync -" + 
    "enablerule:AppOffline -enableRule:DoNotDeleteRule -retryAttempts:20",".")
  • msdeploy containes the path to the msdeploy.exe which is usually C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe.
  • publishFolder is the publish target folder from the previous command.
  • publishWebName is the name of the Azure Web App name, which also is the target content path.
  • computername is the name/URL of the remote machine. In our case "https://" + publishWebName + ".scm.azurewebsites.net/msdeploy.axd"
  • username and password are the deployment credentials. the password is hashed, as in the publish profile that you can download from Azure. Just copy paste the hashed password.

conclusion

I didn't mention all the work that needs to be done to prepare the web app. We also use Angular2 with TypeScript. So we also need to get all the NPM dependencies, we need to move the needed files to the wwwroot folder and we need to bundle and to minify all the JavaScript files. This is also done in our build & deployment chain. But in this post, it should be enough to describe just the basic steps for a usual ASP.NET Core 1.0 app.

Manfred Steyer: Slides and Samples of my talk about the new newest router and Angular 2 at AngularCamp in Barcelona 2016

Below the slides and samples of my talk about the new newest router and Angular 2 at AngularCamp in Barcelona 2016.

The sample has been updated to Angular 2 RC 4 and Router Beta 4.

It shows:

  • Guards
  • Child-Routes
  • Aux-Routes

Downloads:

Manfred Steyer: Unterlagen von Session zum Upgrade von AngularJS 1.x auf Angular 2 von der DWX 2016 in Nürnberg

Nachfolgend meine Unterlagen von der Session zum Upgrade von AngularJS 1.x auf Angular 2 von der DWX 2016 in Nürnberg:

Manfred Steyer: Unterlagen von Session zu Web APIs mit ASP.NET Core von der DWX 2016 in Nürnberg

Nachfolgend die Unterlagen zu meiner Session über Web APIs mit ASP.NET von der DWX 2016 in Nürnberg:

Manfred Steyer: Authentication in Angular 2 with OAuth2, OIDC and Guards for the newest new Router [English Version]

The new router for Angualr 2 provides so called Guards to influence routing. Those are services with methods that are called when the router activates or deactivates a route. The names of this methods are canActivate and canDeactivate. If such a method returns true, the router performs the current routing-action; otherwise it skips it. Furthermore, those methods can return an Observable<boolean> to postpone this decision.

In in my post here I've showed with an example how to use canDeactivate. It displays a warning when the user tries to exit a route and gives them the option to decide to stay.

This post shows how an application can use canActivate to keep an unauthenticated or unauthorized user away from specific routes. This isn't really about security, cause in browser-based applications security has to be implemented at server-side. Rather it's about usability cause it gives the application the possibility to ask the user to login in such cases. The whole source code of this sample can be found here. Besides Guards it also uses the security standards OAuth 2 and OpenId Connect (OIDC) to decouple the authentication and authorization from the application.

Preperation

To use OAuth 2 and OIDC, the here described sample uses my implementation, which can be installed via npm:

npm install angular2-oauth2 --save

After downloading this library has to import the OAuthService and create a provider for it. This provider is passed to bootstrap in this sample:

import { OAuthService } from 'angular2-oauth2/oauth-service';
[...]

var APP_PROVIDERS = [
  OAuthService
];

var providers = [
  APP_PROVIDERS,
  HTTP_PROVIDERS,
  [...]
];

bootstrap(AppComponent, providers);

The top level component can be used to configure the OAuthServices. The settings in the next sample point to an OAuth2/OIDC Auth Server that is available online an can be used for testing:

import { Component } from '@angular/core'
import { Router, ROUTER_DIRECTIVES } from '@angular/router'
import { HomeComponent} from './home/home.component';
import { OAuthService} from 'angular2-oauth2/oauth-service';

@Component({
    selector: 'flight-app',
    directives: [ROUTER_DIRECTIVES],
    template: require('./app.component.html')
})
export class AppComponent {

    constructor(private oauthService: OAuthService, private router: Router) {

        this.oauthService.loginUrl = "https://steyer-identity-server.azurewebsites.net/identity/connect/authorize"; //Id-Provider?
        this.oauthService.logoutUrl = "https://steyer-identity-server.azurewebsites.net/identity/connect/endsession?id_token={{id_token}}";
        this.oauthService.redirectUri = window.location.origin + "/index.html";
        this.oauthService.clientId = "spa-demo";
        this.oauthService.scope = "openid profile email voucher";
        this.oauthService.issuer = "https://steyer-identity-server.azurewebsites.net/identity";
        this.oauthService.setStorage(localStorage);
        this.oauthService.oidc = true;

        this.oauthService.tryLogin({});


    }
}

The method tryLogin checks, whether the app has got security tokens via the hash-fragment of the URL. It parses those tokens and extracts information of the current user.

In cases where this information is used for security-relevant procedures, the app has to validate the token. This is especially the case in hybrid and native apps that use it to access local resources. The following sample uses a callback to validate the token. For this, it calls a web api, that checks its signature:

this.oauthService.tryLogin({
    validationHandler: context => {
        var search = new URLSearchParams();
        search.set('token', context.idToken); 
        search.set('client_id', oauthService.clientId);
        return http.get(validationUrl, { search }).toPromise();
    }
});

Login

To redirect the user to the login-form of the Auth Server, the app has only to call the method initImplicitFlow that is provided by the OAuthService.

The method login in the following sample shows this. The method logout logs off the current user. For this purpose it deletes the saved tokens. If the service has been initialized with a logout url, it also redirects the user to this URL:

import { Component } from '@angular/core';
import { OAuthService} from 'angular2-oauth2/oauth-service';

@Component({
    selector: 'home',
    template: require('./home.component.html')
})
export class HomeComponent {

    constructor(private oauthService: OAuthService) {
    }

    public login() {
        this.oauthService.initImplicitFlow();
    }

    public logout() {
        this.oauthService.logOut();
    }

    public get userName() {

        var claims = this.oauthService.getIdentityClaims();
        if (!claims) return null;

        return claims.given_name;
    }

}

In addition to that, the getter userName tries to find out the user's first-name. For this, it accesses the claims that the library found within the security-token. The template of this component binds to those properties:

<h1 *ngIf="!userName">Welcome!</h1>
<h1 *ngIf="userName">Hello, {{userName}}!</h1>
<p>Welcome to this demo-application.</p>
<p>
    <button (click)="login()" class="btn btn-default">Login</button>
    <button (click)="logout()" class="btn btn-default">Logout</button>
</p>    
<p>
    Username/Passwort: max/geheim
</p>

Keeping away unauthorized users with Guards

To keep unauthorized users away from some routes the application can use guards. The following sample shows an implementation for this. Its just an Angular-2-Service that implements CanActivate and receives the OAuthService by the means of dependency injection.

The interface defines a method canActivate. The presented implementation checks, whether there are the necessary security tokens. Those are an Access-Token (OAuth2) as well as an Id-Token (OpenId Connect). If there are both, it returns true to signal the router that the component in question can be activated. Otherwise it skips the current routing-action by returning false:

import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import { OAuthService} from 'angular2-oauth2/oauth-service';
import { Injectable} from '@angular/core';

@Injectable()
export class FlightBookingGuard implements CanActivate {

    constructor(private oauthService: OAuthService) {
    }

    canActivate(
        route: ActivatedRouteSnapshot, 
        state: RouterStateSnapshot) {

            var hasIdToken = this.oauthService.hasValidIdToken();
            var hasAccessToken = this.oauthService.hasValidAccessToken();

            return (hasIdToken && hasAccessToken);
    }
}

The parameters of canActivate inform about the current route as well as about the requested route.

In addition to that, the guard has to be registered with the property canActivate in the routing-configuration. This property does not directly point to the guards to use but to tokens that can be used to request the guards via DI:

import { RouterConfig, provideRouter } from '@angular/router';
import { HomeComponent} from './home/home.component';
import { FlightSearchComponent} from './flight-search/flight-search.component';
import { PassengerSearchComponent} from './passenger-search/passenger-search.component';
import { FlightEditComponent} from './flight-edit/flight-edit.component';
import { FlightBookingComponent} from './flight-booking/flight-booking.component';
import { FlightBookingGuard} from './flight-booking/flight-booking.guard';
import { FlightEditGuard} from './flight-edit/flight-edit.guard';
import { InfoComponent} from './info/info.component';
import { DashboardComponent} from './dashboard/dashboard.component';


const APP_ROUTES: RouterConfig = [
    {
        path: '/home',
        component: HomeComponent,
        index: true
    },
    {
        path: '/info',
        component: InfoComponent,
        outlet: 'aux'

    },
     {
        path: '/dashboard',
        component: DashboardComponent,
        outlet: 'aux'
    },    
    {
        path: '/flight-booking',
        component: FlightBookingComponent,
        canActivate: [FlightBookingGuard],
        children: [
            {
                path: '/flight-search',
                component: FlightSearchComponent
            },
            {
                path: '/passenger-search',
                component: PassengerSearchComponent
            },
            {
                path: '/flight-edit/:id',
                component: FlightEditComponent
            }
        ]
    }
];

In the current case, the guard is used as its token as well. Therefore, it can be directly mentioned within the provider configuration. This configuration also gets the provider for the router. For this, the sample calls the function provideRouter and passes the routing configuration to it:

const APP_PROVIDERS = [
  OAuthService
];

export const APP_ROUTER_PROVIDERS = [
    FlightBookingGuard,
    provideRouter(APP_ROUTES),
];

var providers = [
  APP_PROVIDERS,
  APP_ROUTER_PROVIDERS,
  HTTP_PROVIDERS
];

bootstrap(AppComponent, providers);

Calling a web api

To call a web api, the application has to pass the access-token. It can retrieve it from the method getAccessToken of the OAuthService. Usually, this Token has to be transmitted via the HTTP header Authorization:

public find(from: string, to: string) {
    var url = this.baseUrl + "/api/flight";

    var search = new URLSearchParams();
    search.set('from', from);
    search.set('to', to);

    var headers = new Headers();
    headers.set('Accept', 'text/json');
    headers.set('Authorization', 'Bearer ' + this.oauthService.getAccessToken())

    return new Observable((observer: Observer<Flight[]>) => {
        this.http
            .get(url, { search, headers })
            .map(resp => resp.json())
            .subscribe((flights) => {
                this.flights = flights;
                observer.next(flights);
            });
    });
}

The value Bearer specifies that the passed value is a so called bearer token. This is a token that gives the bearer - here the SPA - the rights that are associated with it.

Fabian Deitelhoff: LEGO Mindstorms EV3: Kostenfreie Education Software

Heute habe ich eine sehr gute Nachricht für alle Fans des LEGO Mindstorms EV3🙂 Genauer gesagt betrifft es die Education Software, die LEGO neben der kostenfreien Home Edition angeboten hat. Bisher war diese Education Software, hauptsächlich für Schulen, AGs und andere Bildungseinrichtungen gedacht, kostenpflichtig. Preislich lag das Paket so um die 130 Euro pro Arbeitsplatz, wenn ich mich richtig erinnere. Oder circa 400 Euro für eine Schullizenz.

Diese Software ist jetzt kostenfrei erhältlich. Woher du dieses Softwarepaket bekommst, beschreibe ich kurz in diesem Beitrag.

Warum die Education Version letztendlich freigegeben wurde, kann ich gar nicht sagen. Mir ist es selber auch gar nicht aufgefallen. Ich wurde vom aufmerksamen Leser Jochen darauf hingewiesen. Wir hatten uns über die Programmierung des Elefanten-Modells unterhalten und in einer E-Mail schrieb er dann, dass er die Education Version herunterladen konnte. Vielen Dank an dieser Stelle noch mal für die Info! LEGO muss ziemlich still und heimlich diese Änderung vorgenommen haben. Denn mir sind auch keine anderen Infos wie Blogposts oder ähnliches darüber bekannt. Eine Pressemitteilung oder so ist mir ebenfalls nicht unter gekommen. Mir war vor 3-4 Wochen lediglich aufgefallen, dass die Education Version aus dem offiziellen LEGO Shop entfernt wurde. Dabei gedacht habe ich mir allerdings nicht viel.

Download der Software

Der Download der Education Version ist sehr simpel. Auf der Seite https://education.lego.com gibt es einen Downloadbereich. Der Link zum Downloadbereich funktioniert allerdings nur, wenn ihr im LEGO-Portal angemeldet seid. Dieser ist allerdings durch eine LEGO ID geschützt. Wer noch keine ID hat, kann über die Seite aber direkt eine erstellen oder sich eben mit einer vorhandenen einloggen (siehe Abbildung 1). Wenn die Links zu englischsprachigen Webseiten führen, kann die Sprache in der Regel oben rechts angepasst werden.

Abb. 1: Login mit einer vorhanden LEGO ID oder eine LEGO ID erstellen.

Abb. 1: Login mit einer vorhanden LEGO ID oder eine LEGO ID erstellen.

Ich hatte mir irgendwann mal eine LEGO ID erstellt. Ich glaube, um im LEGO Shop etwas zu bestellen. Das scheint die gleiche LEGO ID zu sein. Zu 100% sicher bin ich mir allerdings nicht. Eine LEGO ID zu erstellen ist allerdings auch kein großes Problem. Abgefragt werden einige Daten wie Benutzername, Passwort, Geburtsdatum und E-Mail Adresse. Danach ist der Account schon bereit.

Nach dem Login mit der LEGO ID stehen drei verschiedene Softwarepakete in einer Übersicht zur Verfügung (siehe Abbildung 2). Unter anderem auch die Software LME EV3-Software (45544), um die es hier geht. Hinter der Abkürzung LME verbirgt sich die LEGO Mindstorms Education Edition. Zusätzlich stehen auch Downloads für das neue Education WeDo 2.0 zur Verfügung.

Abb. 2: Downloads im Education Portal nach dem Login.

Abb. 2: Downloads im Education Portal nach dem Login.

Die jeweiligen Downloads lassen sich über die Weiter-Schaltflächen starten. Die führen auf die Produktseiten, wo dann die Downloads für Windows und Mac OS X bereitstehen.

Installation

Die Installationen sind denkbar einfach. Einfach die Installationspakete starten und die richtige Installations-Art auswählen. Die LEGO Mindstorms EV3 Education Edition steht in einer Schüler- und einer Lehrer-Version zur Verfügung. Diese Option ist schon bei der Installation auszuwählen (siehe Abbildung 3). Die parallele Installation beide Versionen ist nicht möglich. Also vorher gut überlegen, was wichtig ist. Privat installiere ich mir aktuell die Lehrer-Version.

Abb. 3: Unterschiedliche Versionen der LEGO Mindstorms EV3 Education Software.

Abb. 3: Unterschiedliche Versionen der LEGO Mindstorms EV3 Education Software.

Je nach System kann sich die Installation etwas hinziehen. Allerdings läuft sie vollautomatisch ab, so dass zwischendurch keine weiteren Entscheidungen getroffen werden müssen. Anschließend ist die Software gleich einsatzbereit (siehe Abbildung 4).

Abb. 4: Startbildschirm der LEGO Mindstorms EV3 Education Edition in der Lehrer-Version.

Abb. 4: Startbildschirm der LEGO Mindstorms EV3 Education Edition in der Lehrer-Version.

Die parallele Installation der Education- und der Home-Edition ist im Übrigen kein Problem. Zumindest konnte ich auf meinen Systemen bisher nichts feststellen. Allerdings ist ein gleichzeitiger Start nicht möglich. Ist also die Education-Edition gestartet, lässt sich die Home-Edition nicht noch zusätzlich starten. Auf meinem Windows 10 System gab es auch keine Fehlermeldungen oder einen sonstigen Hinweis, dass das nicht möglich ist. Es passierte einfach nichts.

Fazit

Ich finde den Schritt von LEGO, die Education-Edition kostenfrei zur Verfügung zu stellen, sehr gut. Warum es zu der Entscheidung gekommen ist kann ich nicht sagen. Vielleicht blieben die Verkäufe hinter den Erwartungen zurück. Meine Vermutung ist eher, dass die zusätzliche Software eine zu große Hürde war. Bildungsträger müssen eh schon tief in die Tasche greifen, wenn der LEGO Mindstorms EV3 eingesetzt werden soll. Dann auch noch Geld für die Software bezahlen war vermutlich nicht wenigen dann doch ein Tick zu viel.

Auf jeden Fall freue ich mich über diesen Schritt. Ich werde jetzt in meinen Kursen auf die Education-Version umsteigen und sie auch privat einsetzen.

Manfred Steyer: Slides and Samples of my Talk about modern Authentication with Angular 2, OAuth 2 and OIDC at AngularCamp 2016 in Barcelona

Below the slides and samples of my talk about modern authentication with Angular 2, OAuth 2 and OIDC at AngularCamp 2016 in Barcelona:

Manfred Steyer: Slides and Samples of my Talk about Databinding and Performance in Angular 2 at AngularCamp 2016 in Barcelona

Below the Slides and Samples of my Talk about Databinding and Performance in Angular 2 at AngularCamp 2016 in Barcelona:


Sven Hubert: Rückblick DWX 2016 – Microsoft HoloLens als Publikumsmagnet am Stand von AIT

Vom 20.6. bis zum 23.6.2016 traf sich die Entwickler Community wieder zur Developer Week (DWX) in Nürnberg. Die AIT präsentierte dort die Microsoft Datenbrille HoloLens. Diese war der Publikumsmagnet in der Ausstellung, die ihm Rahmen der Konferenz stattfand.

WP_20160622_10_57_50_Pro

Eröffnet wurde die Konferenz mit einer Keynote von Jürgen Appelo unter dem Titel „Managing for Happiness“. Diese Keynote können Sie Sich hier in voller Länge anschauen:

Auch die AIT war wieder mit vielen Vorträgen rund um Prozesse und Technologien in der Softwareentwicklung im Microsoft Umfeld vertreten:

Falls Sie Interesse an den Folien zu einem der Vorträge haben melden Sie Sich einfach bei franz.mattes@aitgmbh.de

In der begleitenden Ausstellung standen die AIT Consultants für vertiefende Fachgespräche zur Verfügung. Mit im Gepäck hatte die AIT auch zwei Exemplare der Microsoft HoloLens. AIT ist aktuell einer der wenigen Microsoft Entwicklungspartner in Europa denen Microsoft schon Entwickler Prototypen der HoloLens zugeteilt hat. Dies war deshalb für die meisten Besucher die erste Möglichkeit der HoloLens in freier Wildbahn zu begegnen, und so war es nicht verwunderlich, dass sie schnell zum Publikumsmagnet wurde. Jeder wollte sie sich einmal aufsetzen und in die Mixed Reality eintauchen. Bald war der Ausstellungsbereich deshalb mit Hologrammen an allen Ecken und Enden gefüllt. Die Besucher ohne Datenbrille mussten deshalb aufpassen, dass sie nicht auf virtuelle Hunde traten, oder mit einem Planeten oder Raumschiff kollidierten, als sie durch den Gang liefen. Mit den ersten Kunden führen wir inzwischen schon Gespräche über den Einsatz der HoloLens in deren Geschäftsumfeld, z.B. als Assistenzsystem in der Fertigung. Wenn auch Sie Projektideen in ihren Umfeld für die HoloLens haben können sie sich jederzeit bei mir melden: franz.mattes@aitgmbh.de. Wir können dann gerne darüber sprechen, wie wir Sie in dieser neuen Technologie unterstützen können.

WP_20160621_16_28_19_Pro

IMG_5678

IMG_5670

IMG_5669

IMG_5681

IMG_5682

 

Manfred Steyer: Authentifizierung in Angular 2 mit OAuth2, OIDC, dem neuen Router und Guards

Der neue Router für Angular 2 bietet mit sogenannten Guards der SPA die Möglichkeit, das Routing zu beeinflussen. Dabei handelt es sich um Services, deren Methoden der Router beim Aktivieren bzw. Deaktivieren von Routen aufruft. Diese Methoden nennen sich sinngemäß canActivate und canDeactivate. Durch das Retournieren eines booleans können sie angeben, ob die jeweilige Aktion tatsächlich erlaubt ist. Zusätzlich können sie auch ein Observable<boolean> zurückliefern, um diese Entscheidung hinauszuzögern. Empfänge der Router über dieses Observable den Wert true, führt er die jeweilige Routingaktion aus. Empfängt er hingegen false, bricht er diese ab.

In meinem Beitrag hier habe ich anhand eines Beispiels die Nutzung von canDeactivate beschrieben. Es zeigt vor dem Verlassen einer Route eine Warnmeldung an und gibt dem Benutzer die Möglichkeit, seine Entscheidung zu revidieren.

Dieser Beitrag zeigt, wie eine Anwendung mit canActivateunberechtigte Benutzer von bestimmten Routen fernhalten kann. Dies dient weniger der Sicherheit, zumal Sicherheit bei Browser-basierten SPAs immer im Backend zu realisieren ist. Vielmehr dient dies der Benutzerfreundlichkeit, da hierdurch die Anwendung den Benutzer im Fall des Falls zur Anmeldung auffordern kann. Der gesamte Quellcode des hier präsentierten Beispiels findet sich hier. Es nutzt neben dem Guard-Konzept auch die Security-Standards OAuth 2 und OpenId Connect (OIDC), um die Authentifizierung und Autorisierung von der Anwendung zu entkoppeln und Single-Sign-On zu ermöglichen.

Vorbereitung

Zunächst benötigt man eine Bibliothek, die OAuth 2 und OIDC implementiert. Das hier betrachtete Beispiel nutzt meine Implementierung, welche via npm zur Verfügung steht:

npm install angular2-oauth2 --save

Danach ist der von dieser Bibliothek bereitgestellte OAuthService zu importieren und beim Bootstrapping der Anwendung zu berücksichtigen:

import { OAuthService } from 'angular2-oauth2/oauth-service';
[...]

var APP_PROVIDERS = [
  OAuthService
];

var providers = [
  APP_PROVIDERS,
  HTTP_PROVIDERS,
  [...]
];

bootstrap(AppComponent, providers);

Zum Konfigurieren des OAuthServices bietet sich der Konstruktor der Top-Level-Component an. Die nachfolgend eingerichteten Einstellungen verweisen auf einen OAuth2/OIDC-Auth-Server, den ich zu Testzwecken in der Cloud zur Verfügung stelle:

import { Component } from '@angular/core'
import { Router, ROUTER_DIRECTIVES } from '@angular/router'
import { HomeComponent} from './home/home.component';
import { OAuthService} from 'angular2-oauth2/oauth-service';

@Component({
    selector: 'flight-app',
    directives: [ROUTER_DIRECTIVES],
    template: require('./app.component.html')
})
export class AppComponent {

    constructor(private oauthService: OAuthService, private router: Router) {

        this.oauthService.loginUrl = "https://steyer-identity-server.azurewebsites.net/identity/connect/authorize"; //Id-Provider?
        this.oauthService.logoutUrl = "https://steyer-identity-server.azurewebsites.net/identity/connect/endsession?id_token={{id_token}}";
        this.oauthService.redirectUri = window.location.origin + "/index.html";
        this.oauthService.clientId = "spa-demo";
        this.oauthService.scope = "openid profile email voucher";
        this.oauthService.issuer = "https://steyer-identity-server.azurewebsites.net/identity";
        this.oauthService.setStorage(localStorage);
        this.oauthService.oidc = true;

        this.oauthService.tryLogin({});


    }
}

Der Aufruf der Methode tryLogin prüft, ob die Anwendung über das Hash-Fragment Security-Token empfangen hat. Sie parst diese Token und entnimmt Informationen über den Benutzer. Falls diese Informationen sicherheits-kritisch sind, muss die Anwendung das Token noch validieren. Dies ist vorallem bei hybriden und nativen Anwendungen, die diese Daten zum Zugriff auf lokale Ressourcen nutzen, der Fall. Das nachfolgende Beispiel nutzt dazu einen Callback, der sich zur Validierung an das Backend wendet:

this.oauthService.tryLogin({
    validationHandler: context => {
        var search = new URLSearchParams();
        search.set('token', context.idToken); 
        search.set('client_id', oauthService.clientId);
        return http.get(validationUrl, { search }).toPromise();
    }
});

Login

Um den Benutzer zur Login-Maske des Auth-Servers weiterzuleiten, ist lediglich die Methode initImplicitFlow des OAuthServices aufzurufen. Das nachfolgende Beispiel veranschaulicht dies mit der Methode login. Die Methode logout meldet den Benutzer ab. Dazu löscht sie alle Security-Token und falls die Anwendung dem Service eine Logout-Url mitgeteilt hat, leitet sie den Benutzer dorthin um:

import { Component } from '@angular/core';
import { OAuthService} from 'angular2-oauth2/oauth-service';

@Component({
    selector: 'home',
    template: require('./home.component.html')
})
export class HomeComponent {

    constructor(private oauthService: OAuthService) {
    }

    public login() {
        this.oauthService.initImplicitFlow();
    }

    public logout() {
        this.oauthService.logOut();
    }

    public get userName() {

        var claims = this.oauthService.getIdentityClaims();
        if (!claims) return null;

        return claims.given_name;
    }

}

Zusätzlich versucht der Getter userName den Vornamen des Benutzers zu ermitteln. Dazu greift er auf die Claims, welche die Bibliothek aus dem Security-Token entnommen hat, zu.

Das dazugehörige Template bindet sich an diese Eigenschaften und Methoden:

<h1 *ngIf="!userName">Welcome!</h1>
<h1 *ngIf="userName">Hello, {{userName}}!</h1>
<p>Welcome to this demo-application.</p>
<p>
    <button (click)="login()" class="btn btn-default">Login</button>
    <button (click)="logout()" class="btn btn-default">Logout</button>
</p>    
<p>
    Username/Passwort: max/geheim
</p>

Mit Guard unauthorisierte Benutzer fernhalten

Um anonyme oder nicht berichtige Benutzer von Routen fernzuhalten, kann sich die Anwendung auf Guards stützen. Das nachfolgende Beispiel zeigt eine entsprechende Implementierung. Es handelt sich dabei um einen Angular-2-Service, der CanActivate implementiert und sich den OAuthService injizieren lässt. Die vom Interface vorgegebene Methode canActivate prüft, ob die nötigen Security-Token vorliegen. Dabei handelt es sich um das von OAuth 2 definierte Access-Token sowie um das von OIDC ergänzte Id-Token. Wenn beide vorliegen und beide noch nicht abgelaufen sind, liefert sie true. Damit signalisiert sie dem Router, dass er die gewünschte Aktion ausführen darf. Ansonsten liefert sie false und bricht damit die Routing-Aktion ab:

import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import { OAuthService} from 'angular2-oauth2/oauth-service';
import { Injectable} from '@angular/core';

@Injectable()
export class FlightBookingGuard implements CanActivate {

    constructor(private oauthService: OAuthService) {
    }

    canActivate(
        route: ActivatedRouteSnapshot, 
        state: RouterStateSnapshot) {

            var hasIdToken = this.oauthService.hasValidIdToken();
            var hasAccessToken = this.oauthService.hasValidAccessToken();

            return (hasIdToken && hasAccessToken);
    }
}

Die von canActivate entgegengenommenen Parameter informieren über die aktuelle Route sowie über die angestrebte Routing-Aktion.

Der Guard ist dann noch in der Routing-Konfiguration in der Eigenschaft canActivate der jeweiligen Routen zu hinterlegen. Dabei handelt es sich zunächst lediglich um ein Token, welches später über einen Provider an einen Service zu binden ist:

import { RouterConfig, provideRouter } from '@angular/router';
import { HomeComponent} from './home/home.component';
import { FlightSearchComponent} from './flight-search/flight-search.component';
import { PassengerSearchComponent} from './passenger-search/passenger-search.component';
import { FlightEditComponent} from './flight-edit/flight-edit.component';
import { FlightBookingComponent} from './flight-booking/flight-booking.component';
import { FlightBookingGuard} from './flight-booking/flight-booking.guard';
import { FlightEditGuard} from './flight-edit/flight-edit.guard';
import { InfoComponent} from './info/info.component';
import { DashboardComponent} from './dashboard/dashboard.component';


const APP_ROUTES: RouterConfig = [
    {
        path: '/home',
        component: HomeComponent,
        index: true
    },
    {
        path: '/info',
        component: InfoComponent,
        outlet: 'aux'

    },
     {
        path: '/dashboard',
        component: DashboardComponent,
        outlet: 'aux'
    },    
    {
        path: '/flight-booking',
        component: FlightBookingComponent,
        canActivate: [FlightBookingGuard],
        children: [
            {
                path: '/flight-search',
                component: FlightSearchComponent
            },
            {
                path: '/passenger-search',
                component: PassengerSearchComponent
            },
            {
                path: '/flight-edit/:id',
                component: FlightEditComponent
            }
        ]
    }
];

Da in diesem Fall das Token gleichzetig auch der zu nutzende Service ist, ist dieser lediglich in die Provider-Konfiguration aufzunehmen. Zusätzlich kommen dort die Provider für den Router rein. Dazu kann die Anwendung die Methode provideRouter, welche die Routing-Konfiguration entgegennimmt, nutzen:

const APP_PROVIDERS = [
  OAuthService
];

export const APP_ROUTER_PROVIDERS = [
    FlightBookingGuard,
    provideRouter(APP_ROUTES),
];

var providers = [
  APP_PROVIDERS,
  APP_ROUTER_PROVIDERS,
  HTTP_PROVIDERS
];

bootstrap(AppComponent, providers);

Web API aufrufen

Beim Aufrufen von Web APIs ist das erhaltene Access-Token zu übergeben. Dieses stellt die Methode getAccessToken des OAuthServices zur Verfügung. Dieses Token ist über den Header Accept zu übergeben:

public find(from: string, to: string) {
    var url = this.baseUrl + "/api/flight";

    var search = new URLSearchParams();
    search.set('from', from);
    search.set('to', to);

    var headers = new Headers();
    headers.set('Accept', 'text/json');
    headers.set('Authorization', 'Bearer ' + this.oauthService.getAccessToken())

    return new Observable((observer: Observer<Flight[]>) => {
        this.http
            .get(url, { search, headers })
            .map(resp => resp.json())
            .subscribe((flights) => {
                this.flights = flights;
                observer.next(flights);
            });
    });
}

Der Wert Bearer gibt an, dass es sich beim übersendeten Wert um ein Bearer-Token handelt. Das sind Tokens, die seinem Überbringer - hier der SPA - die damit einhergehenden Rechte einräumen.

Manfred Steyer: Slides and Case Study from my talk about Progressive Web Apps with Angular 2 at AngularCamp in Barcelona 2016

Below you find the slides and the Case Study from my talk about Progressive Web Apps with Angular 2 at AngularCamp in Barcelona 2016.

The Case Study shows:

  • Caching with Service Worker and the Service Worker Toolbox
  • Storing data with PouchDB (which uses IndexedDb, WebDb or LocalStorage)
  • AppShell Pattern with Caching to quickly provide value to the user
  • Web App Manifest and a Fallback using Meta-Tags to install the App to the Home Screen
  • Background Synchronisation with Service Workers
  • Push Notifications with Service Worksers
Downloads:



Johannes Renatus: T4 Template als Service/Proxybuilder für AngularJs TypeScript Services

Wenn man einen AngularJs HTTP Service erstellt der die Verbindung zum .NET Controller herstellen soll um Daten abzufragen oder zu speichern, handelt es sich immer um den “gleichen” boilerplate Code der geschrieben werden muss. Genau hier setzt mein T4 Template der Proxybuilder an und generiert die passenden AngularJs Services in JavaScript oder auch in TypeScript […]

Jürgen Gutsch: .NET Core 1.0 RTM and ASP.​NET Core 1.0 RTM was announced

Finally we get .NET Core 1.0 RTM and ASP.​NET Core 1.0 RTM. Yesterday Microsoft announces the release of .NET Core 1.0 and ASP.​NET Core 1.0.

Scott Hanselman posted a great summery about it: .NET Core 1.0 is now released! You'll find more detailed information about .NET Core 1.0 on the .NET Blog in the Post "Announcing .NET Core 1.0" and pretty much detailed information about ASP.​NET Core 1.0 in the .NET Web Development and Tools Blog in the post "Announcing ASP.NET Core 1.0"

Updating exiting .NET Core RC applications to the RTM, needs some attention. (Not as much as from RC1 to RC2, but there is a little bit to do). First of all: The Visual Studio 2015 Update 3 is needed, as pretty much mentioned in all of the Blog posts. To learn more about the need things to do, Rick Strahl posted a great and pretty detailed post about updating an existing application: Upgrading to ASP.NET Core RTM from RC2

codefest.at [MS]: Announcing .NET Core 1.0

Tataa, .NET Core 1.0 ist da! Heute wurde im Microsoft dotnet-Blog die erste Release von .NET Core 1.0, ASP.NET Core 1.0 und Entity Framework 1.0 für Windows, OS X und Linux angekündigt!

.NET Core ist die Cross-Platform und Open Source Version des Microsoft .NET Frameworks, welches bereits vor 14 Jahren (2002) das Licht der Welt erblickt hat. Ich erinnere mich noch daran, dass damals Bill Gates in Wien war und Visual Studio .NET angekündigt wurde… lange ists her.

Allerdings ist .NET Core eine völlige Neuentwicklung, um modulare .NET Applikationen wie moderne Web Apps, Microservices, Libraries und Console Applications zu entwickeln.

Die Original-Ankündigung mit den Details sind unter Announcing .NET Core 1.0 zu finden.

Die Dokumentation von .NET Core 1.0 gibt es unter der (neuen) Microsoft Doku-Plattform docs.microsoft.com. Zum raschen Einstieg wird nur das NET Core SDK benötigt (siehe auch hier). Als Startpunkt bietet sich die .NET Core Website an.

SNAGHTML2460bd8

Zum ersten Mal können mit ASP.NET nun Web-Apps entwickelt werden, die unter Windows, Mac und Linux lauffähig sind, dank des Cross-Platform ASP.NET Core Frameworks.

Wer in ASP.NET Core 1.0 einsteigen möchte findet hier, auf Channel9, das Startvideo von Scott Hanselman: Introducing ASP.NET Core 1.0

image

Weiter gehts dann mit Deploying ASP.NET Core Applications

Die Session Entity Framework Core 1.0 informiert über das neue Datenbank-Framework. Die Dokumentation dafür ist unter docs.efproject.net erreichbar.

Weitere BUILD-Sessions zu diesem Thema sind hier aufgelistet – einfach auf der Build 2016-Event Seite nach den entsprechenden Titeln suchen:

image

Viel Spaß beim Entwickeln mit .NET Core 1.0, ASP.NET Core 1.0 und Entity Framework 1.0 unter Windows, iOS und Linux!

Kay Giza [MS]: Welche Screen Capture Software verwende ich?

Ich werde von Zeit zu Zeit immer wieder gefragt, welche Tools ich für meine Präsentationen bei Vorträgen oder für meine Blogpostings benutze; so zuletzt auch auf der Developer Week. Dies nehme ich mal als Anlass dies zu skizzieren, insbesondere für alle Tekkis oder Menschen, die täglich dies brauchen könnten. Um es kurz zu machen, ich nutze generell... [... mehr in diesem Blogeintrag auf Giza-Blog.de]


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

Holger Schwichtenberg: Microsoft veranstaltet wieder einen Technical Summit.

Im dritten Jahr in Folge veranstaltet Microsoft einen Technical Summit. Veranstaltungsort ist Darmstadt.

Karsten Kempe: Prozessanpassungen in Visual Studio Team Services – Work Item States

VSTSVor knapp zwei Monaten habe ich das erste Mal über Prozessanpassungen in Visual Studio Team Services geschrieben. Damals konnte man nur einfache Felder einem Work Item hinzufügen. Heute stelle ich Euch die Möglichkeit vor, wie man einen eigenen Prozess-Workflow mit Work Item States erzeugt.

Innerhalb eines individuellen Prozesses (wie man einen eigenen Prozess erzeugt, findet Ihr in den Basics), ist es seit kurzem möglich eigene Work Item Workflows oder auch Prozess-Workflows zu erzeugen. Dafür müssen in den Standard-Work Items neue Zustände definiert werden und/oder vorhandene Zustände ausgeblendet werden. Das Vorgehen hat rein gar nichts mehr mit dem Vorgehen beim Anpassen des Team Foundation Servers zu tun; keine XML-Dateien, kein WitAdmin, kein kompliziertes Handling mehr.

Wie beim Erstellen von neuen Feldern, wird in der Administrationsseite für Prozesse das zu verändernde Work Item ausgewählt und anschließend der Bereich „States“ selektiert. In den Details werden dann die einzelnen Zustände des Work Item Typen angezeigt.

Task Workflow

In meinem Task Work Item habe ich zum Beispiel den vorhandenen Initial-Zustand „ToDo“ ausgeblendet und durch den neuen Zustand „New“ ersetzt. Ausserdem habe ich den Zustand „Ready“ aufgenommen. Schön zu erkennen ist, dass die Zustände in Kategorien eingeteilt werden (Proposed, InProgress, Completed, Removed), die vergleichbar mit den bekannten Meta-Zuständen von Work Item Typen sind.

Wichtig: Vorhandene oder auch abgeleitete Zustände können nicht gelöscht werden, sondern nur aus dem Prozess ausgeblendet werden.

Das Erstellen eines neuen Zustands ist so einfach wie unspektakulär. Name vergeben, Kategorie und Farbe wählen und fertig.

Create State InReview

Durch die Veränderung der Zustände ist es nun auch erstmals möglich, die Spalten auf dem Task Board anzupassen, da diese sich ja nach dem Workflow des Task Work Items richten. Von vielen Nutzern sicherlich lang erwartet.

Task Board

Gut zu erkennen ist der neue Start-Zustand „New“ und der zusätzliche Zustand „Ready“.

Hinweis: Wer ein Work Item abändert, dass auf einem Kanban-Board angezeigt werden soll, darf sich nicht wundern, denn der neue State nicht automatisch auf dem Board angezeigt. Er muss erst über die Board-Einstellungen hinzugefügt werden.

Es ist natürlich noch nicht alles Gold was glänzt und vieles was im TFS funktioniert, geht im neuen Prozess-Modell des VSTS noch nicht. Es fehlen zum Beispiel noch das Bearbeiten der Zustandsübergänge, Zustands-Regeln und Workflow-Automatismen. Aber das Team arbeitet hart daran uns diese Feature so schnell wie möglich auch noch bereit zustellen.

Stay tuned!

[0] States customization on Team Services

[1] Prozessanpassungen in Visual Studio Team Services – einfache Felder

[2] Prozessanpassungen in Visual Studio Team Services – die Basics

Norbert Eder: Visual Studio 2015: Sprache ändern

Ich habe heute Visual Studio 2015 versehentlich in Deutsch installiert. Da ich allerdings Englisch bevorzuge, stellte sich die Frage, ob ich die Sprache ohne Neuinstallation ändern kann (denn von Haus aus unterstützt das Visual Studio nicht). Kann man:

Dazu gibt es ein Visual Studio 2015 Language Pack.

Nach der Installation findet sich ein neuer Eintrag in den Optionen: Internationale Einstellungen:

Visual Studio 2015 - Sprache wechseln

Visual Studio 2015 – Sprache wechseln

Damit die Änderungen wirksam werden ist Visual Studio neu zu starten.

Danke Dariusz für den Tipp.

The post Visual Studio 2015: Sprache ändern appeared first on Norbert Eder.

Wolfgang Kinkeldei: FAKE und Sass

Gerne wird CSS nicht mehr direkt selbst geschrieben, sondern mit Präprozessoren wie z.B. SASS erzeugt. Schnell werden dann Projekte mit meist node.js basierenden Hilfsprogrammen ausgestattet, die lokal natürlich immer prima funktionieren, aber auf CI-Servern durchaus Probleme bereiten können. Genau das ist uns kürzlich passiert.

Kurzerhand haben wir beschlossen, die wesentlichen Schritte auf unserem CI Server durch entsprechende Funktionalitäten von FAKE zu ersetzen, was neben durchgängiger Versionskontrolle nur noch Abhängigkeiten von NuGet Paketen hatte.

Und eine Bibliothek für die Compilierung von SASS in das FAKE Script einzubauen war selbst für mich als F# Neuling nicht das große Problem.

Die relevanten Teile des Build Scripts sehen so aus – vermutlich lässt sich noch einiges daran verbessern aber die Abhängigkeit zu "Fremdkörpern" ist hiermit verschwunden:

#r @"packages/FAKE/tools/FakeLib.dll"
#r @"packages/libsassnet/lib/net40/LibSass.x86.dll"
#r @"packages/libsassnet/lib/net40/libsassnet.dll"

open Fake
open System.IO
open LibSassNet

let compileScss files =
    let compile file =
        let filename ext = Path.ChangeExtension(file, ext)

        let compiler = new LibSassNet.SassCompiler()

        tracefn "Compiling %s..." file

        let generateOutput outputStyle cssFile =
            let mapFile = cssFile + ".map"
            let result = compiler.CompileFile(file, outputStyle, mapFile)
            File.WriteAllText(cssFile, result.CSS)
            File.WriteAllText(mapFile, result.SourceMap)

        generateOutput LibSassNet.OutputStyle.Compact (filename ".css")
        generateOutput LibSassNet.OutputStyle.Compressed (filename ".min.css")

    files

        |> Seq.iter compile

// Targets (Auszug)
Target "Css" (fun _ ->
    !! "**/Content/*.scss"
        |> compileScss


)
...

Alexander Schmidt: ReSharper verhindert SmartTag-Shortcut

SmartTag-Shortcut mit ReSharper-Installation beheben.

friends header

bloggers headline

links header

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