HAVIT Knowledge Base

Vývoj webových aplikací, .NET, SQL, návrh
Welcome to HAVIT Knowledge Base Sign in | Join | Help
-
Home Články Forums Obrázky Soubory

ASP.NET

Vývoj webových aplikací ASP.NET

Proč nejde udělat rozumný AjaxValidator?

Po půl dni snažení a bádání jsem dospěl k subjektivnímu závěru, že nelze udělat rozumný ASP.NET validátor založený na AJAXu. Přesněji řečeno bylo mým cílem vytvořit obdobu CustomValidatoru, který by měl běžný ServerValidate a navíc klientskou jscript část, která by pomocí AJAXového HTTP-requestu validovala hodnotu vůči tomuto ServerValidate.

Narazil jsem na následující zásadní překážky, které podle mě nelze snadno překonat:

  1. Současné ASP.NET validátory, resp. všechny jejich Microsoftí obslužné klientské skripty a API jsou nekompromisně synchronní. V okamžiku požadavku validace (obvykle před submitem stránky) jsou volány prosté validační funkce všech povolených validátorů a od těchto se očekává jen true/false dle výsledku validace. V současném konceptu validátorů nikde není rozumný prostor pro asynchronní operace či nějakého zásahu do průběhu validace. 
  2. Je prakticky nemožné rozumným způsobem provést synchronní AJAXové volání vůči serveru a stejnětak je nemožné rozumně toto synchronní volání simulovat nějakým blokováním threadu uvnitř validační funkce. Javascript nezná žádné sleep/wait/pause a veškeré snahy o jeho implementaci vždy končí v tupé smyčce zatěžující CPU ze 100% do okamžiku splnění nějaké podmínky (přijetí AJAXového callbacku, dosažení určitého času, naplnění čítače, atp.)

Pro současný koncept ASP.NET validátorů jsem dospěl k těmto závěrům:

  1. Protože je koncept založen především na jednorázové kontrole hodnot před submitem formuláře a má za účel tento submit povolit/zakázat, je oprávněně založen na synchronních operacích a pro jakékoliv dlouhotrvající operace či asynchronní volání zde není prostor a poměrně logicky se s nimi nepočítá.
  2. Asynchronní AJAXová validace vůči serveru by byla použitelná u konceptu průběžné validace, kdy by byly hodnoty kontrolovány ihned po jejich zadání (onchange) a takováto validace by díky svému zpoždění nemohla blokovat odeslání formuláře, spíše by sloužila jako proaktivní kontrola uživatelského zadání.
  3. Současný koncept validátorů připouští pouze zběsilá řešení se synchronizačním blokováním threadu v různých sleep smyčkách (byť s timeoutem), popř. "chováním nekompatibilní" on-change implementace dle bodu 2.

Veškeré pokusy o implementace AjaxValidatoru, které jsem na netu viděl, trpěly jedním nebo několika nedostatky z výše uvedených a jejich praktická použitelnost se tak blíží nule (spíše se tak stávají přetěžovači serverů, než účinnými validátory).

Avšak! Pokud by se našel někdo, koho by napadlo, jak výše uvedená omezení účinně obejít a funkční AjaxValidator vytvořit, sem s myšlenkou a pochvala ho nemine... ;-)))

PS: Sám jsem dospěl k implementaci AjaxValidatoru, který měl nastavitelný Timeout a ve validační funkci po zavolání asynchronního AJAX requestu na ServerValidate čekal po dobu tohoto timeoutu na odezvu serveru (čekal = různé hnusné implementace zatěžujících smyček čekajících na nějaký příznak nebo timeout). Pokud do Timeoutu nebyl AJAXem výsledek od serveru získán, propustila klientská část validaci jako IsValid=true, a tak se to v případě submitu zvalidovalo na serveru, nebo v případě onchange validace dovalidovalo později asynchronně (až dorazil callback, tak se aktualizoval validátor). Výsledek mi přišel pro praxi nepoužitelný, už timeout 1s je pro ovládání webového formuláře nepříjemný, stránka nereaguje na odeslání formuláře okamžitě, proto jsem to celé zahodil... Můj poznatek je, že pokud validátorem chápeme to, co ASP.NET, tedy blokaci odeslání formuláře, tak přes AJAX cesta nevede, i kdyby to šlo bez toho cyklického pollingu s timeoutem. Leda by byla odezva v řádu milisekund, což při serverových validacích moc nehrozí (obvykle nějaký dotaz do DB na exists, atp.).

Published 22. května 2007 14:03 by Robert Haken
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

d.aemon said:

Já teda nevím, ale proč by měl být AJAX ausgerechnet asynchronní? Pokud se mi to nehodí, zavolám request synchronně a funguje to, jak má. Prostě zavolej XMLHttpRequest.open( "GET", "http://url.com", false ) a je to.

září 12, 2007 9:59
 

Josef Skramuský said:

tak jsem chtel demona zprudit protoze

XMLHttpRequest.open is not a function

ale jelikoz mne to dovedlo k reseni meho problemu tak nebudu a radeji sem dam funkcni priklad :)

<code>

function SafeJavascriptIncludeInitXmplHttpObject()

{

if(typeof xmlhttp == "undefined")

{

xmlhttp = false;

/*@cc_on @*/

/*@if (@_jscript_version >= 5)

// JScript gives us Conditional compilation, we can cope with old IE versions.

// and security blocked creation of the objects.

try {

 xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");

} catch (e) {

 try {

  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

 } catch (E) {

  xmlhttp = false;

 }

}

@end @*/

if (!xmlhttp && typeof XMLHttpRequest!='undefined') {

try {

xmlhttp = new XMLHttpRequest();

} catch (e) {

xmlhttp=false;

}

}

if (!xmlhttp && window.createRequest) {

try {

xmlhttp = window.createRequest();

} catch (e) {

xmlhttp=false;

}

}

}

}

function SafeJavascriptInclude(url)

{

var errorText = "Could not include file '" + url + "'.";

SafeJavascriptIncludeInitXmplHttpObject();

try

{

xmlhttp.open('GET', url, false);

xmlhttp.send(null);

if(xmlhttp.status == 200)

{

eval(xmlhttp.responseText);

}

else

{

throw("Request returns: " + xmlhttp.status);

}

}

catch (e)

{

throw(errorText + " (" + e.toString() + ")");

}

}

</code>

října 31, 2007 17:19
 

Robert Haken said:

Možná jsem to málo zdůraznil, ale řeč je o Microsoft ASP.NET AJAX 1.0, kde to synchronně moc nejde.

listopadu 5, 2007 17:37
 

Jan Semorád said:

AjaxValidating.aspx

------------------------------------

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AjaxValidating.aspx.cs" Inherits="WebApplication1.AjaxValidating" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

   <title>Untitled Page</title>

<style type="text/css"   >

       .Hide{ display:none; }

</style>

<script language="javascript" type="text/javascript">

// <!CDATA[

function OKButton_onclick() {

   //put following in OKCallBackFunction

   window.document.getElementById("SubmitButton").click();    

}

// ]]>

</script>

</head>

<body>

   <form id="form1" runat="server">

   <div>

       <asp:Label ID="ResultLabel" runat="server" Text="Jak to dopadne?"></asp:Label>

   </div>

   <asp:Button ID="SubmitButton" runat="server" Text="SubmitButton"

       onclick="SubmitButton_Click" CssClass="Hide" />

   </form>

   <input id="OKButton" type="button" value="OKButton" onclick="return OKButton_onclick()" />

</body>

</html>

AjaxValidating.aspx.cs

-------------------------------------------

using System;

using System.Collections;

using System.Configuration;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

namespace WebApplication1

{

   public partial class AjaxValidating : System.Web.UI.Page

   {

       protected void Page_Load(object sender, EventArgs e)

       {

       }

       protected void SubmitButton_Click(object sender, EventArgs e)

       {

           ResultLabel.Text = "Je to O.K.!";

       }

   }

}

června 13, 2008 17:55

What do you think?

(required) 
(optional)
(required) 
Enter the code you see below

Submit