Ce que ce Framework apporte dépend pas mal de ceux qui l'utilisent...
En ce qui concerne les couches :
Pour les débutants, il offre un projet pré structuré en couches très claires.
Il y en a beaucoup, c'est vrai, mais c'est très pratique (surtout quand c'est déjà fait).
Pour les développeurs plus confirmés, ma structuration en couche n'est pas super moderne mais j'ai voulu qu'elle soit très claire et éviter les concepts compliqués.
Toutes les références entre les couches sont faites et il ne faut pas y toucher.
En ce qui concerne la génération :
Le framework contient des .tt répartis à des endroits appropriés.
On génère l'EDMX en choisissant la stratégie de génération de code : aucune
On reconstruit l'ensemble des tt
- tables d'options (que j'ai l'habitude d'appeler lookups) sont automatiquement converties en enum. Ce qui permet de faire des switch à l'aide d'un petit outil du framework EnumTypeTo<T> qui permet de passer de l'int de l'Id à sa valeur ennumérée, c'est SUPER PRATIQUE.
et ça fonctionne aussi dans l'autre sens EnumTools.EnumTypeTo<int>(enTypesBranches.applicationpool)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 switch (EnumTools.EnumTypeTo<enTypesBranches>(model.typeNodeId)) { #region applicationpool case enTypesBranches.applicationpool: bla bla bla break; }
- domain (je pense que j'aurais du appeler ça entities mais finalement c'est assez clair) : C'est là que sont générées les classes entités à la place de celles qui sont générées par l'edmx. Ces classes ont les mêmes limitations que les entities de l'EF.
- MetaData : Ce sont des objets qui ont strictement la même signature que les entités mais sans la navigation. Il sont décorés des data annotations localisées (toutes, y compris celles qui ne pouvaient pas l'être dans la version d'origine), les ressources associées sont liées par un Tag préfixé Ety_...
Depuis hier, un nouveau tt va générer l'ensemble des ressources dont les chaines seront préfixées par deux _ (ce tt conserver les chaines ajoutées à la main d'une génération à l'autre, il génère autant de lanques qu'on veut, il suffit donc d'envoyer les XML à un traducteur par langue et de réintégré ça.
- Dto : Même principe que les MetaData mais les classes et les membres sont dévorés avec les [DataContract] et [DataMember]
- DataRepository : une seule classe pour tous les datarepositories (on aurait pu faire une classe par DR comme certain le font, c'était plus simple pour moi de faire comme ça).
TRES IMPORTANT : L'ensemble des E/S en base supporte les Transactions.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 [HttpPost] public JsonResult Arbre_CreationBranche(string authority) { JavaScriptSerializer serializer = new JavaScriptSerializer(); Arbre_ActionBranche_JSon model = serializer.Deserialize<Arbre_ActionBranche_JSon>(Request.Form[0]); using (TransactionScope TS = new TransactionScope()) { try { using (InnovaCMSRepositories _context = new InnovaCMSRepositories()) { InnovaTreeTools TreeTools = new InnovaTreeTools(_context); Hierarchy nouvelleBranche = TreeTools.CreationBranche(model.title, model.parentId, model.position, model.typeNodeId); switch (EnumTools.EnumTypeTo<enTypesBranches>(model.typeNodeId)) { case enTypesBranches.storagefolder: using (InnovaCMSServices.IOManagerClient _serviceContext = new InnovaCMSServices.IOManagerClient()) { //ToDo:Ici //_serviceContext.Folder_Create() } break; case enTypesBranches.storagefile: break; default: throw new NotSupportedException(); } } TS.Complete(); } catch (Exception ex) { TS.Dispose(); throw ex; } } throw new NotImplementedException(); }
La combinaison de ces trois catégories d'objets (mappés les un sur les autres avec EmmitMapper) permet d'utiliser une couche business commune aux portails et aux web services (en gros on développe le portail en rangeant bien son code dans la couche business et il devient naturel de doter les portails d'une API en plus des services business).
Sur mon projet en cours, il n'y a plus que le système des ressources générées mais je n'ai pas encore eu le temps de le ré-intégré au Framework.
En ce qui concerne la communication entre le modèle et la vue
la vue et la vue layout, il y a un les contrôleurs héritent d'un _Controllers_Base<T> where T:_Models_Base
En d'autres termes, toutes les membres nécessaires à la vue layout sont déclarés dans _Models_Base, ça permet de convertir le model en _models_base dans la vue layout et donc de bénéficier de membres fortement typés et permet de ne pas avoir à utiliser le ViewBag.
Petit désavantage, manipulation d'un seul modèle par controlleur (pour ceux qui utilisent la vue layout et donc, pas pour les vues partielles).
En ce qui concerne la communication entre les controlleurs et les fichiers CSS et Javascript.
Chaque Vue [View] dispose
- Javascript (JQuery) ino[View].js
- Javascript (JQuery) ino[View]DocReady.js
- Javascript (JQuery) inoDynamic[View].js (facultatif) générée par une vue afin de passer des valeurs depuis le serveur aux scripts chargés par l'intermédiaire de variables (script construit côté serveur)
C'est ultra pratique pour configurer dynamiquement certains composants JQuery UI (jstree, jqgrid que j'utilise en JQuery UI Pur et non dans sa version mvc).- css ino[View].css
- css inoDynamic[View].css (facultatif) même principe que le fichier javascript dynamique.
En ce qui concerne le javascript, plus de javascript au profit du JQuery.
Pour ma part, j'utilise power amc combiné avec 3 scripts SQL en plus de celui qui est généré par power amc
Destruction de la base
Re création de la base
Injection de la structure générée par Power AMC
Re injection des données (bien entendu, ce script doit parfois être modifié à la main).
La connections à la base est ouverte une seule fois par méthode publique (get/post) du contrôleur.
Je dois encore améliorer le concept en particulier pour la couche de sécurité qui ne s'appuie pas sur cette connexion mais qui ouvre et ferme une connexion indépendantes.
Lorsque le starter kit sera terminé, il y aura des controleurs et des vues pour concus pour faciliter la compréhension de tout ça.
De mon point de vue (mais je ne suis pas objectif)... Ca me parait être le meilleur compromis souplesse / stabilité.
Une fois qu'on a compris la façon de l'utiliser, ça fait gagner beaucoup de temps et en particulier en mode agile où on restructure la base fréquemment.
Tous les web services sont structurés de la même facon :
MethodeResult Methode (MethodeQuery query) {
implementation.... (utilisation de classes d'implémentation qui utilisent les classes de la couche business).
}
C'est super pratique...
MethodeResult hérite de IResult
MethodeQuery hérite de IQuery
ces deux interfaces permettent de forcer le développeur à implémenter des membres qui permettent de monitorer le tout.
La couche common permet de partager les objets entre plusieurs portails et plusieurs web services.
Pour conclure (pour ce soir) je dirais que c'est un projet hyper factorisé, quasement pas de redondance de code.
Implémentation de log4net
il y a tout les outils nécessaires pour réussir son projet MVC aussi important soit-il (encore une fois, c'est selon moi et je ne suis pas objectif).
++
Laurent
Partager