Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    View Cyril Durand's profile on LinkedIn

    hit counters

Référencement et UpdatePanel : la solution CrawlableLinkButton

Les UpdatePanels sont très agréables pour l'utilisateur puisque, bien utilisés, ils permettent d'avoir une expérience utilisateur plus fluide. Pour arriver à ce résultat, ils utilisent une requête XMLHttpRequest (requête Ajax) qui n'est pas référençable par les moteurs de recherche.

Comment utiliser les UpdatePanels sans sacrifier son référencement ? 

Pour qu'un utilisateur puisse utiliser les résultats du moteur de recherche, il faut que le contenu soit accessible à partir d'une requête GET, lorsque l'utilisateur clique il faut qu'il arrive directement sur ce qui l'intéresse, ce n'est pas le cas si on utilise les UpdatePanels avec un LinkButton.

Prenons un exemple : une page qui liste les processus en cours sur la machine et qui affiche le détail du processus sélectionné :

<script type="text/C#" runat="server"> void Page_Load(Object sender, EventArgs e) { if (!Page.IsPostBack) { BindData(); } } private System.Diagnostics.Process _currentProcess; public System.Diagnostics.Process CurrentProcess { get { if (_currentProcess == null) { int pid = -1; if (Page.IsPostBack) { if (ViewState["PID"] != null) { pid = (int)ViewState["PID"]; } } else { int.TryParse(Request.QueryString["PID"], out pid); } if (pid > -1) { _currentProcess = Processes.Find(delegate( System.Diagnostics.Process process){ return process.Id == pid; }); } else { _currentProcess = Processes[0]; } } return _currentProcess; } set { ViewState["PID"] = value.Id; _currentProcess = value; } } private static List<System.Diagnostics.Process> _processes; public static List<System.Diagnostics.Process> Processes { get { // Ne faites pas ça, c'est pour l'exemple mais attention // c'est pas thread safe ... if (_processes == null) { _processes = new List<System.Diagnostics.Process>( System.Diagnostics.Process.GetProcesses()); } return _processes; } } void gvProcess_SelectedIndexChanged(object sender, EventArgs e) { // ca aussi c'est mal, c'est pour simplifier l'exemple CurrentProcess = Processes[gvProcess.SelectedIndex]; } void BindData() { gvProcess.DataSource = Processes; gvProcess.DataBind(); } </script> <asp:Content ID="Content1" ContentPlaceHolderID="CPH1" runat="Server"> <asp:UpdatePanel runat="server" UpdateMode="Conditional" > <ContentTemplate> <%=CurrentProcess.ProcessName %> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="gvProcess" /> </Triggers> </asp:UpdatePanel> <asp:GridView runat="server" ID="gvProcess" AutoGenerateColumns="false" OnSelectedIndexChanged="gvProcess_SelectedIndexChanged"> <Columns> <asp:CommandField ShowSelectButton="true" /> <asp:BoundField DataField="ProcessName" /> <asp:BoundField DataField="VirtualMemorySize" /> </Columns> </asp:GridView> </asp:Content>

Cette page fonctionne parfaitement, mais regardons le code html généré au niveau d'une ligne d'un gridview.

<tr class="AspNet-GridView-Alternate"> <td><a href="javascript:__doPostBack('ctl00$CPH1$gvProcess','Select$15')">Select</a></td> <td>WebDev.WebServer</td> <td>283324416</td> </tr>

Le détail de ce processus ne peut pas être indexé par un robot. Même si un robot était capable d'exécuter JavaScript et donc de lire le détail du processus, comment ferait-il ressortir ce résultat ? Lorsque l'utilisateur fais une recherche il veut voir directement le contenu qui l'intéresse : il faut que la contenu soit accessible à partir d'une URL.

Comment contourner le problème ? L'idée est d'exécuter le postback donc du JavaScript pour les clients riches tout en laissant une vrai url pour les robots.

Ainsi la ligne plus haut se transformerait en :

<tr class="AspNet-GridView-Alternate"> <td> <a href="temp.aspx?PID=1092" onclick="void(__doPostBack('ctl00$CPH1$gvProcess$ctl17$ctl00',''));return false;"> Select </a> </td> <td>WebDev.WebServer</td> <td>285884416</td> </tr>

Pour arriver à ce résultat, j'ai créé un contrôle héritant de LinkButton : le CrawlableLinkButton qui rajoute la propriété NavigateUrl. Les sources du contrôle CrawlableLinkButton se trouve sur aspfr.

Le gridview se transforme alors en

<asp:GridView runat="server" ID="gvProcess" AutoGenerateColumns="false" OnSelectedIndexChanged="gvProcess_SelectedIndexChanged"> <Columns> <asp:TemplateField> <ItemTemplate> <cs:CrawlableLinkButton runat="server" CommandName="Select" Text="Select" NavigateUrl='<%# "temp.aspx?PID=" + Eval("id").ToString() %>' /> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="ProcessName" /> <asp:BoundField DataField="VirtualMemorySize" /> </Columns> </asp:GridView>

On voit qu'avec un minimum de code (le CrawLableLinkButton ne fait pas 100 lignes) il est possible de trouver des solutions pour référencer des UpdatePanels, il suffit de se mettre à la place d'un moteur de recherche et analyser le code HTML.

Posted: mardi 16 octobre 2007 12:43 par cyril
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

guitoux1 a dit :

"On voit qu'avec un minimum de code (le CrawLableLinkButton ne fait pas 100 lignes) il est possible de trouver des solutions pour référencer des UpdatePanels, il suffit de se mettre à la place d'un moteur de recherche et analyser le code HTML."

... et aussi créer la page temp.aspx qui permettra d'afficher le contenu à référencer :)

# octobre 16, 2007 14:25

cyril a dit :

Dans mon exemple, la page temp était celle qui contient l'UpdatePanel ;-). Il a aussi fallu que je change la méthode CurrentProcess pour prendre en compte le querystring mais 2 lignes de codes à rajouter.

On peut bien sur faire 2 pages différentes et utiliser des UserControls pour ne pas réécrire la partie de détail, ou alors fournir un contenu complétement différent entre l'updatepanel et la page de destination, bref ce n'est pas quelque chose de compliqué ;-)

# octobre 16, 2007 14:52

Aurelien a dit :

Et ca marche, c'est exactement le stratagème que j'ai mis en place sur le site wygwam en 2005 ;-)

Pas d'updatepanel en cause, mais de simples requêtes XmlHttp, à cette époque, on ne parlait pas encore "Atlas" !

Par contre, j'ai un moteur de rendering pour reconstruire les urls que les robots indexent ...

# octobre 17, 2007 00:29
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Conversion de fichiers RAW en fichier JPEG avec WPF par Perspective le il y a 32 minutes

- Mise à Jour du Moteur de Recherche des Arrêts de Bus de Montréal par Jerome Laban le il y a 1 heure et 16 minutes

- [WPF] XPSReader v0.2 par Blog Technique d'Audrey PETIT le il y a 2 heures et 17 minutes

- Entity Framework : providers Oracle, MySQL et PostgreSQL par Matthieu MEZIL le il y a 8 heures et 52 minutes

- [WPF] Nouvel article sur c2i.fr par Richard Clark le 09-06-2008, 17:33

- F# nouvelle CTP 1.9.6.2 (update) par Pierrick's Blog le 09-06-2008, 13:27

- La suite ...Proposition de collaboration rédactionnelle entre les communautés de développeurs et Microsoft France par LucasR le 09-05-2008, 17:45

- [Fun] Votre simulateur de vol avec Microsoft ESP par Julien Chable le 09-05-2008, 12:02

- [Best Practices] Customisation du My Site : Comment le modifier en amont et en aval par The Mit's Blog le 09-05-2008, 10:47

- Patrick Tisseghem s'en est allé ... par The Mit's Blog le 09-05-2008, 10:04