The first argument for the text box extension method sets the name of the input element that's eventually created and also tries to get an entry from ViewData/Model (for the model it uses TypeDescriptors / reflection) based on that argument.
The way it does this is just by splitting up the input string at the dots then checking the ViewDataDictionary for specific keys and the Model via reflection so in the case you give it'll try and look for Contacts[0] rather than Contacts and won't pick up your property.
To get around this you just need to supply the actual value of the object e.g.
Html.TextBox("Comments.Contacts[0].ContactName",
Model.Comments.Contacts[0].ContactName)
You can see this yourself if you look at the MVC source and take a peek at the ViewDataDictionary class.