title: Model property bindings with [FromBody] attribute
body: <p>I want to apply some preprocessing to raw data before it assigned to model properties. Namely to replace comma with dot to allow converting both this strings "324.32" and "324,32" into double. So I wrote this model binder</p>
  
  <pre><code>public class MoneyModelBinder: IModelBinder
      {
          private readonly Type _modelType;
          public MoneyModelBinder(Type modelType)
          {
              _modelType = modelType;
          }
  
          public Task BindModelAsync(ModelBindingContext bindingContext)
          {
              if (bindingContext == null)
              {
                  throw new ArgumentNullException(nameof(bindingContext));
              }
  
              string modelName = bindingContext.ModelName;
  
  
              ValueProviderResult providerResult = bindingContext.ValueProvider.GetValue(modelName);
  
              if (providerResult == ValueProviderResult.None)
              {
                  return TaskCache.CompletedTask;
              }
  
              bindingContext.ModelState.SetModelValue(modelName, providerResult);
  
              string value = providerResult.FirstValue;
  
              if (string.IsNullOrEmpty(value))
              {
                  return TaskCache.CompletedTask;
              }
  
              value = value.Replace(",", ".");
  
              object result;
              if(_modelType == typeof(double))
              {
                  result = Convert.ToDouble(value, CultureInfo.InvariantCulture);
              }
              else if(_modelType == typeof(decimal))
              {
                  result = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
              }
              else if(_modelType == typeof(float))
              {
                  result = Convert.ToSingle(value, CultureInfo.InvariantCulture);
              }
              else
              {
                  throw new NotSupportedException($"binder doesn't implement this type {_modelType}");
              }
  
  
              bindingContext.Result = ModelBindingResult.Success(result);
              return TaskCache.CompletedTask;
          }
  
      }
  </code></pre>
  
  <p>then appropriate provider</p>
  
  <pre><code> public class MoneyModelBinderProvider : IModelBinderProvider
      {
          public IModelBinder GetBinder(ModelBinderProviderContext context)
          {
              if (context == null)
              {
                  throw new ArgumentNullException(nameof(context));
              }
  
              if(context.Metadata?.ModelType == null)
              {
                  return null;
              }
  
  
              if (context.Metadata.ModelType.In(typeof(double), typeof(decimal), typeof(float)))
              {
                  return new MoneyModelBinder(context.Metadata.ModelType);
              }
              return null;
          }
      }
  </code></pre>
  
  <p>and registering it inside Startup.cs</p>
  
  <pre><code>services.AddMvc(options =&gt;
          {
              options.ModelBinderProviders.Insert(0, new MoneyModelBinderProvider());
  
          });
  </code></pre>
  
  <p>but I noticed some strange behavior or maybe I missed something. If I use this kind of action</p>
  
  <pre><code> public class Model
      {
          public string Str { get; set; }
          public double Number { get; set; }
      }
  
  
      [HttpPost]
      public IActionResult Post(Model model)
      {
  
          return Ok("ok");
      }
  </code></pre>
  
  <p>and supply parameters inside query string everything works fine: first provider is called for model itself then for every property of the model. <strong>But</strong> if I use [FromBody] attribute and supply parameters by JSON, provider is called for model but never called for properties of this model. But why? How can I use binders with FromBody? </p>