那么,我该如何防止这种荒谬的事情被渲染到HTML中呢?我希望能够创建一个继承HtmlGenericControl的类(我没有使用Web控件,我只是在每个input标签上添加了runat="server"),并覆盖将此“容器ID”放在ID和NAME属性开头的逻辑。然后,我可以在web.config中使用tagMapping进行全局更改。这可行吗?
暂时的安慰是,这个“特性”将在Asp.Net 4.0中得到修复。您将获得可设置的ClientID属性。
除此之外,其他回答都很好。
使用<%= control.ClientID %>
或者添加JQuery并使用$("[id$='myId'])
或者,在您的输入标签上,不要添加runtime='server'。您应该能够通过Form成员检索值(就像传统的asp一样)
或者,跳过Asp.Net WebForms并直接使用Asp.Net MVC,它可以完全控制生成的HTML标记。您需要更改做事情的方式,但这可能会让您感到 less frustrating。
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim Html As New StringWriter()
Dim Render As New HtmlTextWriter(Html)
MyBase.Render(Render)
writer.Write(Html.ToString().Replace("name=""ctl00$ContentBody$", "name=""").Replace("id=""ctl00_ContentBody_", "id="""))
End Sub
我不知道有什么办法可以从控件ID中移除命名容器。过去我使用了一个便利的方法,在javascript中查找这些id,它会遍历标记名称并使用正则表达式匹配那个以$realID
结尾的标记名称,其中realID
是我在标记中给控件的id。现在,我会使用jQuery来完成这个操作,使用类似下面的选择器:
$('[id$="realID"]')
这基本上与我的旧便捷方法做的一样,但它已经内置到框架中了。
Josh的解决方案:
代码后台:
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
StringWriter Html = new StringWriter();
HtmlTextWriter Render = new HtmlTextWriter(Html);
base.Render(Render);
writer.Write(Html.ToString()
.Replace("name=\"ctl00$ContentBody$", "name=\"")
.Replace("id=\"ctl00_ContentBody_", "id=\""));
}
解决方案1,存在PostBack问题(注意:我无法更改ID以解决此问题):
代码后台:
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
var html = new StringWriter();
var render = new HtmlTextWriter(html);
base.Render(render);
writer.Write(html.ToString()
.Replace("name=\"ctl00$contentBody$rbl",
"name=\"ctl00_contentBody_rbl"));
}
解决方案 2,改变 JavaScript:
在使用约定“rbl[name]”的单选按钮列表的 aspx 文件中的 JavaScript:
if (!validateRadioButtonList("<% =rblTitle.ClientID %>"))
代码后台:
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
var html = new StringWriter();
var render = new HtmlTextWriter(html);
base.Render(render);
writer.Write(html.ToString()
.Replace("validateRadioButtonList(\"ctl00_contentBody_rbl",
"validateRadioButtonList(\"ctl00$contentBody$rbl"));
}
我想在这个问题上加入我的两分钱:
我是按照被接受的答案所述的方法来做的,但我认为覆盖 Render 控件以写入新的 TextWriter,然后将其内容写入页面的 OutputStream
似乎浪费资源。我发现可以通过创建一个小类来覆盖 HtmlTextWriter
类来完成此操作。这样我们就可以直接写入流,只有在用作属性时才尝试替换文本。
public class CleanHtmlTextWriter : HtmlTextWriter
{
private const string MASTER_PAGE_ID = "ctl00";
private const string CONTENT_NAME = "MainContent";
public CleanHtmlTextWriter(TextWriter writer)
: base(writer)
{
}
public override void WriteAttribute(string name, string value)
{
if (name == "name")
value = value.Replace(CONTENT_NAME + "$", "").Replace(MASTER_PAGE_ID + "$", "");
if (name == "id")
value = value.Replace(CONTENT_NAME + "_", "").Replace(MASTER_PAGE_ID + "_", "");
base.WriteAttribute(name, value);
}
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(new CleanHtmlTextWriter(writer));
}
function alertValue(textID){
alert(document.GetElementById(textID).value);
}
<input id="txtBox" runat="server" type="Button" text="Click Me" onClick="alertValue('<%= txtBox.ClientID %>');" />
这真的取决于您的JS是如何实现的。
看起来您只是想从最终输出中删除客户端ID,因此您可能可以在页面上覆盖“render”事件并使用正则表达式将它们删除。您可以在下面的帖子中看到示例。
在获得要处理的文本后,您很可能可以编写类似于以下内容的东西...
output = Regex.Replace(
output,
@"id\=""ctl00\$[^\""]*""",
string.Empty,
RegexOptions.IgnoreCase
);
然后将最终输出写入HtmlTextWriter。
希望这有所帮助。
请查看:http://clientidless.codeplex.com/ - 您可以关闭几乎任何控件的ClientID。 这里有一个演示:http://show-demos.net/NoClientId/ - 点击“render without IDs”或“render with IDs”以查看页面大小如何变化。查看源代码以查看差异。
我需要的是快速而简单的解决方案,感谢HBoss,我成功地找到了一个非常简单的解决方案。在相关页面的代码后台中,我只需添加这个子程序...
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim Html As New StringWriter()
Dim Render As New HtmlTextWriter(Html)
MyBase.Render(Render)
writer.Write(Html.ToString().Replace("name=""ctl00$ContentBody$", "name=""").Replace("id=""ctl00_ContentBody_", "id="""))
End Sub