Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
679 views
in Technique[技术] by (71.8m points)

asp.net mvc - How to filter form data with custom model binder

I have a bunch of forms where currency values are entered and I want them to be able to enter "$1,234.56". By default, the model binders won't parse that into a decimal.

What I am thinking of doing is creating a custom model binder the inherits DefaultModelBinder, override the BindProperty method, check if the property descriptor type is decimal and if it is, just strip out the $ and , from the values.

Is this the best approach?

Code:

public class CustomModelBinder : DefaultModelBinder
{
 protected override void BindProperty( ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor )
 {
  if( propertyDescriptor.PropertyType == typeof( decimal ) || propertyDescriptor.PropertyType == typeof( decimal? ) )
  {
   var newValue = Regex.Replace( bindingContext.ValueProvider[propertyDescriptor.Name].AttemptedValue, @"[$,]", "", RegexOptions.Compiled );
   bindingContext.ValueProvider[propertyDescriptor.Name] = new ValueProviderResult( newValue, newValue, bindingContext.ValueProvider[propertyDescriptor.Name].Culture );
  }

  base.BindProperty( controllerContext, bindingContext, propertyDescriptor );
 }
}

Update

This is what I ended up doing:

public class CustomModelBinder : DataAnnotationsModelBinder
{
    protected override void BindProperty( ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor )
    {
        if( propertyDescriptor.PropertyType == typeof( decimal ) || propertyDescriptor.PropertyType == typeof( decimal? ) )
        {
            decimal newValue;
            decimal.TryParse( bindingContext.ValueProvider[propertyDescriptor.Name].AttemptedValue, NumberStyles.Currency, null, out newValue );
            bindingContext.ValueProvider[propertyDescriptor.Name] = new ValueProviderResult( newValue, newValue.ToString(), bindingContext.ValueProvider[propertyDescriptor.Name].Culture );
        }
        base.BindProperty( controllerContext, bindingContext, propertyDescriptor );
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's reasonable to do it in the binder. However, I think that Decimal.Parse with the currency format provider or number style (see the docs) would be more reliable than stripping the "$" and calling base. For starters, it would handle non-US currency, which might be an issue for you some day.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...