【问题标题】:ScriptManager using AJAX gets data from WebService asynchronously and throws an error?ScriptManager 使用 AJAX 从 Web Service 异步获取数据并抛出错误?
【发布时间】:2014-07-01 23:19:15
【问题描述】:

我在 ASP.NET 中有一个网站,我正在使用 ScriptManager 通过 AJAX 从 WebService 获取数据。

加载 default.aspx 页面时,会触发 onload 事件并从我的 Javascript 调用 getCategoryDataSet() 函数。 javascript中的getCategoryDataSet()函数只是调用webservice中的方法来获取数据。

问题:

当 getCategoryDataSet() 被调用时,这是我得到的错误消息:

“JavaScript 运行时错误:无法获取未定义或空引用的属性‘0’”

当 getCategoryDataSet() 函数被触发时,似乎函数在接收到来自 Web 服务的数据之前就结束了。我这样说是因为我在访问 web 服务的数据之前添加了一个 alert() 函数,而且似乎我在警报框上按下 ok 的时间足以从 web 服务调用中检索数据。

如何在不使用提醒按钮为通话留出更多时间的情况下解决此问题?还是其他问题?

以下照片显示了使用警报框的代码:

这是我的解决方案资源管理器:

我的 default.aspx 代码:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="category_selection_02._default" %>

<!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 type="text/javascript" src="script/JScript_01_GetCategories.js"></script>
</head>
<body onload="getCategoryDataSet()">
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
            <asp:ServiceReference Path="~/WebService_GetCategories.asmx" />
        </Services>
    </asp:ScriptManager>
    <div>
    </div>
    <div id="divListBoxes">
        THIS DIV WILL BE POPULATED WITH LISTBOXES
    </div>
    </form>
</body>
</html>

我的 WebService_GetCategories.asmx.cs 代码:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
[System.Web.Script.Services.ScriptService]
public class WebService_GetCategories : System.Web.Services.WebService
{

    [WebMethod]
    public List<Category> GetCategoriesWebService(int index_left)
    {
        //Debug.WriteLine("in WEBMETHOD");
        List<Category> listCategory = new List<Category>();
        DataSet ds = (new DataBase_DataSet_Generator(index_left)).getDataSet();
        DataTable dt = new DataTable();


        dt = ds.Tables[0];

        foreach (DataRow dr in dt.Rows)
        {
            Category categoryFields = new Category();
            categoryFields.category_id = (int)dr["category_id"];
            categoryFields.index_left = (int)dr["index_left"];
            categoryFields.index_right = (int)dr["index_right"];
            categoryFields.categoryName = (dr["categoryName"]).ToString();
            //categoryFields.categoryInfo= (dr["categoryInfo"]).ToString();

            listCategory.Add(categoryFields);

            //Debug.WriteLine("This is the total items in the listCategory: "+ listCategory.Count);
        }


        return listCategory;
    }
}

我的 JScript_01_GetCategories.js 代码:

var public_categoryDataSet; //this is the category dataset retreived from the webservice


function getCategoryDataSet() {
    var index_left = 1;

    category_selection_02.WebService_GetCategories.GetCategoriesWebService(index_left, GetCategoryIdSuccessCallBack, GetCategoryIdFailedCallBack)

    function GetCategoryIdSuccessCallBack(results_from_webservice) {
        public_categoryDataSet = results_from_webservice;
    }

    function GetCategoryIdFailedCallBack(errors) {
        alert("AJAX Failed callback invalid data inserted in textbox");
    }
    alert("Alert Fired");  //<--if this alert() call is removed I get an error???
    alert(public_categoryDataSet[0].category_id);
}

【问题讨论】:

    标签: javascript jquery asp.net ajax web-services


    【解决方案1】:

    正在发生的事情是您的函数getCategoryDataSet() 正在执行,并且它正在逐步执行代码程序。换句话说:

    1. 设置var index_left = 1
    2. 调用 AJAX 调用,将两个回调绑定为返回参数
    3. (火灾警报)
    4. alertcategory_id

    所以本质上,一旦到达第 2 步,它就会调用对 Web 服务的调用然后继续执行,因此它到达第 4 步并执行 之前Web 服务已返回数据,返回空引用异常。将您的虚拟警报放在中间(第 3 步)使其有足够的时间在您访问之前完成加载 Web 服务数据。

    解决方案

    您编写的任何从 AJAX 调用访问结果变量的代码都必须放在成功处理程序中。这有两个原因:

    1. 首先,在访问结果变量之前,您需要确保 AJAX 调用已完成;因此将其放在成功处理程序中可以确保这一点。
    2. 其次,如果您的 Web 服务方法失败并且不返回任何变量,会发生什么情况?当您访问它们时会发生什么?大问题!

    这就是 SuccessError 回调的用武之地——它们应该分别包含应该在每个场景下执行的代码。

    一些代码:

    function getCategoryDataSet() {
        var index_left = 1;
    
        category_selection_02.WebService_GetCategories.GetCategoriesWebService(
            index_left, 
            GetCategoryIdSuccessCallBack, 
            GetCategoryIdFailedCallBack);
    
        function GetCategoryIdSuccessCallBack(results_from_webservice) {
            public_categoryDataSet = results_from_webservice;
            //process public_categoryDataSet here
            alert(public_categoryDataSet[0].category_id);
        }
    
        function GetCategoryIdFailedCallBack(errors) {
            alert("AJAX Failed callback invalid data inserted in textbox");
        }
    
        alert("Alert Fired");  
        //don't process anything here as it will execute before the AJAX call completes
    }
    

    【讨论】:

    • 所以来自 results_from_webservice 的数据在 public_categoryDataSet 中被“处理”或被一般处理的事实会阻止我的代码进入下一步?
    • 不确定你的确切意思 - public_categoryDataSet 变量在 GetCategoryIdSuccessCallback 函数内初始化,但在回调执行之前被访问,因此变量为空。
    • 有没有办法检查回调是否完成?
    • 并非如此 - 您只是想在回调中放置调用完成后要执行的任何代码,这样您就可以确保 ajax 调用已完成。如果您所有的后续代码都在回调中,则无需检查,因为它会运行。
    猜你喜欢
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 2023-03-15
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    相关资源
    最近更新 更多