۱۳۸۸/۰۵/۱۰

استفاده از jQuery Ajax جهت تعيين اعتبار يك فرم


فرض كنيد تعيين اعتبار يكي از فيلدهاي فرم نياز به انجام محاسباتي در سمت سرور دارد و اين‌كار را مي‌خواهيم با استفاده از jQuery Ajax‌ انجام دهيم. مشكلي كه در اينجا وجود دارد، اين است كه A در Ajax به معناي asynchronous است. يعني زمانيكه كاربر دكمه submit را فشرد، ديگر برنامه منتظر اين نخواهد شد كه پاسخ كامل دريافت شود ، ساير پردازش‌ها صورت گيرد و سپس فرم را به سرور ارسال نمايد (شبيه به ايجاد يك ترد جديد در برنامه‌هاي ويندوزي). مثال زير را در نظر بگيريد:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestCustomValidation.aspx.cs"
Inherits="TestJQueryAjax.TestCustomValodation" %>

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

<script src="js/jquery.js" type="text/javascript"></script>

<script type="text/javascript">
function validate() {
var number1 = $("#<%=txtNumber1.ClientID %>").val();
var number2 = $("#<%=txtNumber2.ClientID %>").val();
var result = false;
$.ajax({
type: "POST",
url: 'AjaxSrv.asmx/ValidateIt',
data: '{"number1":' + number1 + ',"number2":' + number2 + '}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success:
function(msg) {
if (msg.d) {
result = true;
alert('بسيار خوب');
}
else {
result = false;
alert('دوباره سعي كنيد');
}
},
error:
function(XMLHttpRequest, textStatus, errorThrown) {
result = false;
alert("خطايي رخ داده است");
}
});
//debugger;
return result;
}
</script>

</head>
<body>
<form id="form1" runat="server">
<div>
number 1 :
<asp:TextBox runat="server" ID="txtNumber1" />
<br />
number 2 :
<asp:TextBox runat="server" ID="txtNumber2" />
<br />
<asp:Button ID="btnSubmit" Text="Submit" UseSubmitBehavior="false" runat="server"
OnClientClick="if(!validate()){ return false;}" OnClick="btnSubmitClick" />
</div>
</form>
</body>
</html>

اين مثال يك نوع اعتبار سنجي سفارشي را در حين submit با استفاده از وب سرويس زير انجام مي‌دهد (حاصلضرب دو عدد دريافتي را بررسي مي‌كند كه بايد مساوي 10 باشند. البته هدف از اين مثال ساده، آشنايي با نحوه‌ي انجام اين نوع عمليات است كه مي‌تواند شامل كار با ديتابيس و غيره هم باشد. و گرنه بديهي است اين بررسي را با دو سطر كد جاوا اسكريپتي نيز مي‌شد انجام داد):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;

namespace TestJQueryAjax
{
/// <summary>
/// Summary description for AjaxSrv
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[ScriptService]
public class AjaxSrv : System.Web.Services.WebService
{
[WebMethod(EnableSession = true)]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public bool ValidateIt(int number1, int number2)
{
return number1 * number2 == 10;
}
}
}
در اين مثال هنگام submit ، عمليات اعتبار سنجي با توجه به وضعيت asynchronous عمليات Ajax ، تمام و كمال رخ نداده ، يا اعتبار سنجي انجام نمي‌شود و يا پيغام خطايي را دريافت خواهيم كرد.

راه حل چيست؟
راه حل‌هاي فضايي بسياري را در وب در اين مورد مي‌توان پيدا كرد؛ اما راه حل استاندارد آن در اين حالت ويژه، استفاده از Ajax در حالت غيرهمزمان است. يعني اين فريم ورك Ajax را وادار كنيم كه تا پايان عمليات مورد نظر، منتظر بماند و سپس فرم را ارسال كند. براي اين منظور تنها كافي است يك سطر زير را پيش از فراخواني تابع Ajax ، اضافه و فراخواني نمائيم:

$.ajaxSetup({async: false}) ;
نكته:
UseSubmitBehavior دكمه ما را به شكل زير رندر مي‌كند (دكمه به يك button معمولي (بجاي حالت submit) تبديل شده و سپس يك doPostBack را اضافه خواهد كرد):

<input id="btnSubmit" type="button" onclick="if(!validate()){ return false;};__doPostBack('btnSubmit','')" value="Submit" name="btnSubmit"/>