0

I've looked into this question and found questions such as:

SO-Link1 SO-Link2

So the problem seems rather common - but i really don't like the solution.

Question:

I've started digging into sources but couldn't find a convenient solution yet. Is there a built in solution to this by now using attributes?

Having to use dynamic parameters in place instead of using attributes on the model is very inconvenient.

Guess i'll see what i can achieve by modifying the ModelBinder in the meantime - there has to be some way i guess.

Update:

Why do i want to do this?

I want to reduce network traffic because properties in code may be long + nested. Imagine 200 Checkboxes x 40 bytes generated names.

I can already make my modelbinder work with aliases - however in order to fully automate it, i need the TextBoxFor etc methods to use alias names instead of the actual property names.

Community
  • 1
  • 1
Dbl
  • 5,634
  • 3
  • 41
  • 66
  • 3
    Why would you want to change the name attribute of a control - which would mean binding and validation will fail? And the purpose of the `ModelBinder` is to bind the model (i.e. when you submit), not when you generate the view (which is done by the html helpers). What are you actually trying to do? –  Jun 17 '15 at 11:04
  • you can change modelbinding to work through alias attributes as well. the reason is quite simple actually: unnecessary network traffic. why would i want it to generate SomePropertyInSomeClassWhichCouldBeRatherLongForNoGoodReasonWithSomeMoreNesting[0].Value. I'd rather have that be "p1[0].Value" – Dbl Jun 17 '15 at 11:25
  • 2
    If your model naming conventions are really that awful, just use a view model and rename the property! A ModelBinder` has got nothing to do with rendering the `name` attribute. That's what the html helpers do. –  Jun 17 '15 at 11:29
  • @StephenMuecke No. I'm not going to change my property names to reduce network traffic. I will find a way to do this - if necessary through contributing to the MVC. I am certainly not going to modify my VIEW to achieve changes in how my MODEL is being transmitted. You should understand the reason why this makes sense rather than telling me my naming conventions are bad. I want to optimize network traffic for mobile devices, not make my whole codebase less readable to satisfy a requirement. – Dbl Jun 17 '15 at 11:33
  • I mean you should be following best practice and using a view model (see [What is ViewModel in MVC?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) ). You can make the property name what ever you want. –  Jun 17 '15 at 11:36
  • @StephenMuecke To then specify names in a format which mvc expects - hardcoded, which could change at any given time rather than the built in version. To me that's more of an anti best practice (which i tried before thinking about posting this question, but doing it felt very much ugly coding, which usually isn't the case for best practice) – Dbl Jun 17 '15 at 11:44
  • The whole point of a viewmodel is that it's property names never change, but the property names of the data a viewmodel is populated with could indeed change. That's the power of viewmodels - they never change unnecessarily. I always use viewmodels whenever I can due to their flexibility and ease of refactoring. I appreciate where the OP is coming from, but it sounds like the design could be re-thought to take advantage of viewmodels plus, maybe, AutoMapper? – Jason Evans Jun 17 '15 at 11:54
  • I am using viewmodels as well. just not for the form names. when i'm transmitting a list of addresses i need a form name syntax like viewmodel.Address[x].SomeProperty in order for a list to be transmitted. That's the bit i want to change. i want my form name to be viewModel.a[x].sp – Dbl Jun 17 '15 at 11:57
  • Ahhh ok cool, Could you provide us with a snippet of that viewmodel please? I just want to get an idea of your current code. That way it will be easier to suggest a naming approach. I've got an idea of how to get `viewmodel.Address[x].SomeProperty` to appear in the HTML of the view, but I just need to double-check your code. – Jason Evans Jun 17 '15 at 12:00

1 Answers1

1

Personally I don't think you should be totally concerned with the size of the the name attribute's values. As long as you're using compression through something like IIS then you aren't going to be saving that much.

You can however, achieve what you're after by creating custom HTML helpers which will create the HTML markup you desire.

Example Model

public class UserModel
{
    public string FullName { get; set; }
}

Helper

public static MvcHtmlString CustomTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string name)
{
    var fieldName = ExpressionHelper.GetExpressionText(expression);

    //
    // Pass in alias or call method to get alias here
    //
    var fullBindingName = String.IsNullOrWhiteSpace(name) ? html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName) : name;
    var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);

    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
    var value = metadata.Model;

    var tag = new TagBuilder("input");
    tag.Attributes.Add("name", fullBindingName);
    tag.Attributes.Add("id", fieldId);
    tag.Attributes.Add("type", "text");
    tag.Attributes.Add("value", value == null ? "" : value.ToString());

    var validationAttributes = html.GetUnobtrusiveValidationAttributes(fullBindingName, metadata);
    foreach (var key in validationAttributes.Keys)
    {
        tag.Attributes.Add(key, validationAttributes[key].ToString());
    }

    return new MvcHtmlString(tag.ToString(TagRenderMode.SelfClosing));
}

Call the Method in your View

   @Html.TextBoxFor(x => x.FullName)

   @Html.CustomTextBoxFor(x => x.FullName, "FName")

Output

<input id="FullName" type="text" value="Heymega" name="FullName">
<input id="FName" type="text" value="Heymega" name="FName">
heymega
  • 9,215
  • 8
  • 42
  • 61
  • While this way certainly would be working i don't want to wrap every component we use just to get a control of the generated name. That's why i'm trying to get this done somehow using the MetadataProvider. Not done with it yet though. – Dbl Jun 17 '15 at 14:09
  • @AndreasMüller Sorry this wasn't what you were after. Good luck with your coding! – heymega Jun 17 '15 at 14:12