1。はじめに
この記事では、AngularJを実際のプロジェクトに適用する方法を紹介します。この記事では、AngularJSを使用して、簡単な許可管理システムを作成します。以下ではあまり言いません。トピックにアクセスしてください。
2。全体的なアーキテクチャデザインの紹介
まず、プロジェクト全体の建築設計図を見てみましょう。
上記の図から、プロジェクト全体の全体的な構造を見ることができます。次に、プロジェクトの全体的な構造を詳細に紹介します。
ASP.NET Web APIを使用して、RESTサービスを実装します。この実装方法により、公共の使用、展開、バックエンドサービスのより良い拡大が達成されました。 Webレイヤーは、アプリケーションサービスインターフェイスに依存し、Castle Windsorを使用して依存関係の注入を実装します。
表示レイヤー(ユーザーUI)
ディスプレイレイヤーは、AngularJSを使用してSPAページを実装します。すべてのページデータは非同期にロードされ、ローカルで更新されるため、この実装によりユーザーエクスペリエンスが向上します。
アプリケーションサービス
AngularJSは、Web APIにHTTPサービスを介してデータを取得するように要求し、Web APIの実装はアプリケーションレイヤーを呼び出してデータを要求することです。
インフラストラクチャレイヤー
インフラストラクチャレイヤーには、倉庫の実装といくつかの一般的な方法の実装が含まれます。
倉庫層の実装は、最初にEFコードに実装され、EF移行法はデータベースの作成と更新に使用されます。
LH.commonレイヤーは、ログヘルプクラス、表現ツリー拡張、その他のクラスなど、いくつかの一般的な方法を実装しています。
ドメインレイヤー
ドメインレイヤーは、主にドメインモデルの実装や倉庫インターフェイスの定義など、プロジェクトのすべてのドメインモデルを実装しています。
完全な構造を導入することに加えて、それぞれプロジェクトのWebフロントエンドのバックエンドサービスの実装と実装を導入します。
3。バックエンドサービスの実装
バックエンドサービスは主にASP.NET Web APIを使用してバックエンドサービスを実装し、Castle Windsorを使用して依存関係の噴射を完了します。
ここでは、許可管理のユーザー管理を使用して、REST Web APIサービスの実装を導入します。
ユーザーデータを提供するレストサービスの実装:
パブリッククラスの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 getuserinfo(int id){return _userservice.getuser(id); } [httppost] [route( "api/user/adduser")] public outputbase createUser([frombody] userdto userdto){return _userservice.adduser(userdto); } [httppost] [route( "api/user/updetwususer")] public outputbase updetuser([frombody] 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/eleterole/{id}/{robleId}")] public outputbase leterole(int id、int roleid){return _userservice.deleterole(id、roleid); }}上記のコードの実装から、ユーザーの休憩サービスはIUSERServiceとのインターフェイスに依存しており、すべてのビジネスロジックを従来の方法でWeb API実装に配置するのではなく、代わりに特定のビジネス実装を対応するアプリケーションレイヤーにカプセル化することがわかります。 REST APIは、対応するアプリケーションレイヤーでサービスを呼び出すことのみを担当します。このデザインの利点は次のとおりです。
RESTサービス部門は、アプリケーションレイヤーとのインターフェイスに依存して、責任を分離し、アプリケーションレイヤーサービスのインスタンス化を、完了するために個別の依存関係噴射コンテナに引き渡します。 RESTサービスは、対応するアプリケーションサービスメソッドを呼び出してデータを取得する責任のみを担当します。特定のクラスで実装の代わりに依存関係インターフェイスを使用すると、クラス間のカップリングが低くなります。 RESTサービスには、特定のビジネスロジック実装は含まれていません。このデザインは、サービスをより良くすることができます。 WCFを使用して後の段階でレストサービスを実装する場合は、WCFのRESTサービスクラスでWeb APIにロジックを繰り返し記述する必要はありません。現時点では、Application Service Interfaceメソッドを呼び出してWCF RESTサービスを実装できます。したがって、ビジネスロジックの実装は、アプリケーションサービスレイヤーに抽出され、実装されます。この設計により、RESTサービスの責任がより単一であり、RESTサービスの実装が拡大しやすくなります。
ユーザーアプリケーションサービスの実装:
パブリッククラスユーザーサービス:BaseService、iUserservice {private readonly iuserrepository _userrepository; private readonly iuserrolerepository _userrolerepository; public userservice(iUserRepository userrepository、iuserrolerepository userrolerepository){_userrepository = userrepository; _USERROLEREPOSITRY = USERROLEREPOSITORY; } public getResults <userdto> getusers(pageinput input){var result = getDefault <getResults <userdto >>(); var filterExp = buildExpression(input); 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、email = user.email、state = name = user.name、user = user.realname、password = "*******"、rololes = user.take(4)。 z.role.id、name = z.role.rolename})。tolist()、totalrole = user.userroles.count()})返品結果; } public updateresult updateUser(userdto user){var result = getDefault <updateresult>(); var expstuser = _userrepository.findsingle(u => u.id == user.id); if(expecuser == null){result.message = "user_not_exist"; result.statecode = 0x00303;返品結果; } if(ishassamename(expessuser.name、expessuser.id)){result.message = "user_name_has_exist"; result.statecode = 0x00302;返品結果; } expstuser.realname = user.realname; expstuser.name = user.name; expessuser.state = user.state; expessuser.email = user.email; _userrepository.update(expecuser); _userrepository.commit(); result.issaved = true;返品結果; } 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;返品結果; } var user = new user(){creationtime = dateTime.now、password = ""、email = userdto.email、state = userdto.state、realname = userdto.realname、name = userdto.name}; _userrepository.add(user); _userrepository.commit(); result.id = user.id; result.iscreated = true;返品結果; } public releteres deleteuser(int userid){var result = getDefault <Eleteresult>(); var user = _userrepository.findsingle(x => x.id == userId); if(user!= null){_userrepository.delete(user); _userrepository.commit(); } result.isdeleted = true;返品結果; } public updateresult updatepwd(userdto user){var result = getdefault <updateresult>(); var userentity = _userrepository.findsingle(x => x.id == user.id); if(userEntity == null){result.message = string.format( "現在編集されたユーザー" {0} "" Noも存在しなくなりました "、user.name);返品結果; } userentity.password = user.password; _userrepository.commit(); result.issaved = true;返品結果; } public getResult <userdto> 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;返品結果; } result.data = new userdto(){createtime = model.creationtime、email = model.email、id = model.id、realname = model.realname、state = model.state、name = model.name、password = "******"};返品結果; } public updateresult updateroles(userdto user){var result = getdefault <updateresult>(); var model = _userrepository.findsingle(x => x.id == user.id); if(model == null){result.message = "use_not_exist"; result.statecode = 0x00402;返品結果; } var list = model.userroles.tolist(); if(user.roles!= null){foreach(user.rolesのvarアイテム){if(!list.exists(x => x.role.id == item.id)){_userrolerepository.add(new userrole {new userrole {alow.id、userid = userid = userid = model.id}); }} foreach(list in list){if(!user.roles.exists(x => x.id == item.id)){_userrolerepository.delete(item); }} _userrolerepository.commit(); _userrepository.commit(); } result.issaved = true;返品結果; } public releteresult leteretole(int userid、int roleid){var result = getDefault <Eleteresult>(); var model = _userrolerepository.findsingle(x => x.userid == userid && x.roleid == roleId); if(model!= null){_userrolerepository.delete(model); _userrolerepository.commit(); } result.isdeleted = true;返品結果; } public boolが存在する(string username、string password){return _userrepository.findsingle(u => u.name == username && u.password == password)!= null; } private bool ishassamename(string name、int userid){return!string.isnullorwhitespace(name)&& _userrepository.find(u => u.name == name && u.id!= userId).any(); } private expression <func <user、bool >> buildexpression(pageinput pageinput){expression <func <user、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);壊す;ケース1:FilterExp = user => user.name.contains(pageinput.name);壊す;ケース2:FilterExp = user => user.email.contains(pageinput.name);壊す; } return filterExp; }}ここでは、アプリケーションサービスレイヤーを実際に最適化し、コードレベルの読み取りと書き込みの分離を実装し、iReadonlyServiceインターフェイスとiWriteservieインターフェイスを定義し、一般的な方法の形でBaseserviceに書き込み操作を抽象化できます。このような追加、削除、および変更操作は公開されています。この操作を公表できる理由は、これらのオペレーションが非常に似ており、オペレーションの異なるエンティティにすぎないためです。実際、この実装は、別のオープンソースプロジェクトであるOnlinestoreで使用されています。これを参照して自分で実装できます。
ストレージレイヤーの実装:
ユーザーアプリケーションサービスは、特定の倉庫クラスに直接依存するのではなく、インターフェイスにも依存しています。対応するユーザーウェアハウジングクラスは、次のように実装されます。
パブリッククラスBaserePository <tentity>:irepository <tentity>ここで、class、ientity {private readonly threadlocal <usermanagerdbcontext> _localctx = new swreetlocal <usermanagerdbcontext>(()= => new usermanagerdbcontext()); public usermanagerdbcontext dbcontext {get {return _localctx.value; }} public Tentity findSingle(expression <func <ttentity、bool >> exp = null){return dbcontext.set <tentity>()。 } public iQueryable <tentity> find(expression <func <ttentity、bool >> exp = null){return(exp); } public iQueryable <tentity> find(expression <func <func <contity、bool >>式、式<func <func <func <func <func <func <func <func <dynamic >> sortorder sortorder、int pageNumber、int pagesize){if(pagenumber <= 0)show new arguptofrangeexception( "pagenumber"、pagenumber、 "pagenumber or") if(pagesize <= 0)throw new argumpoutOutofRangeException( "pagesize"、pagesize、 "pagesizeは1よりも等しくなければなりません"); var query = dbcontext.set <tentity>()。where(expression); var skip =(pagenumber -1) * pageize; var take = pagesize; if(sortpredicate == null)新しいInvalidoperationException( "ページングに基づくに基づく必要がある必要があります。 switch(sortorord){case sortorder.assand:var pagedascending = query.sortby(sortpredicate).skip(skip).take(take); Pagedassindを返します。 case sortorder.descending:var pageddescending = query.sortbydescending(sortpredicate).skip(skip).take(take); PagdeScendingを返します。 }新しいInvalidOperationException( "ページングに基づいて、並べ替えフィールドと並べ替え順序を指定する必要があります。"); } public int getCount(expression <func <cttentity、bool >> exp = null){return(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>()。remove(entity); } public void delete(icollection <tentity> entityCollection){if(entityCollection.count == 0)return; dbcontext.set <tentity>()。attach(entitycollection.first()); dbcontext.set <tentity>()。removerange(entitycollection); } private iqueryable <tentity>フィルター(式<func <contity、bool >> exp){var dbset = dbcontext.set <tentity>()。asqueryable(); if(exp!= null)dbset = dbset.where(exp); dbsetを返します。 } public void commit(){dbcontext.savechanges(); }} public class userrepository:baserepository <user>、iuserrepository {}4。AngularJSフロントエンドの実装
Webフロントエンドの実装は、AngularJを使用してそれを実装し、モジュラー開発モデルを採用することです。 Webフロントエンドの特定のコード構造を以下の図に示します。
アプリ /画像// Webフロントエンドアプリ /スタイルで使用される画像リソースの保存アプリ/モジュール//プロジェクト依存関係ライブラリ、Angular、Bootstrap、JQuery Library App/Views // Angularjsビューテンプレートストレージディレクトリ
AngularJSを使用して開発されたWebアプリケーションのコード間の呼び出しレベルとバックエンドは、基本的にバックエンドと同じであり、ビューページ - コントローラーモジュール - サービスモジュール - Web APIサービスでもあります。
さらに、フロントエンドWebでのCSSおよびJSリソースのロードにより、バンドルメソッドが採用され、要求されたリソースの数が減り、ページの読み込み時間が高速化されます。特定のバンドルクラスの構成:
パブリッククラスBundleconfig {//バンドリングの詳細については、http://go.microsoft.com/fwlink/?linkid=301862 public static void restorgbundles(bundlecollection bundles){//クラスライブラリ依存ファイルバンドルズ。 "〜/app/modules/jquery-1.11.2.min.js"、 "〜/app/modules/angular/angular.min.js"、 "〜/app/modules/angular/angular-route.min.js"、 "〜/app/modules/boottrap/js "〜/app/modules/bootstrap-notify/bootstrap-notify.min.js")); // Angularjsプロジェクトファイルbundles.add(new ScriptBundle( "〜/js/angularjs/app")。 "〜/app/scripts/app.js")); // style bundles.add(new StyleBundle( "〜/js/base/style"))。 }}Home index.cshtml
<!doctype html> <html ng-app = "lh"> <head> <meta name = "viewport" content = "width =" device-width "/> <title>シンプルな許可管理システムデモ</title> @styles.render("〜/js/base/style ") @scripts.render("〜/js/ligter ") <nav> <div> <div> <ボタンType = "button" data-toggle = "collapse" data-target = "#navbar" aria-expanded = "false" aria-controls = "navbar"> <span>トグルナビゲーション</span> <span> </span> <span> </span> </smapmed> <a href> <a href> <a href> </button> </div> <div> <ul> <li ng-repeat = "item in ls"> <a href = "#{{item.urls [0] .link}}"> {{item.name}}} </a> </li> </ul> <> <a href = "@url.action {{lang.exit}} </a> </div> </div> </nav> <div> <div> <div> <ul> <li ng-repeat = "item in urls"> <a href = "#{{item.link}}"> {{item.title}}}} </</</</</</</</</</</</< ng-view> </div> </div> </div> </div> </div> @scripts.render( "〜/js/angularjs/app")</body> </html>5。操作効果
フロントエンドとバックエンドの実装を導入した後、プロジェクト全体の操作効果を見てみましょう。
6。概要
この時点で、この記事のすべての内容が導入されましたが、この記事のAngularJSアプリケーションプロジェクトには、バッファリングサポート、読み取りと書き込みの分離なし、一部のAPIでのストレステストなど、多くの完璧な領域がまだありますが、実際のプロジェクトでのAngularJSの適用は基本的にこのようなものです。プロジェクトでAngularjsを使用する必要があり、会社のバックエンドが.NETである場合、この記事の共有は良い参照になると思います。さらに、他のオープンソースプロジェクトであるOnlinestoreおよびFastWorks for Architecture Designについても参照することもできます。
上記は、AngularJSを使用して、エディターが紹介した許可管理システムを作成する方法です。私はそれが誰にでも役立つことを願っています!