Masataka Miki's Blog

すみません、わかりません。もっと勉強して改善します。

[C#/MVC]カンマ区切りの数値をdecimal型のメンバにBinding

   

Modelには、decimal型でメンバが定義されていて、
Viewでは、テキストボックスにそのメンバが割り当てられている。

単なる数値の場合、問題ないが、
テキストボックスの表示形式や、onblur時の編集で3桁のカンマ区切りとなっている場合、
想定通りBindingされない。

例えば、
700の場合、700がBindingされるが、
1,700の場合、カンマがあることで数値と認識されず、0がBindingされる。

以下、カンマ区切りの数値形式でも、Bindingされるようにカスタムクラスを作成(拡張)すれば簡単にできるようになったのでメモ。

IModelBinderを拡張した DecimalModelBinderを作成する

public class DecimalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
var modelState = new ModelState { Value = valueResult };
object actualValue = null;
try
{
var isNullableAndNull = (bindingContext.ModelMetadata.IsNullableValueType &&
string.IsNullOrEmpty(valueResult.AttemptedValue));
if (!isNullableAndNull)
{
actualValue = decimal.Parse(valueResult.AttemptedValue, NumberStyles.Any, CultureInfo.CurrentCulture);
}
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}

それをApplication_Start時に登録しておく(Global.asax.cs)

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

// ここに追加
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
}

ちなみにバージョンは4.6.1

 - 技術 ,