1

オブジェクトに[Decimal]という属性が割り当てられていても、何らかの理由でトリガされるのはModelBinderですが、実際にはデータが消されても投稿されたデータは更新されませんモデル。C#ASP.NET Core ModelBinderはモデルを更新しません

誰かが私のコードから、私が間違っている可能性があるかどうか分かりますか?

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); 
} 

私は、額面に252.83という値を入力してフォームを送信します。

私はその後、ラインvar value = valueProviderResult.FirstValue;にbrakepointを配置した場合、私はその価値が£252.83であると私はラインmodelBindingContext.Result = ModelBindingResult.Success(result);にブレークポイントを置く場合、私は結果が252.83Mであることがわかります見ることができます。

しかし、私はさらに、コードをステップ実行し、有効な状態が偽であると私はオブジェクトAmountモデルtestを調べる場合は、誰もが、それはずっとだろう助けることができる場合は0

あるif (ModelState.IsValid)行にブレークポイントを配置する場合ありがとうございます:-)

答えて

0

ModelStateエラーをさらに調べて、Amountプロパティが無効で、例外が存在する必要があります。

私はそれがInvalidCastExceptionであると推測しています。 DecimalAttributeでDecimalを生成している間は、TestクラスのAmountプロパティがDoubleであることがわかりました。

したがって、Testクラスを処理する組み込みモデルバインダー(ComplexTypeModelBinderである必要があります)はAmountプロパティを異なるタイプとして設定できません。

関連する問題