NancyFx / Nancy

Lightweight, low-ceremony, framework for building HTTP based services on .Net and Mono
http://nancyfx.org
MIT License
7.15k stars 1.46k forks source link

Possible Model Binding issue with Decimals #1587

Open phillip-haydon opened 10 years ago

phillip-haydon commented 10 years ago

http://stackoverflow.com/questions/24439997/nancy-decimal-property-binding-not-working

Oh noes! ---> Nancy.ModelBinding.ModelBindingException: Unable to bind to type: Nancy.Models.SomeModel
at Nancy.ModelBinding.DefaultBinder.Bind(NancyContext context, Type modelType, Object instance, BindingConfig configuration, String[] blackList)
at Nancy.ModelBinding.DynamicModelBinderAdapter.TryConvert(ConvertBinder binder, Object& result)
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at Nancy.ModelBinding.ModuleExtensions.Bind[TModel](INancyModule module)
at KBZServisNancy.Modules.SomeModule.<.ctor>b__2(Object x) in d:\Nancy\Modules\SomeDecimalModule.cs:line 38
at CallSite.Target(Closure , CallSite , Func`2 , Object )
at Nancy.Routing.Route.<>c__DisplayClass4.b__3(Object parameters, CancellationToken context)
--- End of inner exception stack trace ---
at Nancy.NancyEngine.InvokeOnErrorHook(NancyContext context, ErrorPipeline pipeline, Exception ex)
at Nancy.NancyEngine.InvokeOnErrorHook(NancyContext context, ErrorPipeline pipeline, Exception ex)

Looks like this is bug, tried it out myself with a route and decimal and got same exception.

Borzoo commented 10 years ago

DecimalConverter.ConvertFrom is used in the context of current culture, It expects "1,1" instead of "1.1" in Turkish culture. A fallback strategy can be implemented by using ConvertFrom with InvariantCulture. Do you accept pull requests ?

xmedeko commented 8 years ago

Just write own ITypeConverter

 /// <summary>
    /// Nancy converter to convert numeric types with InvariantCulture.
    /// </summary>
    public class NancyNumericConverter : ITypeConverter
    {
        public bool CanConvertTo(Type destinationType, BindingContext context)
        {
            return destinationType.IsNumeric();
        }

        public object Convert(string input, Type destinationType, BindingContext context)
        {
            if (string.IsNullOrEmpty(input))
            {
                return null;
            }

            return System.Convert.ChangeType(input, destinationType, CultureInfo.InvariantCulture);
        }
    }
yallie commented 6 years ago

Just write own ITypeConverter

Thanks for the suggestion, it works great! But looks like System.Convert.ChangeType doesn't support nullable types.

Can be fixed using Nullable.GetUnderlyingType like this:

/// <summary>
/// Nancy converter to convert numeric types with InvariantCulture.
/// </summary>
public class InvariantCultureNumericConverter : ITypeConverter
{
    public bool CanConvertTo(Type destinationType, BindingContext context)
    {
        return destinationType.IsNumeric();
    }

    public object Convert(string input, Type destinationType, BindingContext context)
    {
        if (string.IsNullOrEmpty(input))
        {
            return null;
        }

        destinationType = Nullable.GetUnderlyingType(destinationType) ?? destinationType;

        return System.Convert.ChangeType(input, destinationType, CultureInfo.InvariantCulture);
    }
}