14

I have been scouring the internet trying to find a way to accomodate dashes from my form elements into the default model binding behavior of ASP.NET's Controllers in MVC 2, 3, or even 4.

As a front-end developer, I prefer dashes in my CSS over camelCase or underscores. In my markup, what I want to be able to do to is something like this:

<input type="text" name="first-name" class="required" />
<input type="text" name="last-name" class="required" />

In the controller, I would be passing in a C# object that would look like this:

public class Person
{
      public string FirstName { get; set; }
      public string LastName { get; set; }
      //etc...
}

Is there some way to extend the Controller class to accommodate this through some regex or other behavior? I hate the fact that I have to do something like this:

<input type="text" name="person.firstname" class="required" />

or even this:

<input type="text" name="isPersonAttending" class="required" />

Thoughts?

1

3 Answers 3

7

You could always create your own model binder.

Here's an example that implements a binder that supports adding Aliases to model properties:

http://ole.michelsen.dk/blog/bind-a-model-property-to-a-different-named-query-string-field/

And with it do something like:

[ModelBinder(typeof(AliasModelBinder))]
public class Person
{
      [BindAlias("first-name")]
      public string FirstName { get; set; }
      [BindAlias("last-name")]
      public string LastName { get; set; }
      //etc...
}

EDIT: This implementation, as the blogger says, is based on Andras' answer on the following SO question: Asp.Net MVC 2 - Bind a model's property to a different named value

Sign up to request clarification or add additional context in comments.

5 Comments

please note that, as the blog author says, that, and therefore this, is a copy of my own answer here: stackoverflow.com/questions/4316301/…
This is logical and makes great sense. Thanks!
Andras, you are totally correct, I hadn't seen the reference to your answer. Sorry about that. BTW, great implementation.
Hi @pabloromeo don't worry, it's cool, and thanks :-) just glad to see it's helping others!
No prob. I just added the reference to your answer too ;)
5

For readers looking for an ASP.NET Core solution, try one of the [From...] attributes. For example:

public class Person
{
    [FromForm(Name = "first-name")]
    public string FirstName { get; set; }
    [FromForm(Name = "last-name")]
    public string LastName { get; set; }
    //etc...
}

The [From...] attributes are briefly described at https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-3.1#sources.

Comments

3

By creating a custom form value provider you could solve this problem easily. The other advantage is you can avoid polluting all the model properties by decorating custom attributes.

Custom Form Value Provider

public class DashFormValueProvider : NameValueCollectionValueProvider
{
    public DashFormValueProvider(ControllerContext controllerContext)
    : base(controllerContext.HttpContext.Request.Form, 
    controllerContext.HttpContext.Request.Unvalidated().Form, 
    CultureInfo.CurrentCulture)
    {
    }

    public override bool ContainsPrefix(string prefix)
    {
        return base.ContainsPrefix(GetModifiedPrefix(prefix));
    }

    public override ValueProviderResult GetValue(string key)
    {
        return base.GetValue(GetModifiedPrefix(key));
    }

    public override ValueProviderResult GetValue(string key, bool skipValidation)
    {
        return base.GetValue(GetModifiedPrefix(key), skipValidation);
    }

    // this will convert the key "FirstName" to "first-name".
    private string GetModifiedPrefix(string prefix)
    {
        return Regex.Replace(prefix, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1-").ToLower();
    }
}

Value Provider Factory

public class DashFormValueProviderFactory : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }

        return new DashFormValueProvider(controllerContext);
    }
}

Global.asax.cs

ValueProviderFactories.Factories.Add(new DashFormValueProviderFactory());

1 Comment

Nice! I would agree with you - if you were using dashes for most of your form element names, using attributes would be a bit much. Thanks for the share!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.