首先,我想让大家知道我使用的是 aspx 引擎而不是 Razor 引擎。
我有一个表格内的表格。我的一个文本框包含 html 标签,例如
</br>Phone: </br> 814-888-9999 </br> Email: </br> [email protected].
当我去构建它时,它给了我一个错误:
从客户端检测到潜在危险的 Request.Form 值
(QuestionAnswer="...ics Phone:<br/>814-888-9999<br...")
。
我尝试了验证请求=“假”,但它不起作用。
很抱歉到目前为止我还没有添加我的 html 代码供您查看。如果需要的话,我正在提出一些问题,我可以在哪里编辑它。
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
EditFreqQuestionsUser
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<script type="text/javascript">
$(document).ready(function () {
$("#freqQuestionsUserUpdateButton").click(function () {
$("#updateFreqQuestionsUser").submit();
});
});
</script>
<h2>Edit Freq Questions User </h2>
<%Administrator.AdminProductionServices.FreqQuestionsUser freqQuestionsUser = ViewBag.freqQuestionsUser != null ? ViewBag.freqQuestionsUser : new Administrator.AdminProductionServices.FreqQuestionsUser(); %>
<%List<string> UserRoleList = Session["UserRoles"] != null ? (List<string>)Session["UserRoles"] : new List<string>(); %>
<form id="updateFreqQuestionsUser" action="<%=Url.Action("SaveFreqQuestionsUser","Prod")%>" method="post" onsubmit+>
<table>
<tr>
<td colspan="3" class="tableHeader">Freq Questions User Details <input type ="hidden" value="<%=freqQuestionsUser.freqQuestionsUserId%>" name="freqQuestionsUserId"/> </td>
</tr>
<tr>
<td colspan="2" class="label">Question Description:</td>
<td class="content">
<input type="text" maxlength="2000" name="QuestionDescription" value=" <%=freqQuestionsUser.questionDescription%>" />
</td>
</tr>
<tr>
<td colspan="2" class="label">QuestionAnswer:</td>
<td class="content">
<input type="text" maxlength="2000" name="QuestionAnswer" value="<%=freqQuestionsUser.questionAnswer%>" />
</td>
</tr>
<tr>
<td colspan="3" class="tableFooter">
<br />
<a id="freqQuestionsUserUpdateButton" href="#" class="regularButton">Save</a>
<a href="javascript:history.back()" class="regularButton">Cancel</a>
</td>
</tr>
</table>
</form>
</asp:Content>
在提交页面之前,您需要使用 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>
对您的代码进行以下更改:
<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>
用
[ValidateInput]
属性装饰你的控制器动作:
[ValidateInput(false)]
[HttpPost]
public ActionResult Foo(MyViewModel model)
{
...
}
客户端 JavaScript:
function codificarTags()
{
document.getElementById('txtDescripcion').value = document.getElementById('txtDescripcion').value.replace(/</g,'<').replace(/>/g,'>');
}
<form id="form1" runat="server" onsubmit="codificarTags();">
服务器:
protected void Page_Load(object sender, EventArgs e)
{
txtDescripcion.Text = txtDescripcion.Text.Replace(@"<", @"<").Replace(@">", @">");
}
我建议使用 AjaxControlToolkit 的 HTML 编辑器。我现在正在实施。如果您的文本框是多行的并且足够大以容纳 HTML,为什么不将其添加到 HTML 编辑器中呢。您的用户也会更高兴。
http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/HTMLEditor/HTMLEditor.aspx
在文本框中使用 html 不是一个好的做法,也许使用换行符 (
Environment.NewLine
) 或
而不是br
?
.NET 参考
示例(C# 语言):
textBox1.Multiline = true;
textBox1.Text = "test" + Environment.NewLine + "test2";
我采取了一些不同的方法。我想在我的应用程序中广泛使用 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>
后面的代码负责在回发之前使用
RegisterOnSubmitStatement
转义控件,并在回发之后使用 RegisterStartupScript
取消转义它们。
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;
}
}
现在我们可以在设置时像这样在任何地方使用它
EscapeHtmlOnPostback="True"
。
<%@ Register TagPrefix="STB" TagName="SavableTextBox" Src="~/SavableTextBox.ascx" %>
<STB:SavableTextBox ID="Txt_HtmlTextBox" EscapeHtmlOnPostback="True" runat="server" />
注意,当我们在回发期间访问
Txt_HtmlTextBox.Text
时,它已经为我们转义了。
我喜欢@clamchoda 的用户控制解决方案,并试用了它。正如他提到的,他的整个控件都是非常自定义的,并且代码反映了更复杂的需求。对于更简单的事情,您可能需要考虑以下内容。
请注意,在此版本中,文本会在回发时自动解码,因此您的页面代码不必这样做(就像使用标准 TextBox 控件一样)。
用户控件 HTML 标记:
<script>
document.forms[0].addEventListener("submit", function (e){
let txtBox = document.getElementById('<%= TxtBox.ClientID %>')
txtBox.value = window.escape(txtBox.value);
});
</script>
<asp:TextBox ID="TxtBox" runat="server" />
代码隐藏(在 VB 中,但很容易转换为 C#):
Public Property Text As String
Get
Return TxtBox.Text
End Get
Set
TxtBox.Text = Value
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack Then
TxtBox.Text = Uri.UnescapeDataString(TxtBox.Text)
End If
End Sub
以上是基本内容。为了允许在 HTML 中进行标记,我添加了如下属性(从最有用的属性开始,并根据出现的给定需求逐渐添加其他属性):
Public Property CssClass As String
Get
Return TxtBox.CssClass
End Get
Set
TxtBox.CssClass= Value
End Set
End Property
Public Property StyleMargin() As String
'Note: use this to set all four margins.
Get
Return TxtBox.Style("margin")
End Get
Set(ByVal value As String)
TxtBox.Style.Add("margin", value)
End Set
End Property
Public Property Width As String
Get
Return TxtBox.Width
End Get
Set
TxtBox.Width= Unit.Parse(value)
End Set
End Property
最后,与所有最佳实践相比,要访问代码隐藏中的完整 TextBox 属性,您可以使用:
Public ReadOnly Property TxtBoxControl() As TextBox
'==> USE RESPONSIBLY !!! <===
Get
Return TxtBox
End Get
End Property
如前所述,要在页面上使用它,您需要在 HTML 标记中注册用户控件:
<%@ Register TagPrefix="STB" TagName="PostBackSafeTextBox" Src="~/PostBackSafeTextBox.ascx" %>
<STB:PostBackSafeTextBox ID="MyTextBoxTxt" runat="server" />
希望以上内容对其他人有帮助。也就是说,这必须归功于@clamchoda,他首先提出了这个想法。谢谢@clamchoda——它真的救了我!