.
Anmeldung | Registrieren | Hilfe

.NET-Blogs Archiv April 2016

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

30.04.2016 09: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 09: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 09: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; }

Die Visual Studio Code-Entwickler bitten um Feedback zur Lokalisierung

22.04.2016 10: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 14: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 19: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.

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

14.04.2016 18: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 19:00:00 | Jürgen Gutsch

Important Note: This blog series is pretty much out of date. It uses an older beta version of Angular2 and the RC2 release of ASP.NET Core. Please have a look int the new posts about Angular2 and ASP.NET Core using the latest versions:

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><a href="" [routerLink]="['Speakers']">Speakers</a></li>
    <li><a href="" [routerLink]="['Usergroups']">Usergroups</a></li>
    <li><a href="" [routerLink]="['Events']">Events</a></li>
    <li><a 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">
    <a href="" [routerLink]="['Speakers', 'NewSpeaker']" class="list-group-item">Neuen Speaker anlegen</a>
    <a href="" [routerLink]="['Usergroups', 'NewUsergroup']" class="list-group-item">Neue Usergroup anlegen</a>
    <a href="" [routerLink]="['Events', 'NewEvent']" class="list-group-item">Neues Event anlegen</a>
    <a 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>
                <a 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">
                <a href="" [routerLink]="['Speaker', {id: speaker.Id}]">
                     
                </a>
                <a href="" class="btn btn-danger btn-xs pull-right">
                    Delete
                </a>
                <a 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>
                <a 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" 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 19:00:00 | Jürgen Gutsch

Important Note: This blog series is pretty much out of date. It uses an older beta version of Angular2 and the RC2 release of ASP.NET Core. Please have a look int the new posts about Angular2 and ASP.NET Core using the latest versions:

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 12: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 12: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

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

06.04.2016 11:50:19 | Kay Giza

Ich habe wieder eine Liste aller verfügbaren Extensions (wie schreibe ich Extensions?) für Visual Studio Code erstellt: Stand 06.04.2016. Natürlich kann man auch im Visual Studio Marketplace schauen oder in Visual Studio Code selber via F1 und 'ext install' und sich die nützlichsten Extensions heraussuchen. Da es die eben 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 Februar gab es im März rund 100 neue Extensions... [... 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

BUILD 2016 - ein Ueberlick der News - was gab es fuer Neuigkeiten?

06.04.2016 09:57:18 | Kay Giza

Leider war ich letzte Woche krank und habe somit natürlich einige News und Infos verpasst zu kommunizieren :-) Das möchte ich hier nachholen, kurz und knapp! Die Build ist ja die wichtigste Entwicklerkonferenz von Microsoft und ist vor wenigen Tagen zu Ende gegangen. Bei zwei Keynotes und jeder Menge weiterer Vorträge, die allesamt als Aufzeichnungen auf Channel 9 zur Verfügung stehen, gab es viele große und kleine Neuerungen sowie interessante technische Einblicke. Mich persönlich haben drei Sachen sehr beschäftigt... [... mehr 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 1

03.04.2016 19:00:00 | Jürgen Gutsch

Important Note: This blog series is pretty much out of date. It uses an older beta version of Angular2 and the RC2 release of ASP.NET Core. Please have a look int the new posts about Angular2 and ASP.NET Core using the latest versions:

The last weeks I played around with Angular2 in a ASP.NET Core application. To start writing Angular 2 components, it needs some preparation. In the first part of this small Angular2 series I'm going to show you how to prepare your project to start working with Angular2.

Since I'm one of the leads of INETA Germany and responsible for the speakers and the user groups, I need a small tool to manage the speakers, the groups and the events where the speakers are talking. I also want to manage and send some newsletters to the speakers and the groups.

Sure, I could use Excel and Outlook, but it seems to be too easy and I need some new challenges. This is why I want to write a small INETA Admin tool, using ASP.NET Core, Typescript and Angular 2. Maybe later I'll host it on an Azure WebSite. This is why I want to prepare the Application to work on Azure.

Prerequisites

I try to create a real single page application (SPA) what is really easy with Angular2. This is why I create an empty ASP.NET Project without any controllers, views and other stuff in it. It only contains a Startup.cs project.json and a Project_Readme.html. I'll create some API Controllers later on to provide some data to Angular2

In this and in future posts, I use some interfaces from a small library, which I always use to connect to Azure Table Storage. The first interface is the IItem to mark objects as an object to use in a GenericTableEntity. The other interface is the ITableClient which is something similar to the EntityContext, to connect to the Azure Table Storage and read objects out of it. In this posts I'll just use a mock of that interface, which will provide objects generated by GenFu.

Let's start

Lets create a new empty ASP.NET Core project. We don't need any views, but just a single Index.html in the wwwroot folder. This file will be the host of our single page application.

The nuGet dependencies

We also need some NuGet dependencies in our project:

"dependencies": {
  "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
  "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
  "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
  "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
  "Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final",
  "Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final",
  "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
  "Microsoft.Extensions.Logging": "1.0.0-rc1-final",
  "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
  "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final",
  "GenFu": "1.0.4",
  "Gos.Tools.Azure": "1.0.0-*",
  "Gos.Tools.Cqs": "1.0.0-*"
},

We need MVC just for the Web API to provide the data. The StaticFiles library is needed to serve the Index.html and all the CSS, images and JavaScript files to run the SPA. We also need some logging and configuration.

  • GenFu is just used to generate some mock data.
  • Gos.Tools.Azure is the already mentioned Azure library to wrap the connection to the Azure Table Storage.
  • Gos.Tools.Cqs is a small library which provides the infrastructure to use the "Command & Query Segregation" pattern in your app. This three libraries are not yet relevant for the part one of this series.

Prepare the Startup.cs

To get the static files (Index.html, CSS, images and JavaScripts) we need to add the needed MiddleWares

app.UseDefaultFiles();
app.UseStaticFiles();

app.UseMvcWithDefaultRoute();

We also need to add MVC with the default routes to activate the Web PI. Because we'll use attribute routing, we don't need to configure a special routing here.

To enable Angular2 routing and deep links in our SPA, we need a separate error handling: In case of any 404 Exception we need to call the Index.html because the called URL could be a Angular2 route. We need to ensure the SPA host (index.html) is called to handle that route:

app.Use(async (context, next) =>
{
    await next();

    if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
    {
        context.Request.Path = "/index.html"; // Put your Angular root page here 
        await next();
    }
});

This code sets the requested path to the index.html, in case we get an 404 status and if there's no call to a file (!Path.HasExtension()) and than we start the pipeline again.

I placed this code before the previously mentioned MiddleWares to provide the static files.

I also need to add MVC to the services in the ConfigureServices method:

services.AddMvc();

bower dependencies

To get a pretty nice looking application I want to use bootstrap. I add a new bower configuration to the project:

{
  "name": "ASP.NET",
  "private": true,
  "dependencies": {
    "bootstrap": "3.3.6",
    "jquery": "2.2.2"
  }
}

After saving this file Visual Studio 2015 starts downloading the dependencies.

NPM dependencies

Now we need to add Angular2 and its dependencies and gulp to prepare our scripts. To do this, I added a NPM configuration file called package.json:

{
  "version": "1.0.0",
  "name": "ASP.NET",
  "private": true,
  "dependencies": {
    "angular2": "2.0.0-beta.11",
    "systemjs": "0.19.24",
    "es6-promise": "3.1.2",
    "es6-shim": "0.35.0",
    "reflect-metadata": "0.1.3",
    "rxjs": "5.0.0-beta.3",
    "zone.js": "0.6.5"
  },
  "devDependencies": {
    "gulp": "3.9.1",
    "gulp-concat": "2.6.0",
    "gulp-cssmin": "0.1.7",
    "gulp-uglify": "1.5.3",
    "rimraf": "2.5.2"
  }
}

BTW: If you add a new file in Visual Studio, you can easily select predefined files for client side techniques in the "add new items" dialog:

Visual Studio 2015 also starts downloading the dependencies just after saving the file. NPM needs some more time to download all the dependencies.

Preparing the JavaScripts

Bower will load the dependencies into the lib folder in the wwwroot. NPM stores the files outside the wwwroot in the Node_Modules. We want to move just the needed files to the wwwroot, too. To get this done we use Gulp. Just create a new gulpfile.js with the "add new items" dialog and add the following lines in it:

/*
This file in the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
*/

var gulp = require('gulp');

gulp.task('default', function () {
    // place code for your default task here
});

var paths = {};
paths.webroot = "wwwroot/";
paths.npmSrc = "./node_modules/";
paths.npmLibs = paths.webroot + "lib/npmlibs/";

gulp.task("copy-deps:systemjs", function () {
    return gulp.src(paths.npmSrc + '/systemjs/dist/**/*.*', { base: paths.npmSrc + '/systemjs/dist/' })
         .pipe(gulp.dest(paths.npmLibs + '/systemjs/'));
});

gulp.task("copy-deps:angular2", function () {
    return gulp.src(paths.npmSrc + '/angular2/bundles/**/*.js', { base: paths.npmSrc + '/angular2/bundles/' })
         .pipe(gulp.dest(paths.npmLibs + '/angular2/'));
});

gulp.task("copy-deps:es6-shim", function () {
    return gulp.src(paths.npmSrc + '/es6-shim/es6-sh*', { base: paths.npmSrc + '/es6-shim/' })
         .pipe(gulp.dest(paths.npmLibs + '/es6-shim/'));

});
gulp.task("copy-deps:es6-promise", function () {
    return gulp.src(paths.npmSrc + '/es6-promise/dist/**/*.*', { base: paths.npmSrc + '/es6-promise/dist/' })
         .pipe(gulp.dest(paths.npmLibs + '/es6-promise/'));
});

gulp.task("copy-deps:rxjs", function () {
    return gulp.src(paths.npmSrc + '/rxjs/bundles/*.*', { base: paths.npmSrc + '/rxjs/bundles/' })
         .pipe(gulp.dest(paths.npmLibs + '/rxjs/'));
});

gulp.task("copy-deps", ["copy-deps:rxjs", 'copy-deps:angular2', 'copy-deps:systemjs', 'copy-deps:es6-shim', 'copy-deps:es6-promise']);

Now you can use the Task Runner Explorer in Visual Studio 2015 to run the "copy-deps" task to get the files to the right location.

Preparing the Index.html

In the header of the Index.html we just need a meaningfull title, a base href to get the Angular routing working and a refernce to the bootstrap css:

<base href="/" />
<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.css" />

At the end of the body we need a little more. Add the following JavaScript references:

<script src="lib/npmlibs/es6-shim/es6-shim.js"></script>
<script src="lib/npmlibs/es6-promise/es6-promise.js"></script>
<script src="lib/npmlibs/systemjs/system-polyfills.src.js"></script>
<script src="lib/npmlibs/angular2/angular2-polyfills.js"></script>
<script src="lib/npmlibs/systemjs/system.src.js"></script>
<script src="lib/npmlibs/rxjs/Rx.js"></script>
<script src="lib/npmlibs/angular2/angular2.js"></script>
<script src="lib/npmlibs/angular2/router.js"></script>
<script src="lib/npmlibs/angular2/http.js"></script>
<script src="lib/jquery/dist/jquery.js"></script>
<script src="lib/bootstrap/dist/js/bootstrap.js"></script>

After that, we have to add some configuration and to initialize our Angular2 app:

<script>
    System.config({
        packages: {
            'app': { defaultExtension: 'js' },
            'lib': { defaultExtension: 'js' },
        }
    });

    System.import('app/boot')
        .then(null, console.error.bind(console));
</script>

This code calls a boot.js in the folder app inside the wwwroot. This file is the Angular2 bootstrap we need to create later on.

Just after the starting body, we need to call the directive of our first Angular2 component:

<my-app>Loading...</my-app>

The string "Loading..." will be displayed until the Angular2 app is loaded. I'll show the Angular2 code a little later.

Configure TypeScript

Since the AngularJS team is using TypeScript to create Angular2, it makes a lot sence to write the app using TypeScript instead of plain JavaScript. TypeScript is an superset of JavaScript to use future technologies. TypeScript will be transpiled (translated/compiled) to JavaScript while compiling the entire application, if the TypeScript support in Visual Studio 2015 is enabled.

In some tutorials they proposed to store the TypeScript files in the wwwroot to. I prefer to work in a separate Scripts folder outside the wwwroot and to transpile the JavaScripts into the wwwroot/app folder. To do this we need a TypeScript configuration called tsconfig.json. This file tells the TypeScript compiler how to compile where to place the results:

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

I placed this file in a folder called scripts which is in the root of the project. I will add all the TypeScript files inside this folder.

Enable ES6

To use Ecma-Script 6 features in TypeScript we need to add the es6-shim definition to the scripts folder. Just download it from the DefinitelyTyped repository on GitHub.

That's pretty much it to start working with Angular2, TypeScript and ASP.NET Core. We haven't seen very much ASP.NET Core stuff until yet, but we will see some more things in one of the next posts about it.

Let's create the first app.

No we have the project set up, to write write Angular2 components using TypeScript and to use the transpiled code in the Index.html, which hosts the app.

As already mentioned we first need to bootstrap the application. I did this by creating a file called boot.ts inside the scripts folder. This files contains just four lines of code:

///<reference path="../node_modules/angular2/typings/browser.d.ts"/>
import {bootstrap}              from 'angular2/platform/browser'
import {AppComponent}           from './app'

bootstrap(AppComponent);

It references and imports the angular2/plattform/browser component and the AppComponent which needs to be created in the next step.

The last line starts the Angular2 App by passing the root component to the bootstrap method.

The AppComponent is in another TypeScript file called app.ts:

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<p>{​{Title}​}</p>'
})
export class AppComponent {
    Title: string;

    constructor() {
        this.Title = 'Hello World';
    }    
}

This pretty simple component just defines the directive we already used in the Index.html and it contains a simple template. Instead if the string "Loading..." we should see the "Hello World" in the browser after compiling and running the application.

Pressing F5 should compile the ASP.NET Core application and transpile the TypeScript code. In case of compilation errors, we will see the TypeScript errors too. This is very helpful.

If the compilation is done and we still don't see any results, we should have a look into the development console in the browser. Angular2 logs pretty detailed information about problems on the client.

Conclusion

This is just a simple "Hello World" example, but this will show you whether the configuration is working or not.

If this is done and if all is working we can start creating some more complex things. But let me show this in another blog post.

Regeln | Impressum