Fermeture du blog

Bonjour à tous, N'ayant plus le temps de mettre à jour ce blog depuis 2007, je reste à votre disposition en tant que MCT Microsoft pour diverses formations officielles sur les techno .NET (WPF,WCF,Team System,Sharepoint,ASP.NET, ADO.NET,SQL Server, C#, Design patterns, etc...) ainsi que certaines formations personnalisées tels que savoir coder proprement ou gérer facilement vos tests unitaires.

Solution pour la gestion et la génération automatique de ressources statiques et dynamiques dans une application Web.


Le projet est téléchargeable ici.


Bonjour à tous,

Aujourd'hui face à l'accessibilité d'internet , les applications se doivent de toucher une clientèle de plus en plus large, cela passe par l'internationalisation des applications et donc la necessité de créer des applications "World-Ready".

Ce terme d'internationalisation au niveau architecture et développement se traduit par la gestion et la mise en place de ressources spécifiques à un public ciblé (Français, Anglais, Allemand, Chinois etc...). 

Prenons le cas d'un site Web, étant donné qu'il s'agit du type d'application à internationaliser par excellence.

Je vais vous expliquer comment gérer et  générer facilement les fichiers ressources d'un site Web, nous nous limiterons aux ressources textuelles afin d'en faire une application Web "World-ready".

1. Externaliser les ressources d'une application Web.

Lorsque vous développez un site Web, vous avez une alternative possible sur la gestion des ressources dans Visual Studio 2005, soit les fichiers ressources seront définis pour le périmètre global de l'application ou soit vous préférez définir une ressource locale applicable sur une partie du projet (juste un répertoire)

Selon que vous optez pour la globalisation ou la spécification des ressources, vous devez créer dans votre application Web deux types de répertoires (ASP.NET Folder) respectivement App_GlobalResources ou App_LocalResources:

Dans notre cas , nous partirons du choix de la globalisation des ressources, ceci afin de rendre la maintenance plus aisée notamment par programmation.

Remarque : Un projet WebSite dans Visual Studio 2005 ne permet pas de générer les ressources dynamiquement car celles-ci sont compilées en DLL nommée : App_GlobalResources.dll se trouvant dans le répertoire "bin" de votre site Web.
Pour cela Microsoft à fournit le service pack 1 de Visual Studio 2005 prenant en charge le projet "Application Web" celui-ci permet de conserver le répertoire App_GlobalResources dans le site déployé et d'éviter cette compilation lors du Publish.

Si vous désirez avoir la possibilité de générer dynamiquement vos ressources pendant que votre site se trouve en production, il vous faut utiliser un projet de type "Application Web ASP.NET" au lieu du projet Web Site ( voir Remarque ci-dessus) plus d'information sont disponible ici, si vous désirez migrer votre WebSite en une Application Web.

Je ne m'étendrai pas sur la façon d'utiliser les ressources dans une application Web, je pense que suffisament de cours sont disponibles sur le net, voir ici par exemple.
Mais plus particulièrement sur la façon de mettre en place une solution afin de générer dynamiquement ces ressources dans une application Web.

Si vous avez déjà travaillé sur une application Web, vous avez dû être confronté à une problématique au niveau des ressources, la necessité de devoir gérer deux types de ressources :

  • Les ressources statiques, celles qui restent indépendantes des événements et du comportement de l'utilisateur (titre d'une page, logo, label)
  • Les ressources dynamiques, celles qui sont construites dynamiquement par concaténation ou provenant d'une base de données.

D'une part, les ressources statiques peuvent être gérées facilement à l'aide de fichier resource ASP.NET dans notre répertoire App_GlobalResources.
D'autre part, les ressources dynamiques doivent être gérées à un niveau plus bas, impliquant le niveau métier et la base de données.

Voici une solution permettant de gérer facilement vos ressources dynamiques dans votre code, je partirai de la couche base de données afin de vous faire bien comprendre l'abstraction des ressources.

2. Une solution pour la gestion de ressource dynamique

2.1. Ressources au niveau base de données

L'internationalisation de notre application Web implique la nécessité de prendre en charge plusieurs cultures.
Selon la culture utilisée par l'utilisateur, les ressources dynamiques doivent s'adapter et s'afficher dans la culture choisie.

Pour cela, il est impératif de dissocier dans une resource dynamique son identifiant et son contenu. En effet, une ressource dynamique pourra avoir différent contenu en fonction de la culture appliquée. Voici comment je schématise cela dans ma base de données: 

2.2. Ressources disponibles au niveau métier

Une fois les ressources dynamiques implémentées en base, nous avons besoin de les rendre disponible dans la couche métier de notre site.

En effet, notre couche métier va uniquement utiliser des codes de ressources et aucune traduction en dur. A partir de cette hypothèse, deux choix sont possibles :

  • Soit utiliser une classe qui fait un appel à la table PORTAL_Translation pour chaque traduction (trop lourd)
  • Soit utiliser une zone de stockage, contenant le dictionnaire des ressources dynamiques définit en base, partagé par l'ensemble des utilisateurs et accessible par chaque couche métier de votre site.

Je garderai donc la deuxième solution. Pour cela, j'utiliserai le pattern Singleton dans une couche partagée, afin de stocker l'ensemble des ressources dynamiques correspondant à la culture de l'utilisateur se connectant, si celles-ci ne sont pas dèja chargées.

Ainsi les couches de mon portail Web auront accès constamment à une classe Singleton dans une couche partagée qui contiendra autant de dictionnaires de ressources dynamiques HashTable<resourceCode,resourceLabel> que de culture existante.

Ma classe Singleton PortalResourcesTranslater possédera une méthode  :
/// <summary> ///
Initializes the object PortalResourcesTranslater with the dictionnary of dynamic data in the table PORTAL_Translation
/// </summary>
/// <param name="referentialDictionnary">Hashtable which represents the referential Code/Label for the user culture in database</param> public static void Initialize(Hashtable referentialDictionnary, CultureInfo cultureToInitialize)

laquelle sera appellée à chaque connection d'un utilisateur afin de charger le dictionnaire des ressources dynamiques correspondant à sa culture si celui-ci n'est pas déja chargé.

Par exemple, si à l'instant T, un anglais, un français et un allemand se connecte au portail, le singleton chargera 3 dictionnaires correspondant aux ressources dynamiques anglaise, française et allemande et les maintiendra en mémoire même lorsqu'un de ces utilisateurs se déconnectera.

Une méthode Reset() permettant de supprimer la liste des dictionnaires chargés dans le Singleton sera utilisé lors de la génération des ressources que nous verrons dans la prochaine partie ci-dessous.

Lorsque une traduction devra se faire dans le code, il suffira d'appeller PortalResourcesTranslater par l'intermédiaire de la méthode statique :

public static string Translate(string code)

Cette méthode traduira automatiquement le code par la traduction définit en base à l'aide du dictionnaire préalablement chargé:

Dans votre code métier, vous pourrez utiliser la syntaxe suivante sans vous soucier de la culture :

this._label = PortalResourcesTranslater.Translate(labelResourceKey);

Cette technique permet de gérer automatiquement les ressources statiques au niveau des fichiers ressources ASP.NET et les ressources dynamiques au niveau métier et base de données.

2. Une solution pour la génération automatique des ressources statiques et dynamiques d'un site Web

Le souci lorsque l'on possède des ressources statiques et dynamiques au niveau d'un site web est qu'il n'existe pas d'outil dans Visual Studio qui permette rapidement de les mettre à jour.

La seule possibilité si vous devez définir 10 cultures différentes est d'ouvrir les 10 fichiers ".resx" afin d'entrer vos traductions statiques en environnement de production, et également d'effectuer des scripts afin d'ajouter les ressources dynamiques en base de production.

De plus, il faut savoir qu'un changement dans des fichiers situés dans le répertoire App_GlobalResources impliquera un redémarrage de votre Site Web par IIS. Par conséquent, il vous faut externaliser le stockage des variables sessions, c'est à dire ne pas utiliser le SessionState en mode "InProc".

Pour résoudre cette problématique, voici une des solutions que vous pouvez envisager :

  1. Créer un projet de type "Web application ASP.NET" ceci afin d'avoir la possibilité d'accéder aux propriétés complètes des fichiers ressources :

  2. Choisir la valeur "Content" concernant la propriété Build Action de vos fichiers ressources, ceci afin qu'ils soient copiés tel quel dans votre site publié.Tout autre choix compilera vos fichiers ressources en DLL comme dans un projet WebSite, ceci rendant leur modification en environnement de production plus difficile. 
  3. Dans votre fichier Web.Config spécifier un SessionState en mode "StateServer"  comme ceci :
    <sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" timeout="20"></sessionState>
  4. Allez dans les services du serveur qui héberge votre site Web et démarrer ce service :

     

  5. Renseignez la chaîne de connection ResourcesConnectionString vers votre base de données dans le web.config:<connectionStrings>
    <
    add name="ResourcesConnectionString" providerName="System.Data.SqlClient" connectionString="Data Source=;Initial Catalog=;User ID=;Password="/>
    </
    connectionStrings>
  6. A présent, votre application Web possède des fichiers ressources facilement modifiable et une indépendance entre les variables sessions et le processus IIS. Nous pouvons donc définir un outil d'administration afin de gérer vos fichiers ressources sans impact majeur sur votre site Web de production.
J'ai donc décidé de créer un outil permettant la génération automatique de resources dynamiques et statiques.
Afin de l'incorporer dans votre application Web, il vous suffit d'ajouter dans une partie "Administration" accessible uniquement par l'administrateur de votre site, la page "default.aspx" définit dans mon projet ainsi que la structure métier et d'éxécuter les scripts définient dans le fichier "scriptResourceTool.sql".

Le métier de cet outil à été pensé selon le pattern Abstract Factory vous permettant par la suite d'ajouter la gestion d'autre type de resources selon vos besoins tel que fichier image etc.. Je me limiterai donc au ressources textuelles pour le moment.



Voici donc le fonctionnement de cette application:

Grâce à cette interface, les ressources se trouvant en base ainsi que les resources globales du site Web sont accessibles.
La liste des resourceId et leurs traductions respectives sont affichés sous forme de référentiel. Les resourceId en rouge signifient que des traductions les conçernant sont manquantes dans certaine culture.  
Vous avez donc la possibilité de piloter vos ressources automatiquement depuis cettte page d'administration.

Lorsque vous modifiez la valeur d'une traduction en base, le simple fait de cliquer sur "Save" la sauvegardera, mais ceci n'assure pas que votre ressource soit mise à jour dans le site.
En effet, comme vu précédemment, la couche métier gérant les traductions peut avoir déjà chargé le dictionnaire de la culture modifié.
Pour forçer donc la mise à jour de l'ensemble des dictionnaires chargés, il vous suffit de cliquer sur le lien "Refresh database resources" en haut à droite àprès la mise à jour de toutes vos ressources en base.

Ceci forcera le rechargement de l'ensemble des dictionnaires dans votre site en production, tout cela sans vous obliger de passer par des scripts rébarbatifs.

Concernant les resources statiques qualifiées ici par le terme "Website Resources", vous devez également effectuer vos modifications de traductions, d'ajout de resourceId, de suppresion de resourceId etc... par l'intermédiaire de l'interface.

Une fois, vos resources statiques mise à jour, lancer la génération des fichiers ".resx" en cliquant sur "Generate resources files".

Les fichiers se trouvant dans le répertoire App_GlobalResources seront automatiquement générés pour chaque culture supportée et spécifié dans la table COMMON_CULTURE de votre base, provoquant le redémarrage de IIS sans conséquence pour vos variables Session étant donnée qu'elles sont désormais externalisées du processus IIS.

Voici une capture d'écran de l'outil d'administration, autant vous dire que je m'en sers constamment depuis sa mise en place, c'est tellement plus sympa d'avoir une console d'administration que devoir s'obliger à passer par des scripts ou de la copie de fichier risquée.

Bonne utilisation !

NetDim.

Déploiement d'application Web IIS, utilisation de app_offline.htm


Il existe de nombreuses façons de déployer une application Web sur un serveur IIS :

  • Utilisation de la commande Publish
  • XCopy
  • Création de Setup Web (.msi)

La façon la plus rapide pour déployer un site Web sur un serveur de Prod reste le XCopy bien que cela ne soit pas la façon la plus professionnelle.

Le problème sur un serveur de Prod et de prévenir les utilisateurs proprement lors de la copie du nouveau site afin de ne pas les surprendre par une belle page jaune .NET :)


la belle page jaune .NET


Pour cela, Il existe une technique simple permettant de personnaliser la page affichée lors de la migration du site.

il suffit de copier une page HTML se nommant "app_offline.htm" à la racine de votre site Web.

Attention! Un comportement spécial a été détecté sur IE, par sécurité il serait bon que votre fichier "app_offline.htm" dépasse les 512 octets.=> plus d'information ici

Si IIS détecte cette page dans la racine du site , il enverra toutes les requêtes sur cette page automatiquement :


appOffline


Lorsque votre site est déployé, il vous suffit de supprimer cette page afin que les utilisateurs aient de nouveau accès à votre site.

 

 

Avoir un fichier Web.config sécurisé


Par les temps qui courent, un développeur qui désire une application sécurisée ... doit être un peu parano si il veut penser à tout...Indifferent

Dans le cas, d'une application Web, la liste des fondamentaux en matière de sécurité, peut être très longues...

  • Validation des entrées (injection de code SQL)
  • Sécurité au niveau des champs cachés (visible par le code source)
  • Sécurité au niveau Ajax (des failles sont encore exploitable)
  • Sécurité au niveau Cookies
  • Gestion de l'application si l'on essaye de vous envoyer 10000 requêtes d'un coup.
  • Cryptage des données sensibles
  • Gestion des pools
  • ....etc...

Bref, la liste des tâches à vérifier peut être très rapidement rébarbatif.


Je vais pour l'instant vous faire une check-list de ce qu'un Web.config sécurisé devrait contenir :

Un web.config sécurisé devrait suivre ces recommandations :

  • les connectionStrings doivent être cryptées en utilisant aspnet_regiis.exe .
  • toutes les sections de configurations contenant des user credentials ou des données sensibles doivent être cryptées en utilisant aspnet_regiis.exe. 
  • L'élément Trace doit être désactivée de l'application et customErrors mode doit être à "On", car l'utilisateur ne doit pas voir de détail sur les exceptions levées par le CLR.
  • Les balises d'autorisation doivent être convenablement configurées avec la liste des roles,users ou verbs devant être "allow" ou "deny".
  • l'Impersonation doit être désactivé si non requise.
  • L'objet Session doit être désactivé si non utilisé.
  • un niveau de confiance (Trust level) est appliqué à votre application et il ne doit pas authorisé plus de droits que ceux requis par votre application.

Afin de crypter une donnée dans votre Web.config

Vous pouvez utiliser la syntaxe suivante de l'utilitaire aspnet_regiis se trouvant dans le framework:

  • aspnet_regiis -pef connectionStrings "c:\MyWebSite"

cela remplacera vos paramètres :

<connectionStrings>
<add name="PricingConnectionString" providerName="System.Data.SqlClient" connectionString="Data Source=18.254.45.95;Initial Catalog=PricingDev;Persist Security Info=True;Max Pool Size=1000;User ID=toto;Password=monmpwd;"/>
<add name="StartConnectionString" providerName="System.Data.OracleClient" connectionString="Server=STARTLIGHT;Uid=tata;Pwd=monmpwd"/>
 </connectionStrings>

 par :

<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider"><EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"xmlns="http://www.w3.org/2001/04/xmlenc#"> .... </KeyInfo> <CipherData> <CipherValue>pRHtzDzZICRStiEvb01laj3OkuaxFe3ip9fE0n5s76fKMveYCqp5F48CwIkmwQcMzaqDXdsOGN6oGHssfIH8BHuL9SC4nNaKcq+7AoguLalb5YUesnfa/xUhUoX1hZ8WILfekV/KMGcHuH39Q+sFCec+VPodyhBgTB8Tu7fa8F0=</CipherValue>
</
CipherData>
</
EncryptedKey></KeyInfo>
<
CipherData>
<
CipherValue>rfu++wRIW2FgvbzEPPqB6DRRgfEw6sLwX97fD6qj4YHCYekHu568mMQY+7kZCljdFIJbUGDlHDCtLKPk8piwdoxPJOobMuNiUG5eLpwcsPX3mUTrD7cRBMcYSy16qQLs9jnYrdzcf6rq9Y0/EFZrm1z/fesG/2eBHES2lq4ItdaQGhvUoJrv30VnLfSMpF63Gwli0aF/5Qig9e9d8BZlwRU7GsqvIy/vDCvmdAfgRN143oy16Y0yU6njl8stZruR0pvVrJRcEPzqctiOu2vdYemRpdFjM47l4Xt7ne4Jx9ER8q9W/IhUOIutUndEVVgqbRZ8D0RPj5WLFq8Gt4ZgO8RhGChz6crFuox0+lhx5mQicQpN5x1lySBeSDRJMk/u1UwmFWSKo6CrjS4QKc2U+/fekdf1rJMRVnyZZSx7rZNAsNg+cqMr5atD895pfAVFfdtYCs0VS+ud5AyahpGWUAI+CSDc6FvIOjCUgiK3uQOw7H6d+HDd9IvWhIxKYtEjz+gtZAec7Jk8Dbh9L7q6aaONXV8vGMBP2L56mHMYufBfZKT1XgmhdqXN4Wni7V6n</CipherValue>
</
CipherData>

...

</

connectionStrings>

Attention la clé utilisée pour le cryptage est liée à la machine, donc si vous exportez le fichier Web.config sur un autre poste cela ne marchera pas.

Crypter toujours sur le serveur hébergeant l'application Web !

Lors de l'éxécution, ASP.NET décryptera lui même la chaîne de connexion.

si vous désirer décrypter le fichier manuellement lancer alors la commande ci-dessous :

  • aspnet_regiis -pdf connectionStrings "c:\MyWebSite"

Anders Hejlsberg ... ça vous dit quelque chose ?


Pour ceux qui ne connaissent pas encore le personnage et qui travaillent sur les technologies .NET. Oui c'est possible, j'en connais :)

Une petite biographie de ce grand Monsieur, qui reste souvent dans l'ombre de Microsoft s'impose.

Pour faire simple Anders pourrait dire à .NET et C#  une phrase célèbre =>"Je suis ton père ! " Surprise

Inutile donc de vous dire qu'on lui doit beaucoup.

Hejlsberg est danois.

Depuis 1980, il se soucie toujours des outils disponibles pour les développeurs.

Son désir était de pouvoir créer un logiciel de programmation avec une infercace conviviale, performante, et qui apporterait une nouvelle ère dans le domaine de la programmation.

Il a donc créé la première application qui apporta du neuf dans le monde des developpeurs: le Turbo Pascal de Borland.

Hejlberg est resté pendant plusieurs années au sein de Borland jusqu'en 1996 en produisant notamment le langage Delphi.

En 1996, Microsoft propose à Anders de rejoindre Microsoft avec également une trentaine de ses collègues de chez Borland.

Autant vous dire qu'il reçu une proposition de transfert digne d'un footballeur Stick out tongue

En mai 1997, Borland, devenu Inprise, devait d'ailleurs déposer une plainte en justice à l'encontre de Microsoft pour pratiques déloyales en matière d'embauche.

il commenca à travailler sur le langage J++ et les Windows Foundation Classes (WFC) qui sont les classes Java pour interface Windows. Le but était de permettre aux programmeurs en Visual J++ (la version Microsoft du compilateur Java) de développer des applications professionnelles dignes de ce nom.

Les relations entre Anders Hejlsberg et la communauté Java sont donc vite devenues tendus.

Pour la version 7 de Visual Studio (l'outil de développement de Microsoft), version rebaptisée Visual Studio.NET, Microsoft a demandé à Anders Hejlsberg de concevoir un système pour rendre le développement d'applications Windows et Web bien plus aisé.

Une nouvelle architecture a été mise au point, des langages ont été modifiés et un nouveau langage est né : le C#, qui devient le langage de référence et principal langage pour Microsoft.

Aujourd'hui, Anders travaille toujours sur les prochaines versions de C# autant vous dire que Anders n'a pas fini de nous étonner Indifferent

Testeur d'expressions régulières


Bonjour à tous,

Tout d'abord, merci à Cyril Wink de m'accueillir dans cette communauté bien sympathique !

Je me présente, je m'appelle Dimitri BOURGOIS, 29 ans marié ,je travaille sur les technos .NET depuis 2002 j'ai commencé à travailler sur Paris.Mais depuis 2005, je travaille à Sophia-Antipolis près de Cannes chez GFI Informatique au soleil donc si vous voulez une petite cooptation ...Big Smile

Je suis également MCAD.NET et passionné comme vous par les technos .NET qui n'arrête pas de prendre de l'ampleur pour notre plus grand bonheur...(tiens ça rime) Smile

Finalement , merci à vous tous pour le savoir et les infos que vous faîtes partager.

J'ai vu que certaines personnes étaient intéressés par un outil afin de tester les expressions régulières.

En effet, cela est bien pratique lorsque vous vous trouvez face à ce genre de chose :)

  •  <asp:RegularExpressionValidator id="RegularExpressionValidator1" ControlToValidate="TextBox1" ValidationExpression="hum c'est quoi déjà ???? :)"  display="Static" EnableClientScript="false" ErrorMessage="Zip code must be 5 numeric digits" runat="server"/>

     un petit outil sur le net m'aide beaucoup dans ces moments là. Smile

    Voici le lien:  http://quentinc.net/javascript/testeur-expressions-regulieres/

    Bonne utilisation.



  • Les 10 derniers blogs postés

    - Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

    - Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

    - Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

    - Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

    - Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

    - Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

    - Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

    - Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

    - Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

    - SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01