Daniel Kolman

Jak rozšířit XPath o vlastní funkce?

| 0 comments |

Že jazyky spojené s XML lze rozšiřovat, ví i můj jedenapůlroční synovec. Přidat si do XSLT šablony vlastní funkce je triviální prkotina a na netu existují tisíce návodů jak to udělat. Buď šoupnete funkci přímo do XSLT šablony do <ms:script> elementu, nebo přidáte objekt implementující kýžené funkce do XsltArgumentList objektu metodou AddExtensionObject (což je hezčí neboť to přímo nabádá k reuse). Takový přehled možností je zde. Jenže s XPath je to o něco komplikovanější.

Pokud voláte XPath dotazy nad nějakým XML dokumentem přímo z kódu, musíte na to jít úplně jinak. Zřejmě to není tak obvyklý scénář, protože jsem šťoural internet skrz naskrz a vůbec nebylo lehké přijít na nějakou stránku s návodem jak to udělat. Trvalo celkem dlouho než jsem objevil tohle: HOW TO: Implement and Use Custom Extension Functions When You Execute XPath Queries in Visual C# .NET.

Klíčový trik spočívá ve vytvoření vlastního XSLT kontextu, tedy třídy dědící od XsltContext. V ní předefinujete dvě metody: ResolveFunction a ResolveVariable. Když XPath parser narazí na něco, co vypadá jako funkce nebo proměnná kterou nezná, zavolá jednu z těchto metod a my máme šanci podstrčit mu vlastní implementaci. Řešení je to ale o něco složitější než u XSLT, protože musíte vrátit objekt implementující správné rozhraní - IXsltContextFunction nebo IXsltContextVariable. Ovšem s návodem už je to brnkačka, takže nemá cenu dál rozebírat detaily:-)

Jak zjistit celkovou velikost ViewState?

| 0 comments |

Když si zapnete podrobné trasování běhu stránky pomocí elementu <trace> v souboru web.config, ASP.NET vám do stránky vypíše strom ovládacích prvků a informaci o velikosti jejich ViewState a ControlState. Jaká je ale celková velikost dat odesílanýchve skrytém HTML poli __VIEWSTATE?

Na internetu lze nalézt několik návodů, jak přidat informaci o velikosti ViewState do trace logu. Jenže všechny co jsem našel zjišťují velikost podle Request["__VIEWSTATE"], ale to je navrácený ViewState, odeslaný z předchozí stránky! Pokud nás zajímá, kolik dat odesíláme ve ViewState aktuálně zpracovávané stránky, musíme použít daleko špinavější trik.

Výchozí PageStatePersister stránky pro ViewState je HiddenFieldPageStatePersister, který v metodě Save() zkomprimuje ViewState a ControlState a vloží jej do interního textového pole ClientState stránky. Stránka jej pak později narenderuje do jednoho nebo více skrytých polí __VIEWSTATE (záleží na nastavení vlastnosti stránky MaxPageStateFieldLength). No a tak si zjistíme jak je toto pole dlouhé a přidáme to do trace logu:

protected override void Render(HtmlTextWriter writer)
{
#if DEBUG
System.Reflection.PropertyInfo secretState =
this.GetType().GetProperty(
"ClientState",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic
);
string viewState = (string)secretState.GetValue(this, null);
if (viewState != null)
Trace.Warn("ViewState Size", viewState.Length.ToString());
else
Trace.Warn("ViewState Size", "0");
#endif
base.Render(writer);
}

No a je to. Informace o velikosti ViewState je vidět přímo v trace logu stránky! Dobrý, ne? Reflexe interního pole je ovšem špinavá technika a jsou k ní potřeba určitá práva. Pro ladění stránek a velikosti ViewState je to však príma.