自动提交表单数据






4.75/5 (6投票s)
使用 ASP.NET 和 JavaScript 自动提交表单数据。
引言
在本文中,我将解释如何在填写表单时自动保存用户输入的数据。此功能类似于 ASP.NET 分析。这对于大型 Web 表单以及用户在保存表单之前关闭浏览器时非常有用。在这里,我还使用 ASP.NET 缓存来检索经过身份验证的用户的数据。
概述
JavaScript 用于在客户端绑定事件,收集用户输入数据,并填充一个哈希表。在给定的时间段内,哈希表被序列化并通过 XmlHttp
对象作为查询字符串发送到 ASPX 页面。AutoSave.aspx 使用查询字符串值填充内存对象,并在会话超时时,将值保存到数据库。
使用代码
- 将所有输入控件的
OnBlur
事件绑定起来,以便在用户输入时填充哈希表。 - 将所有用户输入数据提交到服务器端。
- 在用户关闭浏览器之前,将所有数据提交到服务器端。
//Default.aspx
<script src="jshashtable.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = bindEvents;
function bindEvents()
{
var textBoxes = document.getElementsByTagName("input");
for (i=0; i< textBoxes.length; i++)
{
if (textBoxes[i].type == 'text' || textBoxes[i].type == 'radio')
{
textBoxes[i].onblur = updateHashTable;
}
}
for (i=0; i< textBoxes.length; i++)
{
if (textBoxes[i].type == 'checkbox')
{
textBoxes[i].onblur = updateHashTableforCheckBox;
}
}
var comboBoxes = document.getElementsByTagName("select");
for (j=0; j< comboBoxes.length; j++)
{
comboBoxes[j].onchange = updateHashTableforCombo;
}
}
var Data = new Hashtable();
function updateHashTable()
{
Data.put(this.id, this.value);
// alert(this.id);
}
function updateHashTableforCheckBox()
{
Data.put(this.id, this.checked);
}
function updateHashTableforCombo()
{
Data.put(this.id, this.options(this.selectedIndex).value);
}
function AutoSave()
{
if(!Data.isEmpty())
{
// qstring = Data.keys();
qstring = Data.toQueryString();
//alert ("Key:"+ qstring[0]);
//SendXmlHttpRequest("GET", "AutoSave.aspx?" +
// qstring.substring(0,qstring.length-1));
SendXmlHttpRequest("AutoSave.aspx?"+qstring)
Data.clear();
}
}
var xmlHttp;
function SendXmlHttpRequest(url)
{
xmlhttp=null;
if (window.XMLHttpRequest)
{
// code for IE7, Firefox, Opera, etc.
xmlhttp=new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if (xmlhttp!=null)
{
xmlhttp.onreadystatechange=state_Change;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
else
{
alert("Your browser does not support XMLHTTP.");
}
}
function state_Change()
{
if (xmlhttp.readyState==4)
{
// 4 = "loaded"
if (xmlhttp.status==200)
{
// 200 = "OK"
var textBoxes = document.getElementsByTagName("input");
for (i=0; i< textBoxes.length; i++)
{
textBoxes[i].id.innerHTML=xmlhttp.status;
}
}
else
{
alert("Problem retrieving XML data:" + xmlhttp.statusText);
}
}
}
window.setInterval(AutoSave, 10000);
window.onbeforeunload = AutoSave;
</script>
// Jshashtable.js
var Hashtable = (function() {
function isUndefined(obj) {
return (typeof obj === "undefined");
}
function isFunction(obj) {
return (typeof obj === "function");
}
function isString(obj) {
return (typeof obj === "string");
}
function hasMethod(obj, methodName) {
return isFunction(obj[methodName]);
}
function hasEquals(obj) {
return hasMethod(obj, "equals");
}
function hasHashCode(obj) {
return hasMethod(obj, "hashCode");
}
function keyForObject(obj) {
if (isString(obj)) {
return obj;
} else if (hasHashCode(obj)) {
// Check the hashCode method really has returned a string
var hashCode = obj.hashCode();
if (!isString(hashCode)) {
return keyForObject(hashCode);
}
return hashCode;
} else if (hasMethod(obj, "toString")) {
return obj.toString();
} else {
return String(obj);
}
}
function equals_fixedValueHasEquals(fixedValue, variableValue) {
return fixedValue.equals(variableValue);
}
function equals_fixedValueNoEquals(fixedValue, variableValue) {
if (hasEquals(variableValue)) {
return variableValue.equals(fixedValue);
} else {
return fixedValue === variableValue;
}
}
function equals_equivalence(o1, o2) {
return o1 === o2;
}
function arraySearch(arr, value, arrayValueFunction,
returnFoundItem, equalityFunction) {
var currentValue;
for (var i = 0, len = arr.length; i < len; i++) {
currentValue = arr[i];
if (equalityFunction(value, arrayValueFunction(currentValue))) {
return returnFoundItem ? [i, currentValue] : true;
}
}
return false;
}
function arrayRemoveAt(arr, idx) {
if (hasMethod(arr, "splice")) {
arr.splice(idx, 1);
} else {
if (idx === arr.length - 1) {
arr.length = idx;
} else {
var itemsAfterDeleted = arr.slice(idx + 1);
arr.length = idx;
for (var i = 0, len = itemsAfterDeleted.length; i < len; i++) {
arr[idx + i] = itemsAfterDeleted[i];
}
}
}
}
function checkKeyOrValue(kv, kvStr) {
if (kv === null) {
throw new Error("null is not a valid " + kvStr);
} else if (isUndefined(kv)) {
throw new Error(kvStr + " must not be undefined");
}
}
var keyStr = "key", valueStr = "value";
function checkKey(key) {
checkKeyOrValue(key, keyStr);
}
function checkValue(value) {
checkKeyOrValue(value, valueStr);
}
/*------------------------------------------------------------------------*/
function Bucket(firstKey, firstValue, equalityFunction) {
this.entries = [];
this.addEntry(firstKey, firstValue);
if (equalityFunction !== null) {
this.getEqualityFunction = function() {
return equalityFunction;
};
}
}
function getBucketEntryKey(entry) {
return entry[0];
}
function getBucketEntryValue(entry) {
return entry[1];
}
Bucket.prototype = {
getEqualityFunction: function(searchValue) {
if (hasEquals(searchValue)) {
return equals_fixedValueHasEquals;
} else {
return equals_fixedValueNoEquals;
}
},
searchForEntry: function(key) {
return arraySearch(this.entries, key, getBucketEntryKey,
true, this.getEqualityFunction(key));
},
getEntryForKey: function(key) {
return this.searchForEntry(key)[1];
},
getEntryIndexForKey: function(key) {
return this.searchForEntry(key)[0];
},
removeEntryForKey: function(key) {
var result = this.searchForEntry(key);
if (result) {
arrayRemoveAt(this.entries, result[0]);
return true;
}
return false;
},
addEntry: function(key, value) {
this.entries[this.entries.length] = [key, value];
},
size: function() {
return this.entries.length;
},
keys: function(keys) {
var startIndex = keys.length;
for (var i = 0, len = this.entries.length; i < len; i++) {
keys[startIndex + i] = this.entries[i][0];
}
},
values: function(values) {
var startIndex = values.length;
for (var i = 0, len = this.entries.length; i < len; i++) {
values[startIndex + i] = this.entries[i][1];
}
},
containsKey: function(key) {
return arraySearch(this.entries, key, getBucketEntryKey,
false, this.getEqualityFunction(key));
},
containsValue: function(value) {
return arraySearch(this.entries, value,
getBucketEntryValue, false, equals_equivalence);
}
};
/*------------------------------------------------------------------------*/
function BucketItem() {}
BucketItem.prototype = [];
// Supporting functions for searching hashtable bucket items
function getBucketKeyFromBucketItem(bucketItem) {
return bucketItem[0];
}
function searchBucketItems(bucketItems, bucketKey, equalityFunction) {
return arraySearch(bucketItems, bucketKey,
getBucketKeyFromBucketItem, true, equalityFunction);
}
function getBucketForBucketKey(bucketItemsByBucketKey, bucketKey) {
var bucketItem = bucketItemsByBucketKey[bucketKey];
// Check that this is a genuine bucket item and not something
// inherited from prototype
if (bucketItem && (bucketItem instanceof BucketItem)) {
return bucketItem[1];
}
return null;
}
/*------------------------------------------------------------------------*/
function Hashtable(hashingFunction, equalityFunction) {
var bucketItems = [];
var bucketItemsByBucketKey = {};
hashingFunction = isFunction(hashingFunction) ? hashingFunction : keyForObject;
equalityFunction = isFunction(equalityFunction) ? equalityFunction : null;
this.put = function(key, value) {
checkKey(key);
checkValue(value);
var bucketKey = hashingFunction(key);
// Check if a bucket exists for the bucket key
var bucket = getBucketForBucketKey(bucketItemsByBucketKey, bucketKey);
if (bucket) {
// Check this bucket to see if it already contains this key
var bucketEntry = bucket.getEntryForKey(key);
if (bucketEntry) {
// This bucket entry is the current mapping of key to value, so replace
// old value and we're done.
bucketEntry[1] = value;
} else {
// The bucket does not contain an entry for this key, so add one
bucket.addEntry(key, value);
}
} else {
// No bucket, so create one and put our key/value mapping in
var bucketItem = new BucketItem();
bucketItem[0] = bucketKey;
bucketItem[1] = new Bucket(key, value, equalityFunction);
bucketItems[bucketItems.length] = bucketItem;
bucketItemsByBucketKey[bucketKey] = bucketItem;
}
};
this.get = function(key) {
checkKey(key);
var bucketKey = hashingFunction(key);
// Check if a bucket exists for the bucket key
var bucket = getBucketForBucketKey(bucketItemsByBucketKey, bucketKey);
if (bucket) {
// Check this bucket to see if it contains this key
var bucketEntry = bucket.getEntryForKey(key);
if (bucketEntry) {
// This bucket entry is the current mapping of key to value, so return
// the value.
return bucketEntry[1];
}
}
return null;
};
this.containsKey = function(key) {
checkKey(key);
var bucketKey = hashingFunction(key);
// Check if a bucket exists for the bucket key
var bucket = getBucketForBucketKey(bucketItemsByBucketKey, bucketKey);
if (bucket) {
return bucket.containsKey(key);
}
return false;
};
this.containsValue = function(value) {
checkValue(value);
for (var i = 0, len = bucketItems.length; i < len; i++) {
if (bucketItems[i][1].containsValue(value)) {
return true;
}
}
return false;
};
this.clear = function() {
bucketItems.length = 0;
bucketItemsByBucketKey = {};
};
this.isEmpty = function() {
return bucketItems.length === 0;
};
this.keys = function() {
var keys = [];
for (var i = 0, len = bucketItems.length; i < len; i++) {
bucketItems[i][1].keys(keys);
}
return keys;
};
this.toQueryString = function ()
{
var result="";
var keys = [];
var values = [];
for (var i = 0, len = bucketItems.length; i < len; i++)
{
//var re = bucketItems[i][1].values(values)
result += bucketItems[i][1].entries[0][0]+
"="+bucketItems[i][1].entries[0][1]+"&"
}
result = result.substring(0,result.length-1);
return result;
}
this.values = function() {
var values = [];
for (var i = 0, len = bucketItems.length; i < len; i++) {
bucketItems[i][1].values(values);
}
return values;
};
this.remove = function(key) {
checkKey(key);
var bucketKey = hashingFunction(key);
// Check if a bucket exists for the bucket key
var bucket = getBucketForBucketKey(bucketItemsByBucketKey, bucketKey);
if (bucket) {
// Remove entry from this bucket for this key
if (bucket.removeEntryForKey(key)) {
// Entry was removed, so check if bucket is empty
if (bucket.size() === 0) {
// Bucket is empty, so remove it
var result = searchBucketItems(bucketItems, bucketKey,
bucket.getEqualityFunction(key));
arrayRemoveAt(bucketItems, result[0]);
delete bucketItemsByBucketKey[bucketKey];
}
}
}
};
this.size = function() {
var total = 0;
for (var i = 0, len = bucketItems.length; i < len; i++) {
total += bucketItems[i][1].size();
}
return total;
};
}
return Hashtable;
})();
服务器端代码
//Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
UserData userData;
if (Cache[Context.User.Identity.Name] == null)
{
userData = new UserData();
Cache.Insert(Context.User.Identity.Name, userData,
null, Cache.NoAbsoluteExpiration,
TimeSpan.FromMinutes(Session.Timeout),
CacheItemPriority.Default, new CacheItemRemovedCallback(CacheExpired));
}
else
{
userData = Cache[Context.User.Identity.Name] as UserData;
}
FillPage(userData); //to populate web form controls with values from DTO
}
}
internal void CacheExpired(string key, object val, CacheItemRemovedReason reason)
{
if (reason != CacheItemRemovedReason.Removed)
{
//Save.aspx invokes userData.updateDB() to update data in database
HttpContext.Current.Server.Execute("Save.aspx", new StringWriter());
}
}
public void FillPage(UserData userData)
{
//Add code here..
}
AutoSave.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
UserData userData = Cache[Context.User.Identity.Name] as UserData;
for (int i = 0; i < Request.QueryString.Count; i++)
{
try
{
userData[Request.QueryString.GetKey(i)] = Request.QueryString.Get(i);
}
catch (Exception ex)
{
continue;
}
}
Cache[Context.User.Identity.Name] = userData;
}
UserData.cs
public class UserData
{
public UserData()
{
//
// TODO: Add constructor logic here
//
}
public string this[string paramName]
{// string indexer
get
{
return this.GetType().GetProperty(paramName).GetValue(this, null).ToString();
}
set
{
this.GetType().GetProperty(paramName).SetValue(this, value, null);
}
}
private string _LastName;
public string LastName
{
get { return _LastName; }
set { _LastName = value; }
}
private string _FirstName;
public string FirstName
{
get { return _FirstName; }
set { _FirstName = value; }
}
private string _Email;
public string Email
{
get { return _Email; }
set { _Email = value; }
}
public void updateDB()
{
/***here: invoke Stored Procedure to update data in database***/
HttpContext.Current.Cache.Remove(HttpContext.Current.User.Identity.Name);
}
}
限制
- 如果页面表单由 Web 表单填充软件自动填写,则此方法将不起作用。
- 在现代浏览器中,查询字符串支持仅限于 2000 个字符;如果超过此长度,则会发生数据丢失。