Plná kontrola nad výstupom ASPX stránky

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)

Skôr ako začneme: nahliadnite do spracovania vašich osobných údajov

Súbory cookies používame najmä na anonymnú analýzu návštevnosti a vylepšovanie našich web stránok. Ak si nastavíte blokovanie zápisu cookies do vášho prehliadača, je možné, že web sa spomalí a niektoré jeho časti nemusia fungovať úplne korektne. Viac info k spracúvaniu cookies.