MVC3 Usuń błędy ModelState

84

Mam sytuację, w której przesyłam obraz wybrany przez użytkownika z jego lokalnego systemu plików. Mój formularz moim zdaniem ma zasadniczo dwa przyciski przesyłania. Jeden jest używany do normalnego przesłania formularza i wykonywane jest wszystkie sprawdzanie poprawności. Drugi służy tylko do przesłania obrazu, w takim przypadku nie chcę jeszcze sprawdzać poprawności.

Udało mi się wyłączyć walidację po stronie klienta, nadając przyciskowi przesyłania „Prześlij obraz” wartość klasy „nazwa stylu anuluj”, więc

<input type="submit" name="UploadImageButton" value="Upload Image" class="style-name cancel" /> 

Teraz, kiedy wysyłam z powrotem, mój model ma właściwość UploadImageButton, po kliknięciu tego przycisku zapełnia tę właściwość (nazwa wejścia jest zgodna z Property). W ten sposób wiem, czy formularz został przesłany przez mój prawdziwy przycisk Prześlij, czy przez przycisk UploadImageButton.

Moje pytanie brzmi… Jak mogę wyłączyć sprawdzanie poprawności ServerSide? Nie chcę, aby podsumowanie walidacji było wyświetlane, gdy użytkownik kliknie ten przycisk. Wiem, że możesz za pomocą tego dodać błędy modelu niestandardowego

ModelState.AddModelError("{key}", "{error msg}");

Szukam sposobu na usunięcie błędów modelu. czy to możliwe?

EDYTOWAĆ:

Oto co wymyśliłem:

foreach (var key in ModelState.Keys.ToList().Where(key => ModelState.ContainsKey(key))) {
     //ModelState.Remove(key); //This was my solution before
     ModelState[key].Errors.Clear(); //This is my new solution. Thanks bbak
}
Jeff Reddy
źródło
Dlaczego robisz Where(key => ModelState.Keys.Contains(key))? Wygląda na to, że klauzula Where jest zbędna, ponieważ każdy klucz w ModelState.Keys będzie miał swoją ModelState.Keys.Contains (key) zwracającą wartość true.
Maxim Zaslavsky
1
Zaktualizowałem pytanie i tekst, aby użyć krótszej metody w ModelState.ContainsKey, chociaż mylisz się w swoich założeniach. Te robią to samo.
Jeff Reddy,
Przepraszam, mogłem źle wytłumaczyć lub źle zrozumieć twoją odpowiedź. Masz rację ModelState.ContainsKey(key)i ModelState.Contains(key)robisz to samo, ale chodzi mi o to, że wszystkie wartości w ModelState.Keys.ToList()will z natury są zawarte w ModelState, więc cała Whereklauzula jest zbędna i spowolni wydajność. Jednak drobiazg.
Maxim Zaslavsky
To był ReSharper, który to połączył. Dziękuję za zwrócenie uwagi.
Jeff Reddy,
1
Zwróć uwagę na sposób, w jaki dowiadujesz się, który przycisk był źródłem przesłania. W ViewModel nie musisz mieć tej właściwości. Wystarczy dodać parametr FormCollection do kontrolera: publiczny indeks ActionResult (model YourViewModelClass, FormCollection formCollection). I sprawdź, czy jest w nim nazwa przycisku: if (formCollection ["UploadImageButton"]! = Null). Myślę, że lepiej, gdy masz więcej przycisku przesyłania.
jannagy02

Odpowiedzi:

146

Możesz usunąć błędy modelu, wykonując coś takiego:

if (ModelState.ContainsKey("{key}"))
    ModelState["{key}"].Errors.Clear();
bbak
źródło
1
To jest dokładnie to, czego szukałem. Zmieniłem wybraną odpowiedź (przepraszam Adama Tulipera).
Jeff Reddy,
Dzięki, to właśnie zaoszczędziło mi kilku godzin!
Agent007
1
Na wszelki wypadek, gdyby ktoś się zastanawiał, dotyczy to równieżModelState.IsValid
Red Taz
2
o dziwo, to nie wystarczyło w moim przypadku. Musiałem dodać ModelState ["{key}"]. ValidationState = ModelValidationState.Valid;
AGuyCalledGerald
68

Opiera się to na poprzednich odpowiedziach, ale trochę je upraszcza:

foreach (var modelValue in ModelState.Values)
{
    modelValue.Errors.Clear();
}
Dan Friedman
źródło
7

Ogólnie rzecz biorąc, nie chcesz wyłączać sprawdzania poprawności po stronie serwera ani ręcznie usuwać błędów ModelState. Jest to wykonalne, ale podatne na błędy, ponieważ musi polegać na łańcuchach jako kluczach. Głosowałem za odpowiedzią, jak usunąć klucze, ponieważ jest poprawna i użyteczna, ale odradzam projektowanie się w przypadku, w którym trzeba to mocno przemyśleć.

W twoim przypadku masz wiele przycisków przesyłania dla tego samego formularza, ale tak naprawdę nie przesyłasz formularza podczas przesyłania obrazu. Aby zapobiec walidacji po stronie klienta, możesz użyć klasy „anuluj”, jak już wskazałeś, ale zalecam również posiadanie drugiego przycisku przesyłania w innej formie, w którym to przypadku nie spowoduje to walidacji na formularzu głównym.

Istnieje druga zaleta korzystania z innego formularza: możesz wysłać go do innej metody ActionResult, która po prostu obsługuje logikę przesłania obrazu. Ta inna metoda po prostu nie zawracałaby sobie głowy sprawdzaniem właściwości „IsValid” stanu modelu: dba tylko o to, czy na obrazie są informacje, które można sprawdzić osobno. (Nawet jeśli używasz tej samej metody ActionResult, możesz przejść do logiki, aby nie polegać na właściwości IsValid stanu modelu).

Jeśli musisz usunąć błędy ze stanu modelu i warto usunąć je wszystkie, spróbuj tego:

foreach (var key in ModelState.Keys)
{
    ModelState[key].Errors.Clear();
}

Uniemożliwia to poleganie na poprawności nazw kluczy, ale zachowuje wartości, jeśli jakiekolwiek wartości (prawidłowe lub nieprawidłowe) już istnieją w modelu.

Ostatnią rzeczą do sprawdzenia w tych przypadkach jest to, czy masz wartości, które są tylko czasami w widoku, co nie spowoduje walidacji po stronie klienta (nie ma ich w widoku), ale powoduje problemy z walidacją po stronie serwera. W takim przypadku najlepiej jest użyć @ Html.HiddenFor (model => model.PropertyName, jeśli możesz, zakładając, że wartość została już ustawiona, po prostu nie jest widoczna w tym widoku.

James
źródło
7

Czasami go używam, więc stworzyłem z niego metodę rozszerzenia:

public static ModelStateDictionary ClearError(this ModelStateDictionary m, string fieldName)
{
    if (m.ContainsKey(fieldName))
        m[fieldName].Errors.Clear();
    return m;
}

Może być używany płynnie do usuwania błędów w wielu polach.

Mahmoodvcs
źródło
3

użyj ModelState.Remove ("{key}"), aby usunąć błąd z modelu, co spowoduje zresetowanie ModelState.IsValid do true

ModelState.Remove("{key}");
Ibrar
źródło