ASP.Net 3.5 ha portato (pochi) nuovi controlli che promettono di essere di notevole aiuto
per addolcire il conflitto che da anni esiste tra la tecnologia WebControls-based e gli aspetti di correttezza formale XHTML/CSS
e di Search Engine Optimization.
Adoro il ListView ovviamente, ma apprezzo forse di più il DataPager che posso associarvi.
Infatti, valorizzando la propretà QueryStringField dello stesso, posso finalmente dimenticami degli odiosi
links javascript dei pager controls passati (illeggibili per i search-bots)!
Bene, tutto a posto allora: ho questi nuovi oggettini, scrivo il mio ultra-hackabile-leggibile-SEOttimizzato website
che è una bomb... whoops!
I Fields del mio DataPager puntano alla pagina fisica e non a quella virtuale?! Sul serio?...
Proprio così :(
Vabbè, magari utilizzo un ControlAdapter custom e risolvo agevolmente il problema.
No-no.
Vabbè, allora prendo - ad esempio - il NumericPagerField, che non è marcato sealed, lo subclasso
e sostituisco con un bell'override il metodo incriminato.
No-no... o almeno, non così facilmente...
Diamo un occhio - grazie Reflector - alla catenaria di classi e metodi che si
avvicendano per la renderizzazione dei nostri link di paginazione:
NumericPagerField espone un metodo virtual (CreateDataPagers) che dà inizio a tutto il processo.
Esso "stuzzica" due subroutines private CreateNextPrevLink e CreateNumericLink
(i nomi sono autoesplicativi direi) le quali a loro volta attingono ad un metodo GetQueryStringNavigateUrl appartenente alla classe
base abstract DataPagerField e che è marcato protected (non virtual)!
Qui non colgo il senso dell'architettura: perché un metodo protected ed, al contempo,
una chiamata esplicita e blindata da una classe derivata alla versione base del
metodo stesso?!
Per ovviare a questo inconveniente si rende necessario scrivere più codice di quanto pensassi...
Di seguito riporto quello che è il metodo centrale da riscrivere, per far funzionare questa sottoclasse di NumericPagerField
in abbinamento con la riscrittura degli URL è però necessario ulteriore, verboso, codice (disponibile nella sua interezza più sotto):
protected new string GetQueryStringNavigateUrl(int pageNumber)
{
string queryStringField = this.DataPager.QueryStringField;
StringBuilder builder = new StringBuilder();
HttpRequest request = this.DataPager.Page.Request;
string url = request.RawUrl;
int qMarkNdx = url.IndexOf("?");
if (qMarkNdx > -1) url = url.Substring(0, qMarkNdx);
builder.Append(url);
builder.Append("?");
foreach (string str2 in request.QueryString.AllKeys)
{
if (string.IsNullOrEmpty(str2) || str2.Equals(DataPager.QueryStringField, StringComparison.InvariantCultureIgnoreCase)) continue;
builder.Append(HttpUtility.UrlEncode(str2));
builder.Append("=");
builder.Append(HttpUtility.UrlEncode(request.QueryString[str2]));
builder.Append("&");
}
builder.Append(queryStringField);
builder.Append("=");
return (builder.ToString() + pageNumber.ToString(System.Globalization.CultureInfo.InvariantCulture));
}
Di seguito il codice scaricabile.
«
UrlRewriteNumericPagerField class (C#)
Take care. Bye.
Feedbacks
-
Re: UrlRewrite vs ASP.Net 3.5 DataPager
Steve (domenica 22 marzo 2009 15.36)
“I recently ran into this problem as well.
Cristian.. Can you describe how one would hook up the code that you provided?
Thanks”
-
Re: UrlRewrite vs ASP.Net 3.5 DataPager
Chad (mercoledì 29 luglio 2009 21.40)
“Steve,
Add this to your web.config
<pages>
<tagMapping>
<add tagType="System.Web.UI.WebControls.NumericPagerField" mappedTagType="Ryoushin.WebControls.RewriteNumericPagerField"/>
</tagMapping>
</pages>
That will automatically map his class to your datapager controls that use the NumericPagerField”
-
Crashes on null keys and adds incorrect querystring fields
Jeff (sabato 3 ottobre 2009 16.23)
“ex url "host.com/products/tables/?a=1&" has a null key at the end that is not handled.
ex url "host.com/products/tables/" could be re-written as "host.com/products.aspx?cat=tables" and this code would product links like "host.com/products/tables/?cat=tables&page=2" and is incorrect. This is because the code isn't parsing querystring fields from the RawUrl.
Replace the "foreach (string str2 in request.QueryString.AllKeys)" block with this:
System.Text.RegularExpressions.MatchCollection matches = System.Text.RegularExpressions.Regex.Matches(request.RawUrl, @"(\?|&)(?<key>[^=]+)=(?<value>[^&]+)");
foreach (System.Text.RegularExpressions.Match m in matches)
{
string key = m.Groups["key"].Value;
string value = m.Groups["value"].Value;
if (key == null || key.Equals(queryStringField, StringComparison.InvariantCultureIgnoreCase))
{
continue;
}
builder.Append(HttpUtility.UrlEncode(key));
builder.Append("=");
builder.Append(HttpUtility.UrlEncode(request.QueryString[value]));
builder.Append("&");
}”
-
flubbed it
Jeff (sabato 3 ottobre 2009 17.11)
“Sorry, should be "builder.Append(HttpUtility.UrlEncode(value));"”
-
Re: UrlRewrite vs ASP.Net 3.5 DataPager
CMerighi (lunedì 5 ottobre 2009 1.43)
“@Jeff
Thanks for the corrections! The null key wasn't handled at all, shame on me (sample code fixed)...
About the QueryString issue, your implementation takes care of Routing Modules that send informations to the physical pages using querystrings and that closes the circle.
Personally, I tend to exploit Context.Items dictionary (as Dynamic Data Routing Engine does) instead of QueryString, it permits to pass complex object and doesn't have size limitations.”
-
CreateNextPrevLink and CreateNumericLink not called
Steve (lunedì 19 ottobre 2009 1.45)
“Code is hooked up and I am getting a call into the funtion "CreateDataPagers",
but breakpoints in "CreateNextPrevLink" and "CreateNumericLink" are not being hit.
I don't think the code is being called. Any help much appreciated.
I do have the appropriate lines in web.config.
Thanks, Steve”
-
Re: UrlRewrite vs ASP.Net 3.5 DataPager
micheal (giovedì 19 agosto 2010 13.03)
“it's very good!”