65.9K
CodeProject 正在变化。 阅读更多。
Home

自动提交表单数据

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (6投票s)

2009年5月17日

CPOL

1分钟阅读

viewsIcon

40578

使用 ASP.NET 和 JavaScript 自动提交表单数据。

引言

在本文中,我将解释如何在填写表单时自动保存用户输入的数据。此功能类似于 ASP.NET 分析。这对于大型 Web 表单以及用户在保存表单之前关闭浏览器时非常有用。在这里,我还使用 ASP.NET 缓存来检索经过身份验证的用户的数据。

概述

JavaScript 用于在客户端绑定事件,收集用户输入数据,并填充一个哈希表。在给定的时间段内,哈希表被序列化并通过 XmlHttp 对象作为查询字符串发送到 ASPX 页面。AutoSave.aspx 使用查询字符串值填充内存对象,并在会话超时时,将值保存到数据库。

使用代码

  1. 将所有输入控件的 OnBlur 事件绑定起来,以便在用户输入时填充哈希表。
  2. 将所有用户输入数据提交到服务器端。
  3. 在用户关闭浏览器之前,将所有数据提交到服务器端。
//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);
    }

}

限制

  1. 如果页面表单由 Web 表单填充软件自动填写,则此方法将不起作用。
  2. 在现代浏览器中,查询字符串支持仅限于 2000 个字符;如果超过此长度,则会发生数据丢失。

参考文献

© . All rights reserved.