2012-10-15 12 views
6

Ogni tanto a Rentler vediamo l'erroreclienti troncando Querystring, provoca FormatException

System.FormatException, stringa non è stata riconosciuta come valida booleano

nel nostro monitoraggio della salute. A quanto pare, sembra che i nostri clienti stiano occasionalmente troncando la fine dell'URL quando copia/incolla altrove. Si dà il caso che un parametro booleano tenda ad essere alla fine della stringa, e quando un cliente lo condivide su alcuni social network viene scaricato con report di errore.

https: // {domain}/ricerca sid = 17.403.777 & nid = 651 & location = 840.065 & propertytypecode = 1 & photosonly = fals

Usiamo modello vincolante per tutto, quindi non sono davvero sicuro di come affrontare questo. Potrei cambiare la proprietà in una stringa e tentare di analizzarla nell'azione del controller, ma è sciatta. Esiste un modo semplice e fluido per ottenere il modello di placchetta su TryParse() e risolvere semplicemente su false se non è possibile?

+0

Sarebbe bello saperlo. Spero che la risposta non riguardi la scrittura del tuo modello di legatura. – Gromer

+0

Questo è quello che spero, Gromer. È un errore così organico, poco frequente, ma estremamente fastidioso. – Dusda

+1

Che dire creare un overload che ha 'photosonly' come parametro stringa invece di un bool, che restituisce solo il risultato di chiamare quello normale con un falso? – Bobson

risposta

1

come utilizzare il raccoglitore modello personalizzato per il tipo di dati booleani? si avrebbe bisogno di qualcosa di simile:

/// <summary> 
/// A custom model binder for boolean values. This behaves the same as the default 
/// one, except it will resolve the value to false if it cannot be parsed. 
/// </summary> 
public class BooleanModelBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

     //MVC checkboxes need specific handling in checked state 
     if (string.Equals(valueResult.AttemptedValue, "true,false")) 
     { 
      AddToModelState(bindingContext, valueResult); 
      return true; 
     } 

     bool parsed = false; 
     if (Boolean.TryParse(valueResult.AttemptedValue, out parsed)) 
     { 
      AddToModelState(bindingContext, valueResult); 
      return parsed; 
     } 

     return false; 
    } 

    private static void AddToModelState(ModelBindingContext bindingContext, ValueProviderResult valueResult) 
    { 
     bindingContext.ModelState.Add(bindingContext.ModelName, new ModelState { Value = valueResult }); 
    } 
} 

//in Global.asax 
protected void Application_Start() 
{ 
    ... 
    ModelBinders.Binders.Add(typeof(bool), new BooleanModelBinder()); 
} 
+0

Bello! Quindi, presumo che questo raccoglitore sarà usato anche in un tipo complesso che ha una proprietà 'bool'? Supponi di avere l'auto di classe {public bool IsAwesome {get; impostato; } public string Name {get; impostato; }} 'Userebbe il binder predefinito per associare l'argomento' car' nel mio metodo action e usare 'BooleanModelBinder' quando incontra i dati' IsAwesome' che arrivano nella richiesta? – Gromer

+1

Sì, la proprietà IsAwesome verrà associata a questo ModelBinder. Le proprietà booleane utilizzeranno questo particolare raccoglitore e il resto della rilegatura del modello procederà normalmente. – pkmiec

+0

Grazie, Dooh. Ho pensato che avrei dovuto implementare un raccoglitore personalizzato, ma speravo che MVC avesse qualche angolo oscuro da qualche parte che mi permettesse di configurare quello predefinito. Oh bene, questo è l'approccio migliore. – Dusda

0

Si può sempre aggiungere un blocco try/catch e hanno un valore predefinito nella cattura.

Un'alternativa sarebbe controllare solo se la prima lettera del parametro è "T" o "F". Questo dovrebbe evitare molti problemi.

+0

Sarebbe meglio TryParse() rispetto a questo, ma preferirei evitare l'implementazione di una convalida personalizzata come quella nell'azione del controller, specialmente dal momento che Rentler ha più integrazioni con altre società, e quindi azioni multiple del controller che dovrei coprire . – Dusda

+0

Sembra che questo sia un problema molto specifico, che richiede una soluzione specifica. Inoltre non vedo alcun beneficio di TryParse per Try/Catch, quindi non posso difendere la mia scelta su questo. – SamuelDavis