2017-09-05 122 views
1

我創建了一個ModelBinder,只有當一個對象有一個[Decimal]屬性分配,但由於某種原因,但它實際上消毒它似乎沒有更新發布的數據模型。C#ASP.NET核心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並提交表單。

如果我再墊上brakepoint上線var value = valueProviderResult.FirstValue;我可以看到,價值是252.83£,如果我把一個斷點上線modelBindingContext.Result = ModelBindingResult.Success(result);我可以看到的結果是252.83M

但是如果我單步執行代碼,並進一步上放置一個斷點行if (ModelState.IsValid)有效狀態是假的,如果我檢查模型test對象Amount爲0

如果有人可以幫助這將是更讚賞:-)

回答

0

嘗試進一步檢查ModelState錯誤,金額屬性應該是無效的,並且必須有一個例外。

我猜測它應該是InvalidCastException。我注意到,在DecimalAttribute中生成Decimal時,Test類中的Amount屬性爲Double。

因此,處理Test類的內置Model Binder(應該是ComplexTypeModelBinder)無法將Amount屬性設置爲不同的類型。