Reputation: 139
Is it possible in .net mvc5 to bind an attribute according to a specific rule? So for example, I have a time input (e.g. 10.30) and I need to bind that to a double. I was hoping for something along the lines of this:
// Model
[CustomAttribute("TimeAttr")]
public double Hours { get; set; }
// Binding
public TimeAttrBinder : IModelBinder
{
// Replace colons with dots
return double.Parse(value.Replace(':', '.'));
}
// Global
ModelBinders.add("TimeAttr", TimeAttrBinder)
So that I can put an annotation on the attribute in the model, and that it's custom model binded everytime...
Is such a thing possible in .net mvc5?
Upvotes: 0
Views: 625
Reputation: 1038730
There's no built-in mechanism for that but you could build a custom PropertyBinder attribute that will apply the model binder only for a given property as shown in this article: http://aboutcode.net/2011/03/12/mvc-property-binder.html
You could make it pretty generic as illustrated in the article but to illustrate the concept you could try something like this.
A metadata aware marker attribute:
public class MyMarkerAttribute : Attribute, IMetadataAware
{
public void OnMetadataCreated(ModelMetadata metadata)
{
metadata.AdditionalValues["marker"] = true;
}
}
A custom model binder that will understand this marker attribute:
public class MyModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelMetadata.AdditionalValues.ContainsKey(MyMarkerAttribute.MarkerKey))
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value != null)
{
// Here you could implement whatever custom binding logic you need
// for your property from the binding context
return value.ConvertTo(typeof(double));
}
}
return base.BindModel(controllerContext, bindingContext);
}
}
and then replace the default model binder with the custom one in your Application_Start
:
ModelBinders.Binders.DefaultBinder = new MyModelBinder();
and that's pretty much it. Now you could decorate your view model with the marker attribute:
[MyMarker]
public double Hours { get; set; }
Upvotes: 1