MSDN Team Blog AT [MS]: ibiola – Mobilität neu erFAHREN!


Möchten Sie Ihren Mitarbeitern ein Mehr an Mobilität bieten und dabei Ihre Fuhrparkkosten um 35% reduzieren? Dann ist Corporate Carsharing das Richtige für Sie. Und wenn alles einfach laufen soll, dann ist ibiola® die richtige Lösung!

Was bereitet Fuhrparkmanagern Kopfzerbrechen?

  1. Unausgelastete Flotte (hohe Stillstandzeiten) – Sie zahlen zu hohe Fixkosten – jede Stunde, jeden Tag
  1. Firmenparkplätze sind überfüllt
  2. Zeitaufwendige Verwaltung von Fahrtenbüchern
  3. Zeitaufwendige Verwaltung der Serviceplanung Ihrer Fahrzeuge
  4. Buchung und Schlüsselverwaltung existierender Pool-Autos

Die Lösung: Keep your fleet running!

Was ist ibiola®?

ibiola® ist die Lösung für Corporate Carsharing auf Azure. Das nahtlose Zusammenspiel von Hard- und Software gewährleistet den reibungslosen Ablauf der Flottenmanagement- und Carsharing-Prozesse.

Was haben Sie davon?

  • Bis zu 30% Kostenreduktion
    • Durch effiziente, gemeinsame Nutzung Ihrer Flotte (Typ II Mobilität) und/oder Reduzierung Ihrer Flotte (Anzahl der Fahrzeuge)
  • Deutliche Einsparung bei Dienstreise-Kosten
    • Durch Verlagerung von Taxi-, Zug- und Mietwagenfahrten auf Firmenfahrzeuge
  • Aufwand- und Zeitersparnis bei der Verwaltung des Fuhrparks
    • Durch schlüsselloses Sharing, automatisches E-Fahrtenbuch & Service Ereignis-Management, automatische Abrechnung und Self-Service Buchungssystem
  • Parkplatzflächen einsparen
  • Motivieren Sie Mitarbeiter ohne eigenes Firmenfahrzeug und monetisieren Sie ungenutzte Fahrzeugstunden für Privatfahrten
  • Gelegenheit elektrische Fahrzeuge einzuführen, deren Kosten schnell zu amortisieren und einen Beitrag zur Nachhaltigkeit leisten!

Funktionalitäten:

  • Corporate Carsharing Komplett-Lösung inkl. Hardware und Software
  • Schlüsselloser Zugang (Smartcard oder App)
  • Einfache Buchung (Reservierung) der Fahrzeuge mittels PC oder App samt Integration mit Unternehmens-Kalendern (z.B. Microsoft Exchange / Outlook)
  • Automatisches elektronisches Fahrtenbuch
  • Echtzeit-Anzeige von Treibstoff, Batterieladestand und Service Ereignisse Ihrer Flotte
  • Schnelle Installation von On-board Units (OBU) für Telemetrie, Ortung und schlüssellosen Zugang
  • Komplettes Softwarepaket für Flotten-Management & -Optimierung (Reporting, Statistik, Analyse, Echtzeit Monitoring, Buchhaltung/Abrechnung)
  • Skalierbare Lösung durch flexible Ressourcen-Nutzung auf Azure: kann von einem Auto bis zu tausenden Fahrzeugen genutzt werden

 

 

 

 

 

 

 

 

 

 

 

 

Möchten Sie ibiola® ausprobieren? Dann nehmen Sie mit uns Kontakt auf unter: office@ibiola-mobility.com oder +43 316 694221 0 und wir richten Ihnen gerne ein oder mehrere Test-Accounts ein!

Sie möchten Autos teilen, haben aber nur ein Auto oder möchten selbst eines vermieten? Kein Problem, dann nutzen Sie unsere Peer-to-Peer Carsharing-Plattform www.carsharing247.com!

 

Manfred Steyer: Angular im Enterprise-Umfeld: Folien und Beispiel von DWX 2017 in Nürnberg


André Krämer: Xamarin Exception: Could not load file or assembly mono.posix beim Debugging

Nach einem der letzten Updates zu Visual Studio 2017.2 erhielt ich folgende Fehlermeldung beim Debugging einer Android App:

EXCEPTION: Mono.Debugging.Soft.DisconnectedException: The connection with the debugger has been lost. The target application may have exited. ---> System.IO.FileNotFoundException: Can not load 'Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756' or its dependencies. File not found.
   at Mono.Debugging.Soft.SoftDebuggerSession.ResolveSymbolicLink(String path)
   at Mono.Debugging.Soft.SoftDebuggerSession.PathsAreEqual(String p1, String p2)
   at Mono.Debugging.Soft.SoftDebuggerSession.FindLocationByMethod(MethodMirror method, String file, Int32 line, Int32 column, Boolean& insideTypeRange)
   at Mono.Debugging.Soft.SoftDebuggerSession.FindLocationByType(TypeMirror type, String file, Int32 line, Int32 column, Boolean& genericMethod, Boolean& insideTypeRange)
   at Mono.Debugging.Soft.SoftDebuggerSession.ResolveBreakpoints(TypeMirror type)
   at Mono.Debugging.Soft.SoftDebuggerSession.HandleTypeLoadEvents(TypeLoadEvent[] events)
   at Mono.Debugging.Soft.SoftDebuggerSession.HandleEventSet(EventSet es)
   at Mono.Debugging.Soft.SoftDebuggerSession.EventHandler()

Eine Lösung des Problems war glücklicherweise schnell gefunden. Wie man auf der Xamarin Release Seite nachlesen kann, wird die Datei Mono.Posix.dll tatsächlich durch den Visual Studio Installer nicht mit intstalliert.

Bis das Problem mit einem Update behoben ist hilft folgender Workarround, der aus dem obigen Link entnommen wurde:

  • Download der fehlenden Datei Mono.Posix.
  • Entpacken des Archivs
  • In den Eigenschaften der Mono.Posix.dll prüfen ob die Datei durch Xamarin Inc. signiert wurde
  • Datei ggfs. im Tab Allgmemein der Eigenschaften “Entblocken”
  • Unter: Visual Studio 2017: Datei Mono.Posix.dll in das “Xamarin.VisualStudio” Erweiterungs-Verzeichnis kopieren. Bei mir lag das unter: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Xamarin.VisualStudio
  • Visual Studio beenden und neustarten falls es während des Kopiervorgangs lief.

Das Problem sollte zum Glück nur temporär bestehen, da es im Xamarin Bugzilla bereits auf den Status gelöst gesetzt wurde. Mit Visual Studio 2017.3 sollte sich das Problem also erledigt haben.

MSDN Team Blog AT [MS]: Build Recap17–Folien der Vortragenden

Keynote mit Nico Sorger, Bereichsleiter DX bei Microsoft Österreich, Georg Binder und Gerwald Oberleitner (beide Microsoft)
BUILD17-on-Tour-Austria-Keynote

Roman Schacherl: Microsoft Azure Cognitive Services
Build-Recap_Schacherl_Cognitive-Services

Andreas Jakl: Bluetooth im allerneuesten Windows 10

Christian Nagel: .NET Standard Überblick

Raphael Schwarz: Entity Framework Core 2

Toni Pohl: Microsoft Graph

Raoul Holzer: Mobile Dev Update und XAML Standard

Christian Nagl: Neuerungen zu ASP.NET Core

Roman Stadlmair: Multiplattform Management (Linux/Windows)
BuildOnTour17-PowerShell

Rainer Stropek: TypeScript wird erwachsen
http://www.software-architects.com/devblog/2017/06/21/build-recap-whats-new-in-typescript

Andreas Pollak: Cosmos DB für Developer
https://blog.spectologic.com/2017/06/22/cosmosdb-build-2017-recap-vienna/

Markus Ehrenmüller: A Game of Hierarchies: Einführung in SQL Server 2017 Graph DB

Alois Reitbauer: Von 0 auf DevOps in 80 Tagen

Hannes Preishuber: Neues über Universal Windows Platform (UWP) Apps

Stefan Koell: DevOps Patterns and Anti-Patterns

Martina Grom: Azure Security

MSDN Team Blog AT [MS]: Kann Microsoft HoloLens die Angst vor Strahlentherapie mindern?

build.well.being. Digital Healthcare Networking Event der FH St. Pölten Kann Virtual Reality die Rehabilitation erfolgreich unterstützen?

Diese und andere Fragen werden beim build.well.being. Digital Healthcare Networking Event der FH St. Pölten diskutiert.

Technik revolutioniert den Healthcare-Sektor. Bei der build.well.being.-Veranstaltung wird ein Querschnitt der aktuellsten Themen im Bereich Digital Healthcare präsentiert.

Was ist build.well.being.?

build.well.being. vernetzt Pionierarbeiten der digitalen Gesundheit. GesundheitswissenschaftlerInnen treffen auf TechnikerInnen, Forschung auf innovative Ideen von Studierenden, Healthcare Unternehmen auf Startups und FachexpertInnen.

Ein kompakter Nachmittag spannt den Bogen von Deep Learning in der Medikamentenentwicklung zur Virtual und Mixed Reality in der Strahlentherapie. Sensorische Sitzmatten erfassen Rückenschmerzen und helfen gemeinsam mit Cloud Computing und Wearables die Arbeit im Reinraum der Zukunft lückenlos zu dokumentieren. Prototypische Ergebnisse der (angewandten) Forschung wie Telehealth-Dienste müssen evidenzbasiert entwickelt und rechtsicher in den Markt überführt werden.

Fotocredits: (C) Martin Lifka Photography  / FH St. Pölten

Albert Weinert: Git einsetzen mit verschiedenen E-Mail Adressen

Git einsetzen mit verschiedenen E-Mail Adressen

Als Freiberufler bin ich regelmäßig bei verschiedenen Kunden im Einsatz. Teilweise auch parallel. Viele nutzen davon auch Git zur Versionskontrolle. Dies ist generell ein gute Entwicklung die ich beobachte.

Globale E-Mail Konfiguration

Jedoch habe ich lange Zeit in der global git config immer meine E-Mail Adresse eingetragen, ist ja so einfach.

git config --global user.mail me@privatemail.com  

Was mich dabei schon lange ein wenig stört ist dass dies halt dann bei jedem Commit mit eingetragen wird. In welchem Repository auch immer ich Commits mache. Auch in Repositories die ich vielleicht mit einer anderen E-Mail Adresse committen muss. Eine die zum Kunden passt.

Dafür kann man nun für das spezielle Repository eine eigenen E-Mail hinterlagen.

git config --local user.mail me@clienmailt.com  

Keine Globale E-Mail Konfiguration

Soweit so gut, jedoch bin ich nur ein Mensch und dieser vergisst das schonmal. Und schon commite ich aus versehen mit der globalen E-Mail Adresse. Gerade wenn man mit mehreren Repositories jongliert, sich ein frisches klont weil man was nachschauen und fixen will. Der Alltag halt.

Damit dies ausversehen nicht mehr passiert habe ich mich dazu entschlossen keine globale E-Mail Adresse mehr zu hinterlegen.

git config --global --unset user.email  

Dann bekommt an bei einem Commit eine fehlermeldung um die Ohren gehauen, dass man doch bitte seine Default Identity setzen soll. Dies kann man dann ignorieren und für das lokale repository die E-Mail Adresse eintragen. Dies muss man dann immer zum ersten Commit in das Repository machen und das wärs dann. Korrekte E-Mail zum Repository.

Wünsche

Gewünscht hätte ich mir jedoch eine art root .gitconfig die ich einen Ordner legen kann und dann werden in allen untergeordneten die Einstellungen übernommen. In einer Hierarchie wie bei etlichen andren Tools (e.g. Nuget, Internet Information Service usw.). Dies gibt leider so nicht.

Doch dann der Tweet https://twitter.com/Philco78/status/877840330296442882 von Phil Scott.

Also check out git conditional includes. Let's you have a folder for each company and a config based on the path https://git-scm.com/docs/git-config#_includes

Update 1: Dazu ist Git erst ab Version 2.13 in der Lage

Git Konfiguration je Ordner

Das habe ich gemacht, [includeif] war fast genau dass was ich gesucht habe. Mit [includeif] kann ich einen Pfad angeben für den Git dann eine zusätzlich angegebene .gitconfig verwendet.

Dieser Pfad kann ein globbing Pattern sein, und wenn man nun alle Repositories für einen bestimmten Kunden in einem Ordner hat man eine spezifische Konfiguration für einen Ordner.

In meinem konkreten Fall bedeutet dies dass ich damit nicht mehr für jedes Repository einzeln die E-Mail Adresse eintragen muss. Sondern dies implizit über den Pfad stattfindet in dem sich das Repository befindet.

Das Beispiel

globale .gitconfig

[user]
    name = Albert Weinert
    useconfigonly = true
[includeif "gitdir:**/Client1/**/.git"]
    path = .gitconfig.client1
[includeif "gitdir:**/Client2/**/.git"]
    path = .gitconfig.client
[includeif "gitdir:**/Private/**/.git"]
    path = .gitconfig.private

Update 2: Git versucht sich in Domain Konfigurationen eine E-Mail Adresse abzuleiten.Mit useconfigonly kann man dies verhindern.

Für die Bedeutung von gitdir: und andere feinheiten schaue bitte in die Git Documentation dazu.

Hier nun die passenden spezifischen Git Konfigurationen
.gitconfig.client1

[user]
   email = a.weinert@client1.mail

.gitconfig.client2

[user]
   email = a.weinert@client2.com

.gitconfig.private

[user]
   email = info@der-albert.com

Woher kommt nun was?

Ich habe weiterhin keine globale E-Mail Adresse hinterlegt. Somit werde ich bei neuen Kunden daran erinnert eine spezifische Konfiguration anzulegen.

Die E-Mail Adresse ist natürlich nur eine Möglichkeit, man kann natürlich jegliche Git-Konfiguration darüber steuern.

Um Konfigurationsüberladungen die man sich damit einfängt zu diagnostizieren kann man

git config --global --list --includes  

verwenden. Damit sieht man, passend zu aktuellen Repository, welcher Wert aus welcher Datei stammt.

Update 3: Leider kann Visual Studio zum heutigen Stand noch nicht damit umgehen. Da es unter anderem auf libgit2 setzt und nicht überall Git selbst verwendet. Aber dafür ist ein PR für libgit2 anhängig, keine Ahnung wann diese Version dann in Visual Studio einfließt. Es schadet sicher für diesen UserVoice Vorschlag für Visual Studio abzustimmen.

Jürgen Gutsch: GraphQL end-point Middleware for ASP.NET Core

The feedback about my last blog post about the GraphQL end-point in ASP.NET Core was amazing. That post was mentioned on reddit, many times shared on twitter, lInked on http://asp.net and - I'm pretty glad about that - it was mentioned in the ASP.NET Community Standup.

Because of that and because GraphQL is really awesome, I decided to make the GraphQL MiddleWare available as a NuGet package. I did some small improvements to make this MiddleWare more configurable and more easy to use in the Startup.cs

NuGet

Currently the package is a prerelease version. That means you need to activate to load preview versions of NuGet packages:

  • Package name: GraphQl.AspNetCore
  • Version: 1.0.0-preview1
  • https://www.nuget.org/packages/GraphQl.AspNetCore/

Install via Package Manager Console:

PM> Install-Package GraphQl.AspNetCore -Pre

Install via dotnet CLI:

dotnet add package GraphQl.AspNetCore --version 1.0.0-preview1

Using the library

You still need to configure your GraphQL schema using the graphql-dotnet library, as described in my last post. If this is done open your Startup.cs and add an using to the GraphQl.AspNetCore library:

using GraphQl.AspNetCore;

You can use two different ways to register the GraphQl Middleware:

app.UseGraphQl(new GraphQlMiddlewareOptions
{
  GraphApiUrl = "/graph", // default
  RootGraphType = new BooksQuery(bookRepository),
  FormatOutput = true // default: false
});
app.UseGraphQl(options =>
{
  options.GraphApiUrl = "/graph-api";
  options.RootGraphType = new BooksQuery(bookRepository);
  options.FormatOutput = false; // default
});

Personally I prefer the second way, which is more readable in my opinion.

The root graph type needs to be passed to the GraphQlMiddlewareOptions object, depending on the implementation of your root graph type, you may need to inject the data repository or a EntityFramework DbContext, or whatever you want to use to access your data. In this case I reuse the IBookRepository of the last post and pass it to the BooksQuery which is my root graph type.

I registered the repository like this:

services.AddSingleton<IBookRepository, BookRepository>();

and needed to inject it to the Configure method:

public void Configure(
  IApplicationBuilder app,
  IHostingEnvironment env,
  ILoggerFactory loggerFactory,
  IBookRepository bookRepository)
{
  // ...
}

Another valid option is to also add the BooksQuery to the dependency injection container and inject it to the Configure method.

Options

The GraphQlMiddlewareOptions are pretty simple. Currently there are only three properties to configure

  • RootGraphType: This configures your GraphQL query schema and needs to be set. If this property is unset an ArgumentNullException will be thrown.
  • GraphApiUrl: This property defines your GraphQL endpoint path. The default is set to /graph which means your endpoint is available under //yourdomain.tld/graph
  • FormatOutput: This property defines whether the output is prettified and indented for debugging purposes. The default is set to false.

This should be enough for the first time. If needed it is possible to expose the Newtonsoft.JSON settings, which are used in GraphQL library later on.

One more thing

I would be happy, if you try this library and get me some feedback about it. A demo application to quickly start playing around with it, is available on GitHub. Feel free to raise some issues and to create some PRs on GitHub to improve this MiddleWare.

Manfred Steyer: AOT und Tree Shaking mit Angular - Folien und Beispiel von meiner Session auf EnterJS in Darmstadt

Nachfolgend die Folien und Beispiele zum Vortrag "AOT und Tree Shaking mit Angular":

Golo Roden: Von Callbacks zu Promises

Die vor einigen Wochen veröffentlichte Version 8.0.0 von Node.js unterstützt die beiden neuen Schlüsselwörter async und await. Sie funktionieren allerdings nur mit Funktionen, die Promises zurückgeben – nicht mit Callbacks. Wie kommt man möglichst einfach aus der einen in die andere Welt?

Stefan Henneken: IEC 61131-3: Additional language extensions

The focus of my post has been the object-oriented extensions so far. But there are several general, usually not so far-reaching innovations within TwinCAT 3. Below, they are briefly described.

Array initialization

If a declared array has to be initialized, the list with the initialization values should be set into square brackets.

VAR
  aTest1	: ARRAY [1..5] OF INT := [1, 2, 3, 4, 5];
  aTest2	: ARRAY [1..5] OF INT := [1, 3(5), 2];  (* short for [1, 5, 5, 5, 2] *)
END_VAR

So far, the square brackets have not been necessary.

Single line comments

C++, Java and C# have certainly their share in it: a comment can be now started with //. The comment ends with the line break.

VAR
  bVar    : BOOL;  // Single line comment
  nVar1   : INT;   (* Comment over
                      several lines *)
  nVar2   : INT;
END_VAR

Comments over several lines can be created with (**).

CONTINUE in loops

So far, a loop could be terminated prematurely within FOR, WHILE and REPEAT-loops with the statement EXIT. It is also possible now to prematurely resume a loop with CONTINUE.

PROGRAM MAIN
VAR
  nVar     : INT;
  nCounter : INT;
END_VAR

nCounter := 0;
FOR nVar := 1 TO 10 DO
  IF ((nVar MOD 2) = 0) THEN
    nCounter := nCounter + 1;
    CONTINUE;
  END_IF
  // other commands
  // ...
END_FOR

In the example above, the value of variable nCounter can only be increased if nVar is an even number. All commands below CONTINUE will not be executed after the calling of CONTINUE.

UNION in user-defined data types

With a UNION, it is possible to define your own data type, all the elements of which share the same storage space. The storage areas of the single elements overlap either completely or at least partly. Thereby, a UNION occupies at least so much memory as its largest component.

TYPE U_Test :
UNION
  nVar1      : WORD;
  nVar2      : BYTE;
END_UNION
END_TYPE

Here an example, where a 16bit variable can be accessed individually on the low byte and the high byte. For this purpose, a structure is created consisting of two bytes.

TYPE ST_Bytes :
STRUCT
  nVar1      : BYTE;
  nVar2      : BYTE;
END_STRUCT
END_TYPE

This structure, which occupies 16 bits, is connected with a WORD in a UNION.

TYPE U_Test :
UNION
  nVar1      : WORD;
  stVar2     : ST_Bytes;
END_UNION
END_TYPE

Both variables of the UNION start from the same address in the memory. The access to the single elements of the UNION is obtained in the same way as in one structure. The only difference is that an access to the variable uVar.nVar1 has also an influence on the variable uVar.stVar2 in this case.

PROGRAM MAIN
VAR
  uVar      : U_Test;
  nVar      : WORD;
  nA, nB    : BYTE;
END_VAR

uVar.nVar1 := 16#1234;
nA := uVar.stVar2.nVar1;    // Value: 16#34 (MSB)
nB := uVar.stVar2.nVar2;    // Value: 16#12 (LSB)

The value of the variable stVar2 changes in the UNION after the start of the program. This example shows, how the least significant bit (LSB) and the most significant bit (MSB) can be determined from the variable of type WORD without bit operations.

Data type LTIME

The data type TIME allows resolution in the range of milliseconds. Since the cycle times of controllers are meanwhile below the 1 ms threshold, it was necessary to define a more exact data type for date specification. LTIME has a size of 64 bits (instead of 32 bits) and allows a resolution in the range of nanoseconds.

PROGRAM MAIN
VAR
  tTest      : LTIME;
END_VAR

tTest := LTIME#134D12H13M34S354MS2US74NS;

Data type WSTRING

The data type STRING codes the characters according to the ASCII character set. Each character is represented by a byte. Thus, it is possible to represent the most letters and other characters, but not all of them. The data type WSTRING was implemented in order to meet the requirements of other languages. It codes the characters according to Unicode. Unicode uses up to 4 bytes per character. In TwinCAT 3, a Unicode variant is used which always occupies 2 bytes per character. In such a way, more than 65.000 different characters can be distinguished. Thus, the most characters used by people are representable, as far as they are included in the Unicode standard. The disadvantage is the higher storage requirement, as the following example shows:

PROGRAM MAIN
VAR
  wsTest          : WSTRING(10) := "abcdefäüöß";
  sTest           : STRING(10) := 'abcdefäüöß';
  nSizeWString    : UDINT;
  nSizeString     : UDINT;
END_VAR

nSizeWString := SIZEOF(wsTest);  // Value: 22
nSizeString := SIZEOF(sTest);    // Value: 11

There are also differences between WSTRING and STRING during initialization. While a STRING constant is defined with an apostrophe (line 4), quotation marks are used for a WSTRING constant (line 3).

Data type REFERENCE

This data type is similar to the data type POINTER. A reference refers to another variable as well. In contrast to a pointer, the pointed value is directly affected. Dereferencing is not necessary as with pointers. Assignments for reference variables take place with the help of the special assignment operator REF=.

PROGRAM MAIN
VAR
  refSample     : REFERENCE TO INT;
  nA            : INT;
  pSample       : POINTER TO INT;
  nB            : INT;
END_VAR

refSample REF= nA;
refSample := 12;
pSample := ADR(nB);
pSample^ := 12;

Both variables nA and nB have a value of 12 after the program start.

References can be initialized directly during the declaration. However, the common assignment operator is used here (line 3).

PROGRAM MAIN
VAR
  refSample     : REFERENCE TO INT := nA;
  nA            : INT;
  pSample       : POINTER TO INT;
  nB            : INT;
END_VAR

refSample := 12;
pSample := ADR(nB);
pSample^ := 12;

With the help of the operator __ISVALIDREF, one can check, whether a reference variable contains a valid value.

PROGRAM MAIN
VAR
  refSampleA    : REFERENCE TO INT := nA;
  nA            : INT;
  refSampleB    : REFERENCE TO INT;
  a, b          : BOOL;
END_VAR

a := __ISVALIDREF(refSampleA);   // TRUE
b := __ISVALIDREF(refSampleB);   // FALSE

A reference variable becomes invalid, if a value of 0 is assigned to it.

refSample REF= 0;
a := __ISVALIDREF(refSample);    // FALSE

Access to strings via []

Single characters of a variable of type STRING or WSTRING can be accessed via index operator. It returns the ASCII code as byte for a variable of type STRING. If a variable of type WSTRING is accessed, the Unicode as WORD is returned.

It has also write access to the characters. The array starts with 0, i.e. the first character (starting from the left) has the index 0.

PROGRAM MAIN
VAR
  wsTest            : WSTRING(10) := "abcdefgh";
  nLetterWString    : WORD;
  sTest             : STRING(10) := 'abcdefgh';
  nLetterString     : BYTE;
END_VAR

nLetterString := sTest[3];     // ASCII code of 'd': 100
nLetterWString := wsTest[5];   // Unicode of 'f': 102
wsTest[5] := 120;              // the 6th letter becomes a 'x'

Conditional compilation

Conditional compilation allows the programmer to make the compilation of certain program parts dependant on certain conditions. Conditional compilation assignments are designed in such a way, that they are executed not at runtime, but during the compilation.

With the help of {IF} and {END_IF}, a source text area can be limited, so that it will be only compiled if a certain condition is fulfilled. If necessary, an {IF}/{END_IF}can have several {ELSIF} instructions and one {ELSE} instruction.

The conditional compilation is very helpful, if a program has to be developed for different specifications. Not always required areas can be excluded from compilation. Thus, only the code is loaded to the controller, which is actually needed.

You can query different conditions:

{IF defined (identifier)}

A query is TRUE, if identifier was defined. The definition can be assigned with {define identifier} in the source text. It refers only to the current validity range. The validity range starts directly after the statement {define identifier} and terminates at latest with the end of the respective source text or with the statement {undefine identifier}.

If the definition has to be made for the whole validity range of the PLC project, it can be done using the properties dialogue of the PLC project. Several definitions are separated by commas.

Picture01 

A global definition cannot be unset by {undefine identifier}.

Statements for the conditional compilation are allowed only in the program area of structured text and in global variable lists. These are (unfortunately) not allowed in the declaration part of variables or in the definition of data types.

PROGRAM MAIN
VAR
  nScaling : INT;
END_VAR

{IF defined (MachineTypeA)}
  nScaling := 5;
{ELSIF defined (MachineTypeB)}
  nScaling := 10;
{ELSE}
  nScaling := 20;
{END_IF}

{IF defined (variable:variableName)}

The condition is met, if the variable variableName was declared in the current validity range.

PROGRAM MAIN
VAR
  nScaling     : INT := 1;
  // nOffset   : INT := 2;
  nX           : INT;
END_VAR

{IF defined (variable:nOffset)}
  nX := 100 * nScaling + nOffset;
{ELSE}
  nX := 100 * nScaling;
{END_IF}

After starting the program, the variable nX has the value of 100.

You can check whether the elements are available within structures, unions and enums. For instance, if a respective structure is located within PLC library, the conditional compilation can help to compile an application either with the new version or with the older version of the PLC library.

PROGRAM MAIN
VAR
  stTest  : ST_Test;
END_VAR

stTest.nA := 1;
stTest.nB := 2;
{IF defined (variable:stTest.nC)}
  stTest.nC := 3;
{END_IF}

{IF defined (type:typeName)}

The query is TRUE, if there exists a structure, enumeration or object composition with the name typeName.

{IF hastype (variable:variableName, dataType)}

The condition is met, if the variable variableName is of type dataType.

PROGRAM MAIN
VAR
  varSample : LREAL;
END_VAR

{IF hastype (variable:varSample, LREAL)}
  varSample := 123.456;
{END_IF}
{IF hastype (variable:varSample, INT)}
  varSample := 123;
{END_IF}

The variable varSample gets the value of 123,456 assigned after the start of the program.

{IF hasvalue (identifierName, identifierValue)}

An identifier can get the value of type STRING optionally assigned, when it is defined. This value can be requested in a condition.

PROGRAM PLC_PRG
VAR
  nSample : INT;
END_VAR

{define identifier '1'}
{IF hasvalue (identifier, '1')}
  nSample := 100;
{END_IF}
{IF hasvalue (identifier, '2')}
  nSample := 200;
{END_IF}

Unfortunately, the assignment of a value to an identifier is not possible in the properties dialogue of the PLC project.

After starting the program, the variable nSample has the value of 100.

{IF defined (pou:pouName)}

The condition is satisfied, if POU (FUNCTION, FUNCTION BLOCK, or PROGRAM) with the name pouName is available. This can be a POU from a PLC library.

PROGRAM MAIN
VAR
  nSample : INT;
END_VAR
 
{IF defined (pou:F_CheckRange)}
  nSample := 100 * GVL.nValue;
{ELSE}
  nSample := 100 * F_CheckRange(GVL.nValue);
{END_IF}

{IF hasattribute (pou:pouName,‘attributeName‘)}

The condition is fulfilled, if the POU pouName has the attribute attributeName. An attribute is assigned to the POUs as follows:

{attribute 'debug'}
FUNCTION TraceInfos : STRING
VAR_INPUT
  i : INT;
END_VAR

{IF hasattribute (variable:variableName,‘attributeName‘)}

Variables can be also declared with attributes, as well as the POUs.

VAR
  {attribute 'debug'}
  nSample : INT;
END_VAR

Operators AND, OR, NOT und ()

Several queries can be also combined with one another.

PROGRAM MAIN
VAR
  nScaling : INT;
END_VAR
 
{IF hasvalue (identifier, '1') AND hastype (variable:nSample, WORD)}
  nScaling := 5;
{ELSIF defined (MachineTypeB)}
  nScaling := 10;
{ELSE}
  nScaling := 20;
{END_IF}

Fabian Deitelhoff: LEGO® Robotik: Neues Projekt online

Nach langer Zeit gibt es mal wieder einen Blogpost von mir. 🙂 Allerdings auch nur einen ganz kleinen, in dem ich Ankündigen möchte, dass ab nun alle LEGO®-Robotik-Themen auf https://www.legorobotik.de anzutreffen sind. Ich werde die bestehenden Beiträge auf diesem Blog nicht löschen oder auf LEGO® Robotik neu veröffentlichen, aber neue Beiträge zu diesem Thema dürft ihr hier auch nicht mehr erwarten.

Mal schauen, wie das neue Projekt so läuft und wie viel Zeit ich im Endeffekt erübrigen kann. Das kann ich gerade selber sehr schlecht einschätzen und ich lasse mich überraschen.

Golo Roden: Gelesen: "Eine kurze Geschichte der Menschheit"

Der israelische Historiker Yuval Noah Harari hat ein Buch geschrieben, in dem er den Aufstieg des Homo Sapiens beschreibt, von der Urzeit bis zur Gegenwart. Das klingt zunächst nach einem spröden Geschichtsbuch. Doch das Gegenteil ist der Fall …

MSDN Team Blog AT [MS]: TFS 2017 Update 2 (RC1)

Für den Visual Studio Team Foundation Server, TFS (die lokale Variante der Visual Studio Team Services, VSTS) kommt ein eher ungewöhnlich großes Funktionsupdate. Derzeit ist das Update 2 als Release Candidate verfügbar. Viele neue Funktionen, wie zum Beispiel die Delivery Plans, werden nun auch im Server verfügbar.

Wie immer gilt, die Visual Studio Team Services sind der erste Platz wo neue Funktionen verfügbar werden. Das Cloudservice (welches auch in Europa gehostet wird) erfreut sich regen Zulaufs und auch die verwalteten Projekte werden immer größer und komplexer. Das x-Plattform Build- und Release-Management wurde auch einem kleinen Update (beim Editor) unterzogen.

Die TFS 2017 Update 2 (RC1) Neuerungen zusammengefasst.

MSDN Team Blog AT [MS]: pwnwin – die eSports Plattform für Alle

pwnwin, die weltweit führende Plattform für eSports Wettbewerbe mit über 100.000 aktiven Nutzern monatlich, hat soeben ihren Marketplace eröffnet.

Wir haben pwnwin im Dezember 2015 in Mondsee gegründet und uns zum Ziel gesetzt, den Markt für eSports Wettbewerbe zu erobern. Mit weltweit über 700.000 registrierten Benutzern und über 100.000 monatlich aktiven Benutzern sind wir auch am besten Weg dorthin. Unterstützt werden wir dabei nicht zuletzt von unseren Investoren Michael Altrichter, unter anderem bekannt aus der Puls 4 Show 2 Minuten 2 Millionen sowie Michael Eisler, dem Gründer des neuen österreichischen Startup Accelerator startup300.

Wettbewerbe für sechs Spiele verfügbar, Tendenz steigend

Begonnen haben wir mit Wettbewerben für League of Legends, eines der derzeit beliebtesten Onlinespiele mit weltweit über 100 Millionen Spielern monatlich. Mittlerweile haben wir mit Dota 2, Smite, World of Tanks, Paladins und Counter-Strike: Global Offensive noch fünf weitere Titel in unser Sortiment aufgenommen. Aber auch Fans von mobile games können sich freuen, mit Vainglory (iOS, Android) kommt demnächst unser Spiel #7 und gleichzeitig unser erster Ausflug in die mobile Welt.

So funktioniert pwnwin

Wir haben einen innovativen Weg gefunden, eSports Wettbewerbe asynchron abzuhalten. Auf pwnwin misst du dich nicht im direkten Duell mit anderen Spielern, sondern wir tracken deine Spielstatistiken und vergeben Punkte für deine in-game Performance, zB in League of Legends bekommst du für jeden Kill 10 Punkte, für jeden Death werden dir 15 Punkte abgezogen usw. Das bedeutet, jedes Mal wenn du spielst, nimmst du automatisch an pwnwin Wettbewerben teil und hast die Chance unsere pwnwin Coins zu gewinnen.

Wir sind der Meinung, dies ist der mit Abstand bequemste und sorgenfreiste Weg sich mit anderen zu messen.

Brandneu: der pwnwin Marketplace

Als heißestes Feature ist seit wenigen Wochen unser Marketplace online. Hier hast du die Möglichkeit, die gewonnenen Coins gegen in-game Währung (zB Riot Points oder WoT Gold), Steam Gift Cards, CSGO & Dota 2 Skins sowie Gaming Equipment und Hardware einzutauschen. Darüber hinaus hast du jeden Tag die Möglichkeit Preise von unseren Sponsoren und Partnern, wie MSI, Lioncast oder G2A zu gewinnen.

Microsoft Azure Services machen es möglich

Wir setzen auf Microsoft Azure Cloud Services um unsere Plattform sicher und zuverlässig anbieten zu können. Microsoft Azure erlaubt es uns, schnell auf sich ändernde Anforderungen und steigenden Traffic reagieren zu können. Unsere Anwendung skaliert automatisch hoch, wenn mehr Power nötig ist und automatisch wieder herunter, wenn sich die Last wieder normalisiert hat.

 

Du spielst gerne eSports Titel? Worauf wartest du noch? Gehe zu http://pwnwin.com, registriere dich und gewinne Preise, Fame & Glory noch heute.

 

 

Kontakt: Roman Knoblechner (Co-Founder): roman@pwnwin.com

Facebook: https://www.facebook.com/pwnwin/

Twitter: https://twitter.com/pwnwin_com

Instagram: https://www.instagram.com/pwnwin/

YouTube: https://www.youtube.com/pwnwincom

Twitch: https://www.twitch.tv/pwnwin

 

Über pwnwin GmbH

pwnwin GmbH ist ein österreichisches Start-Up Unternehmen, gegründet von vier eSports Enthusiasten, mit dem Ziel eine großartige Plattform zu entwickeln.

http://www.pwnwin.com/

Stefan Lieser: Abhängigkeiten reduzieren

Abhängigkeiten sind das Grundübel der Softwareentwicklung. Viele Entwickler nehmen sie als gegeben hin. Doch wir können Abhängigkeiten so reduzieren, dass Testbarkeit, Lesbarkeit und damit die Wandelbarkeit deutlich verbessert werden.

Der Beitrag Abhängigkeiten reduzieren erschien zuerst auf Refactoring Legacy Code.

Stefan Lieser: Podcast für Fachinformatiker

Stefan Macke präsentiert schon einige Zeit seinen Podcast für Fachinformatiker Anwendungsentwicklung. Er hat mich zum Thema Clean Code Developer interviewt.

Der Beitrag Podcast für Fachinformatiker erschien zuerst auf Refactoring Legacy Code.

AIT: Dependency Manager – Abkündigung der XAML-Build-Aktivitäten

Das neue Build-System in Visual Studio Team Services (VSTS) bzw. im Team Foundation Server (TFS) gewinnt immer mehr an Bedeutung. Deshalb haben wir uns nach reiflicher Überlegung entschieden, die Unterstützung der XAML-Build-Aktivitäten CleanDependencies und GetDependencies im AIT Dependency Manager abzukündigen. An der aktuellen Produktversion ändert sich nichts, alles funktioniert wie gewohnt. Bei zukünftigen Releases werden wir die Abwärtskompatibilität mit den o.g. XAML-Build-Aktivitäten jedoch nicht mehr sicherstellen.

Da wir den Quellcode bereits vor längerem auf GitHub veröffentlicht haben, kann die Software gerne weiterhin an die eigenen Bedürfnisse angepasst werden (siehe speziell im Workflow). Für weitere Informationen im Umgang mit Pull Requests zum Teilen der Änderungen siehe auch unseren vorangegangenen Blogpost Pull Request auf GitHub über einen Fork.

Der Download der aktuellen Version befindet sich wie gewohnt auf der Produktseite im Downloadbereich.

AIT: WiX: Automatische Fragmenterzeugung mit Heat

Das WiX Toolset ist ein mächtiges Werkzeug um Installationsroutinen mit Hilfe von XML zu erzeugen.

Herzstück eines WiX Projektes ist das Product Element. Innerhalb diesem werden die Elemente der Installationsroutine definiert. Um außerhalb des Product Elements Installationselemente wie Components oder Directorys zu definieren wird ein Fragment Element benötigt, in welchem die einzelnen Elemente angelegt werden. Für die Übersichtlichkeit ist es daher sinnvoll eine neue Fragmentdatei außerhalb des Product Elements zu erzeugen.

Wer seine WiX Fragmente von Hand erzeugt, wird schnell merken, dass diese mit jeder Erweiterung der Software erneut angepasst werden müssen. Vor allem bei stetig wachsender Software kann dies zu Problemen führen. Nicht zuletzt, weil Fragmente gerne mal zu hunderten XML-Zeilen heranwachsen.
Schnell wird die Integration einer neuen DLL vergessen und die Anwendung startet nach Installation nicht.

An dieser Stelle ist die Frage angebracht ob man das Problem nicht automatisiert lösen kann?

Die Antwort ist: ja, man kann!

Das Harvest Tool „Heat“, welches im WiX Toolset mitgeliefert wird, bietet diverse Möglichkeiten um ganze Ordner, Projekte und sogar IIS Webseiten quasi zu „farmen“.

In diesem Blogpost wird speziell auf die Möglichkeit eingegangen, Verzeichnisse zu farmen.

Als Software kommen im Folgenden das WiX Toolset v3.10 sowie Visual Studio 2015 zum Einsatz.

Um aus einem Verzeichnis mit Heat ein Fragment zu erzeugen genügt der Aufruf von Heat über das MSBuild Target BeforeBuild innerhalb der .wixproj Datei. Der folgende Screenshot zeigt eine beispielhafte Definition eines solchen Aufrufs.

BeforeBuild Target

Wichtig ist der Aufruf der heat.exe über die MSBuild Task Exec. Heat benötigt zum Aufruf  weitere Parameter. Die Wichtigsten werden im Folgenden vorgestellt:

  1. dir definiert das Ausgangsverzeichnis in welchem Heat beginnen soll. Es werden zusätzlich alle Unterordner durchforstet.
  2. -var gibt die Pfadvariable zur Datei an, in unserem Beispiel würden im Fragment alle Dateien im Source Attribut also den Wert „$(var.Persistence.WindowsService.TargetDir)\<Datei>“
    Um die Projekt Referenz Variable TargetDir nutzen zu können, muss darauf geachtet werden, das zu installierende Projekt zu den Referenzen des WiX Installationsprojekts hinzuzufügen.
  3. -dr gibt die Referenz zum gewünschten Directory innerhalb des Products. In dieses Verzeichnis werden die Komponenten während der Installation kopiert.
  4. -cg definiert den ComponentGroup Namen, welcher innerhalb der Feature Auflistung verwendet werden kann.
  5. -ag lässt GUIDs zur Kompilierungszeit automatisch über „*“ generieren. Dies ist für Components problemlos möglich, da die GUID über den Pfad erzeugt wird und so jedes Mal gleichbleibt.
  6. -o definiert den Output Pfad in welchen das Fragment erzeugt werden soll.

Heat besitzt noch weitere Parameter, diese können bei Bedarf in der Dokumentation nachgelesen werden.

Das von Heat erzeugte Fragment hat die Form, welche im folgenden Screenshot dargestellt ist.

Beispiel Fragment

Zunächst wird ein Fragment geöffnet und das über -dr angegebene Verzeichnis über DirectoryRef referenziert. Anschließend werden alle Komponenten sowie Dateien gelistet. Abschließend wird ein zweites Fragment geöffnet und die ComponentGroup wird mit den einzelnen Komponentenreferenzen zusammengefügt.

Die so erstellte ComponentGroup kann nun innerhalb des Produktfeatures einfach über eine Id eingebunden werden.

WiX Feature mit Referenz zum automatisierten Fragment

Ab diesen Zeitpunkt müssen Sie sich nun keine Sorgen mehr darüber machen, dass z.B. Assemblies aus neuen NuGet Paketen nicht mehr eingebunden werden. Dank des zuvor angepassten BeforeBuild MSBuild Targets wird bei jedem Build das Fragment neu erzeugt.

Filterung

Mit jedem Build überschreibt Heat den Inhalt der erzeugten Datei. Dieses Verhalten kann vor allem störend sein, wenn bestimmte Dateien während der Installation ignoriert werden sollen.

Was also tun, wenn bestimmte Dateien gesondert behandelt werden sollen? Auch hier bietet Heat eine Lösung: Filter in Form von XSLT Dateien.

Soll also exemplarisch die Datei „DoNotCopyThisFile.config“ nicht mitgeliefert und im Fragment ignoriert werden, muss eine neue XSLT Filter Datei angelegt werden.
Den beispielhaften Code zeigt der folgende Screenshot.

XSLT Filter

Die Filterdatei muss nun über den Parameter -t zum Heat Aufruf im MSBuild Target BeforeBuild hinzugefügt werden. Beispiel:

„WIX)bin\heat.exe“ dir $(SolutionDir)Persistence.WindowsService\bin\$(Configuration) -var var.Persistence.WindowsService.TargetDir -t Filter.xslt -dr INSTALLLOCATION -cg PersistenceServiceBinariesCG -ag -scom -sreg -sfrag -srd -o $(ProjectDir)Fragments\BinariesFragment.wxs

Aufgrund des Filters werden nun alle File Elemente nach dem Source Attribut geforstet und auf den angegebenen Wert überprüft. Wurde eine Übereinstimmung gefunden wird die Id der Datei gespeichert und anschließend jede Component sowie ComponentRef, welche die Id beinhaltet, entfernt.

Sollte die Component um diverse Funktionen erweitert werden müssen, kann Sie nun manuell in einem neuen Fragment bzw. einer neuen ComponentGroup bearbeitet werden.

Fazit

Um die Inhalte Ihrer Installationsroutinen automatisiert auf dem aktuellsten Stand zu halten, müssen sie ihre WiX Fragmente nicht immer händisch bearbeiten. Mit nur wenigen Anpassungen ist es möglich mit Hilfe von Heat Fragmente automatisch erzeugen zu lassen. Gibt es Sonderfälle, so können auch diese mit Hilfe von Filtern praktisch angegangen werden.

Im Rahmen unserer Blogserie über das WiX Toolkit erfahren Sie außerdem wie Sie unkompliziert Installer mit Hilfe des WiX Toolsets erstellen können.

Holger Schwichtenberg: Feststellen der .NET-Version

Eine ältere .NET-Anwendung startet ohne weiteres auf einem neueren .NET 4.x, könnte aber im Ablauf Probleme bekommen. Wer prüfen will, ob die .NET-Version, für die die Anwendung kompiliert wurde, der installierten .NET-Version entspricht, kann folgenden C#-Code verwenden.

Golo Roden: Alles neu macht der Mai: Neuerungen in npm 5

Vor einigen Tagen ist Node.js 8.0 erschienen, das die Basis für die künftige LTS-Version der JavaScript-Laufzeitumgebung darstellt. Zusätzlich enthält Node.js auch die neue Version 5 der Paketverwaltung npm. Was hat sich hier getan?

MSDN Team Blog AT [MS]: C3 Loyalty Services – die neue Kunst der Kundenbindung

Was macht C3 Loyalty Services?

Das österreichische Unternehmen C3 Loyalty Services entwickelt einen neuen und innovativen CRM-Ansatz, mit dem insbesondere international agierende Handelskonzerne den vielschichtigen Herausforderungen der Digitalisierung begegnen können. Die dringend notwendige und aktuell stark diskutierte „digitale Transformation“ im stationären Handel hat einen entscheidenden Einfluss auf das zukünftige Kundenbeziehungsmanagement – und somit auf die Wettbewerbsfähigkeit vieler Branchen.

Neukundengewinnung und Kundenbindung, bei gleichzeitiger höherer Wertschöpfung für die Handelskonzerne, sind dabei die wesentlichen Bereiche, auf die sich C3 bei der Konzeption und Entwicklung seines innovativen Produktes fokussiert hat. Grundlage ist ein neuartiges Kundenbindungsprogramm, das es den Handelskonzernen ermöglicht, Konsumenten über eine Omni-Channel-Plattform auf individualisierte und personalisierte Weise anzusprechen. Das Programm bietet Konsumenten nicht nur Promotions und Produktinformationen, sondern auch redaktionelle Beiträge rund um Lifestyle- und Infotainment-Themen – und das alles speziell auf die Interessen, Vorlieben und Einstellungen des einzelnen Konsumenten ausgerichtet. Passend dazu werden kostenlos via App oder Website-Account dynamische Einkaufswelten angeboten, die unterschiedliche Konsumententypen ansprechen. So erhalten Kunden Informationen zu Angeboten und Inhalten, die sie wirklich interessieren, und bekommen bei jedem Einkauf obendrein Geld zurück.

 


 

 

 

 

 

 

 

 

 

 

 

 

 

Data-driven decision making

C3 setzt bei der Entwicklung und Operation auf einen data-driven Ansatz und entwickelt gemeinsam mit Experten der TU Graz und deren Know-Center anspruchsvolle Data-Analytics-Methoden, die es Händlern ermöglichen, ihre Angebote auf die richtigen Kundenprofile und Zielgruppen abzustimmen und mithilfe von branchenübergreifenden Analysen neue Kundengruppen zu erschließen, zu denen sie sonst keinen Zugang haben. Händler können Konsumenten auf diese Weise zum richtigen Zeitpunkt am richtigen Ort adressieren und Streuverluste vermeiden – und Konsumenten müssen sich nicht mehr durch lange Prospekte blättern oder uninteressante Newsletter löschen, auf der Suche nach dem einen Angebot, das sie wirklich anspricht.

Warum Microsoft Azure?

Die korrekte, effiziente und effektive Auslegung und Interpretation von Daten ist ein integraler Bestandteil des C3-Kundenbindungsprogramms. Zudem wird das Programm für Konsumenten und Händler sukzessive in mehreren Märkten verfügbar sein. Daher war es von Anfang an enorm wichtig, eine technische Infrastruktur zu haben, die zuverlässig und vertrauenswürdig ist und dieses Wachstum problemlos mittragen kann – ohne dabei unnötige Ressourcen zu verschwenden.

Durch die Nutzung von Microsoft Azure als Cloud-Plattform können modernste Technologien eingesetzt werden, speziell im Bereich Data Warehousing und Analytics, wobei nur für die tatsächliche Nutzung Kosten anfallen. Es gibt weder teure Hardware noch Software-Lizenzen, die „auf Vorrat“ angeschafft werden müssten und die während der Entwicklungsphase ungenutzt bleiben würden oder im Betrieb dann entweder zu groß oder zu klein dimensioniert wären.

Die C3-Systeme laufen bereits bei der Entwicklung auf der gleichen Plattform wie später im Live-Betrieb. Die benötigte Leistung kann innerhalb kürzester Zeit beliebig nach oben oder unten skaliert werden. Somit können Leistungsspitzen flexibel abgedeckt werden, wie sie etwa bei der Eröffnung eines neuen Marktes oder während Marketing-Kampagnen auftreten.

Zudem wird die reibungslose Operation dieser Systeme durch Microsoft sichergestellt. „Das ist gerade für Unternehmen im Aufbau ein entscheidender Vorteil,“ erklärt Markus Hendrich, IT-Geschäftsführer von C3 Loyalty Services. „Wir können eine Vielzahl von verschiedenen Technologien einsetzen, ohne dafür jeweils ein eigenes Team aus Spezialisten für den Betrieb aufbauen zu müssen. Stattdessen können wir uns mit ganzer Kraft auf die businessrelevanten Aspekte unserer Produkte und Services konzentrieren.“

 

Mehr Informationen auf www.c3-ls.com

Kontakt für Rückfragen:

Bettina Pries

E-Mail: b.pries@c3-ls.com

MSDN Team Blog AT [MS]: //BUILD on Tour Neuigkeiten für Devs und IT-Pros – UPDATE

WANN: 21. Juni 2017 | 08:30 Uhr – 17:30 Uhr
WO: Microsoft Österreich, Am Euro Platz 3, 1120 Wien

Keine Karten für die //build  in Seattle bekommen? Und dann auch noch das Keynotestreaming verpasst?
Nicht traurig sein, denn wir holen Euch die wichtigsten Neuerungen der //build nach Wien!
Die Community unserer Regional Directors und Most Valuable Professionals bietet exklusiv für Euch Inhalte für IT-Spezialisten, DevOps und Entwickler. Egal ob Ihr Open Source Enthusiasten seid oder aus dem klassischem Microsoft Umfeld kommt. Anhand praxisrelevanter Vorträge zeigen wir wie die neuen Lösungen umgesetzt werden können. Themen rund um Azure, Office 365, Cognitive Services, Windows und vieles mehr werden dabei behandelt.

Außerdem bieten wir einen Workshop in Zusammenarbeit mit SecureGuard an der parallel zu der Recap Veranstaltung läuft. In diesen Workshops haben Teilnehmer die Möglichkeit entweder Szenarien in einem Hyper Converged Cluster auszutesten oder Azure Stack selber auszuprobieren. Die Server für die Labumgebung sowie die ausgearbeiteten Szenarien werden von der Firma SecureGuard bereitgestellt. Für eine Teilnahme ist jeweils ein eigener PC mit Windows 10 notwendig von dem aus die Teilnehmer Ihre Übungen durchführen.

AGENDA

Time

 

ENTWICKLER

(AUDIT A)

IT-PROs

(IMPACT)

OPEN SOURCE SOFTWARE
(AUDIT B)

WORKSHOP (Helmut
Otto)

9:00-10:00

Keynote mit Nico Sorger, Bereichsleiter DX bei Microsoft
Österreich, Georg Binder und Gerwald Oberleitner (beide
Microsoft)

10:00-10:15

Pause

 

10:30-11:30

Roman Schacherl: Microsoft Azure Cognitive Services

Auditorium A

Andreas Jakl: Bluetooth im allerneuesten Windows

10

 

Impact

Christian Nagel mit einem .NET   Standard  Überblick

Auditorium B

Zusätzlich wird Helmut  Otto rings um Azure Stack und Hyper Converged Cluster Hands

On Workshops anbieten.

11:30-11:45

Pause

11:45-12:45

Raphael Schwarz: Entity Framework Core 2

 

Auditorium A

Toni Pohl: Microsoft Graph

 

 

Impact

Raoul Holzer:

Mobile Dev Update und XAML Standard

 

 

Auditorium B

 Azure Stack und Hyper Converged Cluster Hands On Workshops

 

Forum A+B

12:45-13:45

Pause

13:45-14:45

Christian Nagl:

Neuerungen zu ASP.NET Core

 

Auditorium A

Roman Stadlmair: Muliplattform Management

(Linux/Windows)

 

Impact

Rainer Stropek : TypeScript wird erwachsen

 

Auditorium B

Zusätzlich wird Helmut  Otto rings um Azure Stack und Hyper Converged Cluster Hands On Workshops anbieten.
14:45-15:00

Pause

15:00-16:00

Andreas Pollak: Cosmos DB für Developer

 

Auditorium A

Markus  Ehrenmüller: A Game of Hierarchies: Einführung in SQL Server 2017 Graph DB

 

Impact

Alois Reitbauer

Von 0 auf DevOps in 80 Tagen

 

Auditorium B

 Azure Stack und Hyper Converged Cluster Hands On Workshops

 

Forum A+B

16:00-16:15

Pause

16:15-17:15

Hannes Preishuber: Neues über Universal Windows Platform (UWP)  Apps

Auditorium A

Stefan Koell: DevOps Patterns and Anti-Patterns

 

Impact

Martina Grom: Azure Security

 

Auditorium B

17:15-17:30

Q&A
/ Closing

 

Bei Fragen, Wünschen und Komplikationen aller Art erreicht Ihr mich wie gewohnt unter meiner E-Mail Adresse.

HIER geht es zur Anmeldung!

Gerhard Göschl, Marketing Leiter – IT-Spezialisten und Software Entwickler

Microsoft Österreich GmbH

Gerhard.Goeschl@Microsoft.com

Manfred Steyer: Shrinking Angular Bundles with Closure

Big thanks to Alex Eagle from the Angular Team and to Carmen Popoviciu for reviewing this post.

Closure is said to be the most sophisticated JavaScript compiler available today. Its advanced optimization mode goes far beyond the tree shaking capabilities of other tools and allows for shrinking bundles to a minimum. Google uses it to improve the performance of its own products like Google Docs and even Microsoft is using it meanwhile for Office 365. However, it's considered to be an expert tool and therefore difficult to configure. In addition to that, it assumes that the underlying JavaScript code has been written in a specific way.

Currently, the Angular team is working hard on making Angular work together with Closure as well as with its build tool Bazel. There are some first examples available, e. g. the Example Alex Eagle from the Angular Team created.

This post uses the mentioned example to show how to use the Closure compiler as well as the advantages it brings regarding bundle sizes. Furthermore, this post explains how to add own and existing packages to a Closure based project.

Building a base line with the Angular CLI

In order to create a baseline for comparing Closure with a 'traditional' build task for Angular, let's create a new Hello World application with the Angular CLI:

ng new baseline
cd baseline

Now, let's create a production build:

ng build --prod

The generated bundles have a size of about 394K:

   1.460 inline.093de888567e5146835d.bundle.js
   9.360 main.0d097609144c942cc763.bundle.js
  60.845 polyfills.d90888e283bda7f009a0.bundle.js
 322.320 vendor.765bef7fc0b73d2d51d7.bundle.js
         
         393.985 Bytes

As the Closure sample in the next sections is directly importing the zone.js polyfill and not importing any other ones, we should omit the polyfills bundle from this observation:

   1.460 inline.093de888567e5146835d.bundle.js
   9.360 main.0d097609144c942cc763.bundle.js
 322.320 vendor.765bef7fc0b73d2d51d7.bundle.js
         
         333.140 Bytes

This leaves about 333K.

After this we are installing Angular Material as well as the Animation package which Angular Material depends on:

npm i @angular/material --save
npm i @angular/animations --save

To import it into the application, its AppModule is referencing some of Angular Material's Modules:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';

import { 
  MdButtonModule, 
  MdAutocompleteModule,
  MdCheckboxModule,
  MdDatepickerModule,
  MdCardModule,
  MdRadioModule,
  MdChipsModule,
  MdListModule,
  MdSnackBarModule,
  MdSliderModule,
  MdDialogModule,
  MdMenuModule,
  MdSidenavModule
} from '@angular/material';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    MdButtonModule, 
    MdAutocompleteModule,
    MdCheckboxModule,
    MdDatepickerModule,
    MdCardModule,
    MdRadioModule,
    MdChipsModule,
    MdListModule,
    MdSnackBarModule,
    MdSliderModule,
    MdDialogModule,
    MdMenuModule,
    MdSidenavModule
  ],
  declarations: [
    AppComponent
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

After recreating a production build (ng build --prod) we see that it grew to about 951K:

   1.460 inline.36030f130bb8b4d4d1e6.bundle.js
 246.959 main.bd55167e3a85bc1edaab.bundle.js
 702.496 vendor.9618c29d7fbb7af5a536.bundle.js
      950.915 Bytes

As the bundle size increased even though we are not using the imported modules from Angular Material this shows that the CLI/ webpack is not able to find this out and shake these modules off.

Now let's see how the sample application can be optimized with Closure.

Using the Closure Compiler

To get started with Angular and the Closure Compiler, I'm using Alex Eagle's example. For this, I've forked the version available when writing this.

I modified it to use npm instead of yarn and after running npm run build I got a bundle with just about 106K:

 105.934 bundle.js

This is an huge improvement over using the CLI with webpack which led to bundles with about 390K for a quite similar "Hello-Word"-App.

In order to make a fair comparison, we also need to include the packages @angular/forms and @angular/http as these packages are also imported into the CLI based app:

npm i @angular/http --save
npm i @angular/forms --save

In order to import them into the Angular App, the AppModule has to reference them:

import {NgModule} from '@angular/core';
import {HttpModule} from '@angular/http';
import {FormsModule} from '@angular/forms';
import {BrowserModule} from '@angular/platform-browser';
import {Basic} from './basic';

@NgModule({
  declarations: [Basic],
  bootstrap: [Basic],
  imports: [BrowserModule, FormsModule, HttpModule],
})
export class AppModule {
}

Unfortunately, the Closure Compiler does not respect the conventions introduced by NodeJS and so it does not automatically search the folder node_modules for these packages. Therefore, they have to be referenced explicitly within the file closure.conf:

node_modules/@angular/forms/@angular/forms.js
--js_module_root=node_modules/@angular/forms

node_modules/@angular/http/@angular/http.js
--js_module_root=node_modules/@angular/http

Those lines reference both, the path where the package is found as well as its entry point which is also the whole content of the package due do the use of the FESM15-Format.

After building everything again (npm run build) we are ending up with about 125K:

	125.134 bundle.js

This is still an huge improvement over using the CLI and/or Webpack.

Please note that this example is using Closure's Advanced Mode. This mode provides better results as other known tools, but is also quite aggressive. That's why it can damage the generated bundle and so it's recommended to use this mode always together with good E2E testing.

Using Closure with an Angular Package through the example of Angular Material

Now let's go on and import Angular Material. Once again, we have to load the following packages:

npm i @angular/material --save
npm i @angular/animations --save

And - of course - we have to import the same Angular Material Modules as before:

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {Basic} from './basic';
import { LibStarterModule } from 'stuff-lib';
import { HttpModule } from "@angular/http";
import { FormsModule } from "@angular/forms";

import { 
  MdButtonModule, 
  MdAutocompleteModule,
  MdCheckboxModule,
  MdDatepickerModule,
  MdCardModule,
  MdRadioModule,
  MdChipsModule,
  MdListModule,
  MdSnackBarModule,
  MdSliderModule,
  MdDialogModule,
  MdMenuModule,
  MdSidenavModule
} from '@angular/material';

@NgModule({
  declarations: [Basic],
  bootstrap: [Basic],
  imports: [
    BrowserModule, 
    HttpModule, 
    FormsModule, 
    MdButtonModule, 
    MdAutocompleteModule,
    MdCheckboxModule,
    MdDatepickerModule,
    MdCardModule,
    MdRadioModule,
    MdChipsModule,
    MdListModule,
    MdSnackBarModule,
    MdSliderModule,
    MdDialogModule,
    MdMenuModule,
    MdSidenavModule
  ],
})
export class AppModule {
}

In addition to that, it is also necessary to tell Closure about the imported modules. Therefore the closure.conf gets the following additional lines:

node_modules/@angular/animations/@angular/animations.js
--js_module_root=node_modules/@angular/animations

node_modules/@angular/material/@angular/material.js
--js_module_root=node_modules/@angular/material

Before we can create a build, we have to update the TypeScript Compiler, as the used version of the example comes with 2.1 while the current version of Angular Material needs 2.2+:

npm uninstall typescript --save-dev
npm install typescript@^2.2 --save-dev

After creating another build our bundles has about 200K:

199.970 bundle.js

This shows two things: First of all, using Closure brings a huge improvement over using the CLI and/or webpack which led to a bundle with about 951K. But this experiment also shows that even Closure is not able to fully shake off the imported but unused Modules.

Creating an own Angular Package that can be used with Closure

Creating an own Angular Package that can be used together with the closure compiler is quite easy. You just need to align with the conventions for the Angular Package Format. The most important thing to consider for Closure is providing a build using the FESM15 format. This means that you have to use EcmaScript 2015+ with EcmaScript Modules. Furthermore, you also have to "flatten" everything into one file which is used as the package's entry file. The Angular Package Format also tells us to provide your code in other formats, but here I'm just focusing on FESM15.

For testing purposes, I've created such a package with some demo code. It's called angular-stuff-lib and just contains a simple Angular Module with some a DemoComponent.

@NgModule({
    imports: [
        CommonModule,
        FormsModule,
        HttpModule
    ],
    declarations: [
        DemoComponent
    ],
    exports: [
        DemoComponent
    ]
})
export class LibStarterModule {

    static forRoot(): ModuleWithProviders {
        return {
            ngModule: LibStarterModule,
            providers: [
                DemoService
            ]
        };
    }

}

Its forRoot method returns this module with a DemoService. Using this method you can make sure that the service is only registered with your application's RootModule and not with other modules that import this one.

The package uses the following tsconfig.json:

{
  "compilerOptions": {
    "module": "es2015",
    "target": "es2015",
    "outDir": "build",
    "noImplicitAny": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "declaration": true,
    "moduleResolution": "node",
    "noUnusedLocals": true,
    "types": [
      "hammerjs",
      "jasmine",
      "node"
    ],
    "lib": ["es2015", "dom"]
  },
  "files": [
    "index.ts"
  ],
  "angularCompilerOptions": {
    "strictMetadataEmit": true,
    "skipTemplateCodegen": true,
    "annotationsAs": "static fields",
    "annotateForClosureCompiler": true,
    "flatModuleOutFile": "stuff-lib.js",
    "flatModuleId": "stuff-lib"
  }
}

Please note several things here:

  • The compilation target is EcmaScript 2015 with EcmaScript (2015) Modules.
  • The destination folder is called built.
  • The configuration directly points to the main file index.ts.
  • Thanks to the property declaration, the TypeScript compiler emits Type Declarations. This allows the compiled EcmaScript-based package to be used within TypeScript projects.
  • There are some options for the Angular Compiler in angularCompilerOptions:
    • strictMetadataEmit creates some meta data the Angular Compiler needs to produce an AOT build for projects that use this package.
    • skipTemplateCodegen is set to true because we don't need compiled template for a library. The final project will create all of them.
    • annotateForClosureCompiler makes the Angular Compiler to generate comments with annotations Closure uses to optimize the emitted code.
    • flatModuleOutFile points to a file the Angular Compiler creates as an entry point. It can be used by tools like rollup to create a flat package (a package that just consists of one file).
    • flatModuleId contains the module name of the generated package. This is the name that can be used together with import statements.

To create the build, I'm using some npm scripts:

"scripts": {
    "build": "npm run clear && npm run ngc && npm run rollup && npm run copy",
    "clear": "rimraf build && rimraf dist",
    "ngc": "ngc",
    "rollup" : "rollup build/stuff-lib.js -o dist/stuff-lib.js",
    "copy": "npm run copy-package && npm run copy-metadata && npm run copy-typedef",
    "copy-typedef": "cd build && cpy **/*.d.ts ../dist --parents",
    "copy-metadata": "cd build && cpy **/*.metadata.json ../dist",
    "copy-package": "cpy dist-package.json dist/package.json"
}

The script build is triggering the whole procedure (npm run build). First of all, it clears the folders that are used for the compilation targets by leveraging rimraf. Then it starts the Angular Compiler ngc which is also using the TypeScript Compiler underneath. The results of this compilation step can be found within the folder build after this. Then, the tool rollup generates the flat package file and puts it into the folder dist. To make sure that all other files needed are located within dist the those files are copied there. It also copies the package.json which contains necessary metadata for this package to the dist folder.

Among others, those meta data contains the following entries:

  "name": "stuff-lib",
  [...]
  "module": "stuff-lib.js",
  "es2015": "stuff-lib.js",
  "typings": "stuff-lib.d.ts",

The property name contains the name of the package and es2015 is pointing to the generated flat ES2015 bundle. Normally, module would point to its ES5 counterpart. But as I'm focusing only on ES2015 here, it is pointing to the generated ES2015 bundle too. In addition to this, typings is pointing to the entry file of the emitted type definitions.

One last thing that isn't specific to Closure or the Angular Module Format but is important nevertheless: To avoid that Angular is installed as a sub dependency when one is downloading this package, Angular is only mentioned within peerDependencies. This tells npm that everyone who is installing this package, should also install those packages.

"peerDependencies": {
  "@angular/core": "^4.0.0",
  "@angular/http": "^4.0.0"
},

To build this project, just run npm run build. After this, you find the compiled package within the folder dist.

Using the own package together with Closure

To test your own Angular package with the Closure Compiler, switch to the dist folder after building it and call npm link. Then switch to the root folder of the Closure project and run npm link stuff-lib which is creating a symbolic link to your package's dist folder.

After this, you have to tell Closure about the added package by inserting some lines into the file closure.conf:

node_modules/stuff-lib/stuff-lib.js
--js_module_root=node_modules/stuff-lib

As mentioned above, the line with --js_module_root is pointing to the package's root directory located within node_modules. This is necessary because Closure doesn't follow the conventions introduced by Node. The other line points to the flat bundle which is the entry point of the package and contains its whole contents.

After this, just import the package's module into the AppModule:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Basic } from './basic';
import { LibStarterModule } from 'stuff-lib';
import { MaterialModule } from '@angular/material';
import { HttpModule } from "@angular/http";
import { FormsModule } from "@angular/forms";

@NgModule({
  declarations: [Basic],
  bootstrap: [Basic],
  imports: [
	BrowserModule, 
	MaterialModule, 
	HttpModule, 
	FormsModule, 
	LibStarterModule.forRoot()
  ],
})
export class AppModule {
}

After building it with Closure, you will see that this isn't affecting the bundle size much, because the used package is just a minimal demo package. You can also assure yourself that the whole application works. To make sure the package is correctly used by Closure, you can inject its DemoService into the Root Component and use it:

import {Component, Injectable} from '@angular/core';
import { DemoService} from 'stuff-lib';

@Component({
  selector: 'basic',
  templateUrl: './basic.ng.html',
})
export class Basic {
  ctxProp: string;
  constructor(private demoService: DemoService) {
    this.ctxProp = `Hello World`;

    this.demoService.info = 'Hello World';
    console.log('demoService', this.demoService.doStuff());
  }
}

After this, rebuild the application again and run it using npm run serve. This opens a demo web server on port 8080. Navigate to it and see that the specified message is written to the javascript console.

Using Closure with a CommonJS/NodeJS Package

I've also tried to use a CommonJS/NodeJS Package with the Closure Compiler. For this, I've installed the package base64-js (npm install base64-js --save) which I also use for my angular-oauth2-oidc project. The easiest way to make Closure aware of such a library seems to be directly pointing to it as you would point to your own files. Alex' sample is this doing for RxJs too. For this, add the following line to your closure.config:

--js node_modules/base64-js/**.js

After reading this, Closure assumes that the folder mentioned contains a CommonJS Module with the name base64-js. The file index.js is assumed to be the entry point you can import by referencing the module itself using require('base64-js') or import ... from 'base64-js'. If there was any other file, it could be referenced using the path base64-js/other-file. To use another entry point, one can also point to the package.json using the --js flag. In this case, the entry point mentioned within this file in the property main is used.

After this, just import the needed parts of the library and use them:

import { fromByteArray } from 'base64-js';

[...]

this.ctxProp = fromByteArray(this.ctxProp);

Dirty Hack: Patching a CommonJS/NodeJS Package to make it work with Closure

I've also tried to use the package sha256 as I'm needing it for my angular-oauth2-oidc project. Unfortunately, it doesn't work with Closure. The reason can be found within its package.json(node_modules/sha256/package.json):

"browser": "./lib/sha256.js",
"main": "index.js",

It contains two fields that specify an entry point. By convention, browser should be used for bundles that are executed within a browser and main should be used when compiling for NodeJS. Unfortunately, at the time of writing this, Closure only evaluates the main field. There are some discussions about supporting further such properties too. The solution I've found was to manually patch this by setting main to ./lib/sha256.js:

"browser": "./lib/sha256.js",
"main": "./lib/sha256.js",

Of course, this is far away from a perfect solution and one has to make sure that the patched files are not overridden by npm. For this, one could copy it to another folder outside of node_modules.

After this, just add the following lines to the file closure.conf:

--js node_modules/sha256/**.js
--js node_modules/convert-string/**.js
--js node_modules/convert-hex/**.js

--js node_modules/sha256/package.json
--js node_modules/convert-string/package.json
--js node_modules/convert-hex/package.json

These lines add the files of sha256 as well as the files of two other packages it depends on. It addition to this, they add the package.json of those files so that Closure knows about them and uses them to infer the entry points.

Now you can import the package which is just a function and use it:

const sha256 = require('sha256');
[...]
this.ctxProp = fromByteArray(sha256(this.ctxProp));

Repository for Packages compatible with Closure

As the last section showed, not every package can be used with Closure seamlessly. To help us with this, Alex Eagle from the Angular Team created the repository angular-closure-compatibility. The goal is to show which packages are supported as well as to provide examples that show how to use them in an Closure environment.

Conclusion

The Closure Compiler is a very powerful expert tool that can reduce bundle sizes dramatically. The Angular Package Format makes sure that (own) Angular Modules work together with it. As Closure assumes that the code is written in a specific way it can be challenging to use it together with other packages.

MSDN Team Blog AT [MS]: DevOps mit Microsoft Azure (für Partner)

Die Kollegen von Microsoft Central & Estern Europe bieten ein kostenloses Partner-Onlinetraining zum Thema DevOps mit Microsoft Azure an.
Das Online-Training wird in englischer Sprache abgehalten:

 

Date:               6, June 2017
Time:               11:30-13:30 (GMT+2)

Registration:  https://www.microsoftevents.com/profile/form/index.cfm?PKformID=0x2108488a43c

Training Agenda

First part:

  • What is DevOps?
  • Using “the cloud” as a development tool
  • Visual Studio for DevOps
  • How to identify a”DevOps opportunity”?

 

Second part:

  • DevOps on Microsoft Azure in action

The session will demonstrate how to setup basic delivery pipeline for Java web application running on Linux virtual machine in Microsoft Azure. The delivery pipeline will cover a couple of DevOps practices like Continuous Integration, Continuous Deployment, and Infrastructure as Code.

 

Please be aware, the training agenda is a subject to small content and organizational changes.
The training will be delivered by

Urs Müller, Area Sales Lead, Microsoft
Dariusz Porowski, Sr. Technical Evangelist, DevOps & Infrastructure, Microsoft

Norbert Eder: Entity Framework SaveChanges beschleunigen

Ich setze das Entity Framework 6 nur ganz selten ein. In einem aktuellen Projekt mussten viele Daten einmalig importiert werden und das Datenbankschema stand bereits fest. Ergo dachte ich mir, ich setze auf EF, generiere mir das Modell, parse die Daten (Anlieferung per JSON) und schreibe sie in die Datenbank.

Die Lösung war super schnell implementiert. Den ersten Importversuch habe ich nach 20 Minuten abgebrochen. Hochgerechnet hätte er an die 5-6 Stunden benötigt. Gut, immerhin sind es 6 Tabellen, die Beziehungen zueinander pflegen und einige Millionen Datensätze. Dennoch, das muss viel schneller gehen.

Detect Changes

Besonders großen Einfluss hat die Einstellung (context ist hier der verwendete DbContext)

context.Configuration.AutoDetectChangesEnabled = false;

Damit wird nicht auf etwaige Änderungen geprüft (d.h. kein Lesen von Daten und keine Prüfungen).

Context verwerfen

SaveChanges habe ich nur einmal nachdem ich alle Daten dem Kontext hinzugefügt hatte, aufgerufen. Das führte bei mir zu einer OutOfMemoryException. Daher habe ich das in kleinere Chunks unterteilt und dafür dann SaveChanges aufgerufen. Es empfiehlt sich dann, den Kontext zu verwerfen und neu zu erstellen. Dadurch wird dieser bereinigt und enthält keine Daten mehr. Umso mehr Daten dieser enthält, umso langsamer wird er:

context.Dispose();
context = new MyDbContext();
context.Configuration.AutoDetectChagnesEnabled = false;

Änderungen asynchron speichern

Eine besonders große Änderung hat dann folgende Verwendung gebracht:

context.SaveChangesAsync().Wait();

Dadurch werden die Änderungen asynchron in die Datenbank übertragen (sofern möglich), was natürlich eine gewaltige Menge an Zeit spart.

Fazit

Durch die gezeigten Verbesserungsmöglichkeiten konnte ich die Verarbeitungszeit auf knapp 10 Minuten reduzieren. Wer es noch schneller braucht, der solle auf ein Bulk-Insert umsteigen, muss dafür allerdings mehr implementieren. Für meinen Fall war es so ausreichend. Gutes

The post Entity Framework SaveChanges beschleunigen appeared first on Norbert Eder.

Manfred Steyer: Moderne Security-Lösungen mit Angular, OAuth 2 und OpenID Connect: Folien und Beispiel von XPC 2017 (München, Online)

Nachfolgend meine Folien und mein Beispiel von der XPC 2017:

Golo Roden: package.json: ~ versus ^

Node.js verwendet das Konzept des Semantic Versioning für die Versionierung von Modulen. Bei Bedarf lassen sich in der Datei package.json dafür auch Bereiche angeben, beispielsweise mit den Zeichen ~ und ^. Was ist der Unterschied zwischen den beiden Varianten?

Sebastian Seidel: Extend your Xamarin.Android app with OpenStreetMap

In my last post I described how you can use OpenStreetMaps within your Xamarin.iOS app. Please read that article first, if you don't know what OpenStreetMaps is. Today I show you how you can make use of OpenStreetMaps in your Xamarin.Android app.

Jürgen Gutsch: A first glimpse into .NET Core 2.0 Preview 1 and ASP.​NET Core 2.0.0 Preview 1

At the Build 2017 conference Microsoft announced the preview 1 versions of .NET Core 2.0, of the .NET Standard 2.0 and ASP.NET Core 2.0. I recently had a quick look into it and want to show you a little bit about it with this post.

.NET Core 2.0 Preview 1

Rich Lander (Program Manager at Microsoft) wrote about the release of the preview 1, .NET Standard 2.0, tools support in this post: Announcing .NET Core 2.0 Preview 1. It is important to read the first part about the requirements carefully. Especially the requirement of Visual Studio 2017 15.3 Preview. At the first quick look I was wondering about the requirement of installing a preview version of Visual Studio 2017, because I have already installed the final version since a few months. But the details is in the numbers. The final version of Visual Studio 2017 is the 15.2. The new tooling for .NET Core 2.0 preview is in the 15.3 which is in preview currently.

So if you want to use .NET Core 2. preview 1 with Visual Studio 2017 you need to install the preview of 15.3

The good thing is, the preview can be installed side by side with the current final of Visual Studio 2017. It doesn't double the usage of disk space, because both versions are able share some SDKs, e.g. the Windows SDK. But you need to install the add-ins you want to use for this version separately.

After the Visual Studio you need to install the new .NET Core SDK which also installs NET Core 2.0 Preview 1 and the .NET CLI.

The .NET CLI

After the new version of .NET Core is installed type dotnet --version in a command prompt. It will show you the version of the currently used .NET SDK:

Wait. I installed a preview 1 version and this is now the default on the entire machine? Yes.

The CLI uses the latest installed SDK on the machine by default. But anyway you are able to run different .NET Core SDKs side by side. To see what versions are installed on our machine type dotnet --info in a command prompt and copy the first part of the base path and past it to a new explorer window:

You are able to use all of them if you want to.

This is possible by adding a "global.json" to your solution folder. This is a pretty small file which defines the SDK version you want to use:

{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.4"
  }
}

Inside the folder "C:\git\dotnetcore", I added two different folders: the "v104" should use the current final version 1.0.4 and the "v200" should use the preview 1 of 2.0.0. to get it working I just need to put the "global.json" into the "v104" folder:

The SDK

Now I want to have a look into the new SDK. The first thing I do after installing a new version is to type dotnet --help in a command prompt. The first level help doesn't contain any surprises, just the version number differs. The most interesting difference is visible by typing dotnet new --help. We get a new template to add an ASP.NET Core Web App based on Razor pages. We also get the possibility to just add single files, like a razor page, "NuGet.config" or a "Web.Config". This is pretty nice.

I also played around with the SDK by creating a new console app. I typed dotnet new console -n consoleapp:

As you can see in the screenshot dotnet new will directly download the NuGet packages from the package source. It runs dotnet restore for you. It is not a super cool feature but good to know if you get some NuGet restore errors while creating a new app.

When I opened the "consoleapp.csproj", I saw the expected TargetFramework "netcoreapp2.0"

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

</Project>

This is the only difference between the 2.0.0 preview 1 and the 1.0.4

In ASP.NET Core are a lot more changes done. Let's have a quick look here too:

ASP.NET Core 2.0 Preview 1

Also for the ASP.NET 2.0 Preview 1, Jeffrey T. Fritz (Program Manager for ASP.NET) wrote a pretty detailed announcement post in the webdev blog: Announcing ASP.NET Core 2.0.0-Preview1 and Updates for .NET Web Developers.

To create a new ASP.NET Web App, I need to type dotnet new mvc -n webapp in a command prompt window. This command immediately creates the web app and starts to download the needed packages:

Let's see what changed, starting with the "Program.cs":

public class Program
{
  public static void Main(string[] args)
  {
    BuildWebHost(args).Run();
  }

  public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
      .UseStartup<Startup>()
      .Build();
}

The first thing I mentioned is the encapsulation of the code that creates and configures the WebHostBuilder. In the previous versions it was all in the static void main. But there's no instantiation of the WebHostBuilder anymore. This is hidden in the .CreateDefaultBuilder() method. This look a little cleaner now, but also hides the configuration from the developer. It is anyway possible to use the old way to configure the WebHostBuilder, but this wrapper does a little more than the old configuration. This Method also wraps the configuration of the ConfigurationBuilder and the LoggerFactory. The default configurations were moved from the "Startup.cs" to the .CreateDefaultBuilder(). Let's have a look into the "Startup.cs":

public class Startup
{
  public Startup(IConfiguration configuration)
  {
    Configuration = configuration;
  }

  public IConfiguration Configuration { get; }

  // This method gets called by the runtime. Use this method to add services to the container.
  public void ConfigureServices(IServiceCollection services)
  {
    services.AddMvc();
  }

  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  {
    if (env.IsDevelopment())
    {
      app.UseDeveloperExceptionPage();
    }
    else
    {
      app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    app.UseMvc(routes =>
               {
                 routes.MapRoute(
                   name: "default",
                   template: "{controller=Home}/{action=Index}/{id?}");
               });
  }
}

Even this file is much cleaner now.

But if you now want to customize the Configuration, the Logging and the other stuff, you need to replace the .CreateDefaultBuilder() with the previous style of bootstrapping the application or you need to extend the WebHostBuilder returned by this method. You could have a look into the sources of the WebHost class in the ASP.NET repository on GitHub (around line 150) to see how this is done inside the .CreateDefaultBuilder(). The code of that method looks pretty familiar for someone who already used the previous version.

BTW: BrowserLink was removed from the templates of this preview version. Which is good from my perspective, because it causes an error while starting up the applications.

Result

This is just a first short glimpse into the .NET Core 2.0 Preview 1. I need some more time to play around with it and learn a little more about the upcoming changes. For sure I need to rewrite my post about the custom logging a little bit :)

BTW: Last week, I created a 45 min video about it in German. This is not a video with a good quality. It is quite bad. I just wanted to test a new microphone and Camtasia Studio and I chose ".NET Core 2.0 Preview 1" as the topic to present. Even if it has a awful quality, maybe it is anyway useful to some of my German speaking readers. :)

I'll come with some more .NET 2.0 topics within the next months.

Code-Inside Blog: Using Visual Studio Code & Team Foundation Version Control (TFVC)

Recently we start working on a Angular 4 app but all other parts of the application (e.g. the backend stuff) were stored in a good old TFVC based repository (inside a Team Foundation Server 2015) . Unfortunately building an Angular app with the full blown Visual Studio with the “default” Team Explorer workflow is not really practical. Another point for using Visual Studio Code was that most other online resources about learning Angular are using VS Code.

Our goal was to keep one repository, otherwise it would be harder to build and maintain.

First plan: Migrate to Git

First we tried to migrate our complete code base to Git with this generally awesome tool. Unfortunately for us it failed because of our quite large branch-tree. I tried it on a smaller code base and it worked without any issues.

At this point we needed another solution, because we wanted to get started on the actual application - so we tried to stick with TFVC.

Important: I always would recommend Git over TFVC, because it’s the way our industry is currently moving and at some point in the future we will do this too.

If you have similar problems like us: Read on!

Second plan: Get the TFVC plugin working in Visual Studio Code

Good news: Since April 2017 there is a Visual Studio Team Services extension for Visual Studio Code that also supports TFVC!

Requirements:

  • Team Foundation Server 2015 Update 2
  • A existing local workspace configuration (at least currently, check this GitHub issue for further information)
  • The actual extension

Be aware: Local Workspaces!

Even I’m using TFS since a couple of years I just recently discovered that the TFS supports to different “workflows”. The “default” workflow always needs a connection to the TFS to checkout files etc. There is an alternative mode called “local” mode which seems to work like SVN. The difference is, that you can create a local file and the TFVC-client will “detect” those changes. Read more about the differences here.

x

Configuration

In our OnPremise TFS 2015 world I just needed only this configuration line in my user settings:

...
"tfvc.location": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer\\TF.exe",
...

Action!

Now when I point VS Code to my local workspace folder, the TFVC plugin will kick in and I see the familiar “change”-tracking:

x

It is not perfect, because I still need to setup and “manage” (e.g. get the history etc.) via the full blown Visual Studio, but with this setup it is “do-able”.

Holger Schwichtenberg: Leere Ordner löschen – ganz einfach mit der Windows PowerShell

Mit einem PowerShell-Skript kann man in einem Dateisystempfad rekursiv nach leeren Verzeichnissen suchen und diese löschen.

Jürgen Gutsch: Exploring GraphQL and creating a GraphQL endpoint in ASP.NET Core

A few weeks ago, I found some time to have a look at GraphQL and even at the .NET implementation of GraphQL. It is pretty amazing to see it in actions and it is easier than expected to create a GraphQL endpoint in ASP.NET Core. In this post I'm going to show you how it works.

The Graph Query Language

The GraphQL was invented by Facebook in 2012 and released to the public in 2015. It is a query language to tell the API exactly about the data you wanna have. This is the difference between REST, where you need to query different resources/URIs to get different data. In GrapgQL there is one single point of access about the data you want to retrieve.

That also makes the planning about the API a little more complex. You need to think about what data you wanna provide and you need to think about how you wanna provide that data.

While playing around with it, I created a small book database. The idea is to provide data about books and authors.

Let's have a look into few examples. The query to get the book number and the name of a specific book looks like this.

{
  book(isbn: "822-5-315140-65-3"){
    isbn,
    name
  }
}

This look similar to JSON but it isn't. The property names are not set in quotes, which means it is not really a JavaScript Object Notation. This query need to be sent inside the body of an POST request to the server.

The Query gets parsed and executed against a data source on the server and the server should send the result back to the client:

{
  "data": {
    "book": {
      "isbn": "822-5-315140-65-3",
      "name": "ultrices enim mauris parturient a"
    }
  }
}

If we want to know something about the author, we need to ask about it:

{
  book(isbn: "822-5-315140-65-3"){
    isbn,
    name,
    author{
      id,
      name,
      birthdate
    }
  }
}

This is the possible result:

{
  "data": {
    "book": {
      "isbn": "822-5-315140-65-3",
      "name": "ultrices enim mauris parturient a",
      "author": {
        "id": 71,
        "name": "Henderson",
        "birthdate": "1937-03-20T06:58:44Z"
      }
    }
  }
}

You need a list of books, including the authors? Just ask for it:

{
  books{
    isbn,
    name,
    author{
      id,
      name,
      birthdate
    }
  }
}

The list is too large? Just limit the result, to get only 20 items:

{
  books(limit: 20) {
    isbn,
    name,
    author{
      id,
      name,
      birthdate
    }
  }
}

Isn't that nice?

To learn more about GraphQL and the specifications, visit http://graphql.org/

The Book Database

The book database is just fake. I love to use GenFu to generate dummy data. So I did the same for the books and the authors and created a BookRepository:

public class BookRepository : IBookRepository
{
  private IEnumerable<Book> _books = new List<Book>();
  private IEnumerable<Author> _authors = new List<Author>();

  public BookRepository()
  {
    GenFu.GenFu.Configure<Author>()
      .Fill(_ => _.Name).AsLastName()
      .Fill(_=>_.Birthdate).AsPastDate();
    _authors = A.ListOf<Author>(40);

    GenFu.GenFu.Configure<Book>()
      .Fill(p => p.Isbn).AsISBN()
      .Fill(p => p.Name).AsLoremIpsumWords(5)
      .Fill(p => p.Author).WithRandom(_authors);
    _books = A.ListOf<Book>(100);
  }

  public IEnumerable<Author> AllAuthors()
  {
    return _authors;
  }

  public IEnumerable<Book> AllBooks()
  {
    return _books;
  }

  public Author AuthorById(int id)
  {
    return _authors.First(_ => _.Id == id);
  }

  public Book BookByIsbn(string isbn)
  {
    return _books.First(_ => _.Isbn == isbn);
  }
}

public static class StringFillerExtensions
{
  public static GenFuConfigurator<T> AsISBN<T>(
    this GenFuStringConfigurator<T> configurator) where T : new()
  {
    var filler = new CustomFiller<string>(
      configurator.PropertyInfo.Name, 
      typeof(T), 
      () =>
      {
        return MakeIsbn();
      });
    configurator.Maggie.RegisterFiller(filler);
    return configurator;
  }
  
  public static string MakeIsbn()
  {
    // 978-1-933988-27-6
    var a = A.Random.Next(100, 999);
    var b = A.Random.Next(1, 9);
    var c = A.Random.Next(100000, 999999);
    var d = A.Random.Next(10, 99);
    var e = A.Random.Next(1, 9);
    return $"{a}-{b}-{c}-{d}-{e}";
  }
}

GenFu provides a useful set of so called fillers to generate data randomly. There are fillers to generate URLs, emails, names, last names, states of US and Canada and so on. I also need a ISBN generator, so I created one by extending the generic GenFuStringConfigurator.

The BookRepository is registered as a singleton in the Dependency Injection container, to work with the same set of data while the application is running. You are able to add some more information to that repository, like publishers and so on.

GraphQL in ASP.NET Core

Fortunately there is a .NET Standard compatible implementation of the GraphQL on GitHub. So there's no need to parse the Queries by yourself. This library is also available as a NuGet package:

<PackageReference Include="GraphQL" Version="0.15.1.678" />

The examples provided on GitHub, are pretty easy. They directly write the result to the output, which means the entire ASP.NET Applications is a GraphQL server. But I want to add GraphQL as a ASP.NET Core MiddleWare, to add the GraphQL implementation as a different part of the Application. Like this you are able to use REST based POST and PUT request to add or update the data and to use the GraphQL to query the data.

I also want that the middleware is listening to the sub path "/graph"

public class GraphQlMiddleware
{
  private readonly RequestDelegate _next;
  private readonly IBookRepository _bookRepository;

  public GraphQlMiddleware(RequestDelegate next, IBookRepository bookRepository)
  {
    _next = next;
    _bookRepository = bookRepository;
  }

  public async Task Invoke(HttpContext httpContext)
  {
    var sent = false;
    if (httpContext.Request.Path.StartsWithSegments("/graph"))
    {
      using (var sr = new StreamReader(httpContext.Request.Body))
      {
        var query = await sr.ReadToEndAsync();
        if (!String.IsNullOrWhiteSpace(query))
        {
          var schema = new Schema { Query = new BooksQuery(_bookRepository) };
          var result = await new DocumentExecuter()
            .ExecuteAsync(options =>
                          {
                            options.Schema = schema;
                            options.Query = query;
                          }).ConfigureAwait(false);
          CheckForErrors(result);
          await WriteResult(httpContext, result);
          sent = true;
        }
      }
    }
    if (!sent)
    {
      await _next(httpContext);
    }
  }

  private async Task WriteResult(HttpContext httpContext, ExecutionResult result)
  {
    var json = new DocumentWriter(indent: true).Write(result);
    httpContext.Response.StatusCode = 200;
    httpContext.Response.ContentType = "application/json";
    await httpContext.Response.WriteAsync(json);
  }

  private void CheckForErrors(ExecutionResult result)
  {
    if (result.Errors?.Count > 0)
    {
      var errors = new List<Exception>();
      foreach (var error in result.Errors)
      {
        var ex = new Exception(error.Message);
        if (error.InnerException != null)
        {
          ex = new Exception(error.Message, error.InnerException);
        }
        errors.Add(ex);
      }
      throw new AggregateException(errors);
    }
  }
}

public static class GraphQlMiddlewareExtensions
{
  public static IApplicationBuilder UseGraphQL(this IApplicationBuilder builder)
  {
    return builder.UseMiddleware<GraphQlMiddleware>();
  }
}

With this kind of MiddleWare, I can extend my applications Startup.cs with GraphQL:

app.UseGraphQL();

As you can see, the BookRepository gets passed into this Middleware via constructor injection. The most important part is that line:

var schema = new Schema { Query = new BooksQuery(_bookRepository) };

This is where we create a schema, which is used by the GraphQL engine to provide the data. The schema defines the structure of the data you wanna provide. This is all done in a root type called BooksQuery. This type gets the BookRepostory.

This Query is a GryphType, provided by the GraphQL library. You need to derive from a ObjectGraphType and to configure the schema in the constructor:

public class BooksQuery : ObjectGraphType
{
  public BooksQuery(IBookRepository bookRepository)
  {
    Field<BookType>("book",
                    arguments: new QueryArguments(
                      new QueryArgument<StringGraphType>() { Name = "isbn" }),
                      resolve: context =>
                      {
                        var id = context.GetArgument<string>("isbn");
                        return bookRepository.BookByIsbn(id);
                      });

    Field<ListGraphType<BookType>>("books",
                                   resolve: context =>
                                   {
                                     return bookRepository.AllBooks();
                                   });
  }
}

Using the GraphQL library all types used in the Query to define the schema are any kind of GraphTypes, even the BookType:

public class BookType : ObjectGraphType<Book>
{
  public BookType()
  {
    Field(x => x.Isbn).Description("The isbn of the book.");
    Field(x => x.Name).Description("The name of the book.");
    Field<AuthorType>("author");
  }
}

The difference is just the generic ObjectGraphType which is also used for the AuthorType. The properties of the Book, which are simple types like the name or the ISBN are mapped directly with the lambda. The complex typed properties like the Author are mapped via another generic ObjectGraphType, which is ObjectGraphType in that case.

Like this you need to create your Schema, which can be used to query the data.

Conclusion

If you want to play around with this demo, I pushed it to a repository on GitHub.

This are my first steps using GraphQL and I really like it. I think this is pretty useful and will reduce the effort on both the client side and the server side a lot. Even if the effort to create the schema is lot more than creating just a Web API controller, but usually you need to create a lot more than just one single Web API controller.

This also reduces the amount of data between the client and the server, because the client could just load the needed data and don't need to GET or POST all unneeded stuff.

I think, I'll use it a lot more in the future projects.

What do you think?

MSDN Team Blog AT [MS]: Microsoft Envision Workshop: Innovation in Entwicklung mit Microsoft Azure

image

Datum: Donnerstag, 29. Juni 2017 | 09:00 – 12:30 Uhr
Ort: Microsoft Österreich GmbH Zentrale, Am Euro Platz 3, 1120 Wien

Jetzt kostenlos registrieren!

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

Vortragende:

Josephine Karner, Partner Business Evangelist – Keynote
Stefan Sennebogen, Geschäftsführer Insight Österreich – Warum Cloud, warum Azure, warum Insight?
Lisa Heinreichsberger, Partner Business Evangelist – Azure Go to Market Strategien
Markus Zechner, Solution Sales Insight Österereich – Was kann Azure eigentlich?
Rina Ahmed, Technical Evangelist – Digitale Transformation mit der Cloud
Markus Zechner, Solution Sales Insight Österereich – Live Demo zum Aufsetzen eines Azure Tenants
Stefan Sennebogen, Geschäftsführer Insight Österreich – Zahlen bitte! Möglichkeiten der Azure Lizenzierung im Überblick

Golo Roden: Gelesen: "Zero to One"

Der US-amerikanische Investor und Unternehmer Peter Thiel, der unter anderem PayPal und Palantir gegründet hat, hat ein Buch geschrieben: "Zero to One". Darin beschreibt er, warum Technologie und nicht Globalisierung die treibende Kraft für die Zukunft ist und worauf beim Aufbau eines Start-ups zu achten sei.

Christian Dennig [MS]: Einstieg in Azure Resource Manager

Moderne Applikationen, die in Azure gehostet werden, bestehen aus vielen verschiedenen Komponenten / Services, die untereinander kommunizieren, Daten austauschen und zwischen denen eine mehr oder minder große Abhängigkeit besteht. Schon einfache Anwendungen bestehen aus einer Datenbank, einem Cache, einer API, einer Webseite usw.  – also vielen einzelnen Komponenten, die gemanaget sein wollen.

Azure Portal

Um die oben genannten Dienste in Azure zu erstellen und zu verwalten, stellt Microsoft als ersten Anlaufpunkt das Azure Portal bereit. Die Oberfläche bietet eine komfortable UI, mit der man alle von Azure angebotenen Services erstellen und managen kann. Es eignet sich hervorragend für Entwickler, die schnell einen Service ausprobieren möchten, für das Erstellen einfacher Prototypen oder einen Proof-Of-Concept – auch kleinere Projekte lassen sich ausreichend gut über das Portal verwalten.

portal
Azure Portal

Es hat jedoch auch seine Nachteile – gerade dann, wenn ein Projekt größer wird und mehrere Personen gleichzeitig an der Infrastruktur arbeiten. Wer kann nachvollziehen, wieso diese eine Einstellung, die aktuell Probleme verursacht, vor zwei Wochen über das Portal an der Web-App gemacht wurde?! Wer hat die Anzahl der Instanzen innerhalb eines VM Scale Sets von „4“ auf „6“ gestellt – und vor allem wieso? Wieso wurde diese eine Resource gelöscht und wer weiß, wie sie nun wiederhergestellt werden kann? Ja, für solche Dinge gibt es auch „Role-Based Access Control„, um zu verhindern, dass bestimmte Personen / Rollen Einstellungen vornehmen können. Spätestens jedoch, wenn die ganze Infrastruktur neu erstellt werden muss (mit allen Abhängigkeiten untereinander), kommt man zu der Einsicht, dass man seine Umgebung auf eine andere Art und Weise managen muss.

Azure Resource Manager / Templates

Bevor man in den Azure Resource Manager und die dazugehörigen Templates einsteigen kann, muss man zunächst einige Begrifflichkeiten klären:

  • Resource – ein über Azure verwaltbares Element. Beispiel: eine virtuelle Maschine, eine Datenbank, eine Web App, Einstellungen einer Web App usw.
  • Resource Group – ein Container für Resources. Eine Ressource kann ohne eine Resource Group (RG) nicht in Azure existieren. Deployments von Ressourcen werden immer auf einer RG ausgeführt. Typischerweise werden Ressourcen mit dem gleichen Lifecycle in eine Gruppe gepackt.
  • Resource Provider – ein Dienst zum Erstellen einer Ressource über den Azure Resource Manager. Beispiel „Microsoft.Web“, um eine Web App zu erstellen. „Microsoft.Storage“, zur Erstellung eines Storage Accounts usw.
  • Azure Resource Manager (ARM) Templates – eine JSON Datei, die eine oder mehrere Ressourcen beschreibt, die über ein Deployment in eine Resource Group bereitgestellt werden. Die Vorlage kann zum konsistenten und wiederholten Bereitstellen der Ressourcen verwendet werden.

Wie nun aus den oben bereitgestellten Informationen abgeleitet werden kann, ist der Azure Resource Manager (ARM) die Komponente in der Azure Cloud, die sich um das Bereitstellen und Verwalten von Ressourcen kümmert. Über ARM werden einzelne Dienste oder Gruppen von Ressourcen gemanaget. Auch können ARM Templates verwendet werden, um eine Infrastruktur wiederholt zu deployen.

Ein, wie ich finde, großer Vorteil bei der Verwendung von ARM Templates ist die Nachvollziehbarkeit von Änderungen an der Infrastruktur. Denn Templates können gemeinsam mit dem Quellcode der Applikation in die jeweilige Source Code Verwaltung abgelegt werden. Hat man im Entwicklungsprozess Continuous Integration/Deployment etabliert, kann man z.B. aus Jenkins, TeamCity oder Visual Studio Team Services heraus das Deployment der Infrastruktur erledigen und niemand muss sich mehr um ein Update der Umgebung kümmern – Web Apps, Datenbanken, Caches usw. werden bereitgestellt, danach erfolgt das Deployment der eigentlichen Applikation (entweder in einem Schritt oder separat) – es sind keinerlei manuelle Schritte mehr notwendig.

Aber – first things first – wie sieht ein einfaches ARM Template aus? Hier ein Beispiel einer einfachen Web App:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "hostingPlanName": {
      "type": "string",
      "defaultValue": "mytestappplan",
      "minLength": 1
    },
    "skuName": {
      "type": "string",
      "defaultValue": "S1",
      "allowedValues": [
        "S1",
        "S2",
        "S3"
      ],
      "metadata": {
        "description": "Describes plan's pricing tier and capacity. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
      }
    },
    "skuCapacity": {
      "type": "int",
      "defaultValue": 1,
      "minValue": 1,
      "metadata": {
        "description": "Describes plan's instance count"
      }
    }
  },
  "variables": {
    "webSiteName": "[concat('webSite', uniqueString(resourceGroup().id))]"
  },
  "resources": [
    {
      "apiVersion": "2015-08-01",
      "name": "[parameters('hostingPlanName')]",
      "type": "Microsoft.Web/serverfarms",
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "HostingPlan"
      },
      "sku": {
        "name": "[parameters('skuName')]",
        "capacity": "[parameters('skuCapacity')]"
      },
      "properties": {
        "name": "[parameters('hostingPlanName')]"
      }
    },
    {
      "apiVersion": "2015-08-01",
      "name": "[variables('webSiteName')]",
      "type": "Microsoft.Web/sites",
      "location": "[resourceGroup().location]",
      "tags": {
        "[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
        "displayName": "Website"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
      ],
      "properties": {
        "name": "[variables('webSiteName')]",
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]"
      }
    }
  ]
}

 

Zugegeben, auf den ersten Blick sieht ein solches Template wild aus und für eine einzelne Webseite wohl auch aufwandstechnisch übertrieben, bei genauerer Betrachtung (und umfangreichen Infrastrukturen) allerdings, löst sich dieser Eindruck schnell wieder auf.

Ein ARM Template besteht in der Regel aus mehreren Teilen:

  • Parameters – Parameter, die von außen an das Template weitergereicht werden. Beispiel im oben genannten Template: „hostingPlanName“. Parameter können typisiert und mit Default-Werten oder erlaubten Werten („allowedValues“) ausgestattet sein.
  • Variables – Variablen zur internen Verwendung. Typischerweise werden Parameter „aufbereitet“, z.B. Namen konkateniert, und in Variablen zur späteren Verwendung gespeichert. Beispiel im oben genannten Template: „webSiteName“.
  • Resources – die eigentlichen Ressourcen, die erstellt werden sollen
  • Outputs – Ausgabe-Parameter, die nach der Erstellung der Ressourcen an den Aufrufer zurückgegeben werden.

Im Template können einfache Funktionen, wie z.B. concat, uniqueString oder toLower verwendet werden, um mit Variablen zu arbeiten. Eine genaue Übersicht der möglichen Funktionen findet sich hier: https://docs.microsoft.com/de-de/azure/azure-resource-manager/resource-group-template-functions

Für die Erstellung der Ressourcen ist wie oben bereits erwähnt, der Abschnitt „Resources“ im Template zuständig. Hier werden die für den Resource Provider geltenden Einstellungen definiert. Jeder Provider Typ bietet verständlicherweise andere Parameter und Abschnitte zur Konfiguration der zu erstellenden Ressource an – die entsprechenden Dokumentationen pro Provider findet man hier unter dem Punkt Reference: https://docs.microsoft.com/en-us/azure/templates/

Im Beispiel-Template wird u.a. eine Web-App erstellt – der zuständige Resource Provider ist hier „Microsoft.Web/sites„. Ein wichtiges Element im hier erwähnte Abschnitt ist der Punkt „dependsOn“. Über dieses Array können unter Angaben der Resource-Id Abhängigkeiten untereinander definiert werden. In diesem speziellen Fall bedeutet…

"dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
]

…dass die Web-App abhängig vom App-Service Plan („Microsoft.Web/serverfarms/„) ist, in den die App deployt wird – was auch logisch erscheint. Über die dependsOn-Angaben kann der Azure Resource Manager einen Deployment-Tree aufbauen und so mit Erstellung der Ressourcen zuerst beginnen, auf die andere eine Abhängigkeit haben.

Das Template kann schlussendlich über verschiedene Wege an den Resource Manager übergeben werden:

  • Powerhell
  • Azure CLI
  • REST
  • Visual Studio

Ich arbeite gerne mit der Azure CLI, da diese plattformübergreifend auf MacOS, Linux und Windows zur Verfügung steht, deshalb hier nun das Beispiel mit der CLI:

Zunächst muss eine Resource Group erstellt werden (falls nicht vorhanden):

az group create --name testdeployment --location westeurope

Nach erfolgreicher Ausführung sollte die Ausgabe folgendermaßen aussehen:

{
  "id": "/subscriptions/[subscriptionid]/resourceGroups/testdeployment",
  "location": "westeurope",
  "managedBy": null,
  "name": "testdeployment",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null
}

Im Anschluss kann das eigentliche Deployment durchgeführt werden („WebSite.json“ ist das Template-File mit den oben dargestellten Inhalten im aktuellen Verzeichnis):

az group deployment create --mode complete --resource-group testdeployment --template-file .\WebSite.json --verbose

Im hier verwendeten Beispiel wird der Modus „complete“ benutzt, um das Template anzuwenden. Es gibt zwei Modi, die verwendet werden können:

  • Complete – Ressourcen, die nicht in der Vorlage vorhanden sind, aber in der Resource Group existieren, werden gelöscht.
  • Incremental – Ressourcen, die nicht in der Vorlage vorhanden sind, aber in der Resource Group existieren, bleiben unverändert

Beide Modi haben Vor- bzw. Nachteile und man muss den für sich passenden Modus herausfinden. Complete sagt mir persönlich mehr zu, da man mit diesem Modus die komplette Infrastruktur beschreibt, wie sie nach dem Deployment aussehen soll.

Nach kurzer Zeit ist das Deployment erfolgreich durchgeführt und das Kommando liefert die Ergebnisse vom Azure Resource Manager zurück.

{
  "id": "/subscriptions/[subscriptionid]/resourceGroups/testdeployment/providers/Microsoft.Resources/deployments/WebSite",
  "name": "WebSite",
  "properties": {
    "correlationId": "1fbfa8f1-44dd-483c-ab9b-38296cd834b7",
    "debugSetting": null,
    "dependencies": [
      {
        "dependsOn": [
          {
            "id": "/subscriptions/[subscriptionid]/resourceGroups/testdeployment/providers/Microsoft.Web/serverfarms/mytestappplan",
            "resourceGroup": "testdeployment",
            "resourceName": "mytestappplan",
            "resourceType": "Microsoft.Web/serverfarms"
          }
        ],
        "id": "/subscriptions/[subscriptionid]/resourceGroups/testdeployment/providers/Microsoft.Web/sites/webSitesycktqb3r6rze",
        "resourceGroup": "testdeployment",
        "resourceName": "webSitesycktqb3r6rze",
        "resourceType": "Microsoft.Web/sites"
      }
    ],
    "mode": "Complete",
    "outputs": null,
    "parameters": {
      "hostingPlanName": {
        "type": "String",
        "value": "mytestappplan"
      },
      "skuCapacity": {
        "type": "Int",
        "value": 1
      },
      "skuName": {
        "type": "String",
        "value": "S1"
      }
    },
    "parametersLink": null,
    "providers": [
      {
        "id": null,
        "namespace": "Microsoft.Web",
        "registrationState": null,
        "resourceTypes": [
          {
            "aliases": null,
            "apiVersions": null,
            "locations": [
              "westeurope"
            ],
            "properties": null,
            "resourceType": "serverfarms"
          },
          {
            "aliases": null,
            "apiVersions": null,
            "locations": [
              "westeurope"
            ],
            "properties": null,
            "resourceType": "sites"
          }
        ]
      }
    ],
    "provisioningState": "Succeeded",
    "template": null,
    "templateLink": null,
    "timestamp": "2017-05-23T16:20:27.645497+00:00"
  },
  "resourceGroup": "testdeployment"
}

Ausblick

Mit dem oben gezeigten Beispiel ist ein erster Einstieg in das Thema „Azure Resource Manager“ und den dazugehörigen Templates geschafft. Wer tiefer einsteigen möchte, kann sich über die folgenden Ressourcen informieren:

Im nächsten Artikel werde ich genauer auf Templates eingehen und ein fortgeschrittenes Szenario aufzeigen, in dem die komplette Infrastruktur für eine Cloud App beschrieben wird (API App inkl. Deployment Slots, SQL DB, Redis Cache, Azure Search, AppInsights…), inklusive Abhängigkeiten der Ressourcen untereinander.

Bis dahin…viel Spaß mit Azure! 🙂


Kazim Bahar: 5 kostenlose eBooks über Machine Learning

Tagtäglich erscheinen Artikel zu Thema Künstliche Intelligenz bzw. Machine Learning. Was hat das aber mit UI-Design und...

MSDN Team Blog AT [MS]: Next Generation Apps am Mobile Developer After Work Nr 15

Das nächste Mobile Developer After Work findet diesmal an der FH St. Pölten am 8. Juni 2017 statt und steht ganz im Zeichen der nächsten Generation von innovativen Apps.

mdawlogo

Das Programm kann sich wieder sehen lassen:

17:40 – 18:10: Azure Machine Learning (30 min)
Rina Ahmed, Microsoft

18:10 – 18:40: Managing Tech Performance in a Portfolio Company like ProSiebenSat.1
If you can measure it, you can manage it (30 min)
Gerald Madlmayr, ProSiebenSat.1 Media SE

18:40 – 18:55: Angular(JS) Jumpstart (15 min)
Georg Beischlager, Tieto

19:10 – 19:35: Robuste Personaleinsatzplanung im (IT-)Projektmanagement (25 min)
Thomas Felberbauer, FH St. Pölten

19:35 – 20:10: Mixing Reality – Bessere Hologramme (35 min)
Philipp Lütge, Philipp Lütge Development

Nähere Infos zu den Vorträgen, sowie den Anmeldelink findet ihr auf der Eventseite. Viel Spaß

Christian Dennig [MS]: Nach Update: Sharing von Laufwerken mit Docker nicht mehr möglich

Das Problem

Ich setze Docker schon eine ganze Weile sowohl privat, als auch beruflich für die unterschiedlichsten Themen ein und bin mit dem Tooling unter Windows mittlerweile sehr zufrieden. Docker integriert sich unauffällig in das Windows Betriebssystem und läuft in der Regel reibungslos.

Vor kurzem wurde jedoch nach einem Windows Update beim Start eines Containers, welcher Dateien aus einem lokalen Windows Folder mit dem Container teilt, von Docker gemeldet, dass ich zuerst Laufwerke mit dem Docker Host teilen muss, bevor ich Verzeichnisse/Dateien in den Container mounten kann. Die Meldung hat mich stutzig gemacht, da ich dies nach der Installation von Docker bereits erledigt hatte. Hat man in diesem Zustand dann versucht, das Laufwerk nochmal zu teilen, wurde von Docker gemeldet, dass die Firewall den entsprechenden Port blockiert und man nach der Docker-Doku bitte vorgehen soll.

docker_firewall

Das Problem ist, dass selbst nach der Durchführung der angegebenen Schritte in der Doku, das Ergebnis das selbe ist: Docker kann nicht auf das jeweilige Laufwerk zugreifen.

Workaround – Step by Step

Nach einigen Recherchen bin ich auf mehrere Lösungsvorschläge gestoßen. Was mir schlussendlich geholfen hat, nun hier – Schritt für Schritt…

Öffnen des Control Panels –> Network and Sharing Center

control_center

Öffnen der Verbindung vEthernet (DockerNAT)

net_share_vEthernet

In den Properties  dann einfach den Haken bei „File and Printer Sharing for Microsoft Networksentfernen und speichern. Danach die gleiche Prozedur nochmal durchführen und den Haken erneut setzen.

net_share_props

Im Anschluss kann man erneut in die Docker Settings gehen und das jeweilige Laufwerk ohne Fehler teilen.

docker_share

 


Johannes Renatus: Out of Memory Exception beim EF Debuggen im IIS Express

Bisher noch nie vorgekommen, aber es gibt immer ein erstes mal. Heute hatte ich beim Abrufen großer Datenmengen um einen Cache zu befüllen auf einmal eine “Out of Memory” Exception, obwohl mein Visual Studio vom RAM her sehr gut aussah und auch noch genug RAM zur Verfügung stand. Leider gibt die Fehlermeldung auch nicht mehr […]

Golo Roden: JavaScript schöner machen

Ein schöner Aspekt von Go ist, dass die Sprache vorgibt, wie Code zu formatieren ist. Diskussionen über die Optik von Code gehören damit der Vergangenheit an. Für JavaScript steht mit prettier seit Kurzem nun auch ein Modul zur Verfügung, das die Formatierung vorgibt.

Holger Schwichtenberg: Die Build-Nachrichten in der Kurzzusammenfassung

Vom 10. bis 12. Mai fand in Seattle Microsofts Entwicklerkonferenz Build 2017 statt mit Neuigkeiten zu .NET, Visual Studio, Azure, PowerShell und Windows.

Johannes Renatus: ngModel like two-way-databinding für Komponenten in Angular

Da es sich bei Angular nur noch im Komponenten handelt, ist es hier natürlich auch wichtig wie man Daten an Komponenten weitergibt und auch wieder zurückgeben kann. Dafür gibt es zwei wichtige Dekoratoren “@Input” um Daten an eine Komponenten zu übergeben und “@Output“ um Daten wieder “zurückzugeben”. Um ein two-way-databinding zu erstellen gibt es mindestens […]

Golo Roden: Einführung in Node.js, Folge 18: Eigene Streams schreiben

Zusätzlich zu den in Node.js integrierten Streams lassen sich auch eigene schreiben. Zur Wahl stehen außer les- und scheibbaren Streams auch die sogenannten Transform-Streams, die Daten verändern und aggregieren können. Wie funktioniert das?

AIT: Pushing Azure IoT to the Edge @ MSBuild 2017

Die Keynotes der ersten beiden Tage waren voller Highlights. In den folgenden Breakout-Sessions werden einige Ankündigungen im Detail vorgestellt. Hier und da gab es auch noch weitere Überraschungen. Auf diese werden wir in den kommenden Tagen gezielt eingehen.

Einen großen Block in den Sessions nahm natürlich das Thema Azure IoT ein. Für Azure IoT Edge wurden die verfügbaren Module (Azure Machine Learning, Azure Stream Analytics, Azure Functions und Cognitive Services) gezeigt. Als Anwendungsszenarien sieht Microsoft vor allem das Filtern und Aggregieren von Daten, bevor diese an den IoT-Hub gesendet werden und die schnellere Reaktionszeit z.B. bei Fehlerinvervention.

clip_image002

Dabei stellt sich natürlich sofort die Frage, wie leistungsfähig ein Endgerät sein muss, um Azure IoT Edge nutzen zu können. Die Anforderungen sind dabei verblüffend gering. Ein Rechenkern und 128 MB RAM sind ausreichend. Es gilt jedoch zu beachten, dass Azure IoT Edge eine containerbasierte Lösung ist, was vom Betriebssystem unterstützt werden muss. Aktuell wurde Azure IoT Edge erfolgreich unter Ubuntu 14.04, Ubuntu 15.10, Yocto Linux 3.0 on Intel Edison, Windows 10 und Wind River 7.0 getestet. Das SDK steht auf GitHub zum Ausprobieren bereit und bringt auch genug Beispiele mit, um direkt loslegen zu können.

clip_image004

Bei dem Thema Geräte geht es auch gleich weiter. Viele Ideen und Prototypen funktionieren mit einem oder wenigen Endgeräten fantastisch. In realistischen Szenarien kommen jedoch mehrere hundert oder tausend Geräte zum Einsatz. Die Provisionierung (initiale Konfiguration und Verbindung mit dem richtigen IoT Hub) der Geräte kann zu einem Alptraum werden. Mit der Enrollment List soll das Ganze nun deutlich einfacher werden. Ein neues IoT-Device meldet sich mit seiner ID beim IoT Hub Device Provisioning Service an und wird entsprechend der Enrollment List mit dem passenden IoT-Hub verbunden. Dieser IoT-Hub führt nun die initiale Konfiguration durch, indem ein passender Device Twin ausgerollt wird. Über die Device Twins kann ab diesem Zeitpunkt die Konfiguration für jedes angemeldete Gerät gesteuert werden. So wird sichergestellt, dass sobald ein Gerät online ist, die neuste Konfiguration verteilt wird. Die Konfiguration von IoT-Devices sollte ausschließlich über den Device Twin und seine Desired Properties durchgeführt werden – dieser Tipp ist wohl einer der Wichtigsten aus der Device Management Session. Die Nutzung von Cloud-to-Device-Messages oder Direct Methods ist aufgrund der zu geringen TTL und des interaktiven Verhaltens nicht zu empfehlen.

clip_image006

Wenn das Device nun verbunden und konfiguriert ist, müssen die anfallenden Daten auch sinnvoll ausgewertet werden. Einer der gebräuchlichsten Wege läuft aktuell vom IoT Hub über Azure Stream Analytics in Power BI Dashboards. Wesentliche Nachteile dieser Lösung können die Verdichtung der Daten via Analytics Stream und die vorkonfigurierten Auswertungen in Power BI sein.

clip_image008

Um zum Beispiel Analysten eine uneingeschränkte Sicht auf Daten zur Auswertung geben zu können, steht mit Azure Time Series Insights eine neue Alternative zur Verfügung. In Azure Time Series Insights werden die Roh-Daten vom IoT-Hub gespeichert und zur Auswertung steht ein umfangreiches Web-UI mit den Daten der letzten 30 Tage zur Verfügung. Der Zeitraum kann aktuell auf maximal 100 Tage erweitert werden. Sehr beeindruckend war die Performance bei der Auswertung. Datenmengen von mehreren hundertmillionen Datenpunkten pro Tag stellen keinerlei Probleme für das System dar. Um eine bessere Auswertung zu ermöglichen, können Referenzdaten aus verschiedensten Quellen genutzt werden. Alternative Darstellungen wie zum Beispiel Heat-Maps sind ein weiterer Schritt hin zu einer einfachen und schnellen Auswertbarkeit von großen Datenmengen.

clip_image010

clip_image012

Diese drei Neuerungen zeigen, dass Microsoft die Schmerzen und Hürden erkennt, die bei der Entwicklung von IoT-Szenarien auftreten und diese versucht zu beheben. Jetzt ist es an uns Entwicklern, die Technologien zum Einsatz zu bringen. Also schauen wir mal, ob die Versprechen auch alle gehalten werden können.

Manfred Steyer: Slides and Sample for my Angular Talk at WAD 2017 in Vienna

Please find below the slides and the sample from my Talk about Angular I did at We Are Developers in Mai 2017 in Vienna:

AIT: We are all creators – Tag 2 @ MSBuild 2017

Die große Frage am Morgen des zweiten Tages auf der BUILD war: “Kann der erste Tag noch getoppt werden?“. Die Antwort war nach den ersten 30 Minuten der Keynote klar: „Ja!“. Aber beginnen wir von vorne…

Die erste Ankündigung der Keynote war das Windows 10 Fall Creators Update, welches im dritten Quartal des Jahres kommen wird. Was in diesem alles enthalten ist, war zu dem Zeitpunkt noch längst nicht absehbar. Doch das änderte sich schnell.

clip_image002

Mit Windows Story Remix wurde die erste neue App des Updates vorgestellt. Es handelt sich dabei um einen Filmeditor, der jedoch deutlich mehr kann, als alles was der normale Windows Benutzer bisher kennt. Durch Machine Learning erkennt die App, welche Videos und Bilder relevant sind, schneidet diese in sinnvolle Szenen und kombiniert das Ganze mit Musik. Es können einzelne Personen als „Star“ definiert werden, wodurch sich der gesamte Film um diese Personen zentriert. Möglich wird dies durch die Gesichtserkennung in Bildern und Videos. Durch Remix 3D können 3D-Modelle, die von der Internet-Community erstellt wurden, in die eigenen Videos integriert werden. Dadurch ergibt sich ein Mixed Reality Erlebnis von besonderem Wert. Das verblüffendste an dieser App ist wie einfach diese Videos erstellt werden können. Es braucht keinerlei Erfahrung. Hier ist das Video aus der Keynote zu finden.

Mit dem kommenden Windows Update wird der Austausch von Daten zwischen mehreren Geräten um ein Vielfaches erleichtert. Wer kennt es nicht. Man hat ein Bild auf dem Handy gemacht und möchte dieses nun auf dem Desktop Rechner haben. Was vorher umständlich über das Zusenden an die eigene E-Mail-Adresse passierte, ist dank dem Cloud-powered Clipboard nun direkt möglich. Hierbei kann nicht nur Text, sondern auch Bilder und Datei können bequem zwischen Geräten kopiert und eingefügt werden. Durch OneDrive Files On-Demand können nun Dateien bequem in der Cloud gespeichert und bei Bedarf nachgeladen werden. Die nötigen Anpassungen wurden direkt in Windows gemacht und nicht über eine Applikation installiert. Somit findet der Mechanismus der On-Demand-Synchronisation komplett im Hintergrund statt, ohne Auswirkung auf die Anwendungen welche auf die entsprechenden Dateien zugreifen.

clip_image004

Um die Entwicklung für unterschiedliche Endgeräte zu erleichtern, wurde der Xamarin Live Player angekündigt. Mit dem Xamarin Live Player ist es nun möglich, eine Xamarin App direkt auf einem iOS oder Android Gerät zu debuggen. Darüber hinaus ist es zur Debug-Zeit möglich, die Logik und die UI der App zu verändern, während die Änderungen direkt dargestellt werden. Die Entwicklung von Oberflächen für mehre Endgeräte auf unterschiedlichen Plattformen soll in Zukunft durch den angekündigten XAML Standard 1.0 ebenfalls vereinfacht werden.

Mit dem neuen Timeline Feature ist es möglich, eine Zeitachse für die letzten verwendeten Dokumente und Apps zu bekommen. Dadurch hat man immer alles auf einen Blick, was man als letztes verwendet hat und kann direkt dort einsteigen. In Verbindung mit Pick off where you left with Cortana wird das Arbeiten mit mehreren Endgeräten eine komplett neue Erfahrung. Dank Microsoft Graph und Project Rome ist die intelligente Assistentin Cortana nun in der Lage zu merken, was man als letztes oder in der Vergangenheit gemacht hat. Diese Aktionen können dann auf anderen Geräten fortgesetzt werden. Fängt man also auf dem Desktop Rechner an, einen Blog Post zu lesen, kann man diesen bequem auf dem Handy weiterlesen. Sofern die passende App nicht verfügbar ist, bietet Cortana direkt an, diese zu installieren.

Die Cross-Plattform und Cross-Device-Strategie von Microsoft wird nun auch im Windows Store ersichtlich. So ging ein großes Raunen durch die Menge, als Microsoft bekannt gab, dass iTunes zukünftig im Windows Store verfügbar ist. Als wichtige Lektion nehmen wir hieraus mit: Um Innovation zu fördern, muss man Kooperationen eingehen, statt zu konkurrieren. Zusätzlich zu Ubuntu für die Windows Bash werden in Zukunft noch SUSE und Fedora im Windows Store verfügbar sein.

clip_image008

Das größte Highlight ist jedoch die Präsentation des Fluent Design System. Light, Depth, Motion, Material, Scale – das sind die neuen Konzepte, die hinter Microsoft Fluent Design System stehen. Auf einfache Art und Weise und mit wenig Zeilen Code, können Entwickler die Oberfläche ihrer UWP Apps verbessern. Durch Light werden Elemente rund um den Cursor hervorgeben. Depth ermöglicht es z.B. über Parallex Scrolling eine zusätzliche Tiefe einzubringen, um aus der zwei dimensionalen Welt auszubrechen. Motion lässt Navigation und Transitionen in Anwendungen flüssig aussehen, in dem z.B. Elemente von einer Ansicht in die nächste Ansicht animiert werden. Bei Material gibt es das neue Acrylic Design, bei dem gewisse Bereiche einer App wie z.B. die Navigation einen transparenten Blureffekt erhalten. Mit Scale soll sich nicht nur auf eine zwei dimensionale Welt beschränkt werden. In Zeiten von Mixed Reality gibt es die Möglichkeit, in die drei dimensionalen Welt zu skalieren. Zusätzlich legt Microsoft großen Wert auf Windows Ink, durch das mit einem digitalen Pen gezeichnet oder geschrieben werden kann.

clip_image010

Mixed Reality ist keine kleine Idee mehr. Es ist die Zukunft der Softwareentwicklung. Dieses Bild wurde von Alex Kipman ganz klar herausgestellt. Schaut man sich an was in den HoloLens-Communities weltweit passiert, fällt es auch nicht schwer das zu glauben. So passt es auch sehr gut ins Bild, dass mit den Acer und HP Mixed Reality Headsets zwei preisgünstige Alternativen zur HoloLens vorgestellt wurden. Beide sind ab sofort für 399$ in den USA und Kanada verfügbar. Als eindrucksvolles Beispiel für die Anwendung von Mixed Reality wurde die Bühnenplanung vom Cirque du Soleil gezeigt.

clip_image012

Wer bei bisherigen Anwendungsszenarien Probleme mit der Gestensteuerung bei der HoloLens hatte, kann nun dank zweier Motion Controller seine Steuerung erweitern. Durch ein Touchpad, einen analogen Stick und mehrere Knöpfen, können verschiedene Aktionen ausgeführt werden. Zusätzlich befinden sich LEDs an den Ringen um die Griffe, mit denen die Controller getracked werden können.

Das war noch längst nicht alles vom zweiten Tag. Weitere Highlights wie Details zu Azure IoT Edge, Azure Service Fabric oder VSTS folgen im nächsten Post. Also bis später…

AIT: With great opportunity comes great responsibility – Tag 1 @ MSBuild 2017

Es gibt eine Menge Entwicklerkonferenzen, und es gibt die BUILD. Keine andere Konferenz im Microsoft Umfeld wird Jahr für Jahr so sehnlich erwartet wie diese. Die Teilnehmer werden dieses Jahr an einem völlig neuen Standort, dem Washington State Convention Center, Downtown Seattle begrüßt.

clip_image002

Die Keynote zu Beginn wurde von CEO Satya Nadella eröffnet und steht unter dem Motto “Opportunity & Responsibility”. Die Inhalte können weltweit im Livestream verfolgt werden. Die enorme Größe dieser Veranstaltung kann dabei jedoch nur erahnt werden.

clip_image004

Die ersten Highlights kommen, wie könnte es auch anders sein, aus dem Azure-Bereich. Mit Azure IoT Edge bietet Microsoft die Möglichkeit, Azure Funktionalität wie Machine Learning oder Azure Functions von der Cloud auf IoT Devices zu übertragen. Diese werden dann in einem eigenen Docker Container auf dem Gerät gehostet.

clip_image006

Durch den entfallenden Roundtrip zur Cloud werden Antwortzeiten enorm verringert, was bei der Erkennung von Fehlerfällen und einem automatischen Gegensteuern von großem Vorteil ist. Aber auch Use Cases, bei denen die Cloud nicht erreichbar ist, können somit abgedeckt werden. Mehr Informationen gibt es hier.

Wer bei der Umsetzung von IoT Szenarien lieber eine Private Cloud der Public Cloud vorzieht, hat mit Azure Stack nun die Möglichkeit, seine eigene Azure Cloud auf seinen eigenen Servern zu betreiben. Dabei ist es aber nicht nur bei sensiblen Daten relevant, sondern auch wenn kein Internetzugriff zu Azure garantiert werden kann. Die Preview 3 von Azure Stack steht als Single-Server-Installation bereit. Für den produktiven Einsatz von Azure Stack ist Microsoft mit Hardwareherstellern wir DELL und Lenovo in Kontakt um Komplettlösungen in jeglichen Größenordnungen liefern zu können.

In Zeiten von Mixed Reality & Co. schaffte es Scott Hanselman das Publikum im Anschluss mit der Vorstellung eines neuen Command Line Interfaces zu begeistern. So wurde das Azure Web Portal um eine Cloud Shell erweitert, die vorkonfiguriert mit der Azure CLI zur Verfügung gestellt wird. Hier können unter anderem Skripte zur Automatisierung zentral abgelegt und ausgeführt werden. Wer auch auf seinem mobilen Endgerät seine Azure Cloud verwalten möchte, hat nun die Möglichkeit dies per App für Android und iOS Geräte zu machen. Und ja, auch in der App kann die Azure Shell genutzt werden!

clip_image008

Die nächsten zwei Highlights waren das Azure Snapshot Debugging und die generelle Verfügbarkeit von Visual Studio for Mac – it’s no longer a preview! Mit Azure Snapshot Debugging ist es nun möglich Fehler auf einer produktiven Umgebung zu debuggen OHNE diese Umgebung zu beeinflussen. Um dies zu ermöglichen werden Abbilder des Produktivsystems gemacht, sobald eine bestimmte Codestelle durchlaufen wird. Diesen Snapshot kann man dann bequem debuggen, ohne Auswirkungen auf die produktive Umgebung. WOW!

Der nächste große Themenblock der Keynote drehte sich rund um das Thema Datenbanken in der Cloud. Mit Cosmos DB erblickte ein völlig neues Datenbankkonzept das Licht der Welt. Microsoft stellt hierbei eine Datenbank zur Verfügung, die nicht nur eine geringe Latenzzeit garantiert, sondern auch mit einem Klick in andere Länder repliziert werden kann. Zusätzlich kann man bei der Struktur zwischen Documents, Key-Value, Graph und Column Family und bei der API zwischen Document DB SQL, Mongo DB, Azure Tables und Gremlin frei wählen. Durch die frei wählbare API ist es umso einfacher, Cosmos DB in bestehenden Anwendungen zu integrieren, da jede Bibliothek welche die gewählte API versteht, verwendet werden kann. Mehr Informationen zu Azure Cosmos DB gibt es hier.

clip_image010

Neben Cosmos DB als völlig neues Datenbank-System können nun auch PostgreSQL und MySQL in Azure gehostet werden. Mit dem Azure Database Migration Service ist es in Zukunft noch einfacher, eine on-premise Datenbank (SQL Server, Oracle oder MySQL) in die Azure Cloud zu bekommen. Mit dem Database Migration Assessment Tool kann die aktuelle Datenbankstruktur auf mögliche Probleme geprüft werden wie z.B. abweichende Features zwischen on-premise und Cloud. Danach können sowohl die Strukturen als auch Daten direkt in die Cloud-Datenbank migriert werden.

Der dritte Teil der Keynote widmete sich dem omnipräsenten Thema Artificial Intelligence. Artificial Intelligence ist DAS Zukunftsthema schlechthin und mit Cognitive Services stellt Microsoft eine enorme Plattform zur Verfügung, um AI zum Leben erwachen zu lassen.

clip_image012

Als die Geschichte von Haiyan Zhang und Emma Lawton dem Publikum präsentiert wurde, gab es mit Sicherheit mehr als ein paar feuchte Augen im Saal. Zu sehen wie mit all diesen Technologien einem kranken Menschen neue Lebensqualität geschenkt werden kann, war einfach unglaublich. Eine Beschreibung mit Worten ist nicht ausreichend für dieses Projekt – hier ist das Video.

Mit den vorgestellten Bot Framework Adaptive Cards bietet Microsoft die Möglichkeit, das Aussehen von Antworten eines Bots in verschiedenen Kanälen (z.B. Skype oder Slack) einheitlich festzulegen. Dadurch werden Nachrichten je nach Kanal automatisch formatiert und versendet. Natürlich muss eine Keynote mit einem Spektakel beendet werden. Der PowerPoint Live Translator übersetzt, wie der Name vermuten lässt, in Echtzeit den gesprochenen Inhalt einer Präsentation in textuelle Form. Es war also sehr leicht dem Vortrag zu folgen als die Sprache auf einmal ins spanische wechselte und dann noch chinesische Kommentare eingeworfen wurden.

Während im Anschluss die einzelnen Sessions starteten, wurde im „Hub“, der zentralen Ausstellungsfläche, der Betrieb aufgenommen. Jede Produktgruppe von Microsoft ist hier vertreten, um im direkten Austausch mit den Teilnehmern ihre Ideen zu erklären und Feedback einzusammeln. Besonders beeindruckend war der Besuch am DevOps-Stand. Auf großen Whiteboards werden Ideen und Schmerzpunkte gesammelt und diskutiert. Dieser direkte Austausch mit Microsoft ist der eigentliche Gewinn der Veranstaltung.

clip_image014     clip_image016

Das war’s vom ersten Tag. Zwei weitere folgen mit hoffentlich nicht weniger Highlights – so stay tuned!

Norbert Eder: SQL Server und CLR Assemblies

In manchen Fällen ist es ganz praktisch, Stored Procedures oder Functions für den SQL Server via CLR zur Verfügung zu stellen. Nachdem dies schon ein alter Hut ist, findet man auch zahlreiche Infos zu diesem Thema, aber nicht in einem Artikel.

Verwaltung von Assemblies

Für den Umgang mit Assemblies im SQL Server gibt es doch einiges, was es zu wissen gilt. Nachfolgend die wichtigsten Informationen, damit der erste Start schnell gelingt.

Erstellen von Assemblies

Damit Assemblies im SQL Server verwendet werden können, müssen sie hinzugefügt/registriert werden:

CREATE ASSEMBLY TestAssembly
FROM 'C:\Path\To\Assembly.dll'
WITH PERMISSION_SET = SAFE;

Wichtig ist hierbei das PERMISSION_SET. Hier gibt es drei unterschiedliche Einstellungen:

  • SAFE: Das ist die restriktivste Einstellung. Externe Ressourcen (Dateien, Netzwerk, Umgebungsvariablen etc.) dürfen nicht verwendet werden.
  • EXTERNAL_ACCESS: Der Zugriff auf einige externe Ressourcen (Dateien, Netzwerk, Umgebungsvariablen, Registry) ist möglich.
  • UNSAFE: Uneingeschränkten Zugriff auf externe und interne Ressourcen. Unmanaged Code kann ebenfalls ausgeführt werden.

Werden externe Ressourcen benötigt, ist zusätzlich die TRUSTWORTHY-Einstellung auf ON zu setzen. Hierfür ist ein Benutzer mit der Serverrolle sysadmin notwendig:

ALTER DATABASE test SET TRUSTWORTHY ON;

Ab SQL Server 2017 ändert sich da ein wenig, siehe CLR strict security. Im Grunde wird die Code Access Security (CAS) nicht mehr länger unterstützt. Deswegen kann es auch bei der Einstellung SAFE dazu kommen, dass Zugriff auf externe Ressourcen besteht. Es wurde eine Option clr strict security (siehe sp_configure) eingeführt.

  • Disabled: Das bisherige Verhalten wird verwendet
  • Enabled: PERMISSION_SET wird ignoriert und Assemblies werden immer als UNSAFE interpretiert. Das ist der Standard für SQL Server 2017

Ist CLR strict security aktiviert, sind folgende Berechtigungen notwendig, damit eine Assembly erstellt werden kann:

  • Der Benutzer muss die CREATE ASSEMBLY Berechtigung besitzen
  • Die Assemly wurde mit einem asymmetischen Schlüssel signiert, zu dem auch ein entsprechendes Login mit der Berechtigung UNSAFE ASSEMBLY besteht ODER
  • die Datenbank-Einstellung TRUSTWORTHY wird auf ON gestellt und die Datenbank besitzt einen Owner mit UNSAFE ASSEMBLY Berechtigung.

Weitere Details sind unter CREATE ASSEMBLY zu finden.

Aktualisierung einer Assembly

Wurde eine Assembly bereits erstellt, kann diese auch aktualisiert werden:

ALTER ASSEMBLY TestAssembly
FROM 'C:\Path\To\Assembly.dll'

Das geht sogar so weit, dass Dateien zur Assembly hinzugefügt werden können:

ALTER ASSEMBLY TestAssembly
ADD FILE FROM 'C:\Path\To\Class.dll'

Auch die Berechtigung kann verändert werden:

ALTER ASSEMBLY TestAssembly WITH PERMISSION_SET = EXTERNAL_ACCESS;

Weitere Informationen gibt es unter ALTER ASSEMBLY.

Löschen einer Assembly

Eine Assembly kann folgendermaßen entfernt werden:

DROP ASSEMBLY TestAssembly

Zu beachten ist, dass keine Funktionalität der Assembly mehr verwendet werden darf, bevor sie gelöscht werden kann.

Die vollständige Dokumentation findet sich unter DROP ASSEMBLY.

Verwenden einer Stored Procedure

Damit eine in der Assembly enthaltene Stored Procedure verwendet werden kann, muss diese am SQL Server noch erstellt werden:

CREATE PROCEDURE dbo.sp_ReadDataFromWebservice @url nvarchar(255)
WITH EXECUTE AS CALLER AS EXTERNAL NAME TestAssembly.StoredProcedures.ReadData;

Im Endeffekt wird hier eine Stored Procedure mit einem Parameter erstellt. Der externe Name ist der volle Namespace inkl. Methoden-Name der CLR Stored Procedure.

Ein Aufruf erfolgt so:

exec sp_ReadDataFromWebservice @url='http://hier.ist-mein.webservice'

Vertiefende Informationen sind unter CREATE PROCEDURE zu finden.

Unterstützendes Tooling

Visual Studio kann uns allerdings unterstützen. So gibt es im Kontextmenü zum CLR-Datenbankprojekt die Möglichkeit Publish Database zu wählen. Damit wird nachfolgender Dialog geöffnet:

Publish Database | Visual Studio

Publish Database | Visual Studio

Hier können wir uns ein passendes Script generieren oder aber die Änderungen direkt in die gewählte Connection einspielen lassen. Unter Advanced verstecken sich zahlreiche Einstellungen, die Beachtung finden sollten.

Sind mehrere Datenbanken betroffen bietet sich die Arbeit mit Profilen an. Diese können über denselben Dialog verwaltet werden. Ein Profil wird im jeweiligen Projekt als XML-Datei abgespeichert und kann jederzeit geladen und für eine Veröffentlichung genutzt werden.

Fazit

Dieser Beitrag hat die wichtigsten Informationen, um ans Ziel zu kommen, aufgezeigt. Für entsprechende Vertiefungen empfiehlt es sich, den ausgehenden Links zu folgen.

Happy Coding!

The post SQL Server und CLR Assemblies appeared first on Norbert Eder.

Golo Roden: Node.js kompiliert

Die JavaScript-Laufzeitumgebung Node.js verwendet intern zwar Googles V8 als Compiler, kann aber trotzdem keine Binärpakete erstellen. Das von dem Unternehmen Zeit entwickelte Modul pkg ändert das. Wie funktioniert das Modul, und was leistet es?

Manfred Steyer: Hochperformante Anwendungen mit Angular: Unterlagen von JAX 2017 in Mainz

Nachfolgend meine Unterlagen von der JAX 2017 in Mainz:

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