1

I am having the same problem many people already had - Model Binder doesn't accept localized decimal input. In all of the threads, here and other forums, the recommended solution is implementing a custom ModelBinder.

My problem is that those solutions somehow don't work for me. Let's use this solution for example: comma decimal seperator in asp.net mvc 5

When I reference all namespaces, two errors remain:

Error CS0115 'DecimalModelBinder.BindModel(ControllerContext, ModelBindingContext)': no suitable method found to override ...

and

Error CS0173 Type of conditional expression cannot be determined because there is no implicit conversion between 'bool' and 'decimal'

Where the second one references the entire return statement.

Did something change in the MVC Framework, so this code is outdated, or am I doing something wrong?

The code I ended up with is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.ModelBinding;
using System.Web.Mvc;

namespace AetMuzickaOprema.App_Start
{
    public class DecimalModelBinder : System.Web.ModelBinding.DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, System.Web.ModelBinding.ModelBindingContext bindingContext) //first error
        {
            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

            return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) : Convert.ToDecimal(valueProviderResult.AttemptedValue); //second error

        }
    }
}

Model property in question:

[Required]
[Range(typeof(decimal), "0", "999999999")]
public decimal Price { get; set; }
dzenesiz
  • 1,388
  • 4
  • 27
  • 58
  • 1
    Here it is explained how to do a custom model binder in an updated manner. https://learn.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding . If you have problems, I'll build for you but try first. – Pedro S Cord Aug 20 '17 at 19:45
  • Thanks, I'll try it and let you know :) I appreciate it – dzenesiz Aug 20 '17 at 20:17
  • @PedroSouki I am looking at the article since you posted your comment, but am I too new to MVC to make use of it in my case. If you were willing to show me how to implement it so decimal values would accept both "1,25" and "1.25", I would be very grateful. – dzenesiz Aug 22 '17 at 18:09

2 Answers2

1

It seems ultimately what you are trying to achieve is property-level binding such as this?:

[PropertyBinder(typeof(PropertyBBinder))]
public IList<int> PropertyB {get; set;}

If that is correct, this post offers a solution: Custom model binder for a property

Thanks.

Brian Mains
  • 50,520
  • 35
  • 148
  • 257
  • Actually, it's a single decimal property which I will include in the question. I don't know if this applies non the less. Thanks for your answer in any case :) – dzenesiz Aug 20 '17 at 20:15
1

In ASP.NET Core 1.1 (Microsoft.AspNetCore.Mvc.Core.Abstraction, 1.0.1.0) you'll see the following interface

using System.Threading.Tasks;

namespace Microsoft.AspNetCore.Mvc.ModelBinding
{
    //
    // Summary:
    //     Defines an interface for model binders.
    public interface IModelBinder
    {
        //
        // Summary:
        //     Attempts to bind a model.
        //
        // Parameters:
        //   bindingContext:
        //     The Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext.
        //
        // Returns:
        //     A System.Threading.Tasks.Task which will complete when the model binding process
        //     completes.
        //     If model binding was successful, the Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext.Result
        //     should have Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult.IsModelSet
        //     set to true.
        //     A model binder that completes successfully should set Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext.Result
        //     to a value returned from Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult.Success(System.Object).
        Task BindModelAsync(ModelBindingContext bindingContext);
    }
}

Model binders are defined in Microsoft.AspNetCore.Mvc.ModelBinding.Binders namespace, assembly Microsoft.AspNetCore.Mvc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60. None of them seem to expose BindModel() method, even less a virtual one. It looks like you are trying to override a non-existing method.

A better approach is to take an existing ModelBinder, one that best suits your needs, inherit from it, and override ModelBindAsync().

Alexander Christov
  • 9,625
  • 7
  • 43
  • 58
  • Thank you for your response. Could I bother you a bit further by asking where do I find existing `ModelBinder`s in my project? – dzenesiz Aug 22 '17 at 18:12
  • 1
    "Model binders are defined in Microsoft.AspNetCore.Mvc.ModelBinding.Binders namespace, assembly Microsoft.AspNetCore.Mvc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60". Strictly speaking, this means that there are no MBs in your project.But you can define one and put it wherever you need, say, in Helpers folder or something like this. Just inherit from DefaultModelBinder and override BindModelAsync. Or simply, rename ModelBind to ModelBindAsync taking signature into account. – Alexander Christov Aug 23 '17 at 14:22