Plná kontrola nad výstupom ASPX stránky
Občas sa môže stať, že ASP.NET generuje do stránok html kód, ktorý vám z akéhokoľvek dôvodu nevyhovuje. Najbežnejší prípad je, ak máte jednoduchú stránku bez formulárových prvkov.
ASP.NET do nej vygeneruje <form> tag, skryté <input> tagy s ViewState a podobne. Keďže takáto stránka nikdy nebude robiť žiaden PostBack, je v nej formulár úplne navyše.
Samozrejme môžete vynechať <form runat=”server”> na aspx stránke, ale potom nemôžete použiť niektoré prvky (controls) ako GridView a podobne. Takže máme nasledovnú jednoduchú aspx stránku:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Theme="Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Generated text</title> </head> <body> <form id="form1" runat="server"> <div id="body"> <h1>Generated text</h1> <hr /> <p>Fuscingillam in vel, iaculisis, nas et por. Cras facinia, at, arcu ero.</p> <p>Vestibus. Etiam eu sagittis laorem condisse at, odio. Pellent molest.</p> <p>Vest sem. Morbi elis nulla, erat velit. Vestas. Pellus males nibh.</p> <p>o congue, ipsum diam ultricitur tincidunt mollis. Vivamus nec quam.</p> <p>Mauristibulum dapien. Pellus. Alique. Lorem. Curabitae wisi, in augue elis mi, ipsum.</p> </div> </form> </body> </html>
Text je vygenerovný mojim obľúbeným generátorom náhodného textu. Takáto stránka generuje nasledovný HTML kód:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head><title> Generated text </title><link href="App_Themes/default/_screen.css" type="text/css" rel="stylesheet" /></head> <body> <form name="form1" method="post" action="Default.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJODExMDE5NzY5ZGTtNznvtVe6+eGcNbMxzilJ1RCydA==" /> </div> <div id="body"> <h1>Generated text</h1> <hr /> <p>Fuscingillam in vel, iaculisis, nas et por. Cras facinia, at, arcu ero.</p> <p>. Vestibus. Etiam eu sagittis laorem condisse at, odio. Pellent molest.</p> <p>Vest sem. Morbi elis nulla, erat velit. Vestas. Pellus males nibh.</p> <p>o congue, ipsum diam ultricitur tincidunt mollis. Vivamus nec quam.</p> <p>Mauristibulum dapien. Pellus. Alique. Lorem. Curabitae wisi, in augue elis mi, ipsum.</p> </div> </form> </body> </html>
Takže by som chcel odstrániť <form> a <input> tagy. V codebehind stránky preťažím metódu Render a upravím výsledný kód pomocou regulárnych výrazov:
public partial class _Default : System.Web.UI.Page { protected override void Render(HtmlTextWriter writer) { System.IO.StringWriter html = new System.IO.StringWriter(); HtmlTextWriter render = new HtmlTextWriter(html); base.Render(render); writer.Write(ProcessHtml(html.ToString())); } private string ProcessHtml(string html) { html = System.Text.RegularExpressions.Regex.Replace(html, @"<form name=""form1"".*?>", string.Empty); html = System.Text.RegularExpressions.Regex.Replace(html, @"</form>", string.Empty); html = System.Text.RegularExpressions.Regex.Replace(html, @"<input.*?>", string.Empty); html = System.Text.RegularExpressions.Regex.Replace(html, @"<div>\s*</div>", string.Empty, System.Text.RegularExpressions.RegexOptions.Singleline); return html; } }
Výsledný HTML kód stránky potom vyzerá takto:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head><title> Generated text </title><link href="App_Themes/default/_screen.css" type="text/css" rel="stylesheet" /></head> <body> <div id="body"> <h1>Generated text</h1> <hr /> <p>Fuscingillam in vel, iaculisis, nas et por. Cras facinia, at, arcu ero.</p> <p>. Vestibus. Etiam eu sagittis laorem condisse at, odio. Pellent molest.</p> <p>Vest sem. Morbi elis nulla, erat velit. Vestas. Pellus males nibh.</p> <p>o congue, ipsum diam ultricitur tincidunt mollis. Vivamus nec quam.</p> <p>Mauristibulum dapien. Pellus. Alique. Lorem. Curabitae wisi, in augue elis mi, ipsum.</p> </div> </body> </html>
Ako vidíte, pomocou metódy Render a System.IO.StringWriter objektu môžem upravovať výstup akejkoľvek stránky. Rovnako, použitím eventu Render môžem meniť výstupné html akéhokoľvek Control.
V priloženom projekte mám vytvorenú základnú triedu, ktorá je odvodená od System.Web.UI.Page. Jej zdrojový kód je:
namespace MyWeb { public class MyPage : System.Web.UI.Page { protected override void Render(HtmlTextWriter writer) { System.IO.StringWriter html = new System.IO.StringWriter(); HtmlTextWriter render = new HtmlTextWriter(html); base.Render(render); ProcessHtmlEventArgs e = new ProcessHtmlEventArgs(); e.Html = html.ToString(); OnProcessHtml(e); writer.Write(e.Html); } public event EventHandler<ProcessHtmlEventArgs> ProcessHtml; protected virtual void OnProcessHtml(ProcessHtmlEventArgs e) { if (ProcessHtml != null) ProcessHtml(this, e); } } public class ProcessHtmlEventArgs : EventArgs { public string Html; } }
Túto novú triedu potom môžem používať ako base triedu pre všetky ostatné stránky, teda:
public partial class _Default : MyWeb.MyPage { protected override void OnProcessHtml(WebTest.MyWeb.ProcessHtmlEventArgs e) { e.Html = System.Text.RegularExpressions.Regex.Replace(e.Html, @"<form name=""form1"".*?>", string.Empty); e.Html = System.Text.RegularExpressions.Regex.Replace(e.Html, @"</form>", string.Empty); e.Html = System.Text.RegularExpressions.Regex.Replace(e.Html, @"<input.*?>", string.Empty); base.OnProcessHtml(e); } }
Prípadne môžem použiť aj event ProcessHtml:
protected override void OnLoad(EventArgs e) { ProcessHtml += new EventHandler<WebTest.MyWeb.ProcessHtmlEventArgs>(Default_ProcessHtml); base.OnLoad(e); } void Default_ProcessHtml(object sender, WebTest.MyWeb.ProcessHtmlEventArgs e) { e.Html = System.Text.RegularExpressions.Regex.Replace(e.Html, @"<form name=""form1"".*?>", string.Empty); e.Html = System.Text.RegularExpressions.Regex.Replace(e.Html, @"</form>", string.Empty); e.Html = System.Text.RegularExpressions.Regex.Replace(e.Html, @"<input.*?>", string.Empty); }
Analogicky sa dá podobné rozšírenie zaviesť aj na akýkoľvek Control. Pochopiteľne nejde o úplne najkrajšie riešenie. Predpokladá, že sa nezmení výstup, čo sa môže napríklad aplikovaním ControlAdapter-u. Lepšie by bolo použiť ControlAdapter, alebo priamo generovať (renderovať) výstup. Ale na druhej strane je to takto rýchle a jednoduché.
Na zmenu výstupu celej stránky si tiež môžete vytvoriť HTTP Modul a zavesiť na Response.Filter vlastnú triedu. Postup nájdete na stránkach aspnet.cz . HTTP modul má obrovskú výhodu, že ho môžete pridať a odobrať do už existujúcej aplikácie. Jediná nevýhoda použitia modulu a funkcie Response.Filter je, že v nej nemáme výstupný HTML kód “naraz”, ale po častiach cez Stream. Akékoľvek globálne nahrádzanie obsahu tak neprichádza do uváhy, keďže nemáme žiadnu kontrolu nad tým, v ktorej časti sa html rozdelí
V ďalšej časti vám ukážem konkrétnu užitočnú aplikáciu tejto techniky na zmenu html výstupu celej stránky.