5

Alcuni decimal e decimal? immobili a mio modello vista sono contrassegnate come tipo di dati "Percentuale", insieme ad altre annotazioni di dati, ad esempio:Manipolare valore del modello prima di passarlo al DefaultModelBinder.BindModel

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

mi piacerebbe come per consentire all'utente una certa flessibilità nel modo in cui inseriscono i dati, cioè con o senza il segno di percentuale, spazi intermedi, ecc. Ma voglio ancora usare il comportamento di DefaultModelBinder per ottenere tutte le sue funzionalità come controllare il RangeAttribute e aggiungere il messaggi di convalida appropriati.

C'è un modo per analizzare e modificare il valore del modello, quindi trasmetterlo? Ecco cosa sto cercando, ma sto ottenendo un'eccezione di runtime. (Ignorare la logica di analisi reale, questo non è la sua forma definitiva io sono solo interessati alla questione modello sostitutivo a questo punto..)

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

risposta

5

Non importa, questo è stato un fraintendimento fondamentale di cui convalida avviene nella Ciclo MVC. Dopo aver trascorso un po 'di tempo nel codice sorgente MVC, vedo come funziona.

Nel caso in cui è utile agli altri, qui è ciò che sta lavorando per me:

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

E nel legante, è sufficiente restituire il valore:

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

Per me il legante personalizzato è mai eseguito C'è qualcos'altro che stai facendo? –

Problemi correlati