portaldacalheta.pt
  • Κύριος
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
Πίσω Μέρος

Γωνιακός πυρήνας 5 και ASP.NET



Σκέφτομαι να γράψω μια ανάρτηση ιστολογίου από την πρώτη έκδοση του Angular σκότωσε πρακτικά τη Microsoft από την πλευρά του πελάτη. Τεχνολογίες όπως το ASP.Net, οι φόρμες Web και το MVC Razor έχουν καταστεί άνευ αντικειμένου, αντικαταστάθηκαν από ένα πλαίσιο JavaScript που δεν είναι ακριβώς η Microsoft. Ωστόσο, από τη δεύτερη έκδοση του Angular, η Microsoft και η Google συνεργάζονται για τη δημιουργία του Angular 2, και αυτό είναι όταν οι δύο αγαπημένες μου τεχνολογίες άρχισαν να συνεργάζονται.

Σε αυτό το blog, θέλω να βοηθήσω τους ανθρώπους να δημιουργήσουν την καλύτερη αρχιτεκτονική που συνδυάζει αυτούς τους δύο κόσμους. Είσαι έτοιμος? Ορίστε!



Σχετικά με την αρχιτεκτονική

Θα δημιουργήσετε έναν πελάτη Angular 5 που καταναλώνει μια υπηρεσία RESTful Web API Core 2.



Η πλευρά του πελάτη:



  • Γωνιακό 5
  • Γωνιακό CLI
  • Γωνιακό υλικό

Η πλευρά του διακομιστή:

  • .NET C # Web API Core 2
  • Εξαρτήσεις εγχύσεων
  • Έλεγχος ταυτότητας JWT
  • Πρώτα ο κωδικός πλαισίου οντοτήτων
  • Διακομιστής SQL

Σημείωση



Σε αυτήν την ανάρτηση ιστολογίου υποθέτουμε ότι ο αναγνώστης έχει ήδη βασικές γνώσεις για TypeScript, γωνιακές ενότητες, στοιχεία και εισαγωγή / εξαγωγή. Ο στόχος αυτής της ανάρτησης είναι να δημιουργήσει μια καλή αρχιτεκτονική που θα επιτρέψει την ανάπτυξη του κώδικα με την πάροδο του χρόνου.

Τι χρειάζεσαι?

Ας ξεκινήσουμε επιλέγοντας το IDE. Φυσικά, αυτή είναι μόνο η προτίμησή μου και μπορείτε να χρησιμοποιήσετε αυτήν που νιώθετε πιο άνετα. Στην περίπτωσή μου, θα χρησιμοποιήσω τον κώδικα Visual Studio και το Visual Studio 2017.

Γιατί δύο διαφορετικά IDE; Δεδομένου ότι η Microsoft δημιούργησε τον Visual Studio Code για τη διεπαφή, δεν μπορώ να σταματήσω να χρησιμοποιώ αυτό το IDE. Τέλος πάντων, θα δούμε επίσης πώς να ενσωματώσουμε το Angular 5 στο έργο λύσης, το οποίο θα σας βοηθήσει εάν είστε το είδος προγραμματιστή που προτιμά να κάνει εντοπισμό σφαλμάτων τόσο πίσω όσο και εμπρός με ένα μόνο F5.



Σχετικά με το πίσω μέρος, μπορείτε να εγκαταστήσετε την τελευταία έκδοση του Visual Studio 2017, η οποία διαθέτει δωρεάν έκδοση για προγραμματιστές, αλλά είναι πολύ πλήρης: Κοινότητα.

Λοιπόν, εδώ είναι η λίστα με τα πράγματα που πρέπει να εγκαταστήσουμε για αυτό το σεμινάριο:



  • Κωδικός Visual Studio
  • Κοινότητα Visual Studio 2017 (ή Οποιοδήποτε)
  • Node.js v8.10.0
  • SQL Server 2017

Σημείωση

Βεβαιωθείτε ότι εκτελείτε τουλάχιστον τον κόμβο 6.9.x και npm 3.x.x εκτελώντας node -v και npm -v σε παράθυρο τερματικού ή κονσόλας. Οι παλαιότερες εκδόσεις προκαλούν σφάλματα, αλλά οι νεότερες εκδόσεις είναι εντάξει.

Το μπροστινό μέρος

Γρήγορη εκίνηση

Αφήστε τη διασκέδαση να ξεκινήσει! Το πρώτο πράγμα που πρέπει να κάνουμε είναι να εγκαταστήσουμε το Angular CLI παγκοσμίως, οπότε ανοίξτε τη γραμμή εντολών node.js και εκτελέστε αυτήν την εντολή:



npm install -g @angular/cli

Εντάξει, τώρα έχουμε το πρόγραμμα δέσμης στοιχείων μας. Αυτό συνήθως εγκαθιστά τη λειτουργική μονάδα στον φάκελο χρήστη. Ένα ψευδώνυμο δεν θα πρέπει να είναι απαραίτητο από προεπιλογή, αλλά εάν το χρειάζεστε, μπορείτε να εκτελέσετε την επόμενη γραμμή:

alias ng='/.npm/lib/node_modules/angular-cli/bin/ng'

Το επόμενο βήμα είναι να δημιουργήσετε το νέο έργο. Θα το ονομάσω angular5-app. Αρχικά, μεταβαίνουμε στον φάκελο στον οποίο θέλουμε να δημιουργήσουμε τον ιστότοπο και μετά:



ng new angular5-app

Πρώτη κατασκευή

Ενώ μπορείτε να δοκιμάσετε τον νέο ιστότοπό σας που τρέχει μόλις ng serve --open, προτείνω να δοκιμάσετε τον ιστότοπο από την αγαπημένη σας υπηρεσία ιστού. Γιατί; Λοιπόν, ορισμένα ζητήματα μπορούν να συμβούν μόνο στην παραγωγή και την κατασκευή του ιστότοπου με ng build είναι ο πλησιέστερος τρόπος προσέγγισης αυτού του περιβάλλοντος. Τότε μπορούμε να ανοίξουμε το φάκελο angular5-app με κώδικα Visual Studio και εκτέλεση ng build στο τερματικό bash:

δημιουργία της γωνιακής εφαρμογής για πρώτη φορά

Ένας νέος φάκελος που ονομάζεται dist θα δημιουργηθεί και μπορούμε να το εξυπηρετήσουμε χρησιμοποιώντας IIS ή οποιονδήποτε διακομιστή ιστού προτιμάτε. Στη συνέχεια, μπορείτε να πληκτρολογήσετε τη διεύθυνση URL στο πρόγραμμα περιήγησης και… τελειώσατε!

σε ποια γλώσσα είναι γραμμένα τα windows

τη νέα δομή καταλόγου

Σημείωση

Δεν είναι ο σκοπός αυτού του σεμιναρίου να δείξει πώς να δημιουργήσετε έναν διακομιστή ιστού, επομένως υποθέτω ότι έχετε ήδη αυτές τις γνώσεις.

Γωνιακή οθόνη καλωσορίσματος 5

Το src Ντοσιέ

Η δομή του φακέλου src

My src ο φάκελος είναι δομημένος ως εξής: Μέσα στο app φάκελο που έχουμε components όπου θα δημιουργήσουμε για κάθε γωνιακό στοιχείο τα css, ts, spec και html αρχεία. Θα δημιουργήσουμε επίσης ένα config φάκελο για να διατηρήσετε τη διαμόρφωση του ιστότοπου, directives θα έχει όλες τις προσαρμοσμένες οδηγίες μας, helpers θα φιλοξενήσει κοινό κώδικα όπως ο διαχειριστής ελέγχου ταυτότητας, layout θα περιέχει τα κύρια συστατικά όπως το σώμα, το κεφάλι και τα πλαϊνά πάνελ, models διατηρεί αυτό που θα ταιριάζει με τα μοντέλα οπίσθιας προβολής και τέλος services θα έχει τον κωδικό για όλες τις κλήσεις προς το πίσω μέρος.

Έξω από το app φάκελος θα διατηρήσουμε τους φακέλους που έχουν δημιουργηθεί από προεπιλογή, όπως assets και environments, και επίσης τα ριζικά αρχεία.

Δημιουργία του αρχείου διαμόρφωσης

Ας δημιουργήσουμε ένα config.ts αρχείο μέσα στο config φάκελο και καλέστε την τάξη AppConfig. Εδώ μπορούμε να ορίσουμε όλες τις τιμές που θα χρησιμοποιήσουμε σε διαφορετικά μέρη του κώδικα μας. για παράδειγμα, το URL του API. Σημειώστε ότι η κλάση εφαρμόζει ένα get ιδιότητα που λαμβάνει, ως παράμετρο, μια δομή κλειδιού / τιμής και μια απλή μέθοδο για να αποκτήσετε πρόσβαση στην ίδια τιμή. Με αυτόν τον τρόπο, θα είναι εύκολο να λάβετε τις τιμές απλώς κλήση this.config.setting['PathAPI'] από τις τάξεις που κληρονομούν από αυτό.

import { Injectable } from '@angular/core'; @Injectable() export class AppConfig { private _config: { [key: string]: string }; constructor() { this._config = { PathAPI: 'http://localhost:50498/api/' }; } get setting():{ [key: string]: string } { return this._config; } get(key: any) { return this._config[key]; } };

Γωνιακό υλικό

Πριν ξεκινήσετε τη διάταξη, ας ρυθμίσουμε το πλαίσιο στοιχείου διεπαφής χρήστη. Φυσικά, μπορείτε να χρησιμοποιήσετε άλλους όπως το Bootstrap, αλλά αν σας αρέσει το στυλ του Υλικού, το προτείνω γιατί υποστηρίζεται επίσης από την Google.

Για να το εγκαταστήσουμε, πρέπει απλώς να εκτελέσουμε τις επόμενες τρεις εντολές, τις οποίες μπορούμε να εκτελέσουμε στο τερματικό του Visual Studio Code:

npm install --save @angular/material @angular/cdk npm install --save @angular/animations npm install --save hammerjs

Η δεύτερη εντολή είναι επειδή ορισμένα στοιχεία Υλικού εξαρτώνται από τις Γωνιακές κινούμενες εικόνες. Συνιστώ επίσης την ανάγνωση την επίσημη σελίδα για να κατανοήσουμε ποια προγράμματα περιήγησης υποστηρίζονται και τι είναι το polyfill.

Η τρίτη εντολή είναι επειδή ορισμένα στοιχεία Υλικού βασίζονται στο HammerJS για χειρονομίες.

Τώρα μπορούμε να προχωρήσουμε στην εισαγωγή των λειτουργικών μονάδων που θέλουμε να χρησιμοποιήσουμε στο app.module.ts αρχείο:

import {MatButtonModule, MatCheckboxModule} from '@angular/material'; import {MatInputModule} from '@angular/material/input'; import {MatFormFieldModule} from '@angular/material/form-field'; import {MatSidenavModule} from '@angular/material/sidenav'; // ... @NgModule({ imports: [ BrowserModule, BrowserAnimationsModule, MatButtonModule, MatCheckboxModule, MatInputModule, MatFormFieldModule, MatSidenavModule, AppRoutingModule, HttpClientModule ],

Το επόμενο βήμα είναι να αλλάξετε το style.css αρχείο, προσθέτοντας το είδος του θέματος που θέλετε να χρησιμοποιήσετε:

@import ' [email protected] /material/prebuilt-themes/deeppurple-amber.css';

Τώρα εισαγάγετε HammerJS προσθέτοντας αυτήν τη γραμμή στο main.ts αρχείο:

import 'hammerjs';

Και τέλος, το μόνο που μας λείπει είναι να προσθέσουμε τα εικονίδια Υλικού στο index.html, στην ενότητα κεφαλίδας:

layout

Η διάταξη

Σε αυτό το παράδειγμα, θα δημιουργήσουμε μια απλή διάταξη όπως αυτή:

Παράδειγμα διάταξης

Η ιδέα είναι να ανοίξετε / αποκρύψετε το μενού κάνοντας κλικ σε κάποιο κουμπί στην κεφαλίδα. Το Angular Responsive θα κάνει το υπόλοιπο έργο για εμάς. Για να το κάνουμε αυτό θα δημιουργήσουμε ένα app.component φάκελο και βάλτε μέσα του το app.component αρχεία που δημιουργήθηκαν από προεπιλογή. Αλλά θα δημιουργήσουμε επίσης τα ίδια αρχεία για κάθε ενότητα της διάταξης όπως μπορείτε να δείτε στην επόμενη εικόνα. Τότε, head.component θα είναι το σώμα, left-panel.component η κεφαλίδα και app.component.html το μενού.

Επισημασμένος φάκελος διαμόρφωσης

Τώρα ας αλλάξουμε Menu ως εξής:

authentication

Βασικά θα έχουμε ένα head.component.html ιδιότητα στο στοιχείο που θα μας επιτρέψει να αφαιρέσουμε την κεφαλίδα και το μενού εάν ο χρήστης δεν είναι συνδεδεμένος και, αντίθετα, να εμφανίσει μια απλή σελίδα σύνδεσης.

Το Logout! μοιάζει με αυτό:

left-panel.component.html

Απλώς ένα κουμπί για να αποσυνδεθεί ο χρήστης - θα επανέλθουμε σε αυτό ξανά αργότερα. Όσο για Dashboard Users , προς το παρόν αλλάξτε απλώς το HTML σε:

import { Component } from '@angular/core'; @Component({ selector: 'app-head', templateUrl: './head.component.html', styleUrls: ['./head.component.css'] }) export class HeadComponent { title = 'Angular 5 Seed'; }

Το κρατήσαμε απλό: Μέχρι στιγμής είναι μόνο δύο σύνδεσμοι για πλοήγηση σε δύο διαφορετικές σελίδες. (Θα επιστρέψουμε επίσης σε αυτό αργότερα.)

Τώρα, έτσι μοιάζουν τα αρχεία TypeScript της κεφαλής και της αριστερής πλευράς:

import { Component } from '@angular/core'; @Component({ selector: 'app-left-panel', templateUrl: './left-panel.component.html', styleUrls: ['./left-panel.component.css'] }) export class LeftPanelComponent { title = 'Angular 5 Seed'; } app.component

Τι γίνεται όμως με τον κωδικό TypeScript για app; Θα αφήσουμε ένα μικρό μυστήριο εδώ και θα το σταματήσουμε για λίγο και θα επανέλθουμε σε αυτό μετά την εφαρμογή του ελέγχου ταυτότητας.

Δρομολόγηση

Εντάξει, τώρα έχουμε Angular Material που μας βοηθά με το περιβάλλον εργασίας χρήστη και μια απλή διάταξη για να αρχίσουμε να δημιουργούμε τις σελίδες μας. Αλλά πώς μπορούμε να περιηγηθούμε μεταξύ σελίδων;

Για να δημιουργήσουμε ένα απλό παράδειγμα, ας δημιουργήσουμε δύο σελίδες: 'Χρήστης', όπου μπορούμε να λάβουμε μια λίστα με τους υπάρχοντες χρήστες στη βάση δεδομένων και 'Πίνακας ελέγχου', μια σελίδα όπου μπορούμε να δείξουμε ορισμένα στατιστικά στοιχεία.

Μέσα στο app-routing.modules.ts φάκελο θα δημιουργήσουμε ένα αρχείο που ονομάζεται import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { AuthGuard } from './helpers/canActivateAuthGuard'; import { LoginComponent } from './components/login/login.component'; import { LogoutComponent } from './components/login/logout.component'; import { DashboardComponent } from './components/dashboard/dashboard.component'; import { UsersComponent } from './components/users/users.component'; const routes: Routes = [ { path: '', redirectTo: '/dashboard', pathMatch: 'full', canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent}, { path: 'logout', component: LogoutComponent}, { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }, { path: 'users', component: UsersComponent,canActivate: [AuthGuard] } ]; @NgModule({ imports: [ RouterModule.forRoot(routes) ], exports: [ RouterModule ] }) export class AppRoutingModule {} μοιάζει με αυτό:

RouterModule

Είναι τόσο απλό: Απλώς εισαγωγή Routes και @angular/router από /dashboard, μπορούμε να χαρτογραφήσουμε τις διαδρομές που θέλουμε να εφαρμόσουμε. Εδώ δημιουργούμε τέσσερις διαδρομές:

  • /login: Η αρχική μας σελίδα
  • /logout: Η σελίδα στην οποία ο χρήστης μπορεί να πραγματοποιήσει έλεγχο ταυτότητας
  • /users: Μια απλή διαδρομή για την αποσύνδεση του χρήστη
  • dashboard: Η πρώτη μας σελίδα όπου θέλουμε να παραθέσουμε τους χρήστες από το πίσω μέρος

Σημειώστε ότι / είναι η σελίδα μας από προεπιλογή, οπότε αν ο χρήστης πληκτρολογήσει τη διεύθυνση URL canActivate, η σελίδα θα ανακατευθύνει αυτόματα σε αυτήν τη σελίδα. Επίσης, ρίξτε μια ματιά στο AuthGuard παράμετρος: Εδώ δημιουργούμε μια αναφορά στην κλάση left-panel.component.html, η οποία θα μας επιτρέψει να ελέγξουμε εάν ο χρήστης είναι συνδεδεμένος. Εάν όχι, ανακατευθύνει στη σελίδα σύνδεσης. Στην επόμενη ενότητα, θα σας δείξω πώς να δημιουργήσετε αυτήν την τάξη.

Τώρα, το μόνο που πρέπει να κάνουμε είναι να δημιουργήσουμε το μενού. Θυμηθείτε στην ενότητα διάταξης όταν δημιουργήσαμε το Dashboard Users αρχείο για να μοιάζει με αυτό;

our.site.url/users

Εδώ είναι όπου ο κώδικάς μας συναντά την πραγματικότητα. Τώρα μπορούμε να δημιουργήσουμε τον κώδικα και να τον δοκιμάσουμε στη διεύθυνση URL: Θα πρέπει να μπορείτε να πλοηγηθείτε από τη σελίδα του πίνακα ελέγχου στους χρήστες, αλλά τι θα συμβεί αν πληκτρολογήσετε τη διεύθυνση URL http://www.mysite.com/users/42 στο πρόγραμμα περιήγησης απευθείας;

κείμενο alt εικόνας

Λάβετε υπόψη ότι αυτό το σφάλμα εμφανίζεται επίσης εάν ανανεώσετε το πρόγραμμα περιήγησης αφού έχετε ήδη επιτυχώς πλοηγηθεί σε αυτήν τη διεύθυνση URL μέσω του πλευρικού πλαισίου της εφαρμογής. Για να κατανοήσω αυτό το σφάλμα, επιτρέψτε μου να αναφερθώ τα επίσημα έγγραφα όπου είναι πραγματικά σαφές:

Μια δρομολογημένη εφαρμογή πρέπει να υποστηρίζει συνδέσμους σε βάθος. Ένας βαθύς σύνδεσμος είναι μια διεύθυνση URL που καθορίζει μια διαδρομή προς ένα στοιχείο εντός της εφαρμογής. Για παράδειγμα, http://www.mysite.com/ είναι ένας βαθύς σύνδεσμος προς τη σελίδα λεπτομερειών του ήρωα που εμφανίζει τον ήρωα με αναγνωριστικό: 42.

Δεν υπάρχει πρόβλημα όταν ο χρήστης πλοηγείται σε αυτήν τη διεύθυνση URL μέσα από έναν πελάτη που εκτελείται. Ο γωνιακός δρομολογητής ερμηνεύει τη διεύθυνση URL και τις διαδρομές προς αυτήν τη σελίδα και τον ήρωα.

Αλλά κάνοντας κλικ σε έναν σύνδεσμο σε ένα email, πληκτρολογώντας τον στη γραμμή διευθύνσεων του προγράμματος περιήγησης ή απλώς ανανεώνοντας το πρόγραμμα περιήγησης ενώ βρίσκεστε στη σελίδα λεπτομερειών του ήρωα - όλες αυτές οι ενέργειες αντιμετωπίζονται από το ίδιο το πρόγραμμα περιήγησης, εκτός της εφαρμογής που εκτελείται. Το πρόγραμμα περιήγησης υποβάλλει άμεσο αίτημα στον διακομιστή για τη συγκεκριμένη διεύθυνση URL, παρακάμπτοντας το δρομολογητή.

Ένας στατικός διακομιστής επιστρέφει συνήθως το index.html όταν λαμβάνει αίτημα για http://www.mysite.com/users/42. Αλλά απορρίπτει src και επιστρέφει ένα σφάλμα 404 - Not Found εκτός εάν έχει ρυθμιστεί να επιστρέφει index.html.

Για να επιλύσετε αυτό το ζήτημα είναι πολύ απλό, απλώς πρέπει να δημιουργήσουμε τη διαμόρφωση αρχείου του φορέα παροχής υπηρεσιών. Εφόσον δουλεύω με τις υπηρεσίες IIS εδώ, θα σας δείξω πώς να το κάνετε σε αυτό το περιβάλλον, αλλά η ιδέα είναι παρόμοια για το Apache ή για οποιονδήποτε άλλο διακομιστή ιστού.

Έτσι δημιουργούμε ένα αρχείο μέσα στο web.config φάκελος που ονομάζεται angular-cli.json μοιάζει με αυτό:

{ '$schema': './node_modules/@angular/cli/lib/config/schema.json', 'project': { 'name': 'angular5-app' }, 'apps': [ { 'root': 'src', 'outDir': 'dist', 'assets': [ 'assets', 'favicon.ico', 'web.config' // or whatever equivalent is required by your web server ], 'index': 'index.html', 'main': 'main.ts', 'polyfills': 'polyfills.ts', 'test': 'test.ts', 'tsconfig': 'tsconfig.app.json', 'testTsconfig': 'tsconfig.spec.json', 'prefix': 'app', 'styles': [ 'styles.css' ], 'scripts': [], 'environmentSource': 'environments/environment.ts', 'environments': { 'dev': 'environments/environment.ts', 'prod': 'environments/environment.prod.ts' } } ], 'e2e': { 'protractor': { 'config': './protractor.conf.js' } }, 'lint': [ { 'project': 'src/tsconfig.app.json', 'exclude': '**/node_modules/**' }, { 'project': 'src/tsconfig.spec.json', 'exclude': '**/node_modules/**' }, { 'project': 'e2e/tsconfig.e2e.json', 'exclude': '**/node_modules/**' } ], 'test': { 'karma': { 'config': './karma.conf.js' } }, 'defaults': { 'styleExt': 'css', 'component': {} } }

Τότε πρέπει να είμαστε σίγουροι ότι αυτό το στοιχείο θα αντιγραφεί στον αναπτυσσόμενο φάκελο. Το μόνο που πρέπει να κάνουμε είναι να αλλάξουμε το αρχείο ρυθμίσεων Angular CLI AuthGuard:

canActivateAuthGuard.ts

Αυθεντικοποίηση

Θυμάστε πώς είχαμε το μάθημα helpers εφαρμοστεί για να ορίσετε τη διαμόρφωση δρομολόγησης; Κάθε φορά που μεταβαίνουμε σε μια διαφορετική σελίδα, θα χρησιμοποιούμε αυτήν την τάξη για να επαληθεύσουμε εάν ο χρήστης έχει πιστοποιηθεί με ένα διακριτικό. Εάν όχι, θα ανακατευθυνθούμε αυτόματα στη σελίδα σύνδεσης. Το αρχείο για αυτό είναι import { CanActivate, Router } from '@angular/router'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Helpers } from './helpers'; import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; @Injectable() export class AuthGuard implements CanActivate { constructor(private router: Router, private helper: Helpers) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | boolean { if (!this.helper.isAuthenticated()) { this.router.navigate(['/login']); return false; } return true; } } —δημιουργήστε το μέσα στο canActivate φάκελο και να έχει την εξής μορφή:

Router

Έτσι, κάθε φορά που αλλάζουμε τη σελίδα η μέθοδος Helper θα κληθεί, το οποίο θα ελέγξει εάν ο χρήστης έχει πιστοποιηθεί και αν όχι, χρησιμοποιούμε το helpers παράδειγμα για ανακατεύθυνση στη σελίδα σύνδεσης. Αλλά ποια είναι αυτή η νέα μέθοδος στο helpers.ts τάξη? Κάτω από το localStorage φάκελος ας δημιουργήσουμε ένα αρχείο localStorage. Εδώ πρέπει να διαχειριστούμε sessionStorage, όπου θα αποθηκεύσουμε το διακριτικό που λαμβάνουμε από το πίσω μέρος.

Σημείωση

Όσον αφορά το sessionStorage, μπορείτε επίσης να χρησιμοποιήσετε cookie ή localStorage και η απόφαση θα εξαρτηθεί από τη συμπεριφορά που θέλουμε να εφαρμόσουμε. Όπως υποδηλώνει το όνομα, sessionStorage είναι διαθέσιμο μόνο για τη διάρκεια της περιόδου λειτουργίας του προγράμματος περιήγησης και διαγράφεται όταν η καρτέλα ή το παράθυρο είναι κλειστό. Ωστόσο, επιβιώνει τις επαναφορτώσεις σελίδων. Εάν τα δεδομένα που αποθηκεύετε πρέπει να είναι διαθέσιμα σε συνεχή βάση, τότε localStorage είναι προτιμότερο από το import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { Subject } from 'rxjs/Subject'; @Injectable() export class Helpers { private authenticationChanged = new Subject(); constructor() { } public isAuthenticated():boolean public isAuthenticationChanged():any { return this.authenticationChanged.asObservable(); } public getToken():any { if( window.localStorage['token'] === undefined || window.localStorage['token'] === null || window.localStorage['token'] === 'null' || window.localStorage['token'] === 'undefined' || window.localStorage['token'] === '') { return ''; } let obj = JSON.parse(window.localStorage['token']); return obj.token; } public setToken(data:any):void { this.setStorageToken(JSON.stringify(data)); } public failToken():void { this.setStorageToken(undefined); } public logout():void { this.setStorageToken(undefined); } private setStorageToken(value: any):void { window.localStorage['token'] = value; this.authenticationChanged.next(this.isAuthenticated()); } } . Τα cookie προορίζονται κυρίως για ανάγνωση από την πλευρά του διακομιστή, ενώ Subject μπορεί να διαβαστεί μόνο από την πλευρά του πελάτη. Το ερώτημα λοιπόν είναι, στην εφαρμογή σας, ποιος χρειάζεται αυτά τα δεδομένα --- τον πελάτη ή τον διακομιστή;


{ path: 'logout', component: LogoutComponent},

Έχει νόημα ο κωδικός ελέγχου ταυτότητας τώρα; Θα επιστρέψουμε στο localStorage τάξη αργότερα, αλλά τώρα ας επιστρέψουμε για ένα λεπτό στη διαμόρφωση δρομολόγησης. Ρίξτε μια ματιά σε αυτήν τη γραμμή:

components/login

Αυτό είναι το συστατικό μας για αποσύνδεση από τον ιστότοπο και είναι απλώς μια απλή τάξη για να καθαρίσετε το logout.component.ts. Ας το δημιουργήσουμε κάτω από το import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Helpers } from '../../helpers/helpers'; @Component({ selector: 'app-logout', template:'' }) export class LogoutComponent implements OnInit { constructor(private router: Router, private helpers: Helpers) { } ngOnInit() { this.helpers.logout(); this.router.navigate(['/login']); } } φάκελος με το όνομα /logout:

localStorage

Έτσι, κάθε φορά που πηγαίνουμε στο URL login.component.ts, το import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { TokenService } from '../../services/token.service'; import { Helpers } from '../../helpers/helpers'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: [ './login.component.css' ] }) export class LoginComponent implements OnInit { constructor(private helpers: Helpers, private router: Router, private tokenService: TokenService) { } ngOnInit() { } login(): void { let authValues = {'Username':'pablo', 'Password':'secret'}; this.tokenService.auth(authValues).subscribe(token => { this.helpers.setToken(token); this.router.navigate(['/dashboard']); }); } } θα καταργηθεί και ο ιστότοπος θα ανακατευθύνει στη σελίδα σύνδεσης. Τέλος, ας δημιουργήσουμε app.component.ts σαν αυτό:

export class AppComponent implements AfterViewInit { subscription: Subscription; authentication: boolean; constructor(private helpers: Helpers) { } ngAfterViewInit() { this.subscription = this.helpers.isAuthenticationChanged().pipe( startWith(this.helpers.isAuthenticated()), delay(0)).subscribe((value) => this.authentication = value ); } title = 'Angular 5 Seed'; ngOnDestroy() { this.subscription.unsubscribe(); } }

Όπως μπορείτε να δείτε, προς το παρόν έχουμε κωδικοποιήσει τα διαπιστευτήριά μας εδώ. Σημειώστε ότι εδώ καλούμε μια τάξη υπηρεσιών. θα δημιουργήσουμε αυτές τις κατηγορίες υπηρεσιών για να αποκτήσουμε πρόσβαση στο πίσω μέρος μας στην επόμενη ενότητα.

Τέλος, πρέπει να επιστρέψουμε στο Subject αρχείο, η διάταξη του ιστότοπου. Εδώ, εάν ο χρήστης έχει πιστοποιηθεί, θα εμφανίσει τις ενότητες μενού και κεφαλίδας, αλλά αν όχι, η διάταξη θα αλλάξει για να εμφανίζει μόνο τη σελίδα σύνδεσης.

Observable

Θυμηθείτε το Observable τάξη στην τάξη βοηθών μας; Αυτό είναι ένα authentication. app.component.html s παρέχουν υποστήριξη για τη μετάδοση μηνυμάτων μεταξύ εκδοτών και συνδρομητών στην εφαρμογή σας. Κάθε φορά που αλλάζει το διακριτικό ελέγχου ταυτότητας, το Menu η ιδιότητα θα ενημερωθεί. Επανεξέταση του services αρχείο, πιθανότατα θα έχει πιο νόημα τώρα:

τι είναι ένα παιχνίδι blockchain
token.service.ts

Υπηρεσίες

Σε αυτό το σημείο μεταβαίνουμε σε διαφορετικές σελίδες, επικυρώνουμε την πλευρά των πελατών μας και αποδίδουμε μια πολύ απλή διάταξη. Αλλά πώς μπορούμε να λάβουμε δεδομένα από το πίσω μέρος; Συνιστώ ανεπιφύλακτα να κάνετε όλη την πρόσβαση back-end από υπηρεσία ειδικότερα τάξεις. Η πρώτη μας υπηρεσία θα βρίσκεται στο import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; import { catchError, map, tap } from 'rxjs/operators'; import { AppConfig } from '../config/config'; import { BaseService } from './base.service'; import { Token } from '../models/token'; import { Helpers } from '../helpers/helpers'; @Injectable() export class TokenService extends BaseService { private pathAPI = this.config.setting['PathAPI']; public errorMessage: string; constructor(private http: HttpClient, private config: AppConfig, helper: Helpers) { super(helper); } auth(data: any): any { let body = JSON.stringify(data); return this.getToken(body); } private getToken (body: any): Observable { return this.http.post(this.pathAPI + 'token', body, super.header()).pipe( catchError(super.handleError) ); } } φάκελος, που ονομάζεται TokenService:

BaseService

Η πρώτη κλήση στο πίσω μέρος είναι μια κλήση POST στο API διακριτικών. Το API διακριτικών δεν χρειάζεται τη συμβολοσειρά διακριτικών στην κεφαλίδα, αλλά τι θα συμβεί αν καλέσουμε άλλο τελικό σημείο; Όπως μπορείτε να δείτε εδώ, import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; import { catchError, map, tap } from 'rxjs/operators'; import { Helpers } from '../helpers/helpers'; @Injectable() export class BaseService { constructor(private helper: Helpers) { } public extractData(res: Response) { let body = res.json(); return body || {}; } public handleError(error: Response | any) { // In a real-world app, we might use a remote logging infrastructure let errMsg: string; if (error instanceof Response) { const body = error.json() || ''; const err = body || JSON.stringify(body); errMsg = `${error.status} - $error.statusText ${err}`; } else { errMsg = error.message ? error.message : error.toString(); } console.error(errMsg); return Observable.throw(errMsg); } public header() { let header = new HttpHeaders({ 'Content-Type': 'application/json' }); if(this.helper.isAuthenticated()) { header = header.append('Authorization', 'Bearer ' + this.helper.getToken()); } return { headers: header }; } public setToken(data:any) { this.helper.setToken(data); } public failToken(error: Response | any) { this.helper.failToken(); return this.handleError(Response); } } (και τάξεις υπηρεσιών γενικά) κληρονομούνται από το super.header τάξη. Ας ρίξουμε μια ματιά σε αυτό:

localStorage

Έτσι, κάθε φορά που πραγματοποιούμε μια κλήση HTTP, εφαρμόζουμε την κεφαλίδα του αιτήματος χρησιμοποιώντας απλώς user.ts. Εάν το διακριτικό είναι export class User { id: number; name: string; } τότε θα προσαρτηθεί μέσα στην κεφαλίδα, αλλά αν όχι, θα ρυθμίσουμε τη μορφή JSON. Ένα άλλο πράγμα που μπορούμε να δούμε εδώ είναι τι συμβαίνει εάν ο έλεγχος ταυτότητας αποτύχει.

Το στοιχείο σύνδεσης θα καλέσει την κλάση υπηρεσίας και η κλάση υπηρεσίας θα καλέσει το πίσω μέρος. Μόλις αποκτήσουμε το διακριτικό, η τάξη βοηθού θα διαχειριστεί το διακριτικό και τώρα είμαστε έτοιμοι να λάβουμε τη λίστα χρηστών από τη βάση δεδομένων μας.

Για να λάβετε δεδομένα από τη βάση δεδομένων, πρώτα βεβαιωθείτε ότι ταιριάζουμε τις κατηγορίες μοντέλων με τα μοντέλα οπίσθιας όψης στην απόκρισή μας.

Σε user.service.ts:

import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; import { catchError, map, tap } from 'rxjs/operators'; import { BaseService } from './base.service'; import { User } from '../models/user'; import { AppConfig } from '../config/config'; import { Helpers } from '../helpers/helpers'; @Injectable() export class UserService extends BaseService { private pathAPI = this.config.setting['PathAPI']; constructor(private http: HttpClient, private config: AppConfig, helper: Helpers) { super(helper); } /** GET heroes from the server */ getUsers (): Observable { return this.http.get(this.pathAPI + 'user', super.header()).pipe( catchError(super.handleError)); }

Και μπορούμε να δημιουργήσουμε τώρα το SeedAPI.Web.API αρχείο:

Web.API

Το πίσω μέρος

Γρήγορη εκίνηση

Καλώς ήρθατε στο πρώτο βήμα της εφαρμογής Web API Core 2. Το πρώτο πράγμα που χρειαζόμαστε είναι να δημιουργήσουμε μια ASP.Net Core Web Application, την οποία θα ονομάσουμε ViewModels.

Δημιουργία νέου αρχείου

Φροντίστε να επιλέξετε το Άδειο πρότυπο για καθαρή εκκίνηση, όπως μπορείτε να δείτε παρακάτω:

επιλέξτε το κενό πρότυπο

Αυτό είναι όλο, δημιουργούμε τη λύση ξεκινώντας από μια κενή εφαρμογή ιστού. Τώρα η αρχιτεκτονική μας θα είναι όπως παραθέτουμε παρακάτω, οπότε θα πρέπει να δημιουργήσουμε τα διαφορετικά έργα:

την τρέχουσα αρχιτεκτονική μας

Για να το κάνετε αυτό, για καθένα απλώς κάντε δεξί κλικ στη Λύση και προσθέστε ένα έργο 'Βιβλιοθήκη κλάσης (.NET Core)'.

πρόσθεσε ένα

Η αρχιτεκτονική

Στην προηγούμενη ενότητα δημιουργήσαμε οκτώ έργα, αλλά σε τι χρησιμεύουν; Ακολουθεί μια απλή περιγραφή του καθενός:

  • Interfaces: Αυτό είναι το έργο εκκίνησής μας και όπου δημιουργούνται τελικά σημεία. Εδώ θα ρυθμίσουμε το JWT, τις εξαρτήσεις έγχυσης και τους ελεγκτές.
  • Commons: Εδώ πραγματοποιούμε μετατροπές από τον τύπο δεδομένων που οι ελεγκτές θα επιστρέψουν στις απαντήσεις στη διεπαφή. Είναι καλή πρακτική να ταιριάζετε αυτά τα μαθήματα με τα μοντέλα front-end.
  • Models: Αυτό θα είναι χρήσιμο στην εφαρμογή των εξαρτήσεων ένεσης. Το συναρπαστικό όφελος μιας στατικά δακτυλογραφημένης γλώσσας είναι ότι ο μεταγλωττιστής μπορεί να σας βοηθήσει να επαληθεύσετε ότι πληρούται πραγματικά ένα συμβόλαιο στο οποίο βασίζεται ο κώδικάς σας.
  • ViewModels: Όλες οι κοινόχρηστες συμπεριφορές και ο κωδικός χρησιμότητας θα είναι εδώ.
  • Models: Είναι καλή πρακτική να μην ταιριάζει απευθείας με τη βάση δεδομένων με την πρόσοψη Maps, οπότε ο σκοπός της ViewModels είναι η δημιουργία κλάσεων βάσεων δεδομένων οντοτήτων ανεξάρτητες από τη διεπαφή Αυτό θα μας επιτρέψει στο μέλλον να αλλάξουμε τη βάση δεδομένων μας χωρίς απαραίτητα να επηρεάσουμε τη διεπαφή μας. Βοηθά επίσης όταν απλά θέλουμε να κάνουμε κάποια αναδιαμόρφωση.
  • Models: Εδώ χαρτογραφούμε Services έως Repositories και αντίστροφα. Αυτό το βήμα καλείται μεταξύ ελεγκτών και υπηρεσιών.
  • App_Start: Μια βιβλιοθήκη για την αποθήκευση όλης της επιχειρηματικής λογικής.
  • JwtTokenConfig.cs: Αυτό είναι το μόνο μέρος όπου καλούμε τη βάση δεδομένων.

Οι αναφορές θα έχουν την εξής μορφή:

Διάγραμμα αναφορών

Έλεγχος ταυτότητας με βάση το JWT

Σε αυτήν την ενότητα, θα δούμε τη βασική διαμόρφωση του ελέγχου ταυτότητας διακριτικών και θα προχωρήσουμε λίγο πιο βαθιά στο θέμα της ασφάλειας.

Για να ξεκινήσετε να ρυθμίζετε το διακριτικό ιστού JSON (JWT) ας δημιουργήσουμε την επόμενη τάξη μέσα στο namespace SeedAPI.Web.API.App_Start { public class JwtTokenConfig { public static void AddAuthentication(IServiceCollection services, IConfiguration configuration) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = configuration['Jwt:Issuer'], ValidAudience = configuration['Jwt:Issuer'], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration['Jwt:Key'])) }; services.AddCors(); }); } } } φάκελος που ονομάζεται appsettings.json. Ο κώδικας στο εσωτερικό θα μοιάζει με αυτόν:

'Jwt': { 'Key': 'veryVerySecretKey', 'Issuer': 'http://localhost:50498/' }

Οι τιμές των παραμέτρων επικύρωσης θα εξαρτηθούν από την απαίτηση κάθε έργου. Ο έγκυρος χρήστης και το κοινό που μπορούμε να ρυθμίσουμε διαβάζοντας το αρχείο διαμόρφωσης ConfigureServices:

startup.cs

Τότε πρέπει να το καλέσουμε μόνο από το // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { DependencyInjectionConfig.AddScope(services); JwtTokenConfig.AddAuthentication(services, Configuration); DBContextConfig.Initialize(services, Configuration); services.AddMvc(); } μέθοδος σε TokenController.cs:

appsettings.json

Τώρα είμαστε έτοιμοι να δημιουργήσουμε τον πρώτο μας ελεγκτή που ονομάζεται 'veryVerySecretKey'. Η τιμή που ορίσαμε στο LoginViewModel έως ViewModels πρέπει να ταιριάζει με αυτό που χρησιμοποιούμε για να δημιουργήσουμε το διακριτικό, αλλά πρώτα, ας δημιουργήσουμε το namespace SeedAPI.ViewModels { public class LoginViewModel : IBaseViewModel { public string username { get; set; } public string password { get; set; } } } μέσα στο namespace SeedAPI.Web.API.Controllers { [Route('api/Token')] public class TokenController : Controller { private IConfiguration _config; public TokenController(IConfiguration config) { _config = config; } [AllowAnonymous] [HttpPost] public dynamic Post([FromBody]LoginViewModel login) { IActionResult response = Unauthorized(); var user = Authenticate(login); if (user != null) { var tokenString = BuildToken(user); response = Ok(new { token = tokenString }); } return response; } private string BuildToken(UserViewModel user) { var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config['Jwt:Key'])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(_config['Jwt:Issuer'], _config['Jwt:Issuer'], expires: DateTime.Now.AddMinutes(30), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } private UserViewModel Authenticate(LoginViewModel login) { UserViewModel user = null; if (login.username == 'pablo' && login.password == 'secret') { user = new UserViewModel { name = 'Pablo' }; } return user; } } } έργο:

BuildToken

Και τέλος ο ελεγκτής:

Authenticate

Το identityDbContext Η μέθοδος θα δημιουργήσει το διακριτικό με τον δεδομένο κωδικό ασφαλείας. Το Models Η μέθοδος έχει μόνο την κωδικοποίηση χρήστη για την στιγμή, αλλά θα χρειαστεί να καλέσουμε τη βάση δεδομένων για να την επικυρώσουμε στο τέλος.

Το πλαίσιο της εφαρμογής

Η ρύθμιση του Entity Framework είναι πολύ εύκολη αφού η Microsoft κυκλοφόρησε την έκδοση Core 2.0— EF Core 2 εν συντομία. Θα πάμε σε βάθος με ένα μοντέλο με κωδικό-πρώτα χρησιμοποιώντας Context, οπότε πρώτα βεβαιωθείτε ότι έχετε εγκαταστήσει όλες τις εξαρτήσεις. Μπορείτε να χρησιμοποιήσετε το NuGet για να το διαχειριστείτε:

Λήψη εξαρτήσεων

Χρησιμοποιώντας το ApplicationContext.cs έργο που μπορούμε να δημιουργήσουμε εδώ μέσα στο IApplicationContext.cs φάκελο δύο αρχεία, EntityBase και EntityBase. Επίσης, θα χρειαζόμαστε ένα User.cs τάξη.

Μαθήματα

Το IdentityUser Τα αρχεία θα κληρονομηθούν από κάθε μοντέλο οντότητας, αλλά namespace SeedAPI.Models { public class User : IdentityUser { public string Name { get; set; } } } είναι μια κλάση ταυτότητας και η μόνη οντότητα που θα κληρονομήσει από namespace SeedAPI.Models.EntityBase { public class EntityBase { public DateTime? Created { get; set; } public DateTime? Updated { get; set; } public bool Deleted { get; set; } public EntityBase() { Deleted = false; } public virtual int IdentityID() { return 0; } public virtual object[] IdentityID(bool dummy = true) { return new List().ToArray(); } } } . Ακολουθούν και οι δύο τάξεις:

ApplicationContext.cs namespace SeedAPI.Models.Context { public class ApplicationContext : IdentityDbContext, IApplicationContext { private IDbContextTransaction dbContextTransaction; public ApplicationContext(DbContextOptions options) : base(options) { } public DbSet UsersDB { get; set; } public new void SaveChanges() { base.SaveChanges(); } public new DbSet Set() where T : class { return base.Set(); } public void BeginTransaction() { dbContextTransaction = Database.BeginTransaction(); } public void CommitTransaction() { if (dbContextTransaction != null) { dbContextTransaction.Commit(); } } public void RollbackTransaction() { if (dbContextTransaction != null) { dbContextTransaction.Rollback(); } } public void DisposeTransaction() { if (dbContextTransaction != null) { dbContextTransaction.Dispose(); } } } }

Τώρα είμαστε έτοιμοι να δημιουργήσουμε App_Start, το οποίο θα μοιάζει με αυτό:

Web.API

Είμαστε πολύ κοντά, αλλά πρώτα θα χρειαστεί να δημιουργήσουμε περισσότερα μαθήματα, αυτή τη φορά στο namespace SeedAPI.Web.API.App_Start { public class DBContextConfig { public static void Initialize(IConfiguration configuration, IHostingEnvironment env, IServiceProvider svp) { var optionsBuilder = new DbContextOptionsBuilder(); if (env.IsDevelopment()) optionsBuilder.UseSqlServer(configuration.GetConnectionString('DefaultConnection')); else if (env.IsStaging()) optionsBuilder.UseSqlServer(configuration.GetConnectionString('DefaultConnection')); else if (env.IsProduction()) optionsBuilder.UseSqlServer(configuration.GetConnectionString('DefaultConnection')); var context = new ApplicationContext(optionsBuilder.Options); if(context.Database.EnsureCreated()) { IUserMap service = svp.GetService(typeof(IUserMap)) as IUserMap; new DBInitializeConfig(service).DataTest(); } } public static void Initialize(IServiceCollection services, IConfiguration configuration) { services.AddDbContext(options => options.UseSqlServer(configuration.GetConnectionString('DefaultConnection'))); } } } φάκελο που βρίσκεται στο namespace SeedAPI.Web.API.App_Start { public class DBInitializeConfig { private IUserMap userMap; public DBInitializeConfig (IUserMap _userMap) { userMap = _userMap; } public void DataTest() { Users(); } private void Users() { userMap.Create(new UserViewModel() { id = 1, name = 'Pablo' }); userMap.Create(new UserViewModel() { id = 2, name = 'Diego' }); } } } έργο. Η πρώτη τάξη είναι να προετοιμάσει το περιβάλλον εφαρμογής και η δεύτερη είναι να δημιουργήσει δείγματα δεδομένων μόνο για σκοπούς δοκιμής κατά τη διάρκεια της ανάπτυξης.

// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { DependencyInjectionConfig.AddScope(services); JwtTokenConfig.AddAuthentication(services, Configuration); DBContextConfig.Initialize(services, Configuration); services.AddMvc(); } // ... // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider svp) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } DBContextConfig.Initialize(Configuration, env, svp); app.UseCors(builder => builder .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials()); app.UseAuthentication(); app.UseMvc(); } App_Start

Και τους καλούμε από το αρχείο εκκίνησης:

DependencyInjectionConfig.cs

Ενεση εξάρτησης

Είναι μια καλή πρακτική να χρησιμοποιείτε ένεση εξάρτησης για να μετακινηθείτε μεταξύ διαφορετικών έργων. Αυτό θα μας βοηθήσει να επικοινωνήσουμε μεταξύ ελεγκτών και χαρτογράφων, χαρτογράφων και υπηρεσιών και υπηρεσιών και αποθετηρίων.

Μέσα στο φάκελο namespace SeedAPI.Web.API.App_Start { public class DependencyInjectionConfig { public static void AddScope(IServiceCollection services) { services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); } } } θα δημιουργήσουμε το αρχείο Map και θα μοιάζει με αυτό:

Service

κείμενο alt εικόνας

Θα χρειαστεί να δημιουργήσουμε για κάθε νέα οντότητα ένα νέο Repository, startup.cs και // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { DependencyInjectionConfig.AddScope(services); JwtTokenConfig.AddAuthentication(services, Configuration); DBContextConfig.Initialize(services, Configuration); services.AddMvc(); } και να ταιριάξουμε με αυτό το αρχείο. Τότε πρέπει απλώς να το καλέσουμε από το namespace SeedAPI.Web.API.Controllers { [Route('api/[controller]')] [Authorize] public class UserController : Controller { IUserMap userMap; public UserController(IUserMap map) { userMap = map; } // GET api/user [HttpGet] public IEnumerable Get() { return userMap.GetAll(); ; } // GET api/user/5 [HttpGet('{id}')] public string Get(int id) { return 'value'; } // POST api/user [HttpPost] public void Post([FromBody]string user) { } // PUT api/user/5 [HttpPut('{id}')] public void Put(int id, [FromBody]string user) { } // DELETE api/user/5 [HttpDelete('{id}')] public void Delete(int id) { } } } αρχείο:

Authorize

Τέλος, όταν πρέπει να λάβουμε τη λίστα χρηστών από τη βάση δεδομένων, μπορούμε να δημιουργήσουμε έναν ελεγκτή χρησιμοποιώντας αυτήν την ένεση εξάρτησης:

Map

Δείτε πώς το Maps υπάρχει ένα χαρακτηριστικό εδώ για να είστε σίγουροι ότι το μπροστινό άκρο έχει συνδεθεί και πώς λειτουργεί η έγχυση εξάρτησης στον κατασκευαστή της κλάσης.

Έχουμε τελικά μια κλήση στη βάση δεδομένων, αλλά πρώτα, πρέπει να κατανοήσουμε το ViewModels έργο.

Το UserMap.cs Εργο

Αυτό το βήμα είναι απλώς στο χάρτη namespace SeedAPI.Maps { public class UserMap : IUserMap { IUserService userService; public UserMap(IUserService service) { userService = service; } public UserViewModel Create(UserViewModel viewModel) { User user = ViewModelToDomain(viewModel); return DomainToViewModel(userService.Create(user)); } public bool Update(UserViewModel viewModel) { User user = ViewModelToDomain(viewModel); return userService.Update(user); } public bool Delete(int id) { return userService.Delete(id); } public List GetAll() { return DomainToViewModel(userService.GetAll()); } public UserViewModel DomainToViewModel(User domain) { UserViewModel model = new UserViewModel(); model.name = domain.Name; return model; } public List DomainToViewModel(List domain) { List model = new List(); foreach (User of in domain) { model.Add(DomainToViewModel(of)); } return model; } public User ViewModelToDomain(UserViewModel officeViewModel) { User domain = new User(); domain.Name = officeViewModel.name; return domain; } } } από και προς μοντέλα βάσεων δεδομένων. Πρέπει να δημιουργήσουμε ένα για κάθε οντότητα και, ακολουθώντας το προηγούμενο, το παράδειγμα Services το αρχείο θα μοιάζει με αυτό:

namespace SeedAPI.Services { public class UserService : IUserService { private IUserRepository repository; public UserService(IUserRepository userRepository) { repository = userRepository; } public User Create(User domain) { return repository.Save(domain); } public bool Update(User domain) { return repository.Update(domain); } public bool Delete(int id) { return repository.Delete(id); } public List GetAll() { return repository.GetAll(); } } }

Φαίνεται για άλλη μια φορά, η εξάρτηση εξάρτησης λειτουργεί στον κατασκευαστή της τάξης, συνδέοντας τους Χάρτες με το έργο Υπηρεσίες.

Το Repositories Εργο

Δεν υπάρχουν πολλά να πούμε εδώ: Το παράδειγμά μας είναι πραγματικά απλό και δεν έχουμε επιχειρηματική λογική ή κώδικα για να γράψουμε εδώ. Αυτό το έργο θα αποδειχθεί χρήσιμο σε μελλοντικές προηγμένες απαιτήσεις όταν πρέπει να υπολογίσουμε ή να κάνουμε κάποια λογική πριν ή μετά τα βήματα της βάσης δεδομένων ή του ελεγκτή. Ακολουθώντας το παράδειγμα, η τάξη θα φαίνεται αρκετά γυμνή:

UserRepository.cs

Το namespace SeedAPI.Repositories { public class UserRepository : BaseRepository, IUserRepository { public UserRepository(IApplicationContext context) : base(context) { } public User Save(User domain) { try { var us = InsertUser(domain); return us; } catch (Exception ex) { //ErrorManager.ErrorHandler.HandleError(ex); throw ex; } } public bool Update(User domain) { try { //domain.Updated = DateTime.Now; UpdateUser(domain); return true; } catch (Exception ex) { //ErrorManager.ErrorHandler.HandleError(ex); throw ex; } } public bool Delete(int id) { try { User user = Context.UsersDB.Where(x => x.Id.Equals(id)).FirstOrDefault(); if (user != null) { //Delete(user); return true; } else { return false; } } catch (Exception ex) { //ErrorManager.ErrorHandler.HandleError(ex); throw ex; } } public List GetAll() { try { return Context.UsersDB.OrderBy(x => x.Name).ToList(); } catch (Exception ex) { //ErrorManager.ErrorHandler.HandleError(ex); throw ex; } } } } Εργο

Φτάνουμε στην τελευταία ενότητα αυτού του σεμιναρίου: Απλώς πρέπει να πραγματοποιούμε κλήσεις στη βάση δεδομένων, επομένως δημιουργούμε ένα

|_+_|
αρχείο όπου μπορούμε να διαβάσουμε, να εισαγάγουμε ή να ενημερώσουμε τους χρήστες στη βάση δεδομένων.

|_+_|

Περίληψη

Σε αυτό το άρθρο, εξήγησα πώς να δημιουργήσετε μια καλή αρχιτεκτονική χρησιμοποιώντας το Angular 5 και το Web API Core 2. Σε αυτό το σημείο, έχετε δημιουργήσει τη βάση για ένα μεγάλο έργο με κώδικα που υποστηρίζει μια μεγάλη αύξηση των απαιτήσεων.

Η αλήθεια είναι ότι τίποτα δεν ανταγωνίζεται τη JavaScript στο μπροστινό μέρος και τι μπορεί να ανταγωνιστεί το C # εάν χρειάζεστε την υποστήριξη του SQL Server και του Entity Framework στο πίσω μέρος; Έτσι, η ιδέα αυτού του άρθρου ήταν να συνδυάσει τα καλύτερα από δύο κόσμους και ελπίζω να το απολαύσατε.

Τι έπεται?

Εάν εργάζεστε σε μια ομάδα Γωνιακοί προγραμματιστές μάλλον θα μπορούσαν να υπάρχουν διαφορετικοί προγραμματιστές που εργάζονται στο μπροστινό και στο πίσω μέρος, οπότε μια καλή ιδέα να συγχρονίσετε τις προσπάθειες και των δύο ομάδων θα μπορούσε να είναι η ενσωμάτωση του Swagger με το Web API 2. Το Swagger είναι ένα εξαιρετικό εργαλείο για την τεκμηρίωση και τη δοκιμή των API RESTFul. Διαβάστε τον οδηγό της Microsoft: Ξεκινήστε με το Swashbuckle και το ASP.NET Core .

Εάν εξακολουθείτε να είστε πολύ νέοι στο Angular 5 και αντιμετωπίζετε προβλήματα με την παρακολούθηση, διαβάστε Ένα Angular 5 Tutorial: Βήμα προς βήμα Οδηγός για την πρώτη σας εφαρμογή Angular 5 από τους συναδέλφους ApeeScapeer Sergey Moiseev.

Κατανόηση των βασικών

Πρέπει να χρησιμοποιήσετε τον Visual Studio Code ή το Microsoft Visual Studio για επεξεργασία διεπαφής;

Μπορείτε να χρησιμοποιήσετε είτε IDE για το frontend, πολλοί άνθρωποι επιθυμούν να ενταχθούν στο frontend σε μια Βιβλιοθήκη Εφαρμογών Ιστού και να αυτοματοποιήσουν την ανάπτυξη. Προτιμώ να διατηρήσω τον κώδικα front-end διαχωρισμένο από το back-end και βρήκα το Visual Studio Code να είναι ένα πολύ καλό εργαλείο, ειδικά με intellisense, για τον κώδικα Typescript.

Τι είναι ο σχεδιασμός γωνιακού υλικού και πρέπει να το χρησιμοποιήσουμε ή όχι;

Το Angular Material είναι ένα πλαίσιο συνιστωσών διεπαφής χρήστη και ενώ δεν απαιτείται να το χρησιμοποιήσετε. Τα πλαίσια UI Component μας βοηθούν να οργανώσουμε τη διάταξη και την απόκριση στον ιστότοπο, αλλά έχουμε πολλά από αυτά στην αγορά, όπως bootstrap και άλλα και μπορούμε να επιλέξουμε την εμφάνιση και την αίσθηση που προτιμούμε.

Τι είναι η γωνιακή δρομολόγηση και πλοήγηση;

Ο γωνιακός δρομολογητής επιτρέπει την πλοήγηση από τη μία προβολή στην άλλη καθώς οι χρήστες εκτελούν εργασίες εφαρμογής. Μπορεί να ερμηνεύσει μια διεύθυνση URL του προγράμματος περιήγησης ως οδηγία για την πλοήγηση σε μια προβολή που δημιουργείται από πελάτη. Επιτρέπεται στον προγραμματιστή να ρυθμίσει ονόματα URL, παραμέτρους και μολυσμένο με CanAuthenticate, μπορούμε να επικυρώσουμε την ταυτότητα χρήστη

Ποια είναι η χρήση της ένεσης εξάρτησης στο C #;

Συχνά τα μαθήματα χρειάζονται πρόσβαση το ένα στο άλλο, και αυτό το μοτίβο σχεδίασης δείχνει πώς να δημιουργείτε χαλαρά συνδεδεμένες τάξεις. Όταν δύο τάξεις συνδέονται στενά, συνδέονται με δυαδικό συσχετισμό.

Τι είναι ο έλεγχος ταυτότητας με βάση το JWT;

Το JSON Web Token (JWT) είναι μια συμπαγής βιβλιοθήκη για την ασφαλή μετάδοση πληροφοριών μεταξύ των μερών ως αντικείμενο JSON. Τα JWT μπορούν να κρυπτογραφηθούν για να παρέχουν επίσης μυστικότητα μεταξύ των μερών, θα επικεντρωθούμε σε υπογεγραμμένα διακριτικά.

Το Realm είναι η καλύτερη λύση βάσης δεδομένων Android

Κινητό

Το Realm είναι η καλύτερη λύση βάσης δεδομένων Android
Art vs Design - Μια διαχρονική συζήτηση

Art vs Design - Μια διαχρονική συζήτηση

Ζωή Σχεδιαστών

Δημοφιλείς Αναρτήσεις
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Πώς να επιλέξετε το καλύτερο πλαίσιο Front-End
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Χρειάζεστε έναν ήρωα: Ο υπεύθυνος έργου
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Πώς να βελτιώσετε την απόδοση της εφαρμογής ASP.NET στο Web Farm με προσωρινή αποθήκευση
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Οι δοκιμασμένοι και αληθινοί νόμοι του UX (με Infographic)
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
Ανώτερος συνεργάτης πελάτη, υγειονομική περίθαλψη και βιοεπιστήμες
 
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
Η άνοδος των αυτοματοποιημένων συναλλαγών: Μηχανές που εμπορεύονται το S&P 500
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
10 πιο κοινές ευπάθειες ασφαλείας στον Ιστό
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Σκέψεις για τη συγκέντρωση του ιδιωτικού σας αμοιβαίου κεφαλαίου
Διευθυντής έργου και διαχείρισης προϊόντων
Διευθυντής έργου και διαχείρισης προϊόντων
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Η σημασία της διατήρησης πελατών - μια εμπειρική μελέτη
Δημοφιλείς Αναρτήσεις
  • τι είναι η δοκιμή μονάδας με παράδειγμα
  • η θεωρία gestalt βασίζεται στην ιδέα ότι
  • τύπος εταιρείας s ή c
  • ποιοι είναι οι διαφορετικοί τύποι llc
  • τι είναι το powerpivot στο excel
  • παραδείγματα αρχών gestalt στην πραγματική ζωή
  • τι είναι οδηγία στο angularjs
Κατηγορίες
  • Επιστήμη Δεδομένων Και Βάσεις Δεδομένων
  • Κατανεμημένες Ομάδες
  • Ευκίνητο Ταλέντο
  • Κερδοφορία & Αποδοτικότητα
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt