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

Asp.net 从呈现的控件ID中删除ctl00$ContentBody$,asp.net,master-pages,Asp.net,Master Pages,我对一个以前只是纯HTML和Javascript的现有应用程序做了一些更改。为了添加服务器端功能,我选择了ASP.NET,并利用了母版页的概念。不幸的是,在一个巨大的web表单上,控件ID都被“ctl00$ContentBody$”前缀弄乱了。我在所有的输入控件上加了一个runat=“server”,这改变了ID。现在ID已经改变了,Javascript(写得太差了,我甚至读不懂,而且我对JS很有经验)完全崩溃了 那么,我怎样才能防止这些废话被呈现到HTML中呢?我希望能够以某种方式创建一个继承

我对一个以前只是纯HTML和Javascript的现有应用程序做了一些更改。为了添加服务器端功能,我选择了ASP.NET,并利用了母版页的概念。不幸的是,在一个巨大的web表单上,控件ID都被“ctl00$ContentBody$”前缀弄乱了。我在所有的输入控件上加了一个runat=“server”,这改变了ID。现在ID已经改变了,Javascript(写得太差了,我甚至读不懂,而且我对JS很有经验)完全崩溃了


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

我知道没有办法将命名容器从控件id前面移除。过去,我使用一种方便的方法在javascript中查找此类id,该javascript迭代标记名,并使用正则表达式匹配以
$realID
结尾的id,其中,
realID
是我在标记中给控件的id。现在,我将使用jQuery,使用如下选择器:

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

基本上,它与我以前的便利方法的功能相同,但它内置于框架中。

据我所知,由于您所说的原因,无法删除它们;确保它们是独一无二的。在我看来,你有两个选择:

  • 创建一个JS变量,并将其添加到所有JS调用之前,以便它查找正确的ID
  • 在javascript中使用,以便它使用新ID
  • 使用#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 %>');" />
    
    函数警报值(textID){
    警报(document.GetElementById(textID.value);
    }
    

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

    目前这是一个小小的安慰,但这个“功能”将在Asp.NET4.0中修复。您将获得可设置的ClientID属性

    除此之外,其他回答都很好。
    使用

    或者加入JQuery并使用$(“[id$='myId']))

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


    或者,跳过Asp.Net WebForms并跳到Asp.Net MVC,这样您就可以完全控制生成的HTML标记。您必须稍微改变一下操作方式,但这可能不会让您感到沮丧。

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

    在你收到你正在处理的文本后,你很可能会写一些像

    output = Regex.Replace(
        output, 
        @"id\=""ctl00\$[^\""]*""", 
        string.Empty, 
        RegexOptions.IgnoreCase
        );
    
    然后将最终输出写入HtmlTextWriter


    希望能有所帮助。

    各位,我需要的是快速和肮脏。多亏了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
    

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

    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检查:-您可以关闭几乎任何控件的ClientID。
    这里是演示:-按“无ID渲染”或“带ID渲染”查看页面大小的变化。查看源代码以查看差异。

    我想将我的两分钱加到这一分钱上:

    我是这样做的(在公认的答案中),但我认为重写呈现控件以写入新的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));
    }
    

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

    乔希的解决方案

    代码隐藏:

    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=\""));
    }
    
    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"));
    }
    
    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"));
    }
    
    解决方案1,存在回发问题(注意:我无法更改可能解决此解决方案的ID):

    代码隐藏:

    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=\""));
    }
    
    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"));
    }
    
    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"));
    }
    
    解决方案2,要更改JavaScript:

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

    if (!validateRadioButtonList("<% =rblTitle.ClientID %>"))
    

    我找不到任何支持我的链接,但我相信下一版本的.NET将使您能够删除此链接。在此之前,您需要解决问题。您可以使用普通控件并添加文字来设置值,例如-1我没有更改或编写任何客户端脚本。当前脚本难以辨认,我的“客户端”(哈哈)没有付钱让我重写它。我在问题中明确了这一点。如果你没有使用服务器端功能,为什么要添加runat=server标记。如果你是,你刚刚破坏了框架将控件正确映射回服务器端的能力。不要尝试将网格或中继器与任何回发的控件一起使用。当然,你'd必须更改您的脚本,因为它们不是ctl00——它们都有一个唯一的编号。我需要runat=“server”进行设置