Визуальный веб-разработчик заменяет внутренний HTML новым HTML

Я сделал веб-страницу для отображения графики, а затем позволил пользователю ввести некоторые комментарии под ней. Пользователю предлагается ввести данные, и я пытаюсь сохранить каждый комментарий в списке, а затем отобразить список в виде упорядоченного списка HTML. Вот соответствующий код:

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

Выход из этого:

Key Messages:
<ol></ol>

Итак, у меня есть две загадки:

1) Почему текст, вводимый в текстовое поле, не добавляется в список

2) Почему новый HTML отображается как обычный текст.

Любые советы приветствуются.

С уважением.


person Kevin    schedule 06.06.2012    source источник


Ответы (3)


1) Почему текст, вводимый в текстовое поле, не добавляется в список

Как утверждают другие, вы не сохраняете данные между запросами.
Каждый раз, когда вы нажимаете кнопку, вся страница заново создается, что приводит к повторной установке вашей переменной message.

Session можно использовать. Например, замените поле message таким свойством:

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) Почему новый HTML отображается как обычный текст.

(В примечании <ol> теги внутри <span> являются недопустимыми HTML-кодами, даже если они могут отображаться)

Вы кодируете свой output.
Чтобы получить желаемый результат, вы просто не кодируете его следующим образом:

(Я не уверен в этом на 100%, но я думаю, что при работе через IIS в работающей системе IIS может автоматически кодировать строки, и у вас снова возникнет та же проблема, посмотрите на предложенный BulletList в качестве альтернативы, если это так. .)

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;
}

Альтернативой может быть использование BulletList с использованием BulletStyle из Numbered для получения того же результата.
Обновите Html следующим образом:

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

Измените код в Button4_Click на этот:

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)));
    }
}

Сводка

  • Сохраните свои данные, используя, например, Session
  • Не кодируйте свои данные, если вы хотите, чтобы html, который вы передаете, отображался (прочитайте предупреждение ниже)
  • Рассмотрите возможность использования BulletList вместо отправки небезопасных строк html.
  • Тег <ol> внутри <span> является недопустимым html

Предупреждение о кодировании

Если данные, поступающие с сервера, не кодируются, можно будет отправлять вредоносные сценарии. Например, скажем, мы делаем следующее:

Message.InnerHtml = "<script>alert('Hello');</script>";

Приведенное выше выполнит скрипт, показывающий предупреждение. Представьте, что это вредоносный скрипт!

Однако, как упоминалось выше, IIS может автоматически кодировать строки, и в этом случае этот скрипт не будет выполняться, а будет отображаться как обычный текст.

person Nope    schedule 06.06.2012

Вы должны понимать, как работают веб-страницы. Каждый щелчок по кнопке/гиперссылке создает новый http-запрос, извлекая в процессе новую страницу (если только вы не используете ajax, но это другой вопрос).

Вы можете установить приватную переменную типа List, но она специфична только для текущего экземпляра страницы. Когда пользователь делает запрос (например, нажимает кнопку), создается новый экземпляр страницы и возвращается пользователю => Список всегда будет пустым. Http не имеет состояния, вам нужен способ сохранения данных между запросами.

Если список предназначен для пользователя, вы можете использовать ViewState или SessionState для сохранения/получения данных по мере необходимости. Если это более глобальная вещь, используйте базу данных/файл в качестве носителя сохранения.

person walther    schedule 06.06.2012
comment
Упс. Неверное место. Не обращайте внимания. - person Quintium; 07.06.2012

Список не является статическим, поэтому он переопределяется каждый раз, когда запрашивается страница.

Причина, по которой вы видите его как текст воспроизведения, заключается в том, что вы HtmlEncode выводит. Таким образом, ‹ и > становятся HTML-представлением символов ( и ).

Message.InnerHtml = output;

должен исправить это

person Quintium    schedule 06.06.2012
comment
Проблема с static заключается в том, что это широкое приложение. Даже при объявлении private static readonly List<string> Messages = new List<string>(); меняем его на static и открываем например Firefox и Chrome (или IE и другой, какой когда нибудь). Вы можете добавить сообщения с помощью одного браузера, а затем нажать Done в другом и получить список. Я не думаю, что использование static и обмен сообщениями по всему приложению - хороший подход, если, конечно, это не то, что предполагал ОП. - person Nope; 07.06.2012
comment
На самом деле я имел в виду не ключевое слово static, а то, что объект не является статическим, когда страница запрашивается каждый раз. Извините за путаницу там. - person Quintium; 07.06.2012