I have made a web page to display a graphic and then allow the user to enter some comments underneath it. The user is prompted for input and I am trying to store each comment in a List and then display the list as an ordered HTML list. Here is the relevant code:
<script runat="server">
private List<string> messages = new List<string>();
protected void Button2_Click(object sender, EventArgs e)
{
messages.Add(TextBox2.Text);
TextBox2.Text = "";
}
protected void Button3_Click(object sender, EventArgs e)
{
messages.Clear();
}
protected void Button4_Click(object sender, EventArgs e)
{
string output = "<ol>";
foreach (string message in messages)
{
output += "<li>";
output += message;
output += "</li>";
}
output += "</ol>";
Message.InnerHtml = Server.HtmlEncode(output);
}
protected void Chart1_Load(object sender, EventArgs e)
{
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
Key Messages:<br />
<span id="Message" runat="server">
<asp:TextBox runat="server" ID="TextBox2" Width="500px"></asp:TextBox>
<asp:Button runat="server" ID="Button2" Text="Enter Message" Onclick="Button2_Click" />
<asp:Button runat="server" ID="Button3" Text="Clear Messages" onclick="Button3_Click" />
<asp:Button runat="server" ID="Button4" Text="Done" onclick="Button4_Click" />
</span>
</div>
</form>
</body>
</html>
The output from this is:
Key Messages:
<ol></ol>
So I have two mysteries:
1) Why isn't the text being entered into the textbox being added to the list
2) Why is the new HTML being displayed as plain text.
Any advice is appreciated.
Regards.
1) Why isn't the text being entered into the textbox being added to the list
As stated by others, you are not persisting the data between requests.
When ever you click a button the whole page is re-instantiated, causing your message
variable to re-set itself.
Session
can be used. For example replace your message
field with a property like this:
private List<string> Messages
{
get
{
var messages = Session["Messages"] as List<string>;
if (messages == null)
{
messages = new List<string>();
Session["Messages"] = messages;
}
return messages;
}
}
2) Why is the new HTML being displayed as plain text.
(On a side-note <ol>
tags inside a <span>
is invalid Html, even though it may render)
You are encoding your output
.
To get the desired result you simply don't encode it like this:
(I'm not 100% sure on this but I think when running through IIS on a live system IIS may auto-encode the strings and you have the same issue again, look at suggested BulletList
as alternative if that is the case.)
protected void Button4_Click(object sender, EventArgs e)
{
string output = "<ol>";
foreach (string message in Messages)
{
output += "<li>";
output += message;
output += "</li>";
}
output += "</ol>";
Message.InnerHtml = output;
}
An alternative would be the use of a BulletList
using the BulletStyle
of Numbered
to get the same result.
Update your Html
like this:
<div>
Key Messages:<br />
<span id="Message" runat="server">
<asp:TextBox runat="server" ID="TextBox2" Width="500px"></asp:TextBox>
<asp:Button runat="server" ID="Button2" Text="Enter Message" OnClick="Button2_Click" />
<asp:Button runat="server" ID="Button3" Text="Clear Messages" OnClick="Button3_Click" />
<asp:Button runat="server" ID="Button4" Text="Done" OnClick="Button4_Click" />
</span>
<asp:BulletedList BulletStyle="Numbered" ID="OutputMessages" runat="server">
</asp:BulletedList>
</div>
Change the code in the Button4_Click
to this:
protected void Button4_Click(object sender, EventArgs e)
{
// If you want to hide the message controls.
Message.Visible = false;
foreach (var message in Messages)
{
OutputMessages.Items.Add(new ListItem(Server.HtmlEncode(message)));
}
}
Summary
Session
BulletList
instead of sending back unsafe strings of html<ol>
tag inside a <span>
is invalid htmlWarning on Encoding
When not encoding data coming down from the server it would be possible to send down malicious scripts. For example, say we do the following:
Message.InnerHtml = "<script>alert('Hello');</script>";
The above would execute the script showing the alert. Imagine this being a malicious script!
However, as mentioned above, IIS may auto-encode the strings in which case this script would not execute but should render as plain text.