Ich möchte einige Rohdaten vor der Zuweisung zu Modelleigenschaften auf Rohdaten anwenden. Nämlich, Komma durch Punkt zu ersetzen, um beide Strings "324.32" und "324, 32" in Doppel zu konvertieren. Also schrieb ich dieses Modell BinderModelleigenschaftsbindungen mit [FromBody] -Attribut
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;
}
}
dann entsprechenden Anbieter
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;
}
}
und Registrierung es in Startup.cs
services.AddMvc(options =>
{
options.ModelBinderProviders.Insert(0, new MoneyModelBinderProvider());
});
aber ich bemerkte ein seltsames Verhalten oder vielleicht habe ich etwas verpasst. Wenn ich diese Art von Aktion verwenden
public class Model
{
public string Str { get; set; }
public double Number { get; set; }
}
[HttpPost]
public IActionResult Post(Model model)
{
return Ok("ok");
}
und Versorgungsparameter innerhalb alles Query-String funktioniert: als erster Anbieter für Modell genannt wird sich dann für jede Eigenschaft des Modells. Aber Wenn ich [FromBody] -Attribut und Versorgungsparameter von JSON verwende, wird Provider für Modell aufgerufen, aber nie für Eigenschaften dieses Modells aufgerufen. Aber warum? Wie kann ich Binder mit FromBody verwenden?
Cant Kommentar zu diesem Thema Sie beschreiben, sondern als eine einfache Arbeit um Sie könnte ein View-Modell akzeptieren (mit diesen Eigenschaften als Zeichenfolgen) und verwenden Sie dann AutoMapper, um es in Ihrer Controller-Aktion Ihrem Entitätsmodell/dto zuzuordnen. – Steveland83
Setzen Sie den Inhaltstyp-Header beim Buchen explizit? Nur weil es wie JSON aussieht, heißt das nicht, dass es als JSON interpretiert wird. –