5

在我看來,模型中的一些decimaldecimal?屬性標記爲「百分比」數據類型,與其他數據一起註釋,例如前操縱模型值:它傳遞給DefaultModelBinder.BindModel

[DataType("Percent")] 
[Display(Name = "Percent of foo completed")] 
[Range(0, 1)] 
public decimal? FooPercent { get; set; } 

我會例如允許用戶在輸入數據方面有一定的靈活性,即有或沒有百分號,中間空格等。但我仍想使用DefaultModelBinder行爲來獲得其所有功能,例如檢查RangeAttribute並添加適當的驗證消息。

有沒有辦法解析並更改模型的值,然後將其傳遞?這是我正在嘗試,但得到一個運行時異常。 (忽略實際的分析邏輯,這不是它的最終形式,我在這一點上的模型替換問題只是感興趣。)

public class PercentModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, 
            ModelBindingContext bindingContext) 
    { 
     if (bindingContext.ModelMetadata.DataTypeName == "Percent") 
     { 
      ValueProviderResult result = 
       bindingContext.ValueProvider.GetValue(
        bindingContext.ModelName); 
      if (result != null) 
      { 
       string stringValue = 
        (string)result.ConvertTo(typeof(string)); 
       decimal decimalValue; 
       if (!string.IsNullOrWhiteSpace(stringValue) && 
        decimal.TryParse(
         stringValue.TrimEnd(new char[] { '%', ' ' }), 
         out decimalValue)) 
       { 
        decimalValue /= 100.0m; 

        // EXCEPTION : This property setter is obsolete, 
        // because its value is derived from 
        // ModelMetadata.Model now. 
        bindingContext.Model = decimalValue; 
       } 
      } 
     } 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

回答

5

沒關係,這是在哪裏驗證發生在一個根本性的誤解MVC週期。在花了一段時間在MVC源代碼之後,我看到它是如何工作的。

如果它是有幫助的人,這裏是什麼工作對我來說:

[DataType("Percent")] 
[Display(Name = "Percent of foo completed")] 
[Range(0.0d, 1.0d, ErrorMessage="The field {0} must be between {1:P0} and {2:P0}.")] 
public decimal? FooPercent { get; set; } 

而在粘合劑,你可以返回值:

public class PercentModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, 
            ModelBindingContext bindingContext) 
    { 
     if (bindingContext.ModelMetadata.DataTypeName == "Percent") 
     { 
      ValueProviderResult result = 
       bindingContext.ValueProvider.GetValue(
        bindingContext.ModelName); 
      if (result != null) 
      { 
       string stringValue = 
        (string)result.ConvertTo(typeof(string)); 
       decimal decimalValue; 
       if (!string.IsNullOrWhiteSpace(stringValue) && 
        decimal.TryParse(
         stringValue.TrimEnd(new char[] { '%', ' ' }), 
         out decimalValue)) 
       { 
        return decimalValue/100.0m; 
       } 
      } 
     } 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 
+0

對我來說,定製粘合劑從未執行過。你還在做什麼? – 2018-03-06 10:30:14