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

如何在Razor页面(CSHTML)的JS函数中调用C#的UpdateRecursiveData方法

问题1解答:JS函数内无法直接调用服务端定义的C#函数

Razor页面的C#代码执行时机是服务端渲染阶段,也就是页面还没发送到用户浏览器的时候就已经执行完毕。你写在JS函数内的@UpdateRecursiveData(tn)会在页面渲染时直接执行,而此时tn是仅存在于浏览器端的JS变量,服务端完全无法识别,自然会报错。等JS在浏览器端运行时,所有C#代码已经执行完成,不存在可以调用的服务端C#方法。

问题2解答:实现需求的具体方案

你的核心需求是在勾选复选框后,动态渲染对应节点的子节点,推荐将原来服务端的UpdateRecursiveData逻辑改写为JS函数,接口请求成功后拿到子节点数据,直接用JS渲染DOM,性能更高逻辑也更清晰。
具体修改代码如下:

  1. 首先修改后端OnPostMyAction接口,返回新增的子节点JSON数据:
public async Task<IActionResult> OnPostMyAction(string itemName,bool deploy)
{
    if (TempData["TreeData"] != null)
        tree_List = TempData.Get<List<TreeNode>>("TreeData");
    TreeNode upTree=null; 
    foreach (var item in tree_List)
    {
        if (item.board_id == itemName)
        {
            upTree = item;
            item.deployment = deploy;
        }
    }
    List<TreeNode> newNodes = new List<TreeNode>();
    if (deploy&&upTree.loadOn==false)
    {
        if(upTree!=null)
        upTree.deployment = true;
        IQueryable<tbl_tree> iqueryTree;
        iqueryTree = _context.tbl_tree.Where(x => x.upcode == itemName);
        var datas =await iqueryTree.ToListAsync();
        for (int i = 0; i < datas.Count; i++)
        {
            TreeNode treeNode = new TreeNode(datas[i].name);
            treeNode.board_id = datas[i].icd11;
            tree_List.Add(treeNode);
            newNodes.Add(treeNode);
        }
        TempData.Set("TreeData", tree_List);
    }
    // 返回新增的子节点数据
    return new JsonResult(newNodes);
}
  1. 改写前端代码,新增JS版递归渲染函数,删除原来无效的@UpdateRecursiveData(tn)调用:
// 新增JS版递归渲染函数,代替原来的服务端C#函数
function renderRecursiveData(parentLoaderId, nodeList) {
    const parentEl = document.getElementById(parentLoaderId).parentNode;
    nodeList.forEach(tn => {
        // 渲染复选框
        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.onclick = () => requestMyAction(tn.board_id, checkbox.checked, `loader-${tn.dataName}`);
        parentEl.appendChild(checkbox);
        // 渲染loader元素
        const loader = document.createElement('div');
        loader.className = 'loader';
        loader.style.display = 'none';
        loader.id = `loader-${tn.dataName}`;
        loader.innerText = tn.dataName;
        parentEl.appendChild(loader);
        // 插入换行
        parentEl.appendChild(document.createElement('br'));
        // 递归渲染子节点
        if(tn.subTreeNodes && tn.subTreeNodes.length > 0) {
            renderRecursiveData(loader.id, tn.subTreeNodes);
        }
    })
}

function requestMyAction(itemId, isChecked, loaderId)
{
    document.getElementById(loaderId).style.display = "inline-block";
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (this.readyState === 4) {
            document.getElementById(loaderId).style.display = "none";
            if (this.status === 200) {
                // 接口请求成功后调用渲染函数
                const newNodes = JSON.parse(this.responseText);
                renderRecursiveData(loaderId, newNodes);
            }
        }
    };
    var url = '@Url.Page("./TreeExample", "MyAction")';
    xhr.open('POST', url);
    xhr.setRequestHeader('RequestVerificationToken', '@Xsrf.GetAndStoreTokens(Model.HttpContext).RequestToken');
    var data = new FormData();
    data.append('itemName', itemId);
    data.append('deploy', isChecked);
    xhr.send(data);
}

问题3解答:可以让渲染逻辑晚于接口请求完成

上面的代码已经实现了该需求,只需要把渲染操作放到XHR的readyState === 4且status === 200的回调函数中即可,此时接口已经完成请求,返回数据也已经拿到,完全符合执行时机要求。


内容的提问来源于stack exchange,提问作者로다현

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:57:01