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.
Príloha
ProcessHtml.zip (4kB)
Tento článok zahŕňa témy:
Page.Render, ViewState, Regular Expression, ASP.NET, codebehind, ASP, State
K tomuto článku zatiaľ nie sú žiadne komentáre. Buďte prvý. ;]
Poraďte sa s nami o službách, ktoré potrebujete. My vám pripravíme konkrétnu cenovú ponuku.
Kontaktujte nás