質問

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

  • Persist your data, using for example the Session
  • Don't encode your data if you want the html you pass to render (Read warning below)
  • Consider using a BulletList instead of sending back unsafe strings of html
  • A <ol> tag inside a <span> is invalid html

Warning 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.

他のヒント

You must understand how web pages work. Every click on a button/hyperlink creates a new http request, retrieving a new page in the process (unless you use ajax, but that's a different matter to deal with).

You may set a private variable of type List, but that is specific only for the current instance of the page. When the user makes a request (e.g. clicks a button), a new instance of the page is created and returned to the user => the List will always be empty. Http is stateless, you need a way how to perform a persistence of the data between the requests.

If the List is specific to the user, you can use ViewState or SessionState to store/retrieve the data as needed. If it's a more global thing, use a database/file as a persistence medium.

The List isn't static, so it is redefined each time the page is requested.

The reason you see it as play text, is because you HtmlEncode the output. So < and > becomes the HTML representation of characters (&lt; and &gt;).

Message.InnerHtml = output;

should correct that

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top