Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC...

12
20 FEATURE 1/2014 Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5 will das Erstellen von modernen Webanwendungen nach dem Model-View-Controller-Entwurfsmuster vereinfachen. Von Sebastian Eschweiler ves Gespann in Webprojekten eingesetzt wer- den kann. Zum Zeitpunkt der Erstellung dieses Artikels steht die Version 5 von ASP.NET MVC als Re- lease Candidate zur Verfügung. Als Entwick- lungsumgebung haben Sie daher die Wahl zwi- schen Visual Studio 2013 RC oder Visual Studio Express 2013 RC for Web. Die beiden Versionen können über www.mi crosoft.com/visualstudio/eng/2013-downloads #d-2013-express heruntergeladen werden. Für die weiteren Programmbeispiele in diesem Ar- tikel kommt die Express-Version der Entwick- lungsumgebung zum Einsatz. Nach der Installation präsentiert sich die Ent- wicklungsumgebung so, wie in Bild 1 zu sehen. Den Zugriff auf die ASP.NET- MVC-5-Projektvorlagen er- halten Sie über den Link Neu- es Projekt. Im sich öffnenden Dialogfenster haben Sie in der Baumstruktur auf der linken Seite zunächst die Wahl zwi- schen Visual Basic und C# als Programmiersprache. Für die nachfolgenden Code-Beispie- le werden wir die C#-Varian- te verwenden. Unterhalb des Visual-C#-Knotens steht die G epaart mit den clientseitigen Möglichkeiten des JavaScript-Frameworks AngularJS las- sen sich in kürzester Zeit beeindruckende Er- gebnisse erzielen. Eine erste Einführung bietet Ihnen das nachfolgende Tutorial. Seit Version 1 des ASP.NET MVC-Frame- works hat sich viel getan, und so bietet auch die neue Version 5 Funktionen, die die Entwick- lung moderner Webanwendungen vereinfa- chen und weiter beschleunigen. Die neuen Pro- jektvorlagen basieren durchgängig auf dem be- kannten Bootstrap-UI-Framework und bringen so bereits im Standard alle Hilfsmittel mit, um Webanwendungen für die Darstellung auf un- terschiedlichen Endgeräten vorzubereiten und ein Responsive Design umzusetzen. Da es sich bei ASP.NET MVC um ein server- seitiges Framework handelt, besteht oftmals die Notwendigkeit, ein weiteres clientseitiges Java- Script-Framework zu integrieren, um die ge- wünschte Dynamik innerhalb der Webseite zu realisieren und zusätzlich die Kommunikations- abläufe mit dem Server auf ein Minimum zu re- duzieren. Google stellt hierzu das Open-Source- Framework AngularJS bereit. Die JavaScript-Bibliothek ist ebenfalls darauf ausgelegt, nach dem MVC-Entwurfsmuster an- gewendet zu werden. AngularJS bietet daher auf Seiten des Clients eine optimale Ergänzung zum serverseitigen ASP.NET MVC. Erste Schritte mit ASP.NET MVC 5 In den folgenden Abschnitten erhalten Sie da- her eine praktische Einführung in beide Tech- nologien und erlernen anhand eines Beispiels, wie ASP.NET MVC und AngularJS als effekti- Sebastian Eschweiler ist IT-Berater im Bereich Product Lifecycle Management (PLM). Weiterhin beschäftigt er sich seit den Anfängen der J2ME mit mo- bilen Technologien. Aktuell lie- gen seine Schwerpunkte auf den Plattformen Android und Win- dows Phone. Seine Erfahrung in diesem Bereich gibt er in Form von Beiträgen in Fachmagazinen sowie Büchern weiter. Inhalt Responsive Web-Apps mit ASP. NET MVC 5 und AngularJS. Ressourcen Die Listings zum Artikel finden Sie auf www.webundmobile.de in der Rubrik Aktuelles Heft. AUTOR Startbildschirm von Visual Studio Express 2013 RC für das Web (Bild 1) using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MvcCustomers.Controllers { public class CustomerController : Controller { // // GET: /Customer/ public ActionResult Index() { return View(); } } } LISTING 1: NEUE KLASSE

Transcript of Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC...

Page 1: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

20

FEATURE

1/2014

Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS

Der richtige MixMicrosofts Web-Framework ASP.NET MVC Version 5 will das Erstellen von modernen Webanwendungen nach dem Model-View-Controller-Entwurfsmuster vereinfachen. Von Sebastian Eschweiler

ves Gespann in Webprojekten eingesetzt wer-den kann.

Zum Zeitpunkt der Erstellung dieses Artikels steht die Version 5 von ASP.NET MVC als Re-lease Candidate zur Verfügung. Als Entwick-lungsumgebung haben Sie daher die Wahl zwi-schen Visual Studio 2013 RC oder Visual Studio Express 2013 RC for Web.

Die beiden Versionen können über www.mi crosoft.com/visualstudio/eng/2013-downloads #d-2013-express heruntergeladen werden. Für die weiteren Programmbeispiele in diesem Ar-tikel kommt die Express-Version der Entwick-lungsumgebung zum Einsatz.

Nach der Installation präsentiert sich die Ent-wicklungsumgebung so, wie in Bild 1 zu sehen.

Den Zugriff auf die ASP.NET-MVC-5-Projektvorlagen er-halten Sie über den Link Neu-es Projekt. Im sich öffnenden Dia logfenster haben Sie in der Baumstruktur auf der linken Seite zunächst die Wahl zwi-schen Visual Basic und C# als Programmiersprache. Für die nachfolgenden Code-Beispie-le werden wir die C#-Varian-te verwenden. Unterhalb des Visual-C#-Knotens steht die

Gepaart mit den clientseitigen Möglichkeiten des JavaScript-Frameworks AngularJS las-

sen sich in kürzester Zeit beeindruckende Er-gebnisse erzielen. Eine erste Einführung bietet Ihnen das nachfolgende Tutorial.

Seit Version 1 des ASP.NET MVC-Frame-works hat sich viel getan, und so bietet auch die neue Version 5 Funktionen, die die Entwick-lung moderner Webanwendungen vereinfa-chen und weiter beschleunigen. Die neuen Pro-jektvorlagen basieren durchgängig auf dem be-kannten Bootstrap-UI-Framework und bringen so bereits im Standard alle Hilfsmittel mit, um Webanwendungen für die Darstellung auf un-terschiedlichen Endgeräten vorzubereiten und ein Responsive Design umzusetzen.

Da es sich bei ASP.NET MVC um ein server-seitiges Framework handelt, besteht oftmals die Notwendigkeit, ein weiteres clientseitiges Java-Script-Framework zu integrieren, um die ge-wünschte Dynamik innerhalb der Webseite zu realisieren und zusätzlich die Kommunikations-abläufe mit dem Server auf ein Minimum zu re-duzieren. Google stellt hierzu das Open-Source-Framework AngularJS bereit.

Die JavaScript-Bibliothek ist ebenfalls darauf ausgelegt, nach dem MVC-Entwurfsmuster an-gewendet zu werden. AngularJS bietet daher auf Seiten des Clients eine optimale Ergänzung zum serverseitigen ASP.NET MVC.

Erste Schritte mit ASP.NET MVC 5

In den folgenden Abschnitten erhalten Sie da-her eine praktische Einführung in beide Tech-nologien und erlernen anhand eines Beispiels, wie ASP.NET MVC und AngularJS als effekti-

Sebastian Eschweiler ist IT-Berater im Bereich Product

Lifecycle Management (PLM).

Weiterhin beschäftigt er sich seit

den Anfängen der J2ME mit mo-

bilen Technologien. Aktuell lie-

gen seine Schwerpunkte auf den

Plattformen Android und Win-

dows Phone. Seine Erfahrung in

diesem Bereich gibt er in Form

von Beiträgen in Fachmagazinen

sowie Büchern weiter.

InhaltResponsive Web-Apps mit ASP.

NET MVC 5 und AngularJS.

RessourcenDie Listings zum Artikel finden

Sie auf www.webundmobile.de

in der Rubrik Aktuelles Heft.

AUTOR

Startbildschirm von Visual Studio Express 2013 RC für das Web (Bild 1)

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;

namespace MvcCustomers.Controllers{ public class CustomerController : Controller { // // GET: /Customer/ public ActionResult Index() { return View(); } }}

LISTING 1: NEUE KLASSE

Page 2: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

21

FEATURE

1/2014

Projektvorlage mit dem Namen ASP.NET-Web-anwendung im Bereich Internet zur Verfügung. Wählen Sie die Projektvorlage aus und vergeben Sie als Vorbereitung für unsere Beispielanwen-dung den Namen MvcCustomers.

Nach Bestätigung des Dialogfensters erhalten Sie ein weiteres Fenster. Hier werden Sie auf-gefordert, den gewählten Projekttyp ASP.NET-Webanwendung näher zu spezifizieren (Bild 2). Angeboten werden die folgenden Optionen:■ Empty: Eine vollkommen leere Vorlage.■ Web Forms: Ermöglicht das Erstellen von klassi-schen ASP.NET-Anwendungen ohne Anwen-dung des MVC-Entwurfsmusters.

■ MVC: Webanwendung auf Basis des MVC-Ent-wurfsmusters.

■ Web API: Webanwendung zum Bereitstellen von RESTful HTTP-Services.

■ Single Page Application: Clientseitige Webanwen-dung auf Basis von JavaScript und HTML5.

■ Facebook: Ermöglicht das Erstellen einer Face-book-Webanwendung.

In unserem Fall fällt die Entscheidung auf den Vorlagentyp MVC. Der abschließende Klick auf die Schaltfläche Projekt erstellen schließt den An-lageprozess des Projekts ab.

Nach der erfolgreichen Projektanlage steht Ih-nen bereits eine lauffähige Anwendung zur Ver-fügung. Zum Starten der Webseite genügt ein Drücken der Taste [F5]. Visual Studio startet im Hintergrund automatisch den Webserver IIS Express und präsentiert Ihnen die Startseite der Anwendung im Browser (Bild 3).

Im Gegensatz zur früheren ASP.NET MVC 4-Projektvorlage ist zu erkennen, dass das Stan-dard-Projekt bereits komplett auf Basis des Boot-strap-UI-Frameworks basiert. Die Seite passt sich daher bereits in dieser Form dem zur Ver-fügung stehenden Bildschirmplatz an (Bild 4). Dies betrifft zum einen die Inhalte der Websei-te als auch das Menü. Die Inhalte werden in Ab-

hängigkeit der Bildschirmbreite entweder nebeneinander oder untereinander ausgebeben. Das Menü wird bei kleineren Bild-schirmen ausgeblendet und verbirgt sich hinter der Menü-Schaltfläche. Ein Klick auf die-se Schaltfläche bringt die Menü-punkte in Form eines Drop-down-Bereichs zum Vorschein. Die Navigation auf der Websei-te wird hierdurch auch für die Touch-Eingabe erleichtert.

Vorbereitung der Beispielanwendung

Wie der Name des Beispielpro-jekts bereits verraten hat, soll ei-

ne Webanwendung entstehen, die das Verwal-ten von Kundendatensätzen erlaubt. Um das Anwendungsbeispiel einfach und überschaubar zu halten, werden zwei Funktionen realisiert, die über zwei Seiten umgesetzt werden:■ Anzeige der Kundendatensätze als Tabelle.■ Hinzufügen von neuen Kundendatensätzen.Übersetzt in das MVC-Entwurfsmuster bedeu-tet dies, dass wir mit einem neuen Controller starten, der zwei Views steuert. Starten Sie den Visual-Studio-Projektmappen-Explorer und öff-nen Sie das Kontextmenü auf dem Projektord-ner Controllers. Wählen Sie an dieser Stelle den Menüpunkt Hinzufügen, Gerüst … aus. Hier-durch gelangen Sie in das Fenster Gerüst hinzufü-gen und haben die Möglichkeit, den gewünsch-ten Typ aus einer Liste zu wählen (Bild 5). Da wir zu Beginn einen leeren Controller benötigen, fällt die Wahl an dieser Stelle auf den Listenein-trag MVC 5 Controller – leer. Nach Bestätigung dieser Auswahl haben Sie im nächsten Fens-ter die Möglichkeit, den Namen für den neuen Controller zu vergeben. Tragen Sie den Namen CustomerController ein und Bestätigen Sie die ▶

Webanwendung der Standard-ASP.NET-MVC-Projektvorlage nach dem erstmaligen Start im Browser (Bild 3)

Die Projektvorlage ASP.NET- Webanwendung unterstützt ver-schiedene Projekttypen (Bild 2)

Automatische Anpassung an die Bildschirmgröße (Bild 4)

LISTING 1: NEUE KLASSE

Page 3: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

22

FEATURE

1/2014

Eingabe mit einem Klick auf den Button Hinzu-fügen. Visual Studio öffnet im Anschluss auto-matisch die Quellcode-Ansicht der neuen Klas-se CustomerController.cs (Listing 1).

Die Index-Methode des neuen Controllers soll die Ansicht zurückliefern, die die Liste al-ler Kundendatensätze in einer Tabelle ausgibt. Damit die notwendigen Anpassungen an der Controller-Klasse vorgenommen werden kön-nen, muss die Applikation zunächst um das Da-tenmodell erweitert werden.

Das Datenmodell unsere Anwendung ist sehr einfach aufgebaut. Zur Verwaltung der Kunden-datensätze genügt eine Entität. Die Abbildung erfolgt über den Einsatz des Entity Frameworks.

Hierbei ist es nicht notwendig, für die benötig-ten Datenstrukturen direkt Änderungen an der Datenbank vorzunehmen. Stattdessen werden die Entitäten direkt über entsprechende Klas-sen im Quellcode beschrieben. Legen Sie daher im ersten Schritt eine neue Klasse mit dem Na- men Customer im Projektordner Models an. In-nerhalb dieser Klasse legen Sie die Eigenschaf-ten fest, die einen Kundendatensatz umfassen (Listing 2).

Weiterhin wird für den Zugriff auf die Daten-bank ein Context benötigt. Hierbei handelt es sich um eine Klasse, die sich direkt von DbCon-text ableitet und festlegt, welche Entitäten über die Datenbankverbindung bereitgestellt wer-den. Legen Sie daher eine weitere Klasse unter-halb des Projektordners Model an und vergeben hierfür den Namen CustomerContext (Listing 3).

Über den Konstruktor der Klasse wird fest-gelegt, dass die Datenbankverbindung mit dem Namen DefaultConnection genutzt werden soll. Diese Verbindung ist innerhalb der Datei Web.config konfiguriert und verweist auf eine lokal gehostetet Datenbankinstanz.

Zusätzlich ist die Eigenschaft Customers vom Typ DbSet<Customers> enthalten, über die der Context den Zugriff auf die Customer-Daten-sätze bietet.

Kundendatensätze

Die Operationen, die mit Hilfe des Contexts auf der Datenbank ausgeführt werden sollen, wer-den üblicherweise über ein Repository bereit-gestellt. In unserem Fall bedeutet dies, dass die Methoden für das Abfragen und für die Neu-anlage von Kundendatensätzen über eine Klas-se mit dem Namen CustomerRepository zur Ver-fügung gestellt werden. Auch diese Klasse wird im Projektordner Models neu angelegt. Um die Schnittstellenbeschreibung von der Implemen-tierung zu trennen, empfiehlt es sich, an dieser Stelle ebenfalls ein Interface ICustomerRepository anzulegen, das die Methodendefinitionen ent-hält (Listing 4).

Die Methode GetCustomers liefert die gesam-te Liste aller Kunden zurück. Die Rückgabe soll hierbei als Objekt vom Typ IQueryable<Customer> erfolgen. Die Methode AddCustomer übernimmt dagegen die Aufgabe, der Datenbank einen neuen Kundendatensatz hinzuzufügen. Hier-zu wird ein Übergabeparameter vom Typ Cus-tomer spezifiziert. Ein Rückgabewert vom Typ bool zeigt an, ob das Hinzufügen erfolgreich ab-geschlossen werden konnte. Die Implementie-rung des Interfaces innerhalb der Klasse Custo-merRepository ist in Listing 5 zu sehen.

Die Klasse verwaltet hierbei eine globale Con-text-Eigenschaft, die über den Konstruktor-Auf-ruf mitgeliefert wird.

public class Customer

{

public int Id { get; set; }

public string CompanyName { get; set; }

public string ContactName { get; set; }

public string ContactTitle { get; set; }

public string Address { get; set; }

public string City { get; set; }

public string PostalCode { get; set; }

public string Country { get; set; }

}

LISTING 2: KLASSE CUSTOMER

public class CustomerContext : DbContext{ public CustomerContext() : base ("DefaultConnection") { }

public DbSet<Customer> Customers { get; set; }}

LISTING 3: KLASSE CUSTOMERCONTEXT

Auswahl des gewünschten Controllers aus der Liste (Bild 5)

Page 4: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

23

FEATURE

1/2014

Für die Rückgabe aller Datensätze genügt es dann, innerhalb der Methode GetCustomers auf die Eigenschaft Customers des Context-Objekts zuzugreifen und diese zurückzuliefern.

Die Methode AddCustomer fügt das übergebe-ne Customer-Objekt schließlich per Aufruf der Add-Methode zur Customers-Collection hinzu.

Dependency Injection

Im vorigen Abschnitt haben Sie gesehen, dass die Initialisierung eines CustomerRepository-Objekts die Übergabe des Context-Objekts er-fordert. Das CustomerRepository ist daher di-rekt vom Context abhängig. Zur Auflösung die-ser Abhängigkeit könnte jeweils vor der Initiali-sierung eines CustomerRepository-Objekts ein Context-Objekt erstellt und übergeben werden.

Um diese Schritte zu vermeiden, wenden wir im Folgenden ein Prinzip mit der Bezeichnung Dependency Injection an. Hierbei werden die Abhängigkeiten an zentraler Stelle konfiguriert. Zur Laufzeit werden die benötigten Abhängig-keiten automatisch aufgelöst.

Ein bekanntes und einfach anzuwendendes Dependency Injection-Framework für .NET- und ASP.NET-MVC-Anwendungen ist Ninject (www.ninject.org).

Installation von Ninject

Die Installation von Ninject erfolgt über den NuGet-Paketmanager. Sie erreichen den Paket-manager über den Menüpunkt Tools, Bibliotheks-Paket-Manager, NuGet-Pakete für Projektmappe verwalten. Geben Sie im sich öffnenden Paket-manager-Fenster den Suchbegriff Ninject in das Suchfeld ein. Installieren Sie das Paket Ninject.MVC3 und stellen Sie außerdem sicher, dass auch die beiden Pakete Ninject und Ninject.Web.Common installiert sind (Bild 6).

Sind die benötigten Ninject-Komponenten dem Projekt hinzugefügt, wechseln Sie zur Kon-figuration der Abhängigkeiten in die Datei Nin-

jectWebCommons.cs innerhalb des Projektord-ners App_Start. Innerhalb der Methode Register-Services hinterlegen Sie die benötigten Abhän-gigkeiten in der folgenden Form:

kernel.Bind<CustomerContext>().To<CustomerContext>(). InRequestScope();

kernel.Bind<ICustomerRepository>().To<CustomerRepository>(). InRequestScope();

Für die ASP.NET MVC-Anwendung ist es au-ßerdem erforderlich, dass die in der globalen Konfiguration das Ninjekt-Kernel-Objekt als ▶

Installation der Ninject- Pakete über den NuGet-Paketmanager (Bild 6)

public interface ICustomerRepository{ IQueryable<Customer> GetCustomers(); bool AddCustomer(Customer customer);}

LISTING 4: INTERFACE FÜR REPOSITORY-KLASSE

public class CustomerRepository : ICustomerRepository{ CustomerContext _ctx;

public CustomerRepository(CustomerContext ctx) { _ctx = ctx; }

public IQueryable<Customer> GetCustomers() { return _ctx.Customers; }

public bool AddCustomer(Customer customer) { try { _ctx.Customers.Add(customer); return true; } catch (Exception ex) { return false; } }}

LISTING 5: REPOSITORY-INTERFACES

Page 5: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

24

FEATURE

1/2014

Dependency Resolver hinterlegen. Hierzu er-gänzen Sie am Ende der CreateKernel-Methode die folgende Zeile Quellcode:

GlobalConfiguration. Configuration.DependencyResolver = new NinjectResolver(kernel);

Mit diesen Vorbereitungen kann die Klasse Cus-tomerController außerdem so erweitert werden, dass das benötigte CustomerRepository an den Konstruktor übergeben wird (Listing 6).

Das CustomerRepository-Objekt wird in der Klasseneigenschaft _repo hinterlegt und inner-halb der Index-Methoden zur Abfrage der Cus-tomer-Datensätze über die Repository-Methode GetCustomers genutzt. Das Ergebnis dieser Ab-frage wird schließlich an die View übergeben, die sich um die Ausgabe der Informationen im Browser kümmert.

Ist die Daten- und Controllerschicht der An-wendung wie in den letzten Abschnitten be-schrieben vorbereitet, kann dazu übergegangen werden, die View für die Ausgabe anzulegen. Für die Index-View des CustomerControllers le-gen Sie einen neuen Unterordner mit dem Na-men Customer innerhalb des Views-Projektord-ners an. Innerhalb des neuen Ordners erstel-len Sie anschließend eine View mit dem Namen Index. Hierzu können Sie erneut auf ein ferti-ges Code-Gerüst zurückgreifen. Wählen Sie aus dem Kontextmenü den Eintrag Hinzufügen, Ge-rüst … und wählen in der Auswahlliste den Ein-trag MVC5 View aus (Bild 7).

View zur Ausgabe der Datensätze anlegen

Bestätigen Sie die Auswahl mit einem Klick auf die Schaltfläche Hinzufügen. Im nächsten Dia-logfenster tragen Sie im Eingabefeld Ansicht-name den Namen Index ein und wählen als Tem-plate aus der Auswahlliste den Eintrag Empty. Bei der neuen Komponente soll es sich um eine typisierte View handeln.

Hierzu wird erwartet, dass die Klasse des Da-tenmodells und des Kontexts festgelegt wird. Treffen Sie daher die Auswahl wie in Bild 8 dar-gestellt. Nach abschließender Bestätigung des Dialogfensters wird das Codegerüst der neuen View innerhalb der Datei Index.cshtml abgelegt und im Quellcode-Editor zur weiteren Bearbei-tung geöffnet (Listing 7).

Die Typisierung wird über das Razor-Tag @model festgelegt. Anschließend wird die Ei-genschaft Title des ViewBag-Objekts auf den Na-men der Ansicht festgelegt. Damit die Custo-mer-Datensätze in der Ansicht ausgegeben wer-den, muss schließlich noch der Quellcode aus Listing 8 in der Datei ergänzt werden:

Die an die View übergebenen Daten stehen über das Model-Objekt zur Verfügung. Über die Methode Count kann die Anzahl der enthaltenen Datensätze abgefragt werden. Wir nutzen die-se Möglichkeit, um diese Information vor der eigentlichen Ausgabe der Datensätze auszuge-ben. Die Ausgabe der Customer-Datensätze er-folgt in Tabellenform.

Mit der Razor-Anweisung @foreach (var cus-tomer in Model) kann hierzu die Collection der Datensätze der Reihe nach durchlaufen werden. Das Ergebnis sehen Sie in Bild 9.

Natürlich benötigen Sie vor dem Aufruf der Webseite einige Beispieldatensätze in der Da-tenbank. Der einfachste Weg ist hierbei, die Ein-gabe der Datensätze über den Visual Studio Ser-ver-Explorer zur Laufzeit der Anwendung vor-zunehmen (Bild 10).

Die bisherigen Abschnitte haben gezeigt, wie eine datengestützte Webanwendung nach dem

public class CustomerController : Controller { private ICustomerRepository _repo;

public CustomerController(ICustomerRepository repo) { _repo = repo; }

// // GET: /Customer/ public ActionResult Index() { var customers = _repo.GetCustomers().ToList();

return View(customers); }}

LISTING 6: REPOSITORY-INTERFACE

Erstellen einer neuen View (Bild 7)

Page 6: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

25

FEATURE

1/2014

klassischen MVC-Entwurfsmuster aufgebaut wird. Durch die Trennung von Model, View und Controller konnte eine klare Trennung der Ver-antwortlichkeiten im Programm erzielt werden. Die Verarbeitung innerhalb des Controllers er-folgt hierbei bisher rein serverseitig.

Im nächsten Schritt soll die Verarbeitung auf die Seite des Clients verlagert werden. Hierzu werden wir das Open-Source-JavaScript-Frame-work AngularJS einsetzen. Bevor dieser Schritt jedoch umgesetzt werden kann, ist es erforder-lich, eine Web-API-Schnittstelle einzurichten um auf diesem Weg den Zugriff auf die Daten-schicht anzubieten.

Web API einrichten

Mit dem Web-API-Framework stellt Microsoft als Bestandteil der ASP.NET-Plattform einen einfachen Weg zur Verfügung, um REST-basier-te Services zu entwickeln. Die entsprechenden Komponenten können in dem bestehenden Vi-sual-Studio-ASP.NET-MVC-Projekt direkt hin-zugefügt werden. Öffnen Sie hierzu das Kon-textmenü des Projektordners Controller und wählen den Menüpunkt Hinzufügen, Gerüst … aus. Im sich öffnenden Dialogfenster wählen Sie den Typ Web API 2-Controller – Leer aus und ver-

geben im nächsten Schritt den Namen Customer-ApiController.

Die neue CustomerApiController-Klasse leitet sich direkt von der Basisklasse ApiController ab. Fügen Sie der leeren Klasse zunächst einen Kon-struktor hinzu, der die Übergabe eines Para-meters vom Typ ICustomerRepository erwartet. Auch in diesem Fall sorgt die bereits hinterleg-te Ninject-Konfiguration dafür, dass bei der In-stanzierung ein CustomerRepository-Objekt auto-matisch bereitgestellt wird. Für die weitere Ver-wendung in der ApiController-Klasse wird das ICustomerRepository-Objekt in einer Klassenei-genschaft mit dem Namen _repo abgelegt.

Für das Anfordern aller Kundendatensätze über eine HTTP-GET-Anfrage wird zusätzlich die Methode Get hinzugefügt:

public IEnumerable<Customer> Get() { ▶

Festlegung der Eigenschaften der neuen View (Bild 8)

@model MvcCustomers.Models. Customer

@{

ViewBag.Title = "Index";

}

<h2>Index</h2>

LISTING 7: NEUES VIEW-GERÜST

<h2>List of Customers</h2>

<div> <div> <p>Number of customers: @Model.Count().ToString() </p> </div> <table class="table"> <thead> <tr> <th>Company Name</th> <th>Contact Name</th> <th>Contact Title</th> <th>Address</th> <th>City</th> <th>Postal Code</th> <th>Country</th> </tr>

</thead> <tbody> @foreach (var customer in Model) { <tr> <td>@customer.CompanyName</td> <td>@customer.ContactName</td> <td>@customer.ContactTitle</td> <td>@customer.Address</td> <td>@customer.City</td> <td>@customer.PostalCode</td> <td>@customer.Country</td> </tr> } </tbody> </table> </div>

LISTING 8: AUSGABE DER DATENSÄTZE

Page 7: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

26

FEATURE

1/2014

return _repo.GetCustomers(). ToList(); }

Die Methode Get liefert die Liste aller Kunden als Collection vom Typ IEnumerable<Customer> zurück.

Bevor die Anwendung zum ersten Testen der Webservice-Schnittstelle ausgeführt wird, soll-te noch ein Blick in die Web-API-Konfigura tion innerhalb der Datei WebApiConfig.cs geworfen werden.

In der Methode Register wird das Routing fest-gelegt. Standardmäßig ist hier eine Route nach folgendem Muster hinterlegt:

config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/ {id}", defaults: new { id = RouteParameter.Optional }

Dies bedeutet, dass der neue Web-API-Control-ler über die URL-Erweiterung api/CustomerApi zur Verfügung steht.

Nach dem Aufruf der Anwendung kann über das Tool Fiddler ein einfacher Funktionstest der Web-API-Schnittstelle durchgeführt werden. Hierzu wird ein GET-Request für den URL http:// localhost:[Port]/api/CustomerApi/ gestellt. Die Da-tensätze werden im JSON-Format zurückgelie-fert (Bild 11).

Neben dem Abruf der Datensätze über ei-ne HTTP-GET-Anfrage soll die WebService-Schnittstelle ebenfalls das Hinzufügen von neu-en Kunden ermöglichen. Die notwendigen Da-ten werden hierzu per HTTP-POST an den Ser-vice gesendet.

Damit der Controller entsprechend vorberei-tet ist und die Daten verarbeiten kann, ist die Aufnahme einer neuen Methode erforderlich (Listing 9).

Der Name der Methode ist in diesem Fall Post. Per Konvention ist festgelegt, dass hier-über HTTP- POST-Anfragen an den Web-API-Con troller verarbeitet werden. Der neue Daten-satz wird im Body-Bereich der HTTP-Anfrage erwartet. Dem Übergabeparameter vom Typ Customer wird daher das Attribut [FromBody] vorangestellt. Die Übergabe im Request Body er-folgt im JSON-Format. Die Umwandlung in ein entsprechendes Objekt vom Typ Customer wird automatisch durch das Web-API-Framework vorgenommen. Ohne weitere Zwischenschrit-te kann das neue Objekt daher direkt an die Da-tenschicht der Anwendung übergeben werden. Hierzu wird die Methode AddCustomer des Re-pository-Objekts aufgerufen.

AngularJS

Mit der vorbereiteten Web-API-Schnittstelle kann das User Interface der Anwendung im Fol-genden durch den Einsatz von AngularJS zu ei- ner Single-Page-Anwendung umgebaut werden.

Bei AngularJS handelt es sich um ein Open-Source-JavaScript-Framework, das das Erstellen von browserbasierten Single-Page-Anwendun-gen auf Basis des MVC-Entwurfsmusters auf Seiten des Clients ermöglicht. AngularJS wird von Google bereitgestellt und kann auf www.angularjs.org heruntergeladen werden.

Für unseren Fall führt der Weg jedoch nicht über die genannte Webseite, sondern über den bereits bekannten NuGet-Paketmanager von Vi-sual Studio. Suchen Sie im Paketmanager nach dem NuGet-Paket mit dem Namen Angular JS und fügen Sie dieses Paket dem bestehenden Projekt hinzu. Durch diesen Schritt werden im Scripts-Order des Projekts einige JavaScript-Da-teien hinzugefügt, die mit dem Namensbestand-teil angular beginnen.

Anpassungen im Layout

Zum Einbinden von AngularJS in unsere beste-hende Webanwendung werden zunächst einige Anpassungen an der Master-Layout-Seite _Lay-out.cshtml vorgenommen.

Damit das Framework für eine Webseite akti-viert wird, ist es erforderlich, das Attribute da-ta-ng-app in einem HTML-Element hinzuzufü-

public HttpResponseMessage Post([FromBody]Customer newCustomer) { if (_repo.AddCustomer(newCustomer) && _repo.Save()) { return Request.CreateResponse(HttpStatusCode.Created, newCustomer); }

return Request.CreateResponse(HttpStatusCode.BadRequest);}

LISTING 9: POST-METHODE DES WEB-API-CONTROLLERS

Ausgabe der Kundendaten in der Beispielanwendung (Bild 9)

Page 8: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

27

FEATURE

1/2014

gen. Damit Angular JS auf der gesamten Sei-te zur Verfügung steht, wird dies üblicherwei-se im <html>-Element auf oberster Ebene vor-genommen:

<html lang="en" data-ng-app= "@ViewBag.InitModule">

Da wir im Folgenden auch noch von der Mög-lichkeit Gebrauch machen werden, eigene An-gularJS-Module zu definieren, wird über das InitModule-Feld des ViewBag-Containers außer-dem der Name des relevanten Moduls über-geben. Das hier angegebene AngularJS-Modul wird beim Seitenaufruf automatisch geladen und initialisiert.

Weiterhin muss innerhalb der Datei _Layout.cshtml das folgende Element zur Einbindung des AngularJS-Skripts aufgenommen werden:

<script src= "~/Scripts/angular.min.js"></script>

Neben den Änderungen an der Master-Layout-Seite wird die in Listing 8 dargestellte Ausga-be der Datensätze komplett aus der Datei Index.cshtml entfernt. Stattdessen wird der Quellcode in Listing 10 eingesetzt.

AngularJS-View einfügen

Es wird lediglich ein <div>-Element eingesetzt, das das AngularJS-Attribut data-ng-view ent-hält. Hierdurch wird die Stelle gekennzeichnet, an der zur Laufzeit die ausgewählte AngularJS-View eingefügt werden soll.

Über entsprechende Razor-Anweisungen werden die beiden Felder Title und InitModule des ViewBag-Containers gesetzt. In unserem Fall soll das noch zu erstellende AngularJS-Mo-dul den Namen customerIndex tragen. Wie be-reits gesehen, wird die InitModule-Eigenschaft genutzt, um den Modulnamen als Wert dem data-ng-app zuzuweisen. Die eigentliche Angu-larJS-Anwendung wird ausgelagert in die Datei

customer.js. Diese Datei wird durch ein entsprechendes script-Element in die Webseite eingebunden.

Die erste Aufgabe innerhalb der Da-tei customer.js besteht darin, das zuvor bereits erwähnte Modul mit dem Na-men customer zu deklarieren und das Routing zu konfigurieren.

Die Anlage eines AngularJS-Moduls ist denkbar einfach und beschränkt sich auf eine Zeile Quellcode:

var customerIndexModule = angular.module ("customerIndex", []);

Über den Aufruf der Funktion angu-lar.module wird zum einen der Name des neuen Moduls als erster Parameter übergeben. An zweiter Stelle erfolgt die Übergabe eines Arrays aller Ab-hängigkeiten zu anderen Modulen. In unserem Beispiel wird hier lediglich ein leeres Array übergeben, da keine Abhängigkeiten bestehen.

Ist das Modul erstellt, kann das Rou-ting über den Aufruf der Funktion config hinter-legt werden (Listing 11).

Config erwartet hierbei die Übergabe einer Funktion. Damit das Routing an dieser Stelle hinterlegt werden kann, benötigt diese Funk tion außerdem Zugriff auf das AngularJS RouteProvi-der-Modul. In AngularJS findet hierzu das glei-che Konzept Anwendung, das wir zuvor bereits mit Ninject vorgestellt haben. Per Dependency Injection wird das $routeProvider-Objekt einfach als Parameter an die Funktion übergeben. Eine separate Initialisierung muss somit nicht vorge-nommen werden.

Die Funktion when des $routeProvider-Objekts kommt schließlich zum Einsatz, um das eigent-liche Routing der Single-Page-Anwendung zu konfigurieren. Hierzu wird jeweils an erster Stelle die Route als String übergeben. An zwei-ter Stelle erfolgt die Übergabe sonstiger Pa-

Aufruf der Web-API-Schnitt-stelle über Fiddler (Bild 11)

Eingabe der Beispieldatensätze über den Visual Studio Server-Explorer (Bild 10)

Page 9: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

28

FEATURE

1/2014

rameter als Objekt. Über den Parameter mit dem Namen controller wird der AngularJS-Controller festgelegt, der die Verarbeitung für die jeweili-ge Route übernimmt. Für die Hauptansicht der Anwendung, die unter der Route / abrufbar sein soll, ist dies der noch zu erstellende Control-ler customerController. Die Eingabe neuer Kun-dendatensätze steht über die Route /newcusto-mer zur Verfügung. Der Controller newCusto-merController übernimmt in diesem Fall die Ver-arbeitung.

Neben dem Controller wird je Route der Pa-rameter templateUrl mit einem Wert belegt. Der zugewiesene String enthält die Pfadangabe zur HTML-Datei, die die Seitenvorlage für die aus-gewählte Ansicht enthält. In der Projektstruk-tur wird hierzu der Ordner mit dem Namen templates aufgenommen. In diesem Ordner wer-den die Dateien customerView.html und newCus-tomerView.html hinterlegt, die die beiden benö-tigten Ansichten enthalten.

Damit die Anwendung auch dann funktions-fähig bleibt, wenn der Anwender eine Route an-spricht, die nicht explizit hinterlegt ist, wird au-

ßerdem die Funktion otherwise des $routeProvi-der-Objekts aufgerufen. Über den Parameter re-directTo wird festgelegt, dass alle sonstigen Rou-ten automatisch zur Route / umgeleitet werden.

AngularJS-Service für den Datenzugriff

Der nächste Schritt in der Implementierung der AngularJS-Webanwendung besteht darin, einen Service für den Datenzugriff zu implementie-ren. Um einen neuen Service zu definieren, ge-nügt es, die factory-Methode auf unserem zuvor erstellten customerIndexModule-Objekt aufzu-rufen:

customerIndexModule.factory("dataService", function ($http, $q) {}

Der Aufruf der factory-Funktion bekommt an erster Stelle den Namen des neuen Services als String übergeben. An zweiter Stelle folgt ei-ne anonyme Funktion, die die Service-Imple-mentierung erhält. Übergeben werden an die-se Funktion die Abhängigkeiten. Erneut kommt an dieser Stelle das Dependeny-Injection-Ent-wurfsmuster zum Einsatz. Das Framework sorgt dafür, dass die benötigten Objektinstanzen zur Verfügung stehen und einfach an den Funk-tionsaufruf übergeben werden können. In An-gularJS kann Dependency Injection daher ohne zusätzliche Komponenten oder Erweiterungen eingesetzt werden.

Die abhängigen Objekte, die im vorliegenden Fall für die Implementierung des Daten-Servi-ces benötigt werden, sind $http und $q. Über das $http-Objekt werden die Anfragen an die zuvor erstellte Web-API-Schnittstelle gestellt. $q ist notwendig, um bei der Einbindung der Web-service-Schnittstelle mit dem Promise/Deferred-Mechanismus arbeiten zu können.

Implementierung des Services

Die Implementierung des Services besteht im Wesentlichen aus den beiden Funktionen _get-Customers und _addCustomers (Listing 12).

Die _getCustomers-Funktion initialisiert zu-nächst ein deferred-Objekt über den Aufruf von $q.defer(). Anschließend wird die HTTP-GET-Anfrage an die Web-API-Schnittstelle gerichtet, die unter /api/CustomerApi die Liste aller Daten-sätze im JSON-Format bereitstellt. Die get-Funk-tion des $http-Objekts nimmt hierzu den URL als Parameter entgegen.

Die Verarbeitung des Rückgabeergebnisses erfolgt per then-Verkettung über eine weitere Funktion. Hierzu werden die Daten über den Aufruf angular.copy vom Rückgabeobjekt in das interne _customers-Array übertragen. Da der Da-

AngularJS-View zur Ausgabe der Kundendatensätze (Bild 12)

@model IEnumerable<MvcCustomers.Models.Customer>

@{

ViewBag.Title = "Customers";

ViewBag.InitModule = "customerIndex";

}

@section scripts {

<script src="~/js/customer.js"></script>

}

<div data-ng-view=""></div>

LISTING 10: AUFNAHME DER ANGULARJS-VIEW

Page 10: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

29

FEATURE

1/2014

tenabruf in diesem Fall erfolgreich durchgeführt werden konnte, wird auch das deferred-Objekt durch die Funktion resolve gelöst.

Für den Fall, dass der Datenabruf nicht erfolg-reich durchgeführt werden konnte, wird eine weitere Funktion an den Aufruf von then über-geben. In diesem Fall übernimmt die Funktion die Aufgabe, das deferred-Objekt über den Auf-ruf von reject als nicht gelöst zu markieren. An-schließend wird das deferred.promise zurückge-liefert.

Ähnlich wie _getCustomer wird die Funktion _addCustomer implementiert. Der Unterschied besteht darin, dass das neue Customer-Objekt als Übergabeparameter an die Funktion ge-liefert wird und die Anfrage an die Web-API-Schnittstelle über den Aufruf von $http.post er-folgt. Der Aufruf von post erfordert die Überga-be von zwei Parametern.

An erster Stelle wird erneut der URL überge-ben, unter dem der Webservice zur Verfügung steht. In unserem Beispiel ist dies der String /api/CustomerApi. An zweiter Stelle wird der neue Kundendatensatz zur Übermittlung an den Webservice separat übergeben. Hierdurch werden die Daten im Body-Bereich der Anfra-ge untergebracht.

Konnten die Daten erfolgreich an den Web-service übergeben werden, wird das _customer-Array ebenfalls um diesen neuen Datensatz er-weitert. Mit dem deferred-Objekt wird in gleicher Art und Weise verfahren, wie zuvor anhand der Funktion _getCustomers erläutert.

Damit der AngularJS-Service die entspre-chenden Methoden und Felder auch tatsäch-lich als Schnittstelle nach außen zur Verfügung stellt, ist es erforderlich, die gewünschten Ele-mente per return-Anweisung zurückzugeben.

AngularJS-Controller

Die eigentliche Logik der AngularJS-Web Appli-kation wird innerhalb der Controller implemen-tiert. Bei der Einrichtung des Routings haben Sie bereits gesehen, dass wir zwei Controller zur Steuerung der Anwendung einsetzen wollen: customerController und newCustomerController.

Beide Controller werden ebenfalls innerhalb der Datei customer.js implementiert. An-

customerIndexModule.factory("dataService", function ($http, $q) { var _customers = []; var _isInit = false;

var _isReady = function () { return _isInit; }

var _getCustomers = function () { var deferred = $q.defer();

$http.get("/api/CustomerApi") .then(function (result) { // success angular.copy(result.data, _customers) _isInit = true; deferred.resolve(); }, function () { // error deferred.reject(); }); return deferred.promise; };

var _addCustomer = function (newCustomer) { var deferred = $q.defer();

$http.post("api/customerapi", newCustomer) .then(function (result) { // success var newlyCreatedCustomer = result.data; _customers.splice(0, 0, newlyCreatedCustomer); deferred.resolve(newlyCreatedCustomer); }, function () { // error deferred.reject(); }); return deferred.promise; };

return { customers: _customers, isReady: _isReady, getCustomers: _getCustomers, addCustomer: _addCustomer };});

LISTING 12: IMPLEMENTIERUNG DES ANGULARJS DATASERVICES

customerIndexModule.config(["$routeProvider", function ($routeProvider) { $routeProvider.when("/", { controller: "customerController", templateUrl: "/templates/customerView.html" });

$routeProvider.when("/newcustomer", { controller: "newCustomerController", templateUrl: "/templates/newCustomerView.html" });

$routeProvider.otherwise({ redirectTo: "/" });}]);

LISTING 11: ROUTING-KONFIGURATION UNTER ANGULARJS

Page 11: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

30

FEATURE

1/2014

gularJS stellt keine besonderen Anforderun-gen an die Controller. Controller können daher als einfache JavaScript-Funktion realisiert sein. Wie zuvor bereits an verschiedenen Stellen be-schrieben, setzt das JavaScript-Framework auch hier auf Dependency Injenction, um die Cont-roller-Funktion mit den notwendigen abhängi-gen Modulen auszustatten. Bezüglich des cus-tomerControllers bedeutet dies, dass zwei Ab-hängigkeiten übergeben werden: $scope und da-taService (Listing 13).

Innerhalb des Controllers wird der dataSer-vice zur Ermittlung der Customer-Datensätze über die Web-API-Schnittstelle eingesetzt. Hier-zu wird die zuvor implementierte Funktion get-Customers des Service-Objekts aufgerufen. Da-durch, dass die Funktion ein Promise-Objekt zu-rückliefert, kann über den Aufruf von then so-wohl auf den Erfolgs- als auch auf den Fehler-fall reagiert werden.

Weitere Abhängigkeit

In ähnlicher Art und Weise erfolgt die Imple-mentierung des newCustomerControllers. Im Unterschied zum customerController benö-

tigt dieser Controller jedoch die Übergabe einer weiteren Abhängigkeit: $window. Hiermit haben wir die Möglichkeit, bei erfolgreicher Übermitt-lung des neuen Customer-Datensatzes eine be-liebige Route anzusprechen.

Wie Listing 14 zeigt, wird hierzu die location-Eigenschaft des Objekts auf #/ gesetzt, um zur Übersichtsseite zurückzukehren. Innerhalb des newCustomerControllers wird die gesamte Pro-grammlogik zum Hinzufügen eines neuen Kun-den in der Funktion save gekapselt. Die Kommu-nikation mit dem Webservice erfolgt über den zuvor implementierten Data Service. Der Aufruf der Data-Service-Methode addCustomer erwartet hierzu die Übergabe des neuen Datensatzes. In vorliegenden Fall wird das entsprechende Ob-jekt direkt aus dem Scope der Webseite über-nommen. Die hierfür notwendigen Binding-An-weisungen innerhalb des HTML-Codes werden im folgenden Abschnitt erläutert.

HTML-Templates

Bei der Konfiguration des Routings für das cus-tomerIndex-Modul haben Sie bereits erfahren, dass je Route entsprechende HTML-Templates zu hinterlegen sind. Diese HTML-Templates er-halten den HTML-Code, der für die Darstel-lung der einzelnen Sichten notwendig ist. Ein-gebunden wird das Template genau an der Stel-le innerhalb von Index.cshtml, an der das <div>-Tag mit dem Attribut data-ng-view zuvor posi-tioniert wurde.

Die beiden HTML-Templates customerView. html und newCustomerView.html werden im tem-plates-Projektordner abgelegt. customerView.html übernimmt die Aufgabe, alle in der Datenbank enthaltenen Kunden in einer Tabelle auszuge-ben. Wie Listing 15 zeigt, wird hierzu das Angu-larJS Data Binding eingesetzt.

Innerhalb der customerController-Funktion wurde das Ergebnis der Datenabfrage in der data-Eigenschaft des Scope-Objekts der Ansicht abgelegt. Die entsprechenden Datensätze kön-nen daher direkt über das data-Objekt zur Aus-gabe eingebunden werden. Hierzu nutzt Angu-lar die Schreibweise {{[Ausdruck]}}.

Da nicht nur ein einziger Datensatz zur Aus-gabe existiert, muss zusätzlich ein Weg gefunden werden, wie die Liste der Datenobjekte der Rei-he nach zur Ausgabe durchlaufen werden kann. Auch diesen Schritt macht Angular durch das Hinzufügen eines weiteren Attributs innerhalb des <tr>-Tags sehr einfach. Durch die Aufnahme von data-ng-repeat="c in data.customers"wird der gesamte <tr>-Block für jeden einzelnen Daten-satz separat ausgegeben. Für jeden Durchlauf steht der aktuelle Kundendatendatz über c zur Verfügung. Auf die einzelnen Datenfelder kann daher über c direkt zugegriffen werden.

var customerController = function ($scope, dataService) { $scope.data = dataService;

if (dataService.isReady() == false) { dataService.getCustomers() .then(function () { // success }, function () { alert("could not load customers"); }); }};

LISTING 13: ANGULARJS CUSTOMERCONTROLLER

AngularJS-View zur Erfassung neuer Daten-

sätze (Bild 13)

Page 12: Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der ... · Responsive Web-Apps mit ASP.NET MVC 5 und AngularJS Der richtige Mix Microsofts Web-Framework ASP.NET MVC Version 5

31

FEATURE

1/2014

Abschließend beinhaltet die Template-Seite noch einen Link zur zweiten Ansicht, die über die Route #/newcustomer innerhalb der Seite er-reichbar ist.

Das Template newCustomerView.html enthält den HTML-Code für die Darstellung des Ein-gabeformulars zur Erfassung eines neuen Kun-den. Beim Absenden der Daten soll die Con-troller-Funktion save die Verarbeitung überneh-men. Über das Attribut data-ng-submit wird die-ses Verhalten direkt im <form>-Tag festgelegt:

<form name="newCustomerForm" novalidate data-ng-submit="save()">

Die Eingabeelemente des Formulars werden mit dem AngularJS-Attribut data-ng-model aus-gestattet, wie das folgende Beispiel zeigt:

<input name="companyName" type="text" data-ng-model="newCustomer. companyName" required />

Der hier zugewiesene Wert legt fest, in welchem Feld des Scopes der Eingabewert abgelegt wird. Um alle Kundendatenfelder zusammenzufas-sen, werden die einzelnen Datenelemente in-nerhalb des newCustomer-Elements zusammen-gefasst.

Das abschließende Ergebnis der Beispielan-wendung kann in Bild 12 und Bild 13 betrach-tet werden. Durch den Einsatz des clientbasier-ten Routings mit Hilfe von AngularJS sind beide Ansichten der Anwendung in einer Seite verfüg-bar. Das Wechseln zwischen der Liste aller Kun-dendatensätze und der Eingabemaske für neue Datensätze erfolgt daher ohne erneute Kommu-nikation mit dem Server. Die HTML-Ansicht wird daher nicht neu geladen und für den Be-nutzer tritt keine Verzögerung im Aufbau der neuen Ansicht auf.

Fazit

Durch den Einsatz von ASP.NET MVC 5, ASP.NET Web API und AngularJS lassen sich Sing-le-Page-Web-Apps auf effektive Art und Weise umsetzen. Durch die vollstände Integration des Bootstrap-Frameworks in die neuen ASP.NET-MVC-5-Projektvorlagen ist die Anwendung au-tomatisch auf den Einsatz auf unterschiedlichen Endgeräten vorbereitet.

Das Web-API-Framework bietet die optima-le Ergänzung, um die Datenschicht der An-wendung über eine REST-basierte Webservice-Schnittstelle für den Einsatz unter AngularJS zur Verfügung zu stellen. AngularJS zeich-net sich hierbei besonders durch den modu-laren Aufbau und die durchgängige Verwen-dung von Dependency Injection aus. Weiter-

hin bietet das Framework die Möglichkeit, das MVC-Entwurfsmuster auf Clientseite umzuset-zen, und bringt hierzu ein eigenes Routing-Sys-tem mit. Die einfache Handhabung des Frame-works wird außerdem dadurch unterstützt, dass Views-Templates als einfache HTML-Sei-ten umgesetzt werden. [mb]

<h2>List of Customers</h2>

<div> <div> <p>Number of customers: {{data.customers.length}}</p> </div> <table class="table"> <thead> <tr> <th>Company Name</th> <th>Contact Name</th> <th>Contact Title</th> <th>Address</th> <th>City</th> <th>Postal Code</th> <th>Country</th> </tr> </thead> <tbody> <tr data-ng-repeat="c in data.customers"> <td>{{c.companyName}}</td> <td>{{c.contactName}}</td> <td>{{c.contactTitle}}</td> <td>{{c.address}}</td> <td>{{c.city}}</td> <td>{{c.postalCode}}</td> <td>{{c.country}}</td> </tr> </tbody> </table></div>

<div><a href="#/newcustomer">New Customer</a></div>

LISTING 15: AUSGABE DER DATENSÄTZE

var newCustomerController = function ($scope, $http, $window, dataService) {

$scope.newCustomer = {};

$scope.save = function () {

dataService.addCustomer($scope.newCustomer)

.then(function () {

// success

$window.location = "#/";

},

function () {

// error

alert("could not save new customer");

});

};

};

LISTING 14: ANGULARJS NEWCUSTOMERCONTROLLER