1. Einführung
In diesem Artikel werden AngularJs auf tatsächliche Projekte angewendet. In diesem Artikel wird AngularJS verwendet, um ein einfaches Berechtigungsmanagementsystem zu erstellen. Ich werde unten nicht viel sagen, gehen Sie einfach zum Thema.
2. Einführung in das allgemeine Architekturdesign
Schauen wir uns zunächst das architektonische Designdiagramm des gesamten Projekts an:
Aus der obigen Abbildung können wir die Gesamtstruktur des gesamten Projekts sehen. Als nächstes werde ich die Gesamtstruktur des Projekts im Detail vorstellen:
Verwenden Sie die ASP.NET -Web -API, um REST -Dienste zu implementieren. Diese Implementierungsmethode hat die öffentliche Nutzung, Bereitstellung und eine bessere Erweiterung von Back-End-Diensten erreicht. Die Webschicht hängt von der Anwendungsdienstschnittstelle ab und verwendet Castle Windsor, um die Abhängigkeitsinjektion zu implementieren.
Schicht anzeigen (Benutzer Benutzeroberfläche)
Die Anzeigeschicht verwendet AngularJs, um Spa -Seiten zu implementieren. Alle Seitendaten werden asynchron geladen und lokal aktualisiert, sodass diese Implementierung eine bessere Benutzererfahrung hat.
Anwendungsdienst
AngularJS fordert die Web -API auf, Daten über den HTTP -Dienst zu erhalten, und die Implementierung der Web -API besteht darin, die Anwendungsebene aufzurufen, um Daten anzufordern.
Infrastrukturschicht
Die Infrastrukturschicht umfasst die Implementierung von Lagerheimen und die Implementierung einiger gemeinsamer Methoden.
Die Implementierung der Lagerschicht wird zuerst im EF -Code implementiert, und die EF -Migrationsmethode wird zum Erstellen und Aktualisieren der Datenbank verwendet.
Die LH.Common -Schicht implementiert einige gemeinsame Methoden wie logarithmische Hilfsklassen, Expressionsbaumerweiterungen und andere Klassen.
Domänenschicht
Die Domänenschicht implementiert hauptsächlich alle Domänenmodelle des Projekts, einschließlich der Implementierung des Domänenmodells und der Definition der Lagerung.
Zusätzlich zur Einführung der vollständigen Struktur werden wir die Implementierung von Back-End-Service und die Implementierung des Web-Front-Ends des Projekts einführen.
3. Implementierung von Back-End-Service
Backend -Dienste verwenden hauptsächlich die ASP.NET -Web -API, um Backend -Dienste zu implementieren, und Castle Windsor wird verwendet, um die Abhängigkeitsinjektion zu vervollständigen.
Hier verwenden wir die Benutzerverwaltung in der Berechtigungsverwaltung, um die Implementierung des REST -Web -API -Dienstes einzuführen.
Implementierung des REST -Dienstes, der Benutzerdaten liefert:
öffentliche Klasse UserController: apicontroller {private readonly iuserService _UserService; public userController (iuserService userService) {_USERService = userService; } [Httpget] [Route ("api/user/getUsers") public outputBase getUsers ([fromuri] pageInput input) {return _USERService.getUsers (input); } [Httpget] [Route ("api/user/userInfo")] public outputBase getUerInfo (int id) {return _userService.getUser (id); } [Httppost] [Route ("api/user/adduser") public outputBase createUser ([from body] userdto userDto) {return _userService.adduser (userDto); } [Httppost] [Route ("api/user/updateUser")] public outputBase updateUser ([from body] userDto userDto) {return _USERService.Updateuser (userDto); } [Httppost] [Route ("api/user/updateroles") public outputBase updateroles ([FromBody] userDto userDto) {return _USERService.updateroles (userDto); } [Httppost] [Route ("api/user/deleteUser/{id}")] public outputBase deleteUser (int id) {return _userService.deleteUser (id); } [Httppost] [Route ("api/user/deleterol/{id}/{rollen}")] public outputBase deleterol (int id, int rollen) {return _userService.deleteroLe (id, rollen); }}Aus der obigen Code -Implementierung ist ersichtlich, dass der Benutzer -REST -Service von der Schnittstelle mit IUSERService abhängt und nicht die gesamte Geschäftslogik in der Web -API -Implementierung auf traditionelle Weise aufstellt, sondern einige spezifische Geschäftsimplementierungen in die entsprechende Anwendungsschicht integriert. Die Rest -API ist nur dafür verantwortlich, die Dienste in der entsprechenden Anwendungsschicht aufzurufen. Diese Entwurfsvorteile umfassen:
Die Abteilung für REST -Service ist auf die Schnittstelle mit der Anwendungsschicht angewiesen, um die Verantwortlichkeiten zu trennen und die Instanziierung des Anwendungsschichtdienstes zum Fertigstellen an einen separaten Abhängigkeitsinjektionsbehälter zu übergeben. Der Restdienst ist nur dafür verantwortlich, die entsprechenden Anwendungsdienstmethoden aufzurufen, um Daten zu erhalten. Die Verwendung von Abhängigkeitsschnittstellen anstelle von Implementierungen mit bestimmten Klassen führt zu einer geringen Kopplung zwischen Klassen. Der REST -Service enthält keine spezifischen Geschäftslogik -Implementierungen. Dieses Design kann Dienste besser separat machen. Wenn Sie WCF verwenden möchten, um REST -Dienste in der späteren Phase zu implementieren, müssen Sie in der Web -API in der REST -Dienstklasse von WCF nicht wiederholt eine Logik in der Web -API schreiben. Zu diesem Zeitpunkt können Sie die Methode für Anwendungsdienstschnittstellen anrufen, um den WCF -REST -Service zu implementieren. Daher wird die Implementierung der Geschäftslogik an die Anwendungsdienstebene extrahiert, um sie zu implementieren. Mit diesem Design wird die REST -Service -Verantwortlichkeiten eine einzelne und die REST -Service -Implementierung erleichtert.
Implementierung von Benutzeranwendungsdiensten:
Public Class UserService: BaseSeService, iUSERService {private readonly iuSerRepository _uSerRepository; private readonly iuSerRolerePository _userrolerePository; public UserService (iUSerRepository userRepository, iUSerRolerePository userrolerePository) {_uSerRepository = userRepository; _UserrolerePository = userrolerePository; } public GetResults <BenerDto> getUsers (pageInput input) {var result = getDefault <getResults <userDto >> (); var filterExp = buildexpression (Eingabe); var query = _userRepository.find (filterExp, user => user.id, sortOrder.descending, input.current, input.size); result.total = _userrepository.find (filterExp) .count (); result.data = query.select (user => new userDto () {id = user.id, createTime = user.creationTime, E -Mail = user.email, state = user.state, name = user.name, RealName = user.RealName, Passwort = "******", user. z.role.id, name = z.role.rolename}). Tolist (), TotalRole = user.userroles.count ()}). Tolist (); Rückgabeergebnis; } public updateresult updateUser (userDto user) {var ressing = getDefault <Kupdateresult> (); var existuser = _userrepository.findsingle (u => u.id == user.id); if (existuser == null) {result.message = "user_not_exist"; result.statecode = 0x00303; Rückgabeergebnis; } if (iShassamename (Exemplar.name, existuser.id)) {result.message = "user_name_has_exist"; result.statecode = 0x00302; Rückgabeergebnis; } existuser.realname = user.realName; existuser.name = user.name; existuser.state = user.state; existuser.email = user.email; _userRepository.Update (Exemplar); _userRepository.commit (); result.issaved = true; Rückgabeergebnis; } public CreateResult <int> adduser (userDto userDto) {var result = getDefault <createResult <int >> (); if (iShassamename (userDto.name, userDto.id)) {result.message = "user_name_has_exist"; result.statecode = 0x00302; Rückgabeergebnis; } var user = new user () {creationtime = datetime.now, password = "", mail = userdto.email, state = userDto.state, Realname = userDto.realname, name = userDto.name}; _userRepository.add (Benutzer); _userRepository.commit (); result.id = user.id; result.iscreated = true; Rückgabeergebnis; } public deleteresult deleteUser (int userID) {var result = getDefault <LeTeteresult> (); var user = _userRepository.findsingle (x => x.id == userId); if (user! = null) {_userrepository.delete (user); _userRepository.commit (); } result.isDeleted = true; Rückgabeergebnis; } public updateresult updatePWD (userDto user) {var result = getDefault <Untateateresult> (); var userEntity = _userrepository.findsingle (x => x.id == user.id); if (userEntity == null) {result.message = string.format ("Der aktuell bearbeitete Benutzer" {0} "existiert nicht mehr", user.name); Rückgabeergebnis; } userEntity.password = user.password; _userRepository.commit (); result.issaved = true; Rückgabeergebnis; } public GetResult <BenerDto> getUser (int userID) {var result = getDefault <getResult <userDto >> (); var model = _userRepository.findsingle (x => x.id == userId); if (model == null) {result.message = "use_not_exist"; result.statecode = 0x00402; Rückgabeergebnis; } result.data = new userDto () {createTime = model.creation time, E -Mail = modell.email, id = modell.id, realName = model.realname, state = modell.state, name = model.name, password = "******"}; Rückgabeergebnis; } public updateresult updateroles (userDto user) {var ressing = getDefault <Untateresult> (); var model = _userRepository.findsingle (x => x.id == user.id); if (model == null) {result.message = "use_not_exist"; result.statecode = 0x00402; Rückgabeergebnis; } var list = model.userroles.tolist (); if (user.roles! }} foreach (var item in list) {if (! user.roles.exists (x => x.id == item.id)) {_userrolerepository.delete (item); }} _userrolerepository.commit (); _userRepository.commit (); } result.issave = true; Rückgabeergebnis; } public deleteresult deleterol (int userId, int rolId) {var result = getDefault <Deleteresult> (); var model = _userrolerepository.findsingle (x => x.userid == userId && x.roleid == rollen); if (model! = null) {_userrolerepository.delete (Modell); _userrolerePository.commit (); } result.isDeleted = true; Rückgabeergebnis; } public bool existieren (String -Benutzername, String -Passwort) {return _uSerRepository.findsingle (u => U.Name == Benutzername && u.password == Passwort)! = null; } private bool iShassamename (String -Name, int userId) {return! String.isnullorwhiteSpace (Name) && _uSerrepository.find (u => u.= Name && u.id! = userId) .any (); } privater Ausdruck <func <Benutzer, bool >> Buildexpression (pageInput pageInput) {Ausdruck <func <Benutzer, bool >> filterExp = user => true; if (string.isnullorwhitespace (pageInput.name)) return filterExp; Switch (pageInput.type) {case 0: filterExp = user => user.name.contains (pageInput.name) || user.email.contains (pageInput.name); brechen; Fall 1: filterExp = user => user.name.contains (pageInput.name); brechen; Fall 2: filterExp = user => user.email.contains (pageInput.name); brechen; } Rückgabe filterExp; }}Hier kann die Anwendungsdienstebene tatsächlich weiter optimiert werden, die Trennung auf Code-Ebene im Lesen und Schreiben von Code implementieren, die IreadonlyService-Schnittstelle und die IwriteServie-Schnittstelle definieren und die Schreibvorgänge in BaseSeService in Form generischer Methoden abstrahieren. Solche Zusatz-, Lösch- und Modifikationsvorgänge sind öffentlich. Der Grund, warum diese Operation veröffentlicht werden kann, ist, dass diese Operationen sehr ähnlich sind und sie nichts anderes als die verschiedenen Unternehmen der Operationen sind. Tatsächlich wurde diese Implementierung in einem anderen Open -Source -Projekt verwendet: Onlinestore. Sie können sich darauf verweisen, um es selbst zu implementieren.
Implementierung der Speicherschicht:
Benutzeranwendungsdienste beruhen nicht direkt auf bestimmte Lagerklassen, sondern auch auf ihre Schnittstellen. Die entsprechende Benutzerlagerklasse wird wie folgt implementiert:
öffentliche Klasse BasieRePository <Tentity>: irepository <Tentity> WHERE TESTITY: CLASS, IENTITY {private readonly threadLocal <BENEMANAGERDBCONTEXT> _localctx = new ThreadLocal <BENEMANAGERDBCONTEXT> public userManagerDBContext dbContext {get {return _localctx.value; }} public Tentity findSingle (Ausdruck <func <tentity, bool >> exp = null) {return dbContext.set <Tentity> (). } public iQueryable <Tentity> find (Ausdruck <func <tentity, bool >> exp = null) {return filter (exp); } public iQueryable <Tentity> find (Ausdruck <func <Tentity, bool >> Ausdruck, Ausdruck <Funktion <Tentität, dynamisch >> sortPredicate, Sorder -Sorder, int pageNumber, int pagesize) {if (pagenumber <= 0) Werfen Sie neue Argumentenoutoutoutofrangexception ("Pagenumber", "Pagenumber", "Pagenumber", "Pagenumber". if (pageSize <= 0) werfen neue argumentoutofrangeException ("pageSize", pageSize, "pageSize muss groß als oder gleich 1."); var query = dbContext.set <Tentity> (). WHERE (Ausdruck); var Skip = (Pagenumber - 1) * pageSize; var take = pageSize; if (sortPredicate == null) wirf eine neue InvalidoperationException ("Basierend auf der Paging -Abfrage muss Sortierfelder und Sortierreihenfolge angegeben."); Switch (sortOrder) {case sortOrder.ascending: var pagedascending = query.sortby (sortPredicate) .skip (überspringen) .Intake (take); Rückkehr pagedascending; Case Sorder.Descending: var pagedDescending = query.SortByDescending (sortPredicate) .skip (überspringen). Take (take); Rückgabe pagedDescending; } Wirf eine neue InvalidOperationException ("Basierend auf der Paging -Abfrage muss Sortierfelder und Sortierreihenfolge angegeben."); } public int getCount (Ausdruck <func <tentity, bool >> exp = null) {return filter (exp) .count (); } public void add (Tentity Entity) {dbContext.set <Tentity> (). add (Entity); } public void update (Tentity entity) {dbcontext.Entry (Entity) .State = EntityState.modified; } public void delete (Tentity Entity) {dbContext.Entry (Entity) .State = EntityState.Deleted; DbContext.set <Tentity> (). REMET (Entity); } public void delete (iCollection <Tentity> EntityCollection) {if (entityCollection.count == 0) return; DbContext.set <Tentity> (). Attach (entityCollection.First ()); DbContext.set <Tentity> (). Entfernung (EntityCollection); } private iQueryable <Tentity> filter (Ausdruck <func <Tentity, bool >> exp) {var dbset = dbContext.set <Tentity> (). Asqueryable (); if (exp! = null) dbset = dbset.where (exp); DBSET zurückgeben; } public void commit () {dbcontext.savechanges (); }} public class userrepository: BasieRePository <BeuNe>, iuSerRepository {}4. AngularJS Front-End-Implementierung
Die Implementierung des Web-Front-Ends besteht darin, AngularJS zu verwenden, um es zu implementieren und ein modulares Entwicklungsmodell zu übernehmen. Die spezifische Codestruktur des Web-Front-Ends ist in der folgenden Abbildung dargestellt:
App/images // Store image resources used by the web front-end App/Styles // Store style files App/scripts // Script files used in the entire web front-end / Controllers // angularJS controller module storage directory / directives // angularJs instruction module storage directory / filters // filter module storage directory / services // Service module storage directory / app.js // Web front-end program configuration module (routing configuration) App/Module // Projektabhängigkeitsbibliothek, Angular, Bootstrap, JQuery Library App/Ansichten // AngularJS -Vorlagenspeicherverzeichnis anzeigen
Die aufrufende Ebene und das Backend zwischen den Codes der mit AngularJS entwickelten Webanwendungen entsprechen im Grunde genommen mit dem Backend und sind auch die Ansichtsseite - Controller -Modul - Service -Modul - Web -API -Dienst.
Darüber hinaus nimmt das Laden von CSS- und JS-Ressourcen im Front-End-Web die Bundle-Methode an, um die Anzahl der angeforderten Ressourcen zu reduzieren und so die Ladezeit der Seite zu beschleunigen. Spezifische Bündelklassenkonfiguration:
Öffentliche Klasse BundleConfig {// Weitere Informationen zum Bündeln finden Sie unter http://go.microsoft.com/fwlink/?linkid=301862 public static void RegisterBundles (BundleCollection Bundles) {// Klassenbibliotheksabhängungs -Datei Bundles.add (neue Skriptbund (New Scriptbundle ("~/js/js/js/base/lib"). "~/app/modules/jQuery-1.11.2.min.js", "~/app/module/Angular/Angular.min.js", "~/app/module/Angular/Angular-Route.min.js", "~/app/module/bootstrap/js/ui-boots- "~/app/modules/bootstrap-notify/bootstrap-notify.min.js")); // AngularJS -Projektdatei bündel.Add (neuer Skriptbund ("~/js/AngularJs/App"). Include ("~/app/scripts/dienste/*. Js", "~/app/scripts/controller/*. js", "~/app/scripts/criptives/*. js", "~/apps/scripts/scripts/scripts/scripts/scripts/scripts/scripts/*. "~/app/scripts/app.js")); // style bündel.add (neuer styleBundle ("~/js/base/style"). Include ("~/app/modules/bootstrap/css/bootstrap.min.css", "~/app/styles/Dashboard.css", "~/app/styles/console.css.css.css"))); }}Home Index.cshtml
<! DocType html> <html ng-app = "lh"> <head> <meta name = "viewport" content = "width = Gerätebidakte"/> <title> Einfache Bewerbung Management System Demo </title> @styles.render ("~/js/base/style/style") @scripts.render ("~/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/js/base/base/lib") ng-controller = "navigation"> <nav> <div> <div> <button type = "button" data-toggle = "collapse" data-target = "#navbar" aria-expanded = "false" aria-controls = "navbar" href = "/"> Einfache Berechtigungsverwaltung systemdemo </a> </div> <div> <ul> <li ng-repeat = "item in ls"> <a href = "#{{item.urls [0] .Link}}" href = "@url.action (" unlogin "," home ", null)"> {{Lang.exit}} </a> </div> </div> </nav> <div> <div> <ul> <li ng-Repeat = "item in urls"> <a a href="#{{item.link}}">{{item.title}}</a></li> </ul> </div> <div> <div ng-view></div> </div> </div> </div> </div> @Scripts.Render("~/js/angularjs/app")</body></html>5. Betriebseffekt
Nach der Einführung der Implementierung der Vorder- und Rückseite sehen wir uns den Betriebseffekt des gesamten Projekts an:
6. Zusammenfassung
Zu diesem Zeitpunkt wurden alle Inhalte dieses Artikels eingeführt, obwohl das AngularJS -Anwendungsprojekt in diesem Artikel immer noch viele perfekte Bereiche hat, z. Wenn Sie AngularJs in Ihrem Projekt verwenden müssen und das Backend Ihres Unternehmens .NET ist, glaube ich, dass die Freigabe dieses Artikels eine gute Referenz sein kann. Darüber hinaus können Sie sich auch auf mein anderes Open -Source -Projekt beziehen: Onlinestore und Fastworks for Architecture Design.
Die oben genannte Methode zur Verwendung von AngularJs zur Erstellung eines vom Editor eingeführten Berechtigungsmanagementsystems. Ich hoffe, es wird für alle hilfreich sein!