Mon article précédent a traité de la façon d'utiliser l'API de Magento avec WCF. Un autre aspect de Magento que j'ai rencontré est que c'est un soutien extrêmement flexible pour le thème.
Vous pouvez concevoir un nouveau thème qui semble radicalement différent de celui par défaut. Non seulement vous pouvez modifier les images et les couleurs dans les feuilles de style en cascade, mais vous pouvez également redéfinir les régions (en-tête, contenu, pied de page ...) qui constituent une page. Par région, vous pouvez spécifier quel HTML est injecté dedans. Cela vous donne une puissance de personnalisation maximale pour le théâtre de votre site.
Le thème dans ASP.NET est pris en charge à l'extérieur. À l'aide du dossier App_Themes, vous pouvez personnaliser l'apparence de votre site, aussi lourde ce système peut être.
Magento est construit en utilisant le modèle MVC, tout comme le framework ASP.NET MVC. Et c'est l'objet de cet article. Comment pouvons-nous mettre en œuvre le thème dans ASP.NET MVC?
Commençons ...
Avant de commencer à coder, résumons les objectifs que nous voulons atteindre. Supposons que nous possédons une entreprise qui importe des meubles fabriqués en Chine, au Vietnam, au sud-boue ... etc. Nous ne vendons pas directement aux utilisateurs finaux, mais aux revendeurs.
Nous voulons concevoir une application Web alimentée par ASP.NET MVC qui peut être utilisée comme site de commerce électronique par tous nos revendeurs. Chaque revendeur a son propre nom de domaine et veut vendre ses produits en ligne. Chacun de ces domaines est lié à notre application Web unique.
La fonctionnalité offerte par l'application Web est la même pour chaque revendeur, mais chaque revendeur souhaite personnaliser sa boutique en ligne en appliquant un thème personnalisé. Nous soutiendrons les situations suivantes:
Nous devons donc comprendre comment nous pouvons remplacer dynamiquement la feuille de style (CSS), la page maître, les vues et les vues partielles.
Avant de commencer, nous devons jeter les bases. Commençons par construire les bases pour une application de démonstration simple.
Remarque : Dans cette section, je donne un aperçu rapide de la configuration d'une application de démonstration afin que la fonction de thème puisse être démontrée. Ce n'est qu'une approche rapide et facile. L'objectif de cet article ne consiste pas à concevoir un modèle de domaine, en concevant votre couche logique commerciale ... etc. Je garde donc cela aussi court que possible. N'hésitez pas à l'améliorer.
Base de données
Créez une nouvelle base de données à l'aide de SQL Server Express (2005 ou 2008). Inspiré par la base de données Northwind, j'ai nommé ma base de données [WindDirection].
Cette base de données contient exactement un tableau appelé [revendeur]. Concevez le tableau comme indiqué dans la figure suivante.
Figure 1 - Tableau [revendeur]
![Table de revendeur [Reseller] Table Design](https://images.downcodes.com/uploads/20250616/img_68500176a3ae030.png)
Comme vous pouvez le voir, la colonne d'ID est la clé principale et il utilise la spécification d'identité (= auto-ONOnCmenment). Ajoutez également une contrainte unique sur la colonne de domaine car chaque revendeur a son propre domaine unique.
Remarque : Le code source accompagnant cet article contient un script (DDL.SQL) qui vous permet de générer rapidement ce tableau si vous ne voulez pas le concevoir à la main.
La dernière partie de la configuration de notre base de données consiste à entrer des enregistrements factice pour le tableau [revendeur]. Veuillez saisir les enregistrements suivants:
Figure 2 - revendeurs

Nous avons quatre revendeurs. Le premier revendeur n'a pas de thème personnalisé et retombe sur celui par défaut. Tous les autres ont leur propre thème personnalisé défini.
Démarrez Visual Studio 2008 et créez une nouvelle solution vierge intitulée "MVCAPPLICATION". Ajoutez une nouvelle bibliothèque de code et appelez-la "cgeers.winddirection.database". Supprimez le fichier Class1.css généré automatiquement.
Ensuite, ajoutez un nouvel élément LINQ à SQL Classes et nommez-le "Datacassles". Renommez le nouveau DataConText à "WindDirectionDatacontext". Faites maintenant glisser la table [revendeur] de l'onglet Explorateur de serveur sur la surface LINQ à SQL Designer.
Figure 3 - Entité de revendeur

Définissez la propriété de connexion de DataConText sur "None" et supprimez le paramètre de l'application de chaîne de connexion et le fichier de configuration de l'application (app.config). Je n'aime pas le fait que Visual Studio injecte la chaîne de connexion pour moi. J'aime le faire moi-même.
C'est pourquoi j'ai ajouté la classe partielle suivante à cet assemblage qui gère l'initialisation du DataConText avec une chaîne de connexion. La seule partie sur laquelle nous devons nous convenir est que la chaîne de connexion est nommée "WindDirection".
Listing 1 - classe WindDirectionDatacontext
public partial class WindDirectionDataContext
{
private static readonly string ConnectionString ;
static WindDirectionDataContext ( )
{
ConnectionStringSettings settings = ConfigurationManager . ConnectionStrings [ "WindDirection" ] ;
ConnectionString = settings != null ? settings . ConnectionString : String . Empty ;
}
public WindDirectionDataContext ( ) : base ( ConnectionString ) { }
}N'oubliez pas d'ajouter une référence à l'assemblage System.Configuration. Tant que vous inclurez une chaîne de connexion appelée "WindDirection" dans les applications qui font référence à cet assemblage, cela fonctionnera très bien.
Nous sommes presque là. Attendez, nous allons passer. Ajoutez maintenant une nouvelle bibliothèque de code à la solution appelée "cgeers.winddirection.managers". Supprimez le fichier Class1.cs généré automatiquement et ajoutez une référence à l'assemblage System.Data.linq.
Ajoutez une nouvelle classe appelée Manager et ajoutez-y le code suivant:
Listing 2 - Résumé Manager
public abstract class Manager
{
protected Manager ( )
{
Context = new WindDirectionDataContext ( ) ;
}
public WindDirectionDataContext Context { get ; set ; }
}Cette classe très simple crée un nouveau DataConText sur lequel nous pouvons libérer nos requêtes LINQ plus tard.
Ensuite, ajoutez une classe appelée "RellerManager" au projet et ajoutez le code indiqué dans Listing 3.
Énumérer 3 revenlemmanager
public class ResellerManager : Manager
{
public string GetThemeForDomain ( string domain )
{
var q = from r in Context . Resellers
where r . Domain == domain
select r . Theme ;
string theme = q . SingleOrDefault ( ) ;
return ! String . IsNullOrEmpty ( theme ) ? theme : "Default" ;
}
}Cette classe Manager descend de notre classe Abstract Manager et ajoute une méthode appelée GetThemeFordomain (...). Cette méthode recherche le thème d'un revendeur basé sur un nom de domaine donné. Comme chaque domaine est uniquement lié à un revendeur, cela ne pose aucun problème.
Voila, c'est tout l'accès aux données qui est nécessaire pour notre application de démonstration. Nous devons déterminer le thème d'un revendeur basé sur le domaine de la demande entrante, puis nous devons l'appliquer.
Remarque : Méfiez-vous de l'utilisation du contexte LINQ vers SQL dans une application alimentée ASP.NET. Bien qu'il ne soit pas démontré dans cet article, car il distrait trop de notre entreprise principale, il est conseillé de créer un seul contexte par demande. Stockez le contexte dans le HTTPContext de la demande afin que vous puissiez y accéder à tout moment pendant la demande.
Il y a quelque temps, j'ai écrit un article spécifiquement à ce sujet, consultez l'article d'ObjectContext de l'entité ici. Bien qu'il traite du framework Entity au lieu de LINQ à SQL, il est toujours applicable.
La dernière étape pour compléter notre application de démonstration de base consiste à ajouter un nouveau projet de site Web à la solution. Ajoutez un nouveau projet à la solution en fonction du modèle de projet d'application Web ASP.NET MVC et nommez-le "MVCAPPLICATION". On vous demandera si vous souhaitez également créer un projet de test unitaire pour cette application. Choisissez «non» pour sauter cela car nous n'en avons pas besoin pour cet article.
Visual Studio générera une application "Hello, World!" - Type ASP.NET MVC qui contient un certain nombre de pages par défaut (à la maison, à propos, se connecter ... etc.). Ajoutez votre chaîne de connexion au fichier web.config et ajoutez des références aux assemblages cgeers.winddirection.database et cgeers.winddirection.managers.
Remarque : le web.config contient un certain nombre de paramètres de configuration se référant à l'appartenance ASP.NET, Profil, Rôles ... fournisseurs. Vous pouvez aller de l'avant et les supprimer car nous n'en avons pas besoin.
Votre explorateur de solution doit ressembler à la figure 4.
Figure 4 - Explorateur de solution

Remarque : Au moment de la rédaction de cet article, j'utilise ASP.NET MVC version 1.0. Cependant, la version 2.0 sera publiée dans un avenir proche.
Lors de l'exécution de l'application Web, la première chose qu'il doit comprendre est le thème dont il doit appliquer. Cela doit être fait pour chaque demande. Donc, brancher un module HTTP personnalisé dans la demande de demande semble approprié.
Ajoutez une nouvelle classe au projet MVCAPPLICATION et appelez-le thèmehttpmodule. Demandez à la classe d'implémenter l'interface IhttpModule. L'ensemble du code de cette classe est affiché dans la liste 4.
Cet article n'est pas une amorce sur la rédaction de modules HTTP, donc si vous avez besoin de plus d'informations, veuillez consulter l'article "Procédure pas à pas: création et enregistrement d'un article HTTP personnalisé" sur MSDN.
Listing 4 - thèmehttpmodule
public class ThemeHttpModule : IHttpModule
{
public void Init ( HttpApplication application )
{
application . BeginRequest += application_BeginRequest ;
}
private void application_BeginRequest ( object sender , EventArgs e )
{
HttpApplication application = ( HttpApplication ) sender ;
HttpContext context = application . Context ;
if ( context . Cache == null )
{
return ;
}
string domain = context . Request . Url . GetDomain ( ) ;
string cacheKey = String . Format ( CultureInfo . InvariantCulture , "theme_for_{0}" , domain ) ;
if ( context . Cache [ cacheKey ] == null )
{
ResellerManager manager = new ResellerManager ( ) ;
string theme = manager . GetThemeForDomain ( domain ) ;
context . Cache [ cacheKey ] = theme ;
}
}
public void Dispose ( ) { }
}Ce module HTTP ajoute un gestionnaire d'événements pour l'événement BeginRequest. Cet événement se produit comme le premier événement de la chaîne d'exécution du pipeline HTTP lorsque ASP.NET répond à une demande.
Ici, nous extrayons le nom de domaine de la demande entrante. Ensuite, nous récupérons le thème de ce domaine en utilisant la méthode GetThemeFordomain (...) de RellerManager. Le résultat est ensuite mis en cache. La prochaine fois qu'une demande pour ce domaine sera déclenchée, le thème sera récupéré du cache et aucune requête de base de données ne sera licenciée.
La méthode getDomain () est une méthode d'extension pour la classe URI. Consultez le code source de cet article pour voir comment cela fonctionne. De la même manière, vous pouvez choisir d'extraire le sous-domaine (par exemple: www, admin ... etc) de la demande. Vous pouvez ensuite étendre votre moteur de théâtre pour appliquer différents thèmes pour chaque sous-domaine d'un domaine.
Enregistrez-vous en dernier mais non le moindre le thèmehttpmodule en créant une entrée dans le fichier web.config. Ceci est requis pour souscrire le module HTTP aux notifications de demande de requête.
Listing 5 - Enregistrez le thèmehttpmodule
< httpModules >
< add name = " ThemeHttpModule " type = " MvcApplication.ThemeHttpModule " />
<!-- ... -->
</ httpModules >Lorsque vous démarrez l'application Web, vous recevrez le look et la sensation par défaut comme affiché dans la figure 5. Visual Studio générera des pages par défaut (à la maison, à propos, se connecter ... etc.) y compris une page maître et une feuille de style. Nous utiliserons ces fichiers pour composer notre thème par défaut.
Figure 5 - Thème par défaut de l'application ASP.NET MVC

Par défaut, tous les fichiers sont enregistrés dans les dossiers de contenu et de vues. Nous devons implémenter notre propre structure de répertoire afin que nous puissions logiquement regrouper nos thèmes. Créez donc un nouveau dossier appelé thèmes. Créez un sous-dossier pour le répertoire des thèmes et appelez-le par défaut. Déplacez le répertoire de contenu et de vues sous ce répertoire par défaut.
Après avoir déplacé les dossiers de contenu et de vues, vous devez ajuster la propriété MasterPageFile de la directive de page pour chacune des vues! L'ancienne valeur fait référence à un emplacement qui n'existe plus. Changer MasterPageFile = "~ / Views / Shared / Site.master" vers MasterPageFile = "~ / Themes / Default / Views / Shared / Site.master" !
Figure 6 - Thème par défaut

Voila, notre thème par défaut a été configuré. Si vous souhaitez créer un nouveau thème, vous n'avez besoin que de créer un nouveau dossier et de le placer sous le dossier des thèmes. Comme vous pouvez le voir dans la capture d'écran précédente, nous créerons d'autres thèmes (vert, orange, rouge) plus tard.
Nous venons de déplacer nos pages maîtres, nos feuilles de style, nos vues ... etc. à un autre répertoire. Si nous commençons notre application Web maintenant, nous recevrons l'exception suivante:
Figure 7 - InvalidOperationException

La vue «index» ou son maître n'a pas pu être trouvée. Les emplacements suivants ont été recherchés:
MVC essaie de localiser une vue pour votre page de démarrage par défaut, mais ne peut pas la trouver dans les emplacements par défaut qu'il recherche, vous recevez donc une exception. Nous avons déplacé ces fichiers vers notre dossier de thème par défaut et nous créerons bientôt d'autres thèmes. Nous avons besoin d'un moyen d'informer MVC des emplacements où rechercher ses vues, page maître, vues partielles ... etc. Ces emplacements diffèrent en déplaçant le thème du revendeur.
Donc, fondamentalement, tout ce que nous devons faire pour soutenir le thème dans ASP.NET MVC est:
Pour ce faire, nous devons écrire notre propre moteur de vue. MVC utilise un moteur de vue pour rendre des pages pour la réponse. Ce moteur de vue est responsable de la localisation de la page maître, des vues et des vues partielles. Par défaut, WebFormViewEngine est utilisé.
Nous devons remplacer notre moteur de vue par défaut par le nôtre. Pour ce faire, ajoutez une nouvelle classe appelée TheMedViewEngine au projet MVCApplication et faites-le descendre de la classe WebFormViewEngine.
Listing 6 - ThemedViewEngine
public class ThemedViewEngine : WebFormViewEngine
{
#region Constructor(s)
// Replace the default search paths by our own.
public ThemedViewEngine ( )
{
// Search paths for the master pages
base . MasterLocationFormats = new [ ]
{
"~/Themes/{2}/Views/{1}/{0}.master" ,
"~/Themes/{2}/Views/Shared/{0}.master"
} ;
// Search paths for the views
base . ViewLocationFormats = new [ ]
{
"~/Themes/{2}/Views/{1}/{0}.aspx" ,
"~/Themes/{2}/Views/{1}/{0}.ascx" ,
"~/Themes/{2}/Views/Shared/{0}.aspx" ,
"~/Themes/{2}/Views/Shared/{0}.ascx" ,
} ;
// Search parts for the partial views
// The search parts for the partial views are the same as the regular views
base . PartialViewLocationFormats = base . ViewLocationFormats ;
}
#endregion
}Dans le constructeur de ce nouveau moteur de vue, nous définissons les MasterLocationFormats, ViewLocationFormats et PartialViewLocationFormats sur de nouveaux emplacements, par exemple: ~ / themes / {2} / vues / {1} / {0} .aspx.
Chaque chemin contient 3 parties déterminées dynamiquement.
Afin d'utiliser le nouveau moteur View, vous devez l'enregistrer. Faites cela en ajoutant le code suivant au gestionnaire d'événements Application_Start situé dans le fichier global.asax.cs.
Listing 7 - Enregistrez le themedViewEngine
protected void Application_Start ( )
{
ViewEngines . Engines . Clear ( ) ;
ViewEngines . Engines . Add ( new ThemedViewEngine ( ) ) ;
RegisterRoutes ( RouteTable . Routes ) ;
}Ici, vous effacez tous les moteurs de vue qui pourraient avoir été chargés plus tôt et injectez le vôtre. Il ne reste plus qu'à instruire le moteur de vue comment formater les nouveaux chemins de recherche afin qu'il trouve correctement les fichiers demandés. Pour ce faire, vous devez remplacer les deux méthodes suivantes:
Listing 8 - FindPartialView (...) & FindView (...) Méthodes
public override ViewEngineResult FindPartialView ( ControllerContext controllerContext , string partialViewName , bool useCache )
public override ViewEngineResult FindView ( ControllerContext controllerContext , string viewName , string masterName , bool useCache )Je ne vais pas inclure le code de ces deux fonctions ici, car il est assez long et a quelques références aux méthodes d'aide privée. Fondamentalement, ces deux méthodes suivent le même modèle:
Ainsi, notre nouveau moteur View recherchez essentiellement notre dossier de thèmes et s'il ne trouve pas la page maître demandée, la vue ou la vue partielle, elle utilise celle du thème par défaut. Bien sûr, le thème par défaut doit être complet et ne peut pas avoir de fichiers manquants.
Cela vous permet de créer des thèmes qui ne contiennent qu'une page maître qui à son tour fait référence à une feuille de style différente ou à des thèmes qui contiennent des vues et / ou des vues partielles pour les sections que vous souhaitez styliser différemment.
En suivant ce modèle, vous pouvez créer des thèmes qui ne remplacent que certaines vues et se replier sur les vues du thème par défaut si aucune vue personnalisée n'est fournie.
J'ai basé mon moteur sur le travail de l'excellent article de Chris Pietschmann sur le thème dans ASP.NET MVC. Je vous suggère de vérifier son article car il contient plus d'informations sur le fonctionnement du moteur View en interne.
Avec le nouveau moteur View en place, nous pouvons à nouveau exécuter l'application Web sans aucune exception car il est désormais en mesure de résoudre les demandes de page maître, de vues et de vues partielles.
Remarque : J'ai un peu modifié le code de sorte que lorsque le moteur de vue ne peut pas résoudre une demande pour une certaine page maître, vue ou vue partielle, elle se replie sur celles trouvées dans le thème par défaut. Assurez-vous donc de consulter le code source de cet article également.
Créons rapidement un nouveau thème. Ajoutez un nouveau dossier appelé "Red" sous le dossier Thèmes. Copiez le site.master et le site.css à partir du thème par défaut comme indiqué dans la figure suivante.
Figure 8 - Thème rouge

Ouvrez la feuille de style du thème rouge et modifiez la propriété en arrière-plan de l'élément corporel. Réglez-le sur rouge. Ouvrez maintenant le tableau [revendeur] et définissez le champ de thème sur "Red" pour le revendeur dont le domaine est défini sur LocalHost. Redémarrez l'application Web et il devrait maintenant utiliser la page maître et la feuille de style du thème rouge.
Figure 9 - Thème rouge en action

De même, vous pouvez créer un thème orange qui contient non seulement une page maître mais aussi une vue différente pour la page d'accueil.
Figure 10 - Thème orange

Le thème Orange rendra la nouvelle vue pour la page d'accueil au lieu de la vue par défaut. Si vous souhaitez remplacer une vue partielle, vous pouvez le faire de la même manière. Copiez simplement la vue partielle par défaut dans le même emplacement sous le nouveau dossier de thème et ajustez-le selon les besoins.
Pour chaque thème, vous pouvez désormais servir différentes pages maîtres, vues et vues partielles. Il y a un scénario restant que je souhaite soutenir. Les revendeurs qui sont satisfaits de la vue par défaut mais qui veulent seulement ajuster le logo, quelques couleurs ... etc. peut facilement être satisfait en appliquant une feuille de style différente au thème par défaut.
Ajoutez un nouveau dossier de thème dans le répertoire des thèmes et appelez-le vert. Copiez la feuille de style du thème par défaut sur le thème vert comme indiqué dans la figure suivante.
Figure 11 - Thème vert

Ouvrez la feuille de style du thème vert et ajustez la propriété en arrière-plan de l'élément corporel en vert. Si vous définissez le thème du revendeur avec le domaine localhost sur vert et démarrez l'application, vous remarquerez qu'il utilise toujours la feuille de style du thème par défaut.
Cela est dû au fait que le thème vert n'a pas sa propre page maître. Il utilise la page maître du thème par défaut et cette page maître fait référence à sa propre feuille de style.
Ouvrez la page maître du thème par défaut et remplacez la ligne:
< link href =" ../../Content/Site.css " rel =" stylesheet " type =" text/css " />avec
< link href =" <% " ="Html.GetThemedStyleSheet()" % /> rel="stylesheet"
type="text/css" / >La méthode GetTheMedStylesHeet () est une méthode d'extension pour la classe d'utilité HTML. Ajoutez une nouvelle classe appelée htmlhelperextensions au projet et ajoutez-y le code suivant.
Listing 9 - htmlhelperextensions
public static class HtmlHelperExtensions
{
public static string GetThemedStyleSheet ( this HtmlHelper html )
{
HttpContext context = HttpContext . Current ;
if ( context == null )
{
throw new InvalidOperationException ( "Http Context cannot be null." ) ;
}
string defaultStyleSheet = context . Server . MapPath ( "~/Themes/Default/Content/Site.css" ) ;
string domain = context . Request . Url . GetDomain ( ) ;
string cacheKey = String . Format ( CultureInfo . InvariantCulture , "theme_for_{0}" , domain ) ;
string theme = ( string ) context . Cache [ cacheKey ] ;
if ( String . IsNullOrEmpty ( theme ) || theme == "Default" )
{
return defaultStyleSheet ;
}
string styleSheet = context . Server . MapPath ( String . Format ( CultureInfo . InvariantCulture ,
"~/Themes/{0}/Content/Site.css" , theme ) ) ;
if ( ! File . Exists ( styleSheet ) )
{
styleSheet = defaultStyleSheet ;
}
return String . Format ( CultureInfo . InvariantCulture , "'{0}'" , styleSheet ) ;
}
}La méthode GetTheMedStylesHeet () charge le thème du cache de HttpApplication et vérifie si ce thème a sa propre feuille de style. Sinon, il retombe sur la feuille de style du thème par défaut. Le code contient des chaînes codées durs, mais pas optimale, elle fait l'affaire. N'hésitez pas à améliorer cette méthode.
Si vous démarrez l'application Web maintenant, vous obtiendrez un joli fond vert.
Cet article vous montre comment vous pouvez activer le thème dans ASP.NET MVC. Pour ce faire, il vous suffit de mettre en œuvre deux choses, à savoir:
Le système de théâtre que nous avons implémenté utilise un thème par défaut et vérifie s'il doit remplacer les parties de ce thème par défaut par celle d'un thème personnalisé. Vous pouvez facilement prendre en charge l'un des scénarios suivants ou les combiner: