.NET et XHTML 1.0 ? - C#/.NET managed - Programmation
Marsh Posté le 09-09-2005 à 00:43:14
Bon, finalement, j'ai réécrit la lib de création de code XHTML 1.0 Strict
C'est loin d'être fini (quoique si on fait abstraction de la validation du document, là j'ai plus que quelques heures de boulot), mais ça fait déjà du XHTML 1.0 Strict
C'est déjà pas mal
http://validator.w3.org/check?uri= [...] form1.aspx
Voilà la bête... Dites-moi si vous voyez des trucs grossiers qui vous choquent
Génération d'une page de test :
Code :
|
Le namespace Xhtml1
Code :
|
Sortie :
Code :
|
http://magicweb.manga-torii.com/te [...] form1.aspx
Comme vous le voyez, c'est assez dépouillé pour le moment, y'a aucun contrôle, et c'est pas forcément ce qu'il y a de plus facile à utiliser
Mais bon... Sorti de ça, vous en pensez quoi ?
PS: M'emmerdez pas avec l'indentation du code généré, j'en ai chié deux heures pour avoir ce résultat (celui que je voulais ), donc il ne risque pas de changer
Marsh Posté le 09-09-2005 à 10:02:41
Oublie pas dans tes url d'escaper les & en les remplaçant par &, sinon tu sera pas valide
Et si t'as pas envie de te faire chier avec tout ça, attend la version 2.0 du framework qui est entièrement valide
Marsh Posté le 09-09-2005 à 12:04:39
c'est pourquoi je vais un attributehtmlencode et un htmlencode sur les attribues et les contenus des balises
sinon, ouais, je peux attendre la 2.0, mais bon... j'ai envie de jouer un peu, et surtout, je ne panne rien aux objets de base du C# (y'a des comportements que je trouve étrange et je ne trouve pas d'explication)
Marsh Posté le 09-09-2005 à 12:50:41
ta variable "output" déclarée en string, c'est mal, étant donné que t'arrètes pas de la concaténer.
une string est une chaine constante, donc tu peux pas la modifier. chaque fois que tu écris
Code :
|
tu créé une copie de output pour rajouter le caractère souhaité. ce qui ruine totalement les performances.
utilise un StringBuilder pour ce genre de truc, c'est fait pour ça
Marsh Posté le 09-09-2005 à 14:17:07
C'est en effet un point que j'ai vu depuis le début.
J'avais commencé à jouer avec un textwriter, mais après je ne savais plus quoi en faire
Après un entretien par mail avec un ancien collègue, il s'avère que je peux faire en rendu dans la méthode Render du Load, et que là j'ai accès à une fonction "htmltextwriter", qui correspond au flux de données utilisé par "Response.Write", ce qui me sembkle parfait
Marsh Posté le 09-09-2005 à 14:17:48
Ouais, à chaque concaténation, le .NET va générer un StringBuilder (c'est fait lors de la compilation). Autant utiliser un StringBuilder direct, ça évitera d'en créer un à chaque concaténation
Marsh Posté le 09-09-2005 à 17:29:55
FlorentG a écrit : Ouais, à chaque concaténation, le .NET va générer un StringBuilder (c'est fait lors de la compilation). Autant utiliser un StringBuilder direct, ça évitera d'en créer un à chaque concaténation |
euh, tu parles de la compilation JIT ? parce que la compilation en IL remplace operator+= par un appel à String.Concat()
Marsh Posté le 09-09-2005 à 20:00:57
Wouala.
J'ai modifié le code pour utiliser directement le HtmlWriter de l'objet Response :
Code :
|
Code :
|
Et en plus ça marche
Marsh Posté le 09-09-2005 à 23:52:10
Harkonnen a écrit : euh, tu parles de la compilation JIT ? parce que la compilation en IL remplace operator+= par un appel à String.Concat() |
Ah mince, effectivement Donc en fait le problème de String.Concat, c'est qu'il alloue une nouvelle string à chaque fois. Alors pour quelques concaténations ça va, mais au dessus le StringBuilder est mieux je crois bien...
Marsh Posté le 10-09-2005 à 13:14:08
Dans tous les cas, un TextWriter est toujours mieu, et maintenant c'est ce que j'utilise
Marsh Posté le 10-09-2005 à 22:04:29
Salut.
Bon, j'ai modifié mon code pour que la class Page contienne directement des tags plutôt que du code en dur.
En bref, j'ai deux lignes en dur (doctype et déclaration xml), puis un tag private "htmlTag", qui contient deux tags visibles publiquement (head et body), qui contiennent les metas (maintenant gérées comme de symples tags) et le contenu de la page.
Maintenant, j'attaque mon application en tant que telle.
Je veux créer des pages "templates", à savoir qu'elles vont contenir un certain nombre prédéfini de tags, dont les valeurs sont allimentées par la base de données.
Je fais ma class "HomePage". Elle est dérivée de Xhtml1.Page.
Seulement, le contructeur de Page est plutôt long, et je ne veux en aucun cas le recopier, car il se pourrait bien que ça change (et puis de toute façon c'est plus propre sans recopier).
J'ai bien la solution batarde, à la fin du constructeur, d'appeler une méthode privée "OnInitialize()" appelée depuis le constructeur de Page, vide dans Page, mais remplie dans les classes dérivées. Seulement, je trouve ça plutôt gore.
Je voudrais donc que mon constructeur déclenche un évènement "Initialize" que je pourrai récupérer dans ma classe dérivée (enfin... je sais pas trop comment).
Mais de toute façon, je ne comprends rien aux évènement, malgré la lecture des 3 exemples de la doc (je pige pas une ligne !)
En résumé, j'ai :
Code :
|
Je ne veux pas que le lancement de ces instructions supplémentaires soient visibles pour le développeur, donc il faut que ça se lance à l'instanciation de la class.
Marsh Posté le 10-09-2005 à 22:09:09
Trouvé une solution
Autre problème (ça ne veut pas dire que j'ai résolu le précédent)
Un tag <meta> ne peut en aucun cas contenir des tags.
Seulement, le fait qu'il soit dérivé de ma class générique Tag fait qu'il a une propriété public "innerTags".
J'ai pas envie de la cacher, ça ferait trop de boulot, et je doute que ce soit possible.
Par contre, je voudrais bien que lorsque j'ajoute un tag (je peux passer "innerTags" en private, et faire deux méthodes "addTag()" et "removeTag()" dans la class mère, je teste le type du tag ajouter, et que je contrôle en fonction de la liste des tags autorisés par le doctype (ce sera à la main, j'ai pas envie de me faire un parseur de DocType juste pour faire cette vérif).
Ainsi, je pourrai ne rien mettre dans la liste, ou mettre la liste des tags acceptés, et vérifier que les tags ajoutés correspondent.
Comment comparer le type d'un objet à... un type ?
En bref :
Code :
|
Solution trouvée :
Code :
|
J'ai mis ça dans ma class "Tag", dans le Render(). Et ça marche, y'a que mes objets de type "Div : Tag" qui ont ce texte à la fin de leur contenu
Marsh Posté le 10-09-2005 à 23:24:54
Vous pensez que je peuc faire mieu comme vérif ?
Code :
|
Marsh Posté le 10-09-2005 à 23:38:09
euh.... là, j'ai un autre problème...
Fichier "xhtml1.cs" :
Code :
|
Fichier "magicweb.cs" :
Code :
|
Quand je compile, j'ai l'erreur :
G:\Documents and Settings\MagicBuzz\VSWebCache\magicweb.manga-torii.com\testdotnet\magicweb.cs(33): No overload for method 'Page' takes '0' arguments
J'ai aussi l'erreur si je rajoute dans "MagicWeb.Templates.HomePage le contructeurs suivant :
Code :
|
Rigoureusement la même erreur !
Alors que deux lignes plus loin, toujours dans le namespace "MagicWeb" j'ai :
Code :
|
Et ça plante pas !
A noter que Tag dont hérite Header1 n'a pas de constructeur.
Mais Header1 a un constructeur.
Marsh Posté le 10-09-2005 à 23:42:45
Grrrr, corrigé avec l'ajout d'un constructeur sans paramètre qui appelle une méthode privée "Init" et déplacement du code du contructeur dans cette méthode.
Pfffff, y'a des fois, je trouve ça vraiment étrange ce truc !
Marsh Posté le 10-09-2005 à 23:43:09
Vous oubliez pas ce problème hein ?
Parcequ'en fait, c'est celui qui me bloque vraiment
http://forum.hardware.fr/forum2.ph [...] 0#t1196793
Marsh Posté le 10-09-2005 à 23:50:28
Grrrr ! Cette histoire de constructeur vide obligatoire m'a mis la puce à l'oreille.
Finalement, un nouveau constructeur dans la classe dérivée ne vient pas écraser le constructeur de la class mère. Et zou ! Problème corrigé
Marsh Posté le 11-09-2005 à 00:01:27
Bon, vous allez me prendre pour un gogole mais c'est pas grave
Finalement, j'ai viré mon test sur les types (qui m'en a pourtant pris du temps !) et remplacé par un test sur le tagName (évident depuis le départ...) pour deux raisons :
Mes "modules" (groupes de tags genre "menu", "news", etc.) ne sont pas des types reconnus lors de l'insertion d'un tag (donc je ne peux pas savoir si c'est valide ou non), et aussi tout bêtement parceque si je me base sur le tagName, rien ne m'empêche par la suite de tenter de rendre compatible mon bordel avec la lecture d'un DOCTYPE... Donc c'est mieu
Marsh Posté le 11-09-2005 à 01:34:10
Yes !
Bon, c'est cool, ça avance bien
Maintenant, je vais pouvoir m'atteler à la construction des templates et de la base, le code côté ASPX marche 100%
http://magicweb.manga-torii.com/te [...] form1.aspx
Généré uniquement à partir de :
Code :
|
Il va tout chercher à partir du nom de domaine et du numéro de page passé en paramètre (ici c'est vide, donc la HP est prise par défaut) dans la base pour savoir quel template utiliser, le contenu de la page, les méta, et s'il faut mettre ou non le copyright
Chuis trop fort (pourriez m'aider un peu, c'est pas facile de se jeter des roses à soit-même )
Marsh Posté le 11-09-2005 à 01:36:55
Le point noir, ça va être pour gérer les styles en dynamique...
J'hésite entre les fournir à la volée dans le HEAD, ou appeler une page dynamique avec un link, sâchant que pour la mise en cache, ça ne marchera pas...
Marsh Posté le 11-09-2005 à 11:30:08
Page dynamique avec un lien Pourquoi ça marchera pas la mise en cache ?
Marsh Posté le 11-09-2005 à 12:46:18
Normalement, les navigateur ne mettent pas un cache les pages ayant un paramètre.
Donc la seule solution envisageable, c'est de faire une page dynamique ne prenant pas de lien, et qui renvoie le style global de tout le site.
Moi j'aurais préféré n'envoyer que les styles spécifiques à la page en cours.
M'enfin c'est pas bien grave.
Marsh Posté le 11-09-2005 à 19:30:53
j'en chie assez déjà en faisant des trucs basiques
je viens de passer l'après-midi à réarranger mon code et avoir une gestion des pages 404 correcte alors...
Marsh Posté le 11-09-2005 à 19:44:52
Je crois bien que je l'ai d'ailleurs trop bien gérée, maintenant on n'est jamais dans le répertoire de l'appli mais à la racinde du site (qui ne supporte que l'ASP, pas .NET)
Marsh Posté le 11-09-2005 à 19:45:20
Mais ça marche quand même
MagicBuzz, le premier gars qui arrive à faire tourner un site web en dehors de son répertoire
Marsh Posté le 12-09-2005 à 22:23:59
Alors...
Maintenant, j'ai un souci d'héritage multiple ou je sais pas quoi. Appellez-le comme vous voulez
En gros :
Code :
|
En résumé :
J'ai une class générique Tag qui représente un tag xhtml. Dedans, y'a une série de propriétés et méthodes relatives au rendu du tag et stockages/rendu de son contenu/ses fils.
La class Div est hérité de Tag, et initialise un certain nombre de propriétés hérités de Tag aux valeurs spécifiques de Tag.
Maintenant, mon module News correspond à un Div. Je l'avais au départ fait hériter de Div donc. Dedans, il y a le code qui permet d'aller cherches les infos spécifiques à une news. Ensuite, j'ajoute mon module News dans un array de Tag qui est dans ma page afin d'en faire le rendu, tous modules confondus.
Seulement, dans l'optique de rendre mon code complètement générique au niveau de l'ajout des modules dans ma page, j'ai besoin de faire une boucle sur un type abstrait. Je désire donc faire une class Module, dont tous mes modules vont hériter.
Seulement, là j'ai un problème : Pour que ça marche Module doit hériter de Tag. Mais si News hérite de Module, alors il perd l'information comme quoi c'est un Div ! Comment faire ?
J'ai bien la solution de boucler avec le type abstrait Tag, mais je ne veux pas : mes modules ont des propriétés et des méthodes partagées spécifiques à un Module, et je ne veux pas polluer mon Tag avec, d'autant plus qu'ils ne sont pas dans le même namespace !
Notamment, un Module a une propriété "linkedToDatabase" qui va me permettre, lors du rendu des informations, de savoir si je dois aller chercher sont contenu dans la base de données ou si j'ai déjà tout initilisé dans son contructeur.
Comment faire ?
Marsh Posté le 12-09-2005 à 22:30:54
Si c'est pas possible, j'ai toujours la possibilité de stocker cette info dans ma table des modules, mais dans l'absolu, je préfèrerais que ce soit fait proprement dans le code plutôt qu'une info bidon stockée dans la base.
Marsh Posté le 12-09-2005 à 22:35:38
Arf, je crois que j'ai trouvé tout seul comme un grand...
Code :
|
Marsh Posté le 12-09-2005 à 22:37:26
Déjà on parle pas de "tag", mais d'éléments. Comme je l'ai dit ailleurs, on a un élément div, composé d'un tag ouvrant (<div> ) et d'un tag fermant (</div> )
Sinon, j'aurais plutôt choisi une aggrégation pour la news : Une news n'est pas une div, elle contient une div. Par contre, c'est bien un module, donc news va bien dériver de module...
Marsh Posté le 13-09-2005 à 00:16:46
Merdoum...
Comment je fais pour imbriquer des requêtes dans des "while" ?
J'obtiens cette erreur :
Citation : Un DataReader associé à cette connexion est déjà ouvert, il doit être tout d'abord fermé. |
Marsh Posté le 13-09-2005 à 00:19:51
Finalement, j'ai laissé tomber le problème de l'héritage multiple. En effet, en faisant calculer mes éléments par le constructeur du module, je me retrouve avec un objet compatible avec la class Tag.
Sinon, pour moi, chaque module sera effectivement un élément en tant que tel :
Si une news est constituée d'un titre, de deux paragraphes et d'une date, j'aurai en sortie :
Code :
|
Marsh Posté le 13-09-2005 à 00:21:06
En fait, j'aurai systématiquement un conteneur pour chacun de mes modules.
D'un point de vue sémantique, c'est pas forcément super, mais c'est ce qui me garanti qu'il ne va pas y avoir de cafouillage de pinceaux lors du rendu... surtout lors de l'application de la CSS !
Marsh Posté le 13-09-2005 à 00:29:12
Arjuna a écrit : Merdoum...
|
je suis quand même pas obligé de créer une nouvelle connection à chaque imbrication ? parceque sinon, bonjour les perfs
Marsh Posté le 13-09-2005 à 09:32:10
Arjuna a écrit : En fait, j'aurai systématiquement un conteneur pour chacun de mes modules. |
Pour la div news, utilise plutôt un id, non ?
Sinon d'un point de vue sémantique, c'est parfait. L'élément <div> servant à grouper des éléments et à donner de la structure à un doc XHTML, t'as parfaitement le droit d'en mettre un pour news. D'ailleurs pour un <h1> (ou <h2> ), la recommandation stipule bien que ça sert à donner un titre à la section dans laquelle il est, y'a un exemple donné où le h se trouve dans un div, justement pour "créer" une section...
Marsh Posté le 13-09-2005 à 14:00:10
Ben j'essaie de faire un truc 100% full compliant XHTML non seulement d'un point de vue syntaxique, mais aussi sémantique.
Sinon, pour mon problème de requêtes imbriquées ?
En fait, j'ai une boucle qui va rechercher les modules d'une page (donc issue d'une requête).
Ensuite, pour chaque module, je l'instancie, et ce dernier peut nécessiter d'aller chercher dans la base (pour le module "Menu", je dois récupérer la liste des pages, pour le module "News", je dois chercher le contenu de la news, etc.).
Donc j'ai besoin de faire une requête à alors que j'ai déjà un dataset ouvert.
Pire : pour le module "ListNews", je dois aller chercher la liste des news, puis, dans leur contenu afin de trouver la date et le titre. Donc j'ai 3 niveaux d'imbrication...
J'avais donc l'idée de faire deux connections, mais dans l'absolu, le nombre d'imbrications n'est pas défini (et peut être infini). Pour cette raison, multiplier les connection dans le scope global ne marche pas.
Enfin, ouvrir et fermer des connections à chaque niveau, d'un point de vue perfs, je crains que ce soit totalement catastrophique !
Comment résoudre ce problème ?
Marsh Posté le 13-09-2005 à 14:49:26
Normalement, t'as juste à clore le DataReader, et non la connexion
Marsh Posté le 13-09-2005 à 17:11:42
Oui, mais si je suis en train de le lire dans une boucle, j'ai pas trop envie de le fermer...
Donc pour ne pas avoir à le fermer, je dois ouvrir une nouvelle connection.
Hors ça, c'est hors de question.
Marsh Posté le 02-09-2005 à 23:37:21
Salut, j'ai un léger souci.
De base, .NET génère du code HTML 4.0 tout pourri.
Je voudrais me faire une class permettant de modéliser une page XHTML 1.0 correctement.
Sauf que déjà, ça part mal...
Ca plante :
Avec ça, je ne vais pas aller loin !
Pourquoi il ne comprend pas la DTD ? Je viens de mettre à jour les parseur XML sur le serveur et le PC de dev, mais j'ai toujours l'erreur :
MSXML 3 SP 7 (releasé la semaine dernière)
MSXML 4 SP 2 (releasé en 2003, et y'a pas de nouvelle version depuis)
Si je suis le lien avec IE, j'ai bien la même erreur : MSXML ne veut pas valider la DTD officielle !
Comment faire ?
http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd
Message édité par Arjuna le 02-09-2005 à 23:41:30