0

I have a Kendo NumericTextbox

 @(Html.Kendo().NumericTextBoxFor(m => m.SomeDecimal)
                                    .Name("SomeDecimal")
                                    .Min(0)
                                    .Max(99999999)
                                    .Decimals(2)
                                  ) 

When posting my form containing this NumericTextbox the value of SomeDecimal is set to null in the model.

Please note: I replaced the Kendo NumericTextbox with a normal textbox and had the same issue because the number that was entered contained a full stop (.) instead of a comma (,). When I replaced the full stop with a comma everything worked as expected.

Do I have to specify a different culture perhaps?

OnaBai
  • 40,767
  • 6
  • 96
  • 125
Andre Lombaard
  • 6,985
  • 13
  • 55
  • 96
  • I think so, because in the French culture, _comma_ is used as decimal, while in UK and US, _point_ is used as decimal – Nadeem_MK Sep 11 '13 at 09:31
  • @Nadeem_MK Found a workaround, thank you – Andre Lombaard Sep 11 '13 at 12:21
  • @user65439 - nice solution. But you could also use the .Format ("c") and .Culture ("fr") methods on the NumericTextBoxFor , to make sure that the textbox doesn't even allow the user to enter "." in the first place...this is probably more robust because you don't need to account for every possible culture you might support. You do need to include the relevant culture file (supplied with kendo) on the page and call kendo.culture("fr") before the textbox is rendered. And of course use razor to write in the desired culture for you :) – Stephen Byrne Sep 11 '13 at 12:40
  • Hi, @StephenByrne, I included the relevant culture file and played around with the .Format and .Culture options but the problem still occurred. So this was unfortunately the only way I could get it to work. – Andre Lombaard Sep 11 '13 at 13:16

1 Answers1

4

I found a workaround for this problem,

I created a new class DecimalModelBinder to overwrite the default model binding of decimal fields. The code is below. Here I attempt to convert the decimal value, if the conversion fails I replace all full stops with commas and try to convert again. If the second conversion attempt fails I replace all commas with full stops and try again.

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
        {
            // Try to convert the actual number that was recieved.
            actualValue = Convert.ToDecimal(valueResult.AttemptedValue, CultureInfo.CurrentCulture);
        }
        catch
        {
            try
            {
                // Replace any . with , and try to convert.
                actualValue = Convert.ToDecimal(valueResult.AttemptedValue.Replace('.',','), CultureInfo.CurrentCulture);
            }
            catch
            {
                try
                {
                    // Replace any , with . and try to convert.
                    actualValue = Convert.ToDecimal(valueResult.AttemptedValue.Replace(',', '.'), CultureInfo.CurrentCulture);
                }
                catch (Exception ex)
                {
                    modelState.Errors.Add(ex);                                               
                }
            }
        }

        bindingContext.ModelState.Add(bindingContext.ModelName, modelState);

        return actualValue;
    }
}

You have to add the DecimalModelBinder in your Global.asx file

protected void Application_Start()
{
    RouteTable.Routes.MapHubs();
    AreaRegistration.RegisterAllAreas();

    ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
    ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());

    // All other code.
}
Andre Lombaard
  • 6,985
  • 13
  • 55
  • 96