views:

1616

answers:

5

I made some changes to an existing application that was previously just straight HTML and Javascript. To add server-side functionality, I chose ASP.NET, and took advantage of the Master Page concept. Unfortunately, on one huge web form, the control IDs are all mangled with the "ctl00$ContentBody$" prefix. I tacked a runat="server" on all the INPUT controls which is what altered the IDs. Now that the IDs have been changed, the Javascript (which is so poorly written I can't even read it, and I'm quite experienced with JS) is completely broken.

So, how can I prevent this nonsense from being rendered into the HTML? I was hoping to somehow be able to create a class that inherits HtmlGenericControl (I am not using Web controls, I just tacked on a runat="server" to every input tag) and somehow override the logic that sticks this "container id" at the beginning of the ID and NAME attributes. Then I could use tagMapping in web.config to make the global change. Is this possible?

+1  A: 

I know of no way to remove the naming container from being prepended to the control id. In the past I've used a convenience method to look up such ids in javascript that iterates through the tag names and uses a regular expression to match the one that ends with $realID, where realID is the id that I gave to the control in mark up. Now, I would use jQuery for this using a selector like:

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

Which basically does the same thing as my old convenience method, but it's built into the framework.

tvanfosson
-1 I am not changing or writing any client-side script. The current script is illegible, and my "client" (hah) is not paying me to rewrite it. I made this clear in the question.
Josh Stodola
A: 

As far as I know there is no way to remove them for the very reason you said; to ensure they are unique. The way I see it you have two options:

  1. Create a JS variable and prepend it to all of your JS calls so it looks for the correct ID
  2. Use <%= control.ClientID %> in your javascript so it uses the new ID.

With #1 if any of your inputs are within any other server tag it won't work. This is prone to many problems so I would go with #2 if you can.

2 depends on either the javascript being on the page itself or if the JS is external you need to be able to pass in ID's. This code isn't tested and is only for an example but here is what I mean:

function alertValue(textID){
     alert(document.GetElementById(textID).value);
}

<input id="txtBox" runat="server" type="Button" text="Click Me" onClick="alertValue('<%= txtBox.ClientID %>');" />

It really depends how your JS is implemented.

Luke
+2  A: 

Small consolation for right now, but this "feature" will be fixed in Asp.Net 4.0. You will get settable ClientID property.

Other than that, the other responses are good.
Use <%= control.ClientID %>

or throw in JQuery and use $("[id$='myId'])

Or, on your input tags, don't put runtime='server'. You should be able to retrieve the values via the Form member (just like in traditional asp)

Or, skip Asp.Net WebForms and skip to Asp.Net MVC, which gives you complete control of the HTML markup that is generated. You have to change how you are doing things a bit more, but that might be less frustrating for you.

Chris Brandsma
A: 

Since it appears you're just trying to remove client ID's from the final output, you might be able to to override the render event on your page and use a Regular Expression to remove them. You can see an example in the post below.

http://stackoverflow.com/questions/710725/rewrite-asp-net-page-output/710770#710770

After you get the text you're working with you could most likely write something like...

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

And then write the final output to the HtmlTextWriter.

Hope that helps.

Hugoware
A: 

Quick and dirty was what I needed, folks. And thanks to HBoss I was able to come up with a very simple solution. On the code-behind of the page in question, I just added this subroutine...

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
Josh Stodola
If you're not using server-side functionality, why put in the runat=server tags. If you are, you've just broken the ability for the framework to map the control back to the server-side correctly. Don't try using grids or repeaters with any controls that postback. Of course, you'd have to change your script because they won't be ctl00 -- they'll each have a unique number.
tvanfosson
I need runat="server" to set values via code-behind. The control maps back to the server-side correctly because I do not have EventValidation enabled and I retrieve the values via Request.Form collection. Thank you.
Josh Stodola