Kolejny “kliento-walidacyjno-mvcowy post”. Tym razem zmagałem się z niedziałającą walidacją po wpięciu w DOM HTMLa zwróconego z serwera. Akcja kontrolera kończyła się instrukcją:
1: return PartialView(viewName, model)
, a wstawianie w odpowiednie miejsce po stronie klienta odbywało się poprzez wywołanie jQuery.html(). Zdziwienie moje było o tyle duże, że kawałek DOMu uzyskiwany przez przeglądarkę najwyraźniej zawierał skrypt odpowiedzialny za walidację (inspected by Firebug).
Przeszukanie internetu zaprowadziło mnie na post “Making ASP.NET MVC 2 client side validation work with AJAX loaded forms“. Jak widać nie tylko ja miałem z tym problemy. Co prawda nie wszystkie informacje w nim zawarte były prawdziwe w przypadku jQuery: w jQuery funkcja html() wykonuje skrypty, co najwidoczniej – według autora, bo ja nie sprawdzałem – nie ma miejsca w przypadku MS Ajax. Nie było zatem potrzeby tak nieładnego babrania się w skanowanie zawartości w poszukiwaniu skryptów i ręczne ich odpalanie, to dzieje się samo.
Tak czy inaczej post ów i tak był pomocny, a to za sprawą nakierowania mnie na trop funkcji:
1: Sys.Mvc.FormContext._Application_Load();
Spojrzenie w kod pliku MicrosoftMvcValidation.debug.js dało jasny dowód, że wywołanie tej funkcji jest konieczne, aby nowe instrukcje walidacji znalazły się w kontenerze przechowującym reguły odpalane przy próbie wysłania formy na serwer.
I… nie działało nadal. Trzeba było dalej zagłębić się w javascript, aby odnaleźć źródło problemu. Funkcja
1: Sys.Mvc.FormContext._parseJsonOptions()
wywoływana podczas inicjalizacji przejeżdża po wszystkich zeskryptowanych regułach. To w sumie oczywiste. Uwagę moją przykuła linijka:
1: var formElement = $get(options.FormId);
Hę? Nigdzie nie nadawałem żadnej formie (ani świeżo ściągniętej z serwera, ani tym obecnym już na stronie) identyfikatora. Wywoływałem po prostu
1: Html.BeginForm(..., FormMethod.Post)
bo niczego innego nie potrzebowałem. Ale, jak się okazuje, ASP MVC stara się być mądrzejsze ode mnie. Każda forma bez ID jest niejawnie nazywana przez silnik według schematu form0, form1 itd. Moja świeżutka, cieplutka forma pobrana z serwera nie była wyjątkiem – Firebug bezlitośnie pokazał id form0, skrypty walidacji również zawierały tą wartość. Ale ja wcześniej już MIAŁEM form0 na swojej stronie… Rozwiązanie okazało się oczywiście banalne:
1: Html.BeginForm(..., FormMethod.Post, new { id = "myDynamicForm" })
I działa.