.
Anmeldung | Registrieren | Hilfe

Blogger

.NET-Blog Archiv

.NET Developer Blogs

Kostenlose E-Books zu Windows 10 Themen

21.05.2016 05:50:50 | Kazim Bahar

Step into Windows 10 UWP Dieses kostenlose E-Book von Daresh M beschreibt die UI Features...

Visual Studio Code 1.0 - Unterlagen zur Lunch-Session auf der dotnet Cologne 2016

17.05.2016 18:30:09 | Kay Giza

Letzte Woche hat die dotnet Cologne 2016 stattgefunden. Wir von Microsoft waren vor Ort und möchten uns für die zahlreichen Gespräche, Diskussionen und den Austausch mit Euch am Stand bedanken. Vielen Dank auch an die zahlreichen Besucher unserer Sessions - wir haben uns sehr gefreut. Ich hatte um 13.40 Uhr eine Lunch-Session zu Visual Studio Code zusammen mit... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Aufzeichnung und Rueckblick: 4 Sonderausgaben des DrWindows.de OneCast: Developer Edition

17.05.2016 17:06:30 | Kay Giza

In den letzten Wochen haben wir zusammen mit Dr. Windows vier Spezialausgaben der OneCast-Webinar-Serie gesendet. Vielen Dank an Martin und Marijan von Dr. Windows für die super Zusammenarbeit und die gemeinsame Umsetzung der Idee dazu. Nachdem die erste Folge gelaufen ist, haben wir nach Rückmeldungen gefragt, ob das Thema Developer und App-Entwicklung interessant ist und wir mehr davon machen sollen. Das Feedback war überwältigend positiv, so dass wir noch drei weitere Folgen nachgelegt haben. Alle Referenten waren - und das möchte ich ausdrücklich noch mal erwähnen, sehr positiv überrascht, wie interaktiv es während der Sendungen zuging. Sehr viele Fragen erreichten uns via Chat und wir bemüht, die meisten auch gleich zu beantworten. Tolle Community dort auf DrWindows.de :-) Die Aufzeichnungen stehen zur Nachschau bereit... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Copy to clipboard with Javascript

13.05.2016 03:55:00 |

Clipboard? Current state of the art…

I think everybody knows the clipboard. The goal is that we can store text inside the users clipboard, so he can just paste it. Most sites uses either Flash or some sort of mini-popup with a pre-selected text inside a textarea.

Both ways are not super user friendly and Flash is definitely done.

Clipboard API?

Currently there are some draft specs for a real clipboard API, but as far as I know, it’s far from done.

The good news: For our use case there is a pretty handy workaround available, which I found on StackOverflow.

The code:

<script>
    function detectIE() {
        var ua = window.navigator.userAgent;

        var msie = ua.indexOf('MSIE ');
        if (msie > 0) {
            // IE 10 or older => return version number
            return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
        }

        var trident = ua.indexOf('Trident/');
        if (trident > 0) {
            // IE 11 => return version number
            var rv = ua.indexOf('rv:');
            return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
        }

        // other browser or edge
        return false;
    }

    // source: http://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
    // enhancement with special case for IEs, otherwise the temp textarea will be visible
    function copyTextToClipboard(text) {
        if (detectIE()) {
            try {
                window.clipboardData.setData('Text', text);
                console.log('Copying text command via IE-setData');
            } catch (err) {
                console.log('Oops, unable to copy via IE-setData');
            }
        }
        else {

            var textArea = document.createElement("textarea");

            //
            //  This styling is an extra step which is likely not required. 
            //
            // Why is it here? To ensure:
            // 1. the element is able to have focus and selection.
            // 2. if element was to flash render it has minimal visual impact.
            // 3. less flakyness with selection and copying which might occur if
            //    the textarea element is not visible.
            //
            // The likelihood is the element won't even render, not even a flash,
            // so some of these are just precautions. 
            // 
            // However in IE the element
            // is visible whilst the popup box asking the user for permission for
            // the web page to copy to the clipboard. To prevent this, we are using 
            // the detectIE workaround.

            // Place in top-left corner of screen regardless of scroll position.
            textArea.style.position = 'fixed';
            textArea.style.top = 0;
            textArea.style.left = 0;

            // Ensure it has a small width and height. Setting to 1px / 1em
            // doesn't work as this gives a negative w/h on some browsers.
            textArea.style.width = '2em';
            textArea.style.height = '2em';

            // We don't need padding, reducing the size if it does flash render.
            textArea.style.padding = 0;

            // Clean up any borders.
            textArea.style.border = 'none';
            textArea.style.outline = 'none';
            textArea.style.boxShadow = 'none';

            // Avoid flash of white box if rendered for any reason.
            textArea.style.background = 'transparent';


            textArea.value = text;

            document.body.appendChild(textArea);

            textArea.select();

            try {
                var successful = document.execCommand('copy');
                var msg = successful ? 'successful' : 'unsuccessful';
                console.log('Copying text command was ' + msg);
            } catch (err) {
                console.log('Oops, unable to copy');
            }

            document.body.removeChild(textArea);
        }

    }
</script>

Usage:

The usage is pretty simple, just call copyToClipboard, e.g.

<button type="button" onclick="copyTextToClipboard('Foobar!')">
	Set Foobar to clipboard
</button>

document.execCommand(‘copy’)

This API is a bit strange, because it only works for visible elements and IE might render a small warning. To get rid of this effect we use a older IE-only API. “document.execCommand” is not limited to copy - there are some nice ideas around it. The Mozilla site has a large documentation about this function.

A full demo is available on JSFiddle and the code is stored on GitHub

Hope this helps.

Microsoft auf der dotnet Cologne 2016 - wir freuen uns!

10.05.2016 12:25:44 | Kay Giza

Auch dieses Jahr sind wir von Microsoft mit Freude wieder bei der dotnet Cologne 2016 dabei. Wir freuen uns diese Woche Freitag (13.05.2016) wieder in Köln dabei zu sein, man findet uns mit unserem Stand im Haus 7 direkt bei der Registrierung. Wir bringen nicht nur 5 Kollegen von Microsoft mit und sind gespannt auf den regen Austausch und die Diskussionen, sondern wir bringen auch einen Surface Hub... [... mehr in diesem Blogbeitrag auf Giza-Blog.de]

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

Finally we got sort of dates

08.05.2016 21:00:00 | Jürgen Gutsch

Every time I watch the ASP.NET Community stand-up, I was pretty curious about the delivery date of ASP.NET Core RC2 and RTM. Last Scott Hunter wrote about the status and the road-map of .NET Core and the tooling around it.

  • In the middle of May
    • .NET Core and ASP.NET Core will be RC2
    • The tooling will be in Preview 1
  • By the end of June
    • .NET Core and ASP.NET Core will be RTM
    • The tooling will be in Preview 2

The tooling will be RTM with Visual Studio "15"

Read lot more about it in Scott Hunters post about the Improvements, Schedule and Roadmap of .NET Core.

Sundays IT: Ever wondered, why chrome runs so many processes ?

08.05.2016 12:00:53 | Sascha Baumann

Hi everyone, did you ever ask yourself, why the hack is chrome running so many processes ? This image shows only 5 processes, but this can go up to an nearly insane amount. According to some articles I read, chrome encapsulates every single page into its own process, to prevent crashing the browser when one […]

Das Web in 2016! Mit der Gesamtsituation unzufrieden!? Los geht’s! Let's fix the web!

06.05.2016 12:09:39 | Kay Giza

Zugegeben, ich bin an der einen oder anderen Stelle auch nicht besser. Webentwickler und technisch versierte Nutzer wissen es aber schon längst: Vielen Webseiten fehlt es an Benutzerfreundlichkeit und Performance. Meine Kollegen bei Microsoft Deutschland und OnPage.org haben sich zusammengetan und gemeinsam die 20.000 beliebtesten Internetseiten in Deutschland näher unter die Lupe genommen. Herausgekommen ist eine ernüchternde... [... mehr in diesem Blogbeitrag auf Giza-Blog.de]

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

Sparen Sie 25 Prozent und upgraden Sie jetzt auf Visual Studio Enterprise 2015 mit MSDN

03.05.2016 18:35:58 | Kay Giza

Wer derzeit Visual Studio Professional oder Test Professional mit einer MSDN Subscription nutzt, der sollte diesen Blogeintrag ein wenig weiterlesen. Für begrenzte Zeit bietet Microsoft einen Rabatt von 25%, wenn man jetzt von Visual Studio Professional oder Test Professional mit MSDN auf Visual Studio Enterprise 2015 mit MSDN umsteigt... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Liste der Visual Studio Code Extensions und Themes - April 2016 Report

02.05.2016 13:12:43 | Kay Giza

Ich habe wieder eine Liste aller verfügbaren Extensions für Visual Studio Code erstellt: Stand 02.05.2016. Natürlich kann man auch im Visual Studio Marketplace schauen oder in Visual Studio Code selber und sich die nützlichsten Extensions heraussuchen. Da es die genannten Möglichkeiten zur Extension-Suche gibt, habe ich mir hier die Kurzbeschreibungen zu den Erweiterungen von Visual Studio Code gespart und nur eine einfache Link-Liste erstellt, viel Spaß beim Durchstöbern! Die Veränderungen im Vergleich: Im Vergleich zum März gab es im April rund 120 neue Extensions. Hier einige Extensions die ich besonders herausstellen möchte... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Sundays IT: Windows Update on my Win7 machine is stuck at 0% again – 4 Steps solution

01.05.2016 12:00:48 | Sascha Baumann

Hi everyone, its annoying when Windows Updates just is not working and its download percentage is Stuck at 0%. I like to share my process to solve this issue – So I do the following: Opening a command prompt with elevated permissions by typing cmd in my searchbox, right-click and select „run as aministrator“ or […]

Exif und C#: Wege um an die GPS-Metadaten aus Bildern zu kommen

30.04.2016 11:59:56 | Johnny Graber

Das Auslesen von Exif-Metadaten aus JPEG-Bildern ist für zahlreiche Anwendungsgebiete sehr interessant. Anhand der GPS-Dateien kann man so beispielsweise seine Sammlung nach Aufnahmeort gruppieren oder alle Fotos finden, die mit einer bestimmten Kamera gemacht wurden. In Ruby ist das Auslesen der Exif-Informationen dank Exifr sehr einfach. Für C# fehlt ein klarer Favorit, was zahlreiche kleine … Exif und C#: Wege um an die GPS-Metadaten aus Bildern zu kommen weiterlesen

Lernen. Weiterbilden. Gewinnen: Bis 15. Mai 2016 u.a. eine Xbox One gewinnen - powered by QUALIERO

29.04.2016 11:35:41 | Kay Giza

Über die Learning-Plattform Qualiero.com hatte ich ja bereits im März berichtet. Die Learning-Plattform bietet ein modernes Fortbildungsangebot und bringt einen in Kontakt mit Gleichgesinnten und Experten. Bis 15. Mai 2016 hat man nun mit etwas Glück die Möglichkeit, einen der folgende Preise zu gewinnen: 1. Preis: Eine Xbox One mit 500 GB... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Guid to Int, Int32, Int64, Int128, BigInteger

28.04.2016 11:40:42 | Paul Mizel

LinqPad5 void Main() { var guid=Guid.NewGuid(); ("GUID:  "+guid).Dump(); var bigint=GuidToBigInteger(guid); var int64=GuidToInt64(guid); var int32=GuidToInt32(guid); ("HEX:    "+bigint.ToString("X")).Dump(); ("BIGINT:"+bigint).Dump(); ("INT64: "+int64).Dump(); ("INT32: "+int32).Dump(); var idFix=Guid.Parse("00000000000000000000000000000000"); idFix.Dump(); GuidToBigInteger(idFix).Dump(); ("int.MaxValue: " + int.MaxValue).Dump(); idFix=Guid.Parse("0000000000000000000000FF00FF00FF"); idFix.Dump(); var bi=GuidToBigInteger(idFix); ("BigInt:  "+bi).Dump(); var i=GuidToInt32(idFix); ("Int Mod: "+i).Dump(); Int64.MaxValue.Dump(); int.MaxValue.Dump(); Int32.MaxValue.Dump(); } public static System.Numerics.BigInteger GuidToBigInteger(Guid id) { var str=id.ToString("N"); var result=System.Numerics.BigInteger.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier); result=result>0?result:-result; if(result<int.MaxValue) { result=result+int.MaxValue; } return result; } public static Int64 GuidToInt64(Guid id) { var result=GuidToBigInteger(id); result=result%Int64.MaxValue; if(result<int.MaxValue) { result=result+int.MaxValue; } return (Int64)result; } public static Int32 GuidToInt32(Guid id) { var result=GuidToBigInteger(id); result=result%Int32.MaxValue; if(result<(Int32.MaxValue/2)) { result=result+(Int32.MaxValue/2); } return (Int32)result; }

Get the Windows 10 or 8 accent color in WPF

27.04.2016 03:55:00 |

x.

Windows Accent Color

Since Windows 8 users can choose a system accent color. The color can be seen on the window borders of the default apps and it can be pretty easy be used inside a UWP App.

How to get the accent color in WPF?

Option 1: SystemParameters.WindowGlassBrush - not 100% the same color

As far as I know there are several ways to get the color code, one easy but not 100% correct way is to use the SystemParameters.WindowGlassBrush property that was introduced in .NET 4.5.

Sadly, the color is not 100% correct - I have no idea where this “similar”, but not identical color is used and why the API is returning this color.

It seems this is just a wrapper around the undocumented DwmGetColorizationParameters Win32 API.

Option 2: GetImmersiveColorFromColorSetEx

I found this solution here, which is just a wrapper around the GetImmersiveColorFromColorSetEx Win32 API.

Option 3: Registry, DwmGetColorizationParameters

The last option would be to read the Registry values - I found some hints on this site, but I wouldn’t recommend it, because it is more or less undocumented and might break in the future. So we will use option 1 or 2.

Usage:

The usage of both options is pretty easy (at least with the option 2 code provided) :

    // https://gist.github.com/paulcbetts/3c6aedc9f0cd39a77c37
    var accentColor = new SolidColorBrush(AccentColorSet.ActiveSet["SystemAccent"]);
    this.Code.Background = accentColor;
    this.Code.Text = "AccentColorSet Immersive 'SystemAccent' " + accentColor.Color.ToString();

    // Available in .NET 4.5
    this.SystemProperties.Background = SystemParameters.WindowGlassBrush;
    this.SystemProperties.Text = "SystemParameters.WindowGlassBrush " + ((SolidColorBrush)SystemParameters.WindowGlassBrush).Color.ToString();

Result:

x.

As you can see, the lower color does match the border color instead of the first option. Crazy, right? ¯\_(ツ)_/¯

From the comments: As Yves Goergen pointed out, the resulting color does not exactly match the border color, but it does match the system accent color, which is ok. I would guess that the border has some chrome behavior attached so that the color is slightly different.

The full code is on GitHub

Hope this helps.

Sundays IT: Harddisc was going crazy

24.04.2016 14:39:36 | Sascha Baumann

Hello everyone, I have no idea how it happend, but suddenly the system harddisc on my good old Windows 7 machine went crazy. After some exploration with Resource Manager (PID: 4 – System was the bad guy) and browsing the internet I stumbled across an article about Prefetch and Superfetch. serverfault.com – system-process-pid-4-constantly-accessing-the-hard-disk Some time […]

Die Visual Studio Code-Entwickler bitten um Feedback zur Lokalisierung

22.04.2016 12:06:20 | Kay Giza

Visual Studio Code 1.0 ist noch keine Woche alt, da hat die Community rund um VS Code bereits ein neues Insiders-Update veröffentlicht. Und dieses hat es in sich. Man hat auch an der Lokalisierung gearbeitet. ie Entwickler bitten hierzu um Feedback, wie die finale Lösung ausschauen soll, eine rege Diskussion ist schon entstanden: Don't localize command names on the command palette Hier der Aufruf an alle VS Code User, beteiligt euch und gebt eure Meinung ab, je mehr desto besser... [... mehr in diesem Blogeintrag auf Giza-Blog.de]

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

Xamarin und Visual Studio

21.04.2016 16:31:55 | Kay Giza

Die Build 2016 ist zu Ende und es gab ja wirklich spannende Neuigkeiten, u.a. zu Xamarin. Die Übernahme des führenden Plattformanbieters für Mobile-App-Entwicklung wurde offiziell abgeschlossen und Microsoft hat Xamarin in Visual Studio integriert. Außerdem wurde das Xamarin SDK als Open Source veröffentlichen. Auf der Build hat Scott Guthrie in seiner Keynote auch über die weitere Zukunft von Xamarin gesprochen. Weitere Details erfährt man... [... in diesem Blogeintrag auf Giza-Blog.de]

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

An update to the ASP.NET Core & Angular2 series

17.04.2016 21:00:00 | Jürgen Gutsch

There was a small but critical mistake in the last series about ASP.NET Core and Angular2. Debugging in the Browser is not possible the way I configured the solution. Fortunately it is pretty simple to fix this problem.

Modern web browsers support debugging typescript sources while running JavaScript. This is a pretty useful browser magic. This works, because there is a mapping file, which contains the info about which line of JavaScript points to the specific line in the TypeScript file. This mapping file is also created by the TypeScript compiler and stored in the output folder.

In my blog series about ASP.NET Core and Angular2, I placed the TypeScript file in a folder called scripts in the root of the project, but outside the wwwroot folder. This was a mistake, because the browsers found the JavaScript and the mapping files, but they didn't find the TapeScript files. Debugging in the browser was not possible with this configuration.

To fix this, I copied all the files inside the scripts folder to the folder /wwwroot/app/

I also needed to change the "outDir" in the tsconfig.json to point to the current directory:

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "commonjs",
    "noEmitOnError": true,
    "noImplicitAny": false,
    "outDir": "./",
    "removeComments": false,
    "sourceMap": true,
    "target": "es5"
  },
  "exclude": [
    "node_modules"
  ]
}

The result looks like this now:

My first Idea was to separate the sources from the output, but I forgot about client side debugging of the TypeScript sources. By making the TypeScript file available to the browsers, I' now able to debug TypeScript in the browsers:

Thanks to Fabian Gosebrink, who points me to that issue. We discussed about that, when we was on the way to the Microsoft Community Open Day 2016 (COD16) in Munich this year.

Slides von den ALM Days 2016

15.04.2016 10:42:00 | Jörg Neumann

Hier die Slides zum Talk "DevOps als Turbo für die Mobile-App-Entwicklung", den ich zusammen mit Neno Loje auf den ALM Days 2016 gehalten habe:

Microsoft veroeffentlicht Visual Studio Code 1.0 // Ein kostenloser Code-Editor

14.04.2016 20:14:42 | Kay Giza

Soeben hat Microsoft die Version 1.0 von Visual Studio Code (VS Code) veröffentlich! Nachdem wir im Mai 2015 die erste Puplic Preview veröffentlich haben, im November 2015 die erste Beta, vermeldet Microsoft jetzt 2 Millionen Installationen. Heute am 14. April erscheint Visual Studio Code 1.0! VS Code ist kostenlos und unterstützt u.a. JavaScript, TypeScript, C++, HTML, CSS, C#, Python, PHP, F#, Node.js, JSON, Go... [… mehr Informationen in diesem Blogeintrag auf Giza-Blog.de]

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

ASP.​NET Core and Angular2 - Part 3

13.04.2016 21:00:00 | Jürgen Gutsch

In the second part of this ASP.NET Core and Angular2 series, I wrote about the back-end to provide the data to the Angular2 Application. In this third part, I'm going to show you how the app is structured and how I used routing to navigate between the different components.

The components

Components in Angular2 in general are ordered hierarchically. You have a root component which is bootstrapped in the HTML page and which hosts the app. As you can see in part one of this series, the index.html calls the app bootstrap and the bootstrap method gets the AppComponent passed in.

I created five sub-components for the INETA Database:

  1. Dashboard to quick access some most used features
  2. The speakers area
  3. The user groups area
  4. The events area
  5. And the newsletter management

Except the dashboard, all of this sub-components also have sub-components for the CRUD operations:

  1. List
  2. Detail
  3. Add
  4. Edit

(It's not CRUD, but CRU: create, read, update. Delete an item doesn't need a separate view or a separate component.)

With this structure we get a hierarchy of three levels:

Templates used

Level 1 and level 2 doesn't contain any logic. The classes are completely empty. Only the AppComponent, the Dashboard and all of the third level components need a detailed view. The AppComponent view provides the main navigation and a <router-outlet> directive to place the result of the routing. The Dashboard contains a link list to the most used feature. And all of the third level components use a detailed template.

@Component({
    selector: 'speakers-list',
    templateUrl: 'app/speaker/speakers-list.template.html',
    directives: [
        ROUTER_DIRECTIVES
    ],
    providers: [SpeakerService, HTTP_PROVIDERS]
})
export class SpeakersListComponent implements OnInit {
	// add logic here
}

The other second level components have an inline template, which is just the <router-outlet> directive to place the results of their routes:


@Component({
    selector: 'speakers',
    template: `
    <router-outlet></router-outlet>
    `,
    directives: [
        ROUTER_DIRECTIVES
    ]
})
export class SpeakersComponent { } // doesn't need any logic here

All the detail templates are in separate HTML files, which are directly stored in the /wwwroot/app/ folder in a similar sub folder structure than the components.

routing

Since I'm planning a single page application (SPA) it is pretty clear that I should use routing to navigate between the different areas.

The routes between the second level components are defined in the AppComponent:

// ...

import {Dashboard} from './Dashboard/dashboard.component';
import {SpeakersComponent} from './Speaker/speakers.component';
import {UsergroupsComponent} from './Usergroup/usergroups.component';
import {EventsComponent} from './Event/events.component';
import {NewsletterComponent} from './Newsletter/newsletters.component';

@Component({
    // ...
})
@RouteConfig([
    { path: '/Dashboard', name: 'Dashboard', component: Dashboard, useAsDefault: true },
    { path: '/Speakers/...', name: 'Speakers', component: SpeakersComponent },
    { path: '/Usergroups/...', name: 'Usergroups', component: UsergroupsComponent },
    { path: '/Events/...', name: 'Events', component: EventsComponent },
    { path: '/Newsletter/...', name: 'Newsletter', component: NewsletterComponent },
])
export class AppComponent {}

The route to the dashboard is configured as the default route. With this configuration the URL in the browsers address bar changes immediately to /dashboard when I call this app. The other routes contain three dots (/...) in the path. This is needed, because I want to configure child-routing in the second level components, otherwise child-routing is not possible. All the routes are named and bound to a component. In the templates, the links to the different app areas are created by using the routes with their names:

<ul class="nav navbar-nav">
    <li><ahttp://feedproxy.google.com href="" [routerLink]="['Speakers']">Speakers</a></li>
    <li><ahttp://feedproxy.google.com href="" [routerLink]="['Usergroups']">Usergroups</a></li>
    <li><ahttp://feedproxy.google.com href="" [routerLink]="['Events']">Events</a></li>
    <li><ahttp://feedproxy.google.com href="" [routerLink]="['Newsletter']">Newsletter</a></li>
</ul>

Inside the second level child-components, I need to access the third level components. This is why I need to configure child-routing inside this components. This child-routing looks a little bit different, because I need to pass entity identifiers to the detail view, or to the edit view component:

// ..

import {SpeakersListComponent} from './speakers-list.component';
import {SpeakersDetailComponent} from './speakers-detail.component';
import {SpeakersEditComponent} from './speakers-edit.component';
import {SpeakersAddComponent} from './speakers-add.component';

@Component({
    // ...
})
@RouteConfig([
    { path: '/', name: 'SpeakersList', component: SpeakersListComponent, useAsDefault: true },
    { path: '/:id', name: 'Speaker', component: SpeakersDetailComponent },
    { path: '/Add', name: 'NewSpeaker', component: SpeakersAddComponent },
    { path: '/Edit/:id', name: 'EditSpeaker', component: SpeakersEditComponent }
])
export class SpeakersComponent { }

The :id tells the route engine, that this is a named placeholder, where we can pass any value (This looks familiar, if you know the ASP.NET MVC routing). The routes are named and bound to the third level components. In this case, the routes to the list components are configured as default routes.

Using the routes in the templates of the specific component, where the route is configured is as easy as shown in the code samples above. But how does it look like, if I need to use a route outside the current context? From the dashboard, I directly want to link to the components to add new entities.

If you carefully read the documentation, you'll see that you can use the herarchy of the reoutes to use it:

<div class="list-group">
    <ahttp://feedproxy.google.com href="" [routerLink]="['Speakers', 'NewSpeaker']" class="list-group-item">Neuen Speaker anlegen</a>
    <ahttp://feedproxy.google.com href="" [routerLink]="['Usergroups', 'NewUsergroup']" class="list-group-item">Neue Usergroup anlegen</a>
    <ahttp://feedproxy.google.com href="" [routerLink]="['Events', 'NewEvent']" class="list-group-item">Neues Event anlegen</a>
    <ahttp://feedproxy.google.com href="" [routerLink]="['Newsletter', 'NewNewsletter']" class="list-group-item">Neuen Newsletter anlegen</a>
</div>

The syntax is like this:

['base-route-name', 'child-route-name', 'grant-child-route-name', 'and-so-on-route-name']

The templates

Each of the third level components (even the Dashboard and the root component) are using detailed templates stored in HTML files in the /wwwroot/app/ folder in the same structure as the TypeScript files in the scripts folder. After compiling the TypeScript code, the transpiled JavasSripts are directly beneath the templates:

I don't want to go deep into the templates and binding stuff, but only show you two of the templates. For more details about the bindings, just visit the Angular2 documentation on http://angular.io/

This is the template of the speakers list:

<h1>All speakers</h1>

<div class="row">
    <div class="col-md-12">
        <ul class="list-group">
            <li class="list-group-item">
                <span>&nbsp;</span>
                <ahttp://feedproxy.google.com href="" [routerLink]="['NewSpeaker']" 
                    class="btn btn-primary btn-xs pull-right">
                    Add new speaker
            </a>
            </li>
            <li *ngFor="#speaker of speakers" class="list-group-item">
                <ahttp://feedproxy.google.com href="" [routerLink]="['Speaker', {id: speaker.Id}]">
                     
                </a>
                <ahttp://feedproxy.google.com href="" class="btn btn-danger btn-xs pull-right">
                    Delete
                </a>
                <ahttp://feedproxy.google.com href="" [routerLink]="['EditSpeaker', {id: speaker.Id}]" 
                    class="btn btn-primary btn-xs pull-right">
                    Edit
                </a>
            </li>
            <li class="list-group-item">
                <span>&nbsp;</span>
                <ahttp://feedproxy.google.com href="" [routerLink]="['NewSpeaker']" 
                    class="btn btn-primary btn-xs pull-right">
                    Add new speaker
                </a>
            </li>
        </ul>
    </div>
</div>

This templates shows mustache syntax to write out the values of the FirstName and the LastName. This is called "interpolation" and it is a one way binding in the direction from the component to the template.

This templates also uses the routing to create link to the edit view or to the add view. You'll also find the *ngFor, which is the same as the old ng-for. It defines a template to repeat for each item of the speakers. That item will be directly assigned to the variable #speaker

The concepts here are pretty similar to old Angular.JS. Because of the new binding concept, the forms are a bit different:

<h1>Edit speaker</h1>

<form class="form-horizontal">
    <div class="form-group">
        <label for="FirstName" class="col-sm-2 control-label">Firstname</label>
        <div class="col-sm-10">
            <input id="FirstName" class="form-control" 
                [(ngModel)]="speaker.FirstName" />
        </div>
    </div>
    <div class="form-group">
        <label for="LastName" class="col-sm-2 control-label">LastName</label>
        <div class="col-sm-10">
            <input id="LastName" class="form-control" 
                [(ngModel)]="speaker.LastName" />
        </div>
    </div>

    <!-- some more fields here-->

    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <a class="btn btn-default"http://feedproxy.google.com href="" 
                [routerLink]="['Speaker', {id: speaker.Id}]">Cancel</a>
            <button type="submit" class="btn btn-primary" 
                (click)="saveSpeaker(speaker)">Save</button>
        </div>
    </div>
</form>

In this template we use different types of binding. The "banana in the box" syntax ([()] called like this by John Papa) defines a two-way binding, which should to be used in forms, to send the users input to the component. For the events we have a one-way binding from the template to the component. This direction is only used for events like this. This is used on the save button.

Conclusion

I'm not completely done with the implementation currently. But I was pretty surprised about how fast I got a running app. Development is pretty fast with Angular2 and you get the first results faster than using the old Angular.JS. Even TypeScript is cool and feels familiar to a C# developer. I'm looking foreward to do a real project with Angular2, TypeScript and ASP.NET Core.

To learn more about the data binding, read excellent the tutorials on http://angular.io/. Another great resource to learn more about Angular2, are the video courses by John Papa on PluralSight.

If you want to go to the details of the INETA Database, please have a look into the GitHub Repository.

ASP.​NET Core and Angular2 - Part 2

11.04.2016 21:00:00 | Jürgen Gutsch

In the last post, I prepared a ASP.NET Core project to use and build TypeScript and to host a Angular2 single page application. Now, in this second part of the ASP.NET Core and Angular2 series, I'm going to prepare the ASP.NET Core Web API to provide some data to Angular2.

I really like to separate the read and the write logic, to optimize the read and the write stuff in different ways and to keep the code clean and simple. To do this I use the "Command & Query Segregation" pattern and a small library I wrote, to support this pattern. This library provides some interfaces, a QueryProcessor to delegate the queries to the right QueryHandler and a CommandDispatcher to get the right CommandHandler for the specific command.

I also like to use the Azure Table Storage, which is a pretty fast NoSQL storage. This makes sense for the current application, because the data wont change so much. I 'll write one or two newsletter per month. I add maybe three events per month, maybe two user groups per year and maybe one speaker every two months. I'll use four tables in the Azure Table Storage: Newsletters, Speakers, Usergroups and Events. The Events table is more like a relation table between the user group and a speaker, containing the date, a title and a short description. This is not an event database for all of the user group events, but a table to store the events, we have to pay travel expenses for the specific speaker.

I'll write a little more in detail about the "Command & Query Segregation" and the Azure Table Storage Client in separate posts. In this post, you'll see the IQueryProcessor and the ICommandDispatcher used in the API controller and simple Query and Command classes which are passed to that services. The queries and the commands will be delegated to the right handlers, which I need to implement and which will contain my business logic. Please look in the GitHub repository to see more details about the handlers. (The details about getting the data from the data source is not really relevant in this post. You are able to use use any data source you want.)

This CQS engine is configured in the Startup.cs by calling services.AddCqsEngine();

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

Registering the handlers in this lambda is optional, but this groups the registration a little bit. I'm also able to register the Handlers directly on the services object.

The methods used to register the Handlers are ExtensionMethods on the ServiceCollection, to keep the Startup.cs clean. I do all the handler registrations in this ExtensionMethod:

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

        services.AddTransient<IHandleQueryAsync<AllEventsQuery, IEnumerable<Event>>, AllEventsQueryHandler>();
        services.AddTransient<IHandleQueryAsync<EventByIdQuery, Event>, EventByIdQueryHandler>();

        // and many more registrations
        
        return services;
    }
}

The Web API

To provide the fetched data to the Angular2 SPA, I want to use a Web API which is now completely included in ASP.NET Core MVC. Right click the Controllers folder and add a new item. Select "Server-side" and than the "Web API Controller Class". I called it SpeakersController:

[Route("api/[controller]")]
public class SpeakersController : Controller
{
    private readonly IQueryProcessor _queryProcessor;
    private readonly ICommandDispatcher _commandDispatcher;

    public SpeakersController(
        IQueryProcessor queryProcessor,
        ICommandDispatcher commandDispatcher)
    {
        _queryProcessor = queryProcessor;
        _commandDispatcher = commandDispatcher;
    }

    [HttpGet]
    public async Task<IEnumerable<Speaker>> Get()
    {
        var query = new AllSpeakersQuery();
        var speakers = await _queryProcessor.ProcessAsync(query);
        return speakers;
    }

    [HttpGet("{id}")]
    public async Task<Speaker> Get(Guid id)
    {
        var query = new SpeakerByIdQuery(id);
        var speakers = await _queryProcessor.ProcessAsync(query);
        return speakers;
    }

    [HttpPost]
    public async void Post([FromBody]Speaker value)
    {
        var command = new InsertSpeakerCommand(value);
        await _commandDispatcher.DispatchCommandAsync(command);
    }
        
    [HttpPut("{id}")]
    public async void Put(int id, [FromBody]Speaker value)
    {
        var command = new UpdateSpeakerCommand(id, value);
        await _commandDispatcher.DispatchCommandAsync(command);
    }
        
    [HttpDelete("{id}")]
    public async void Delete(int id)
    {
        var command = new DeleteSpeakerCommand(id);
        await _commandDispatcher.DispatchCommandAsync(command);
    }
}

As you can see in the Controller, I injected a IQueryProcessor and a ICommandDispatcher and I use this services by creating a query or a commend and passed it to the DispatchAsync or ProcessAsync methods

The client side

Ho does it look like to access the Web APIs with Angular2?

First I need to create a service in Angular2. This Service is also a component and exactly this is what I really love with Angular2: Everything is a component and just needs to be stacked together :)

I create a Angular2 service for every entity in the project. First I need to import some Angular2 modules:

  • Http is to call remote resources.
  • Headers need to be send additionally to the server.
  • And we need to work with Responses and RequestsOptions.
  • We get an Observable type from the Http service
  • and we have to import our Speaker type:
import {Injectable, Component} from 'angular2/core';
import {Http, Response, HTTP_PROVIDERS, Headers, RequestOptions} from 'angular2/http';
import {Observable} from 'rxjs/Observable';

import {Speaker} from './speaker';

@Component({
    providers: [Http]
})
@Injectable()
export class SpeakerService {

    constructor(private _http: Http) { }

    private _speakersUrl: string = '/api/speakers/';

	// methods to access the data
}

The Http service gets injected via the constructor and can be used like this:

getSpeakers() {
    let data: Observable<Speaker[]> = this._http.get(this._speakersUrl)
        .map(res => <Speaker[]>res.json())
        .catch(this.handleError);

    return data;
}

getSpeaker(id: string) {
	let data: Observable<Speaker> = this._http.get(this._speakersUrl + id)
        .map(res => <Speaker>res.json())
        .catch(this.handleError);

    return data;
}

private handleError(error: Response) {
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');
}

In both public methods we return an Observable object, which needs special handling in the specific consuming component, because all requests to the server are async. To consume the data, I need to subscribe to that Observable:

this._speakerService.getSpeakers()
    .subscribe(
        speakers => this.speakers = speakers,
        error => this.errorMessage = <any>error);

Subscribe calls the first delegate in case of success and assigns the speaker to the property of the current component. In case of errors the second delegate is executed and the error object gets assigned to the error property.

This is how a complete Angular2 speaker list component looks like:

import {Component, OnInit} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
import {ROUTER_DIRECTIVES} from 'angular2/router';

import {Speaker} from './speaker';
import {SpeakerService} from './speaker.service';

@Component({
    selector: 'speakers-list',
    templateUrl: 'app/speaker/speakers-list.template.html',
    directives: [
        ROUTER_DIRECTIVES
    ],
    providers: [SpeakerService, HTTP_PROVIDERS]
})
export class SpeakersListComponent implements OnInit {

    constructor(private _speakerService: SpeakerService) { }

    speakers: Speaker[];
    errorMessage: any;

    ngOnInit() {
        this._speakerService.getSpeakers()
            .subscribe(
                speakers => this.speakers = speakers,
                error => this.errorMessage = <any>error);
    }
}

To save an entity, I use the post or put method on the Http object, I need to specify the content type and to add the data to the body:

saveSpeaker(speaker: Speaker) {

    let body = JSON.stringify(speaker);

    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    let temp = this._http.post(this._speakersUrl, body, options)
        .map(res => console.info(res))
        .catch(this.handleError);
}

Conclusion

That's about how I provide the data to the client. Maybe the CQS part is not really relevant for you, but this is the way how I usually create the back-ends in my personal projects. The important part is the Web API and only you know the way how you need to access your data inside your API Controller. ;)

In the next blog post, I'm going to show you how I organize the Angular2 app and how I use the Angular2 routing to navigate between different components.

Vielen Dank / Thank you for 3000 followers on Twitter!

11.04.2016 14:33:13 | Kay Giza

Thank you very much for 3000 followers on Twitter (@KayGiza) and @karolikl for being my 3000 follower!

Thank you very much for 3000 followers on twitter!



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

Download for free! eBook: Visual Studio Code - Tips and Tricks Vol. 1 (Englisch/German)

06.04.2016 14:24:50 | Kay Giza

It is my pleasure to announce the first version of our 'Visual Studio Code - Tips and Tricks Vol. 1' eBook. In this tips & tricks eBook, we collected more than 30 tips and explain them in great detail. Starting from our favorite keyboard shortcuts, configuration tips, command line parameters to changing the language of the interface of VS Code, you can find dozens of tips and tricks in this free eBook...

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

Regeln | Impressum