Az a tény, hogy a böngészők totálisan inkompatibilisek egymással, minden napra új meglepetéseket tartogat. Egyes böngészők már akkor is máshogy viselkednek, ha egy vagy több szövegdoboz van egy űrlapon.
Az egyik új projektünkben a biztonság érdekében használjuk az AntiCSRF modult, ami tökéletesen működött is, míg nem egyszer csak időnként sikerült kiakasztani. Az adott rész épp a webalkalmazás fejlécében lévő kereső, ahol a felhasználó tetszőleges szöveget beírhat, választhat az AutoCompleteExtender által felkínált listáról, a Keres gomb megnyomására azonban nem postbackelünk, hanem átirányítjuk a böngészőt egy másik oldalra, ami egy sima GET kérésnél query stringben megkapja a keresett kifejezést. Na, ennek sikerült kiakasztani az AntiCSRF modult, pedig az csak a POST kéréseket védi, miközben sehol egy POST, csak GET. Legalábbis a terv szerint.
A Fiddler elárulta, hogy bizony valaki küld egy sunyi POSTot a szerverre, azonban sem az __EVENTTARGET, sem pedig az __EVENTARGUMENT mező nem volt kitöltve. Itt kezdtem gyanakodni, hogy nem az ASP.NET lesz a bűnös, de azért szépen sorban kizártam mindent:
- Nem a mi átirányításunk a problémás.
- Nem futottunk bele olyan problémába, amibe mások az AutoCompleteExtendernél.
- Az Enter kezelése Panelhez rendelt DefaultButtonnal volt megoldva, mégsem ez volt a bűnös.
Hosszas kísérletezgetés és számtalan órányi guglizás után eljutottam oda, hogy még ez is böngészőfüggő:
<form action="DefaultPostbackTarget.htm">
<fieldset>
<input id="txt" type="text" />
<input id="btn" type="button" value="Mehet" />
</fieldset>
</form>
Ugyanis, ha csak ennyi van az oldalon és a felhasználó a szövegdobozban Entert nyom, akkor a böngészők egy része nem csinál semmit, más részük viszont elpostolja az egész űrlapot a form action attribútumában megadott címre. Mindezt persze közvetlenül, figyelmen kívül hagyva a __doPostBack metódust, ami beállítgatná az __EVENTTARGET és az __EVENTARGUMENT értékeket.
Itt a minimalista repro oldal, ki lehet próbálni (IE8-ban nem érdemes, ott jó):
Ennek szemmel láthatóan az az oka, hogy a böngésző úgy gondolja, hogy ha csak egy szövegdoboz van az oldalon és abban a felhasználó Entert nyom, akkor biztos el akarja küldeni annak az egy szövegdoboznak az értékét. Nem tudom, hogy ezt ki találta ki – (a szabvány vagy a böngésző kiagyalói), de hogy nem bug, az biztos, mert több böngésző is így csinálja, – de az meg sem fordult a fejükben, hogy esetleg az Enterrel más szándékunk van kliens oldalon. A mi esetünkben a GETes átirányítás és az AutoCompleteExtender is tudott volna mit kezdeni ezzel a billentyű leütéssel, ha idő előtt a böngésző nem töltötte volna újra az egész oldalt (hiszen az ASP.NET a form action attribútumot az aktuális oldal URL-jére állítja), ráadásul mindezt egy POST kéréssel, amitől az AntiCSRF modul kifeküdt. További szépség, hogy ha nem lett volna ott ez a modul, akkor valószínűleg észre sem vesszük ezt a plusz POSTot, mert az oldal épp elég gyors ahhoz, hogy a böngésző villanása is alig észrevehető.
És hogy mi a megoldás? Kell még egy beviteli mező az űrlapra, például így:
<input type="text" style="visibility:hidden; display: none;" />
Ezt is ki lehet próbálni:
Lehet, hogy mások ebbe már régen belefutottak, nekem még csak most sikerült. Mostantól ez lesz a kedvenc böngésző inkompatibilitási demóm.
Nektek van hasonló kedvencetek?