You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AjaxToolkit CascadingDropdown子级下拉框不加载,knownCategoryValues为空

问题描述

我使用AjaxToolkit的CascadingDropdown控件搭配三个DropDownList,数据从ASMX WebService获取。第一个下拉框可正常加载,但选择父级选项后,子级下拉框无法加载,甚至无法触发断点。在Visual Studio中测试ASMX WebService能得到预期结果,但在应用中,填充子级下拉框的Web方法未被调用,本应携带父级选中项键值对的knownCategoryValues参数为空。已尝试重装AjaxToolkit、检查引用、添加服务引用,仍未解决。

排查与解决建议
  • 补全Web服务方法的参数:CascadingDropdown要求Web方法必须包含string knownCategoryValues和string category两个参数,当前子级方法(GetEmpresaAcceso、GetPuestoAcceso)只定义了knownCategoryValues,缺少category参数,这会导致控件无法正常发起请求。修改方法签名如下:
    [WebMethod]
    public CascadingDropDownNameValue[] GetEmpresaAcceso(string knownCategoryValues, string category)
    {
        // 现有逻辑保持不变
    }
    
  • 验证[ScriptService]特性:确保ASMX类上的[ScriptService]特性未被注释或遗漏,这是AJAX能够调用Web服务的核心配置。
  • 检查路径与方法名拼写:确认CascadingDropdown的ServicePath(如~/services/WebService1.asmx)与实际文件路径一致,ServiceMethod与Web服务中的方法名大小写、拼写完全匹配。
  • 用浏览器开发者工具排查请求:按F12打开开发者工具,切换到「网络」面板,选择父级下拉框选项,观察是否有AJAX请求发出:
    • 若没有请求:说明控件的事件绑定存在问题,检查页面是否引入了正确的AjaxToolkit脚本。
    • 若有请求但报错:查看请求的状态码(如404表示路径错误,500表示服务端异常),根据响应内容定位问题。
  • 修复SQL注入风险:当前代码使用字符串拼接SQL语句,存在严重安全隐患,同时可能因参数格式问题导致数据库查询失败。改为参数化查询:
    string sql = "SELECT * FROM GetEmpresasAccesoUsuario(@CodigoUser, @Pais)";
    OleDbCommand cmd = new OleDbCommand(sql, dbCon);
    cmd.Parameters.AddWithValue("@CodigoUser", _codigoUser);
    cmd.Parameters.AddWithValue("@Pais", pais);
    
  • 优化GetData方法:将private修饰的GetData改为支持参数化查询的重载版本,提升代码安全性和可维护性。
相关代码

ASPX页面标记

<div class="card-body">
    <div class="row mb-2 d-flex flex-column">
        <div class="col">
            <div class="form-group">
                <label class="form-label">País</label>
                <asp:DropDownList ID="ddlPais" runat="server" CssClass="form-select form-select-sm" ></asp:DropDownList>
                <ajaxToolkit:CascadingDropDown ID="cdlPais" TargetControlID="ddlPais" PromptText="Seleccione País"
                    PromptValue="" ServicePath="~/services/WebService1.asmx" ServiceMethod="GetPaisAcceso"
                    runat="server" Category="CategoryPais" LoadingText="Cargando..." />
            </div>
        </div>
        <div class="col">
            <div class="form-group">
                <label class="form-label">Empresa</label>
                <asp:DropDownList ID="ddlEmpresa" runat="server" CssClass="form-select form-select-sm" ></asp:DropDownList>
                <ajaxToolkit:CascadingDropDown ID="cdlEmpresa" TargetControlID="ddlEmpresa" PromptText="Seleccione Empresa" PromptValue="" ServicePath="~/services/WebService1.asmx"
                    ServiceMethod="GetEmpresaAcceso" runat="server" ParentControlID="ddlPais" Category="CategoryEmpresa" LoadingText="Cargando..." />
            </div>
        </div>
        <div class="col">
            <div class="form-group">
                <label class="form-label">Puesto</label>
                <asp:DropDownList ID="ddlPuesto" runat="server" CssClass="form-select form-select-sm"></asp:DropDownList>
                <ajaxToolkit:CascadingDropDown ID="cdlPuesto" TargetControlID="ddlPuesto" PromptText="Seleccione Puesto" PromptValue="" ServicePath="~/services/WebService1.asmx" ServiceMethod="GetPuestoAcceso" ParentControlID="ddlEmpresa" runat="server" Category="CategoryPuesto" LoadingText="Cargando..."  />
            </div>
        </div>
        <div class="col">
            <hr />
            <asp:Button ID="btnGuardar" runat="server" CssClass="btn btn-success" OnClick="btnGuardar_OnClick" Text="Guardar Cambios" />
        </div>
    </div>
</div>

修正后的ASMX WebService代码

using AjaxControlToolkit;
using FACTURACION_CLASS;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;

namespace WebAppVB.services
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ScriptService]
    public class WebService1 : WebService
    {
        private readonly seguridad _seguridad = new seguridad();
        private readonly database _database = new database();

        private string _codigoUser = HttpContext.Current.Request.Cookies["CodigoUser"]?.Value;

        [WebMethod]
        public CascadingDropDownNameValue[] GetPaisAcceso(string knownCategoryValues, string category)
        {
            string sql = "SELECT * FROM GetPaisesAccesoUsuario(@CodigoUser)";
            List<CascadingDropDownNameValue> paises = GetData(sql, new OleDbParameter("@CodigoUser", _codigoUser));
            return paises.ToArray();
        }

        [WebMethod]
        public CascadingDropDownNameValue[] GetEmpresaAcceso(string knownCategoryValues, string category)
        {
            string pais = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues)["CategoryPais"];
            string sql = "SELECT * FROM GetEmpresasAccesoUsuario(@CodigoUser, @Pais)";
            
            List<CascadingDropDownNameValue> empresas = GetData(sql, 
                new OleDbParameter("@CodigoUser", _codigoUser),
                new OleDbParameter("@Pais", pais));
            return empresas.ToArray();
        }

        [WebMethod]
        public CascadingDropDownNameValue[] GetPuestoAcceso(string knownCategoryValues, string category)
        {
            string empresa = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues)["CategoryEmpresa"];
            string sql = "SELECT * FROM GetPuestosAccesoUsuario(@CodigoUser, @Empresa)";
            
            List<CascadingDropDownNameValue> puestos = GetData(sql,
                new OleDbParameter("@CodigoUser", _codigoUser),
                new OleDbParameter("@Empresa", empresa));
            return puestos.ToArray();
        }

        private List<CascadingDropDownNameValue> GetData(string sql, params OleDbParameter[] parameters)
        {
            List<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();

            using (OleDbConnection dbCon = new OleDbConnection(_seguridad.conn))
            {
                dbCon.Open();

                OleDbCommand cmd = new OleDbCommand(sql, dbCon);
                cmd.Parameters.AddRange(parameters);
                
                using (OleDbDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        values.Add(new CascadingDropDownNameValue
                        {
                            name = reader[1].ToString(),
                            value = reader[0].ToString()
                        });
                    }

                    return values;
                }
            }
        }
     }
}

内容的提问来源于stack exchange,提问作者Gabriel Z

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 18:55:24