7

Anyone coming from ASP.NET (pre-MVC) has become accustomed to being able to give their controls whatever IDs they want. You can create a field called Email in an .asmx file, a field called Email in your main page, a field called Email in your master page, place multiple instances of your .asmx file on the page and they'll all get their own unique IDs.

Now there are big problems with this that have all been discussed before. Often the solution suggested is to 'switch to MVC' where you can control your IDs. Fantastic!... except...

...the problem you end up with (after switching to MVC) if you're not careful is something like the following :

  • two forms on the page both containing an email field with Email as the ID.
  • the browser will render just fine (duplicate ids are not 'allowed by XHTML', but they're not rejected by the browser)
  • even the form submissions will work since the FORM will send its own corresponding content to the server action.

This you can get away with - if you're a really bad programmer that doesnt care about standards. However you will quickly start seeing some really wierd things if you begin to use jQuery or even just getElementById(..):

Let's say:

  • you have two user controls, one for 'Submit comments' and one for 'Join mailing list'. Each has an Email field inside. They each have id="Email"
  • you have javascript in the 'submit comments' control for validation :

    if ( $("#Email").val().indexOf("@") == -1 ) {
        // invalid email 
    }
    
  • Oops! The #Email selector will select the first instance of <input id="Email"> on the page. Therefore you may end up actually validating the FIRST Email field's value when submitting the SECOND form. But check the database - and you'll have the correct values. This can quickly drive your QA up the wall ;-)

I'm looking for any clever tricks anyone may have come up with. I found some interesting ideas in the question : ASP.NET MVC View User Control - how to set IDs but I didn't feel the answers went far enough or took advantage of some of the latest binding models.

Theres a few obvious things you could do such as always using unique IDS by prefixing every ID with a control prefix or something. This is starting quickly to look like ASP.NET 1.0 !

Another thing you COULD do is use a selector like $('#contatUsForm #Email') to get the Email ID. But only if you're fine with not having XHTML. I consider this solution to be very bad. In fact its so bad I havent even tested to see if jQuery even lets you run it!

One useful thing I came up with (with help from sunsean) is the following jQuery function - which I put on my master page and will certainly leave on until I deply.

// Warning Duplicate IDs - place on master page in $(function() { ... });
$('[id]').each(function(){
  var ids = $('[id='+this.id+']');
  if(ids.length>1 && ids[0]==this)
    alet('Multiple IDs #'+this.id);
});

This will help you quickly find which controls may exhibit this problem but leaves me still lookin for an elegant solution.

I'm especially interested in solutions that work in conjunction with model binding. As soon as I start adding in prefixes manually i'm going to start breaking model binding all over the place.

There has to be someone cleverer than me that's already thought through this...

Community
  • 1
  • 1
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689

2 Answers2

4

I think you're over-thinking it. The simple answer is, they're not the same, so don't give them the same ID. If they share similarities, that's what classes are for. If one input is for a newsletter sign up, call it NewsletterEmail. If another is for a user sign in form, call it UserEmail. Using more descriptive IDs is good HTML and not even remotely close to the mess Webforms creates.

John Sheehan
  • 77,456
  • 30
  • 160
  • 194
  • im already in the process of renaming like that until i don't have any duplicate ids left ) curious what 'complex' ideas people are going to come up with ) better exmple : i have an 'address control' with Address1, City etc. and I want two of those controls on the page but i want them to bind – Simon_Weaver Feb 04 '09 at 04:52
  • i'm DELIBERATELY trying to over-think first, have fewer problems later. theres a little devils advocate playing in there too : http://i57.photobucket.com/albums/g212/nicoleavila75/devils_advocate.jpg – Simon_Weaver Feb 04 '09 at 04:53
  • are they in a databound list of items? if so, just append the ID of the item. e.g. Address1_123, City_123, etc – John Sheehan Feb 04 '09 at 04:53
  • If you overcomplicate early on, you're going to have more problems later than just keeping it simple. – John Sheehan Feb 04 '09 at 04:54
  • 1
    i also wanted to raise awareness of the problem becuause its important to understand the problem. in fact even if you DO understand the problem you're going to mess up sometime by mistake - hence the jQuery dupe detector function. but yes definitely shouldn't be 'afraid' of over descriptive names – Simon_Weaver Feb 04 '09 at 04:55
  • i never said i wanted to overcomplicate - i just want to overthink it. its fun to think through all this stuff. learning a lot although i wish i wasnt having to do it at such an accelerated pace – Simon_Weaver Feb 04 '09 at 04:56
2

As far as form fields go, I think you are confusing the id attribute with the name attribute.

The jQuery you referred to would work well for form fields (tweaked slightly):

$('#contactUsForm input[name="Email"]')
Brannon
  • 25,687
  • 5
  • 39
  • 44
  • Yeah, that's a very important distinction to make. – John Sheehan Feb 04 '09 at 04:55
  • thanks brannon - see now why i made a point of saying i hadn't tested it :-) i forgot for a second that you automatically get the ability to search by ID or name for the same field. this strategy MAY be part of the 'over complicated' solution. i just dont know enough about binding to write one – Simon_Weaver Feb 04 '09 at 04:58
  • Yeah, the id attribute isn't really necessary for form fields. In the past it was easier to give a field an id, but with jQuery you might as well just lookup by name :) – Brannon Feb 04 '09 at 05:02