从呈现的控件ID中删除ctl00 $ ContentBody $

时间:2009-05-06 02:08:45

标签: asp.net master-pages

我对以前只是简单的HTML和Javascript的现有应用程序进行了一些更改。为了添加服务器端功能,我选择了ASP.NET,并利用了Master Page概念。不幸的是,在一个巨大的Web表单上,控件ID都被“ctl00 $ ContentBody $”前缀所破坏。我在所有INPUT控件上添加了一个runat =“server”,它改变了ID。现在已经更改了ID,Javascript(编写得很糟糕,我甚至无法阅读它,而且我对JS很有经验)完全被破坏了。

那么,我怎样才能防止这种废话被渲染到HTML中呢?我希望以某种方式能够创建一个继承HtmlGenericControl的类(我没有使用Web控件,我只是在每个输入标记的runat =“server”上添加)并以某种方式覆盖了粘贴这个“容器id”的逻辑ID和NAME属性的开头。然后我可以在web.config中使用tagMapping来进行全局更改。这可能吗?

9 个答案:

答案 0 :(得分:6)

现在的小安慰,但这个“功能”将在Asp.Net 4.0中修复。您将获得可设置的ClientID属性。

除此之外,其他反应都很好 使用<%= control.ClientID%>

或抛出JQuery并使用$(“[id $ ='myId'])

或者,在输入标记上,不要将runtime ='server'。您应该能够通过Form成员检索值(就像在传统的asp中一样)

或者,跳过Asp.Net WebForms并跳到Asp.Net MVC,它可以让您完全控制生成的HTML标记。你必须改变你的工作方式,但这对你来说可能不那么令人沮丧。

答案 1 :(得分:4)

我尝试了这段代码,由于某种原因,它重新整理了整个页面:

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

如果您希望查看示例,请提交URL

答案 2 :(得分:2)

我知道无法将命名容器移除到控件ID之前。在过去,我使用了一种方便的方法在javascript中查找这样的id,它遍历标记名称并使用正则表达式匹配以$realID结尾的那个,其中realID是id我在标记中给控制权。现在,我将使用jQuery来使用像这样的选择器:

 $('[id$="realID"]')

这与我的旧方便方法基本相同,但它内置于框架中。

答案 3 :(得分:0)

据我所知,由于你说的原因,没有办法删除它们;确保它们是独一无二的。我看到它的方式有两种选择:

  1. 创建一个JS变量并将其添加到所有JS调用中,以便它查找正确的ID
  2. 使用<%= control.ClientID%>在您的JavaScript中,所以它使用新的ID。
  3. 如果您的任何输入都在任何其他服务器标签内,那么#1将无效。这很容易出现很多问题所以如果可以,我会选择#2。

    2取决于页面本身的javascript或者JS是外部的,你需要能够传入ID。此代码未经过测试,仅用于示例,但这就是我的意思:

    function alertValue(textID){
         alert(document.GetElementById(textID).value);
    }
    
    <input id="txtBox" runat="server" type="Button" text="Click Me" onClick="alertValue('<%= txtBox.ClientID %>');" />
    

    这实际上取决于你的JS是如何实现的。

答案 4 :(得分:0)

由于您似乎只是尝试从最终输出中删除客户端ID,因此您可以覆盖页面上的呈现事件并使用正则表达式删除它们。您可以在下面的帖子中看到一个示例。

Rewrite ASP.NET page output

在你得到你正在处理的文本之后,你很可能会写出类似......

的内容
output = Regex.Replace(
    output, 
    @"id\=""ctl00\$[^\""]*""", 
    string.Empty, 
    RegexOptions.IgnoreCase
    );

然后将最终输出写入HtmlTextWriter。

希望有所帮助。

答案 5 :(得分:0)

人们,我需要快速而肮脏的东西。感谢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

答案 6 :(得分:0)

选中此项:http://clientidless.codeplex.com/ - 您可以将ClientID关闭到几乎任何控件。 以下是演示:http://show-demos.net/NoClientId/ - 按“无ID渲染”或“使用ID渲染”以查看页面大小的变化情况。查看来源以查看差异。

答案 7 :(得分:0)

我想加上我的两分钱:

我是这样做的(在接受的答案中),但是考虑重写Render控件以写入新的TextWriter,然后将其内容写入Page的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));
}

答案 8 :(得分:0)

实际上,为了回顾Josh的回答,我发现下面的第一个解决方案是有问题的,其他输入控制元素和PostBacks无法正常工作。因此,我选择了下面的第二个解决方案来改变JavaScript而不是元素名称,而不是进行空白更改。

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:

aspx文件中的JavaScript,其中单选按钮列表使用约定'rbl [name]':

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