C# 如何允许在asp.net的文本框中提交HTML标记?

C# 如何允许在asp.net的文本框中提交HTML标记?,c#,javascript,asp.net-mvc,decoding,C#,Javascript,Asp.net Mvc,Decoding,首先,我想让大家知道我使用的是aspx引擎,而不是Razor引擎 我有一张表格里的桌子。我的一个文本框包含html标记,如 电话:814-888-9999电子邮件:aaa@gmail.com. 当我去构建它时,它会给我一个错误,上面写着: 潜在危险的请求。从客户端检测到表单值(QuestionAnswer=“…ics Phone:814-888-9999在文本框中使用html不是一个好做法,可能使用换行符(Environment.NewLine)或\r\n而不是br? 例如(用C#表示)

首先,我想让大家知道我使用的是aspx引擎,而不是Razor引擎

我有一张表格里的桌子。我的一个文本框包含html标记,如


电话:
814-888-9999
电子邮件:
aaa@gmail.com.
当我去构建它时,它会给我一个错误,上面写着:


潜在危险的请求。从客户端检测到表单值
(QuestionAnswer=“…ics Phone:
814-888-9999在文本框中使用html不是一个好做法,可能使用换行符(
Environment.NewLine
)或\r\n而不是
br

例如(用C#表示):


使用
[ValidateInput]
属性装饰控制器操作:

[ValidateInput(false)]
[HttpPost]
public ActionResult Foo(MyViewModel model)
{
    ...
}

在提交页面之前,您需要使用window.escape(…)对文本框的值进行html编码

如果需要服务器端的未转义文本,请使用
HttpUtility.UrlDecode(…)
方法

非常快速的示例:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="SO.WebForm1" %>

<!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></title>
    <script>
        function makeSafe() {
            document.getElementById('TextBox1').value = window.escape(document.getElementById('TextBox1').value);
        };

        function makeDangerous() {
            document.getElementById('TextBox1').value = window.unescape(document.getElementById('TextBox1').value);
        }
    </script>
</head>
<body>
    <form id="form1" runat="server" onsubmit="makeSafe();">
    <div>
        <asp:TextBox ID="TextBox1" runat="server" TextMode="MultiLine" Rows="10" ClientIDMode="Static"></asp:TextBox>
    </div>
    <asp:Button ID="Button1" runat="server" Text="Button" />
    </form>


     <script>
         makeDangerous();
    </script>
</body>
</html>

函数makeSafe(){
document.getElementById('TextBox1').value=window.escape(document.getElementById('TextBox1').value);
};
函数makehazard(){
document.getElementById('TextBox1').value=window.unescape(document.getElementById('TextBox1').value);
}
使危险();
对代码进行以下更改:

<script type="text/javascript">
    $(document).ready(function () {
        makeDangerous();
        $("#freqQuestionsUserUpdateButton").click(function () {
            makeSafe();
            $("#updateFreqQuestionsUser").submit();
        });
    });

    // Adding an ID attribute to the inputs you want to validate is simplest
    // Better would be to use document.getElementsByTagName and filter the array on NAME
    // or use a JQUERY select....

    function makeSafe() {
        document.getElementById('QuestionAnswer').value = window.escape(document.getElementById('QuestionAnswer').value);
    };

    // In this case adding the HTML back to a textbox should be 'safe'
    // You should be very wary though when you use it as actual HTML
    // You MUST take steps to ensure the HTML is safe.
    function makeDangerous() {
        document.getElementById('QuestionAnswer').value = window.unescape(document.getElementById('QuestionAnswer').value);
    }
</script>

$(文档).ready(函数(){
使危险();
$(“#频率问题更新按钮”)。单击(函数(){
makeSafe();
$(“#更新问题解答”).submit();
});
});
//向要验证的输入添加ID属性是最简单的
//最好使用document.getElementsByTagName并根据名称筛选数组
//或者使用JQUERY选择。。。。
函数makeSafe(){
document.getElementById('QuestionAnswer').value=window.escape(document.getElementById('QuestionAnswer').value);
};
//在这种情况下,将HTML添加回文本框应该是“安全的”
//但是,当您将它用作实际的HTML时,应该非常小心
//您必须采取措施确保HTML是安全的。
函数makehazard(){
document.getElementById('QuestionAnswer').value=window.unescape(document.getElementById('QuestionAnswer').value);
}

我建议使用AjaxControlToolkit的HTML编辑器。我现在正在实现这一点。如果您的文本框是多行的,并且足够大,可以容纳HTML,为什么不将其升级为HTML编辑器呢。您的用户也会更高兴

客户端JavaScript:

function codificarTags() 
{
     document.getElementById('txtDescripcion').value = document.getElementById('txtDescripcion').value.replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
    
<form id="form1" runat="server" onsubmit="codificarTags();">
cartags()函数
{
document.getElementById('txtDescription')。value=document.getElementById('txtDescription')。value.replace(//g',);
}
服务器:

protected void Page_Load(object sender, EventArgs e)
{
     txtDescripcion.Text = txtDescripcion.Text.Replace(@"&lt;", @"<").Replace(@"&gt;", @">");
}
受保护的无效页面加载(对象发送方,事件参数e)
{
txtDescription.Text=txtDescription.Text.Replace(@“”@“”);
}

我采取了一种不同的方法。我希望在我的应用程序中广泛使用html文本框。我创建了一个用户控件,可以避免每次添加新控件时编辑javascript。我的整个控件都非常自定义,但html处理的核心如下所示

UserControl
标记有一些简单的javascript来转义和取消显示文本框

<script type="text/javascript">

    function UnescapeControl(clientId) {
            $('#' + clientId).val(window.unescape($('#' + clientId).val()));
    }

    function EscapeAllControls() {
       var escapeControList = JSON.parse('<%= new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(EscapeControlList) %>');
       for (var i = 0; i < escapeControList.length; i++) 
           EscapeControl(escapeControList[i]);            
    }

    function EscapeControl(textClientId) {
       document.getElementById(textClientId).value = window.escape(document.getElementById(textClientId).value); 
    }
</script>

<asp:TextBox ID="Txt_SavableText" CssClass="form-control" Width="100%" runat="server" ></asp:TextBox>
现在,在设置
EscapeHtmlOnPostback=“True”
时,我们可以在任何类似的地方使用它



注意,当我们在回发过程中访问
Txt\u HtmlTextBox.Text
时,它已经为我们转义了。

我可以在文本框中使用它//n或/r?我将\n放在文本框中,它不起作用。它也没有给我一个错误。它只是输入了\n,所以现在类似于\n814-888-9999@Yusuf如果文本框的类型是多行的,它会!使用text1.text=“test”+”\r\n“+”test2";抱歉,我颠倒了\n和\r,这是为了工作。更改freqQuestionsUser.questionAnswer,应该可以-1:虽然这是一个有效的答案,但不是一个好答案。我认为建议用户盲目禁用验证不是一个好主意。相反,他们应该确定验证失败的原因,然后想出一个解决方案hat不仅仅是关闭了一个重要的安全机制。像和提供的建议是一个很好的开始。@KevinBabcock,重要的安全机制?我笑了。你能解释一下这个验证有什么这么重要吗?你也只是为了这个特定的操作禁用了验证。在ASP.NET MVC 3中,你可以通过使用
[allowtml]
属性装饰视图模型属性,可以实现更细粒度的逻辑。在提交之前使用javascript逃避用户输入有什么意义?说真的吗?你认为输入验证很可笑,也不重要?“不正确的中和”用户输入的类型是。你只是告诉那个家伙在没有任何解释的情况下禁用输入验证。没有解释,没有选择,什么都没有。在将用户输入提交到服务器之前对其进行编码有什么意义?请检查。显然,这只是一种第一线防御,输入也应该在服务器上验证。这很旧,但是@DarinDimitrov是正确的,我知道如何验证我自己的输入,这里我特别希望允许HTML——正如标题所说。
protected void Page_Load(object sender, EventArgs e)
{
     txtDescripcion.Text = txtDescripcion.Text.Replace(@"&lt;", @"<").Replace(@"&gt;", @">");
}
<script type="text/javascript">

    function UnescapeControl(clientId) {
            $('#' + clientId).val(window.unescape($('#' + clientId).val()));
    }

    function EscapeAllControls() {
       var escapeControList = JSON.parse('<%= new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(EscapeControlList) %>');
       for (var i = 0; i < escapeControList.length; i++) 
           EscapeControl(escapeControList[i]);            
    }

    function EscapeControl(textClientId) {
       document.getElementById(textClientId).value = window.escape(document.getElementById(textClientId).value); 
    }
</script>

<asp:TextBox ID="Txt_SavableText" CssClass="form-control" Width="100%" runat="server" ></asp:TextBox>
public partial class SavableTextBox : System.Web.UI.UserControl
{

    public List<string> EscapeControlList
    {
        get
        {
            if (Session["STB_EscapeControlList"] == null)
                Session["STB_EscapeControlList"] = new List<string>();
            
            return (List<string>)Session["STB_EscapeControlList"];
        }
        set { Session["STB_EscapeControlList"] = value; }
    }

    

    protected void Page_Load(object sender, EventArgs e)
    {
        if (EscapeHtmlOnPostback && !EscapeControlList.Contains(GetClientId()))
            EscapeControlList.Add(GetClientId());

        // When using a script manager, you should use ScriptManager instead of ClientScript.
        if (EscapeHtmlOnPostback)
            ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "UnescapeControl_" + GetClientId(), "UnescapeControl('" + GetClientId() + "');", true);

        // Ensure we have our escape script called before all post backs containing escapable controls.
        // This is like calling OnClientClick before everything.
        if (EscapeControlList != null && EscapeControlList.Count > 0)
            this.Page.ClientScript.RegisterOnSubmitStatement(this.GetType(), "SaveableTextBoxEscaper", "EscapeAllControls();");
        
    }


   public string Text
    {
        get
        {
            return Txt_SavableText.Text;
        }
        set
        {
            Txt_SavableText.Text = value;
        }
    }

    public string GetClientId()
    {
        return Txt_SavableText.ClientID;
    }
}
<%@ Register TagPrefix="STB" TagName="SavableTextBox" Src="~/SavableTextBox.ascx" %>
<STB:SavableTextBox ID="Txt_HtmlTextBox" EscapeHtmlOnPostback="True" runat="server" />