I have a bunch of forms where currency values are entered and I want them to be able to enter "
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.
我有一堆表格,其中输入货币值,我希望他们能够输入“$ 1,234.56”。默认情况下,模型绑定器不会将其解析为小数。
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.
我想要做的是创建一个自定义模型绑定器继承DefaultModelBinder,重写BindProperty方法,检查属性描述符类型是否为十进制,如果是,只需从值中删除$和。
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 );
}
}
3 个解决方案
#1
5
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.
在活页夹中这样做是合理的。但是,我认为使用货币格式提供者或数字样式(参见文档)的Decimal.Parse比剥离“$”和调用base更可靠。对于初学者来说,它会处理非美国货币,这可能会让你有一天成为问题。
#2
5
In MVC3 you can just register a custom modelbinder that implements the IModelBinder interface specifically for decimal types and then tell it to handle currency or decimal by using the ModelMetaData.DataTypeName property on the bindingContext.
在MVC3中,您只需注册一个自定义模型绑定器,专门为十进制类型实现IModelBinder接口,然后通过使用bindingContext上的ModelMetaData.DataTypeName属性告诉它处理货币或十进制。
I've modified the sample provided by Phil Haack in his article to demonstrate how it could be done:
我已经修改了Phil Haack在他的文章中提供的示例,以演示如何完成它:
public class DecimalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
var modelState = new ModelState { Value = valueResult };
decimal actualValue = 0;
try
{
if(bindingContext.ModelMetadata.DataTypeName == DataType.Currency.ToString())
decimal.TryParse(valueResult.AttemptedValue, NumberStyles.Currency, null, out actualValue);
else
actualValue = Convert.ToDecimal(valueResult.AttemptedValue,CultureInfo.CurrentCulture);
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
#3
1
You could create your own ValidationAttribute which checks if value has correct format. Then you could look if property is decorated with this attribute and bind it in proper way. Attribute doesn't need to be ValidationAttibute, but it seems like good idea.
您可以创建自己的ValidationAttribute来检查值是否具有正确的格式。然后你可以查看属性是否使用此属性进行修饰并以适当的方式绑定它。属性不需要是ValidationAttibute,但它似乎是个好主意。
,234.56". By default, the model binders won't parse that into a decimal.I have a bunch of forms where currency values a