C#返回JsonResult场景下如何通过ActionFilter注入执行Javascript
方案1:将脚本注入Json返回值,前端触发执行(适配绝大多数场景,无兼容问题)
这个方案不需要修改原有Controller的业务逻辑,只需要调整ActionFilter和前端Ajax回调即可实现需求。
调整ActionFilter代码
在OnActionExecuted方法中直接扩展原有JsonResult的返回结构,追加script字段:
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public class InsertJavascriptAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { var jsonResult = filterContext.Result as JsonResult; if (jsonResult == null) { return; } var script = GenerateMyJavascript(); // 扩展原有Json返回结构,追加script字段 // 如果用Newtonsoft.Json,直接转JObject追加字段即可 var jsonObj = Newtonsoft.Json.Linq.JObject.FromObject(jsonResult.Data); jsonObj.Add("script", script); jsonResult.Data = jsonObj; } }
前端添加脚本执行逻辑
你已经在Ajax.BeginForm中绑定了OnSuccess回调,直接在对应的JS方法中添加脚本执行逻辑即可:
// 你绑定的OnSuccessId对应的JS函数 function yourOnSuccessHandler(response, status, xhr) { // 原有业务逻辑,比如渲染partial html、处理错误字段等 // ... // 新增:判断返回值是否带脚本,有就执行 if (response.script) { // 方式1:直接eval执行(适合脚本逻辑和当前上下文关联的场景) // eval(response.script); // 方式2:创建script标签插入DOM执行(更稳妥,避免上下文冲突) const scriptEl = document.createElement('script'); scriptEl.textContent = response.script; document.body.appendChild(scriptEl); } }
如果不想每个Ajax请求都单独加逻辑,可以注册全局Ajax成功事件统一处理所有带script字段的返回:
$(document).ajaxSuccess(function(event, xhr, settings, response) { if (response?.script) { const scriptEl = document.createElement('script'); scriptEl.textContent = response.script; document.body.appendChild(scriptEl); } });
方案2:脚本放入响应头传递(适合短脚本场景)
如果不想修改原有Json返回结构,且待插入的脚本长度很短,可以把脚本编码后放到自定义响应头中传递:
ActionFilter代码
public override void OnActionExecuted(ActionExecutedContext filterContext) { var jsonResult = filterContext.Result as JsonResult; if (jsonResult == null) { return; } var script = GenerateMyJavascript(); // 编码后放入自定义响应头,避免特殊字符报错 filterContext.HttpContext.Response.Headers.Add("X-Custom-Run-Script", Uri.EscapeDataString(script)); }
前端执行逻辑
function yourOnSuccessHandler(response, status, xhr) { // 原有业务逻辑 // ... // 取响应头中的脚本 const rawScript = xhr.getResponseHeader("X-Custom-Run-Script"); if (rawScript) { const script = decodeURIComponent(rawScript); // 执行脚本逻辑和方案1一致 const scriptEl = document.createElement('script'); scriptEl.textContent = script; document.body.appendChild(scriptEl); } }
注意:该方案受浏览器响应头长度限制,仅适合长度小于1KB的短脚本使用。
内容的提问来源于stack exchange,提问作者M. Chris
相关产品推荐
相关产品推荐

