1

Ich habe einen ModelBinder erstellt, der nur ausgelöst wird, wenn ein Objekt ein [Decimal] Attribut zugewiesen hat, aber aus irgendeinem Grund, obwohl es tatsächlich die Daten bereinigen scheint es nicht die geposteten zu aktualisieren Modell.C# ASP.NET Core ModelBinder aktualisiert nicht Modell

Ich frage mich, wenn jemand unten von meinem Code sehen konnte, wo ich vielleicht falsch gehen.

Startup.cs

public void ConfigureServices(IServiceCollection serviceCollection) 
{ 
    serviceCollection.AddMvc(config => config.ModelBinderProviders.Insert(0, new DecimalModelBinderProvider()));   
} 

DecimalModelBinderProvider.cs

public class DecimalModelBinderProvider : IModelBinderProvider 
{ 
    public IModelBinder GetBinder(ModelBinderProviderContext modelBinderProviderContext) 
    { 
     if (modelBinderProviderContext == null) 
     { 
      throw new ArgumentNullException(nameof(modelBinderProviderContext)); 
     } 

     if (!modelBinderProviderContext.Metadata.IsComplexType) 
     { 
      try 
      { 
       var propertyName = modelBinderProviderContext.Metadata.PropertyName; 

       var property = modelBinderProviderContext.Metadata.ContainerType.GetProperty(propertyName); 

       if (property != null) 
       { 
        var attribute = property.GetCustomAttributes(typeof(DecimalAttribute), false).FirstOrDefault(); 

        if (attribute != null) 
        { 
         return new DecimalModelBinder(modelBinderProviderContext.Metadata.ModelType, attribute as IDecimalAttribute); 
        } 
       } 
      } 
      catch (Exception exception) 
      { 
       var message = exception.Message; 

       return null; 
      } 
     } 

     return null; 
    } 
} 

DecimalModelBinder.cs

public class DecimalModelBinder : IModelBinder 
{ 
    private readonly IDecimalAttribute _decimalAttribute; 

    private readonly SimpleTypeModelBinder _simpleTypeModelBinder; 

    public DecimalModelBinder(Type type, IDecimalAttribute decimalAttribute) 
    { 
     if (type == null) 
     { 
      throw new ArgumentNullException(nameof(type)); 
     } 

     _decimalAttribute = decimalAttribute; 

     _simpleTypeModelBinder = new SimpleTypeModelBinder(type); 
    } 

    public Task BindModelAsync(ModelBindingContext modelBindingContext) 
    { 
     if (modelBindingContext == null) 
     { 
      throw new ArgumentNullException(nameof(modelBindingContext)); 
     } 

     var valueProviderResult = modelBindingContext.ValueProvider.GetValue(modelBindingContext.ModelName); 

     if (valueProviderResult != ValueProviderResult.None) 
     { 
      modelBindingContext.ModelState.SetModelValue(modelBindingContext.ModelName, valueProviderResult); 

      var value = valueProviderResult.FirstValue; 

      bool success; 

      var result = _decimalAttribute.Decimal(value, out success); 

      if (success) 
      { 
       modelBindingContext.Result = ModelBindingResult.Success(result); 

       return Task.CompletedTask; 
      } 
     } 

     return _simpleTypeModelBinder.BindModelAsync(modelBindingContext); 
    } 
} 

IDecimalAttribute.cs

public interface IDecimalAttribute 
{ 
    object Decimal(string value, out bool success); 
} 

DecimalAttribute.cs

[AttributeUsage(AttributeTargets.Property)] 
public class DecimalAttribute : Attribute, IDecimalAttribute 
{ 
    public object Decimal(string value, out bool success) 
    { 
     var tryModelValue = string.IsNullOrEmpty(value) ? "0.00" : value.Replace("£", "").Replace("%", ""); 

     decimal @decimal; 

     success = decimal.TryParse(tryModelValue, out @decimal); 

     return @decimal; 
    } 
} 

Test.cs

public class Test 
{ 
    [Display(Name = "Name", Description = "Name")] 
    public string Name { get; set; } 

    [Decimal] 
    [Display(Name = "Amount", Description = "Amount")] 
    public double Amount { get; set; } 
} 

Homecontroller

[ValidateAntiForgeryToken] 
[HttpPost] 
public IActionResult Index(Test test) 
{ 
    if (ModelState.IsValid) 
    { 

    } 

    return View(test); 
} 

Für den Test werde ich den Wert £ 252.83 in das Feld Betrag eingeben und das Formular abschicken.

Wenn ich dann eine brakepoint auf der var value = valueProviderResult.FirstValue; Linie platzieren kann ich dieser Wert sehen ist £ 252,83 und wenn ich einen Haltepunkt auf der Linie modelBindingContext.Result = ModelBindingResult.Success(result); platzieren kann ich sehen, dass das Ergebnis 252.83M ist.

Allerdings, wenn ich durch den Code Schritt weiter und einen Haltepunkt setzen auf der Linie if (ModelState.IsValid) der gültigen Zustand ist falsch und wenn ich das Modell prüfen test das Objekt Amount ist 0.

Wenn jemand helfen kann, es wäre viel geschätzt :-)

Antwort

0

Versuchen Sie weiter auf dem Fehler Model zu überprüfen, sollte der Betrag Eigenschaft ungültig sein, und es muss eine Ausnahme sein.

Ich vermute, es sollte InvalidCastException sein. Ich bemerke, dass die Amount-Eigenschaft in der Test-Klasse Double ist, während Sie Decimal in Ihrem DecimalAttribute produzieren.

So ist die build-in Modell Binder, dass die Test-Klasse Verarbeitung nicht in der Lage, um den Betrag Eigenschaft (sollte ComplexTypeModelBinder sein), wie es ist anders Art.

Verwandte Themen