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?
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
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());
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://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-3.1#sources.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With