2012-10-15 11 views
6

Każdy więc często w Rentler widzimy błądKlienci obcinania kwerendy, powoduje FormatException

System.FormatException, String nie został rozpoznany jako prawidłowy Boolean

w naszej monitorowania stanu zdrowia. Jak się okazuje, wygląda na to, że nasi klienci czasami skracają koniec adresu URL podczas kopiowania/wklejania go w innym miejscu. Tak się składa, że ​​parametr boolowski pojawia się na końcu łańcucha, a gdy klient udostępnia go w sieci społecznościowej, dostajemy raporty o błędach.

https: // {domeny}/wyszukiwanie sid = 17403777 & nid = 651 & location = 840065 & propertytypecode = 1 & photosonly = Fals

Używamy modelu wiążące dla wszystkich, więc nie jestem pewien, jak sobie z tym poradzić. Mógłbym zmienić właściwość na ciąg znaków i spróbować przetworzyć go w akcji kontrolera, ale to jest niechlujstwo. Czy istnieje prosty, płynny sposób, aby uzyskać model spoiwa do TryParse() i po prostu rozwiązać na false, jeśli nie może?

+0

Byłoby miło wiedzieć. Mam nadzieję, że odpowiedź nie wymaga napisania własnego segregatora. – Gromer

+0

Tego właśnie oczekuję, Gromer. To taki organiczny, nieczęsty błąd, ale bardzo denerwujący. – Dusda

+1

Co z tworzeniem przeciążenia, które ma 'photosonly' jako parametr łańcuchowy zamiast bool, który zwraca wynik wywołania normalnego z błędem? – Bobson

Odpowiedz

1

Co zrobić z niestandardowym modelem spoiwa dla danych typu boolean? potrzebujesz czegoś takiego:

/// <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

Nice! Zakładam więc, że ten segregator będzie używany nawet w złożonym typie, który ma właściwość 'bool'? Powiedzmy, że masz 'class car {public bool IsAwesome {get; zestaw; } public string Name {get; zestaw; }} 'Użyłby domyślnego spoiwa do powiązania z argumentem' car' w mojej metodzie akcji i użył 'BooleanModelBinder' gdy napotka dane' IsAwesome' pojawiające się w żądaniu? – Gromer

+1

Tak, właściwość IsAwesome zostanie powiązana z tym modelemBinder. Właściwości boolowskie będą wykorzystywać ten konkretny środek wiążący, a pozostałe wiązania modelu będą przebiegać normalnie. – pkmiec

+0

Dzięki, Dooh. Pomyślałem, że będę musiał zaimplementować niestandardowy segregator, ale mam nadzieję, że MVC ma gdzieś ciemny zakątek, który pozwoliłby mi skonfigurować domyślny. No cóż, to jest najlepsze podejście. – Dusda

0

Zawsze możesz dodać blok try/catch i mieć domyślną wartość w haczyku.

Alternatywnym rozwiązaniem byłoby sprawdzenie, czy pierwsza litera parametru to "T" lub "F". Powinno to zapobiec wielu problemom.

+0

Byłoby lepiej, aby TryParse() niż to, ale wolałbym uniknąć wykonywania niestandardowych walidacji, takich jak w akcji kontrolera, zwłaszcza, że ​​Rentler ma wiele integracji z innymi firmami, a tym samym wielu działań kontrolera, które musiałbym objąć . – Dusda

+0

Wygląda na to, że jest to bardzo specyficzny problem, wymagający konkretnego rozwiązania. Nie widzę też żadnej korzyści ze stosowania TryParse w Try/Catch, więc nie mogę bronić mojego wyboru w tej kwestii. – SamuelDavis

Powiązane problemy