无控制器源码时实现ASP.NET表单提交后跳转Shop页面的方法
无控制器部分访问权限,网站已完成编译,不持有源代码,仅能拿到编译后的.dll文件。
当前Razor视图中的表单代码如下:
@using (Html.BeginForm("Details", "Shop", FormMethod.Post, new { role = "form"})) { <p>Select Character:</p> if (Model.Chars != null && Model.Chars.Count > 0) { @Html.AntiForgeryToken() @Html.ValidationSummary("", new {@class = "text-danger"}) if (Request.IsAuthenticated) { @Html.HiddenFor(x => Model.Guid, Model.Guid) for (var index = 0; index < Model.Chars.Count; index++) { var charInfo = Model.Chars[index]; var chdata = charInfo.Name + " (lv." + charInfo.Level + ")"; if (index == 0) { <div> @Html.RadioButtonFor((x) => Model.CharName, charInfo.Name, new {Checked = "checked"}) @chdata </div> } else { <div> @Html.RadioButtonFor((x) => Model.CharName, charInfo.Name) @chdata </div> } } } <p/> <input type="submit" class="position: center !important" value="Confirm Purchase"/> } else if (Model.Chars == null) { <h4 class="nk-title h4" style="color: red">To purchase items, you must first log in to your account</h4> } else { <h4 class="nk-title h4" style="color: red">You cannot buy items, you don't have any characters in your account</h4> } }
按照_Layout.cshtml中的预设逻辑,正常情况下收到BuyOk通知时应当跳转至Shop页面,但实际并未生效,_Layout.cshtml中的通知处理代码如下:
@{ var messages = ViewBag.Errors as List<ViewError>; var notifications = ViewBag.Notifications as List<ViewNotification>; } @if (notifications != null && notifications.Count > 0) { <div class="alert" style="background: #00ff00"> @foreach (var message in notifications) { <span class="closebtn" onclick="this.parentElement.style.display='none';">×</span> string msg; switch (message) { case ViewNotification.BuyOk: msg = "Purchase complete"; break; case ViewNotification.ChangePwdOk: msg = "Password change request successful, description sent to your email"; break; case ViewNotification.ChangePwdSuccess: msg = "Password Changed"; break; case ViewNotification.ChangeEmailSuccess: msg = "Email has been changed"; break; default: msg = "Unknown notification"; break; } @msg } </div> }
点击Confirm Purchase提交表单后无报错,购买操作可正常完成,但case ViewNotification.BuyOk:分支未被触发,提交后不会自动跳转至Shop页面。
需要实现点击「Confirm Purchase」按钮提交表单后跳转至Shop页面的效果,但仅持有编译后的项目文件,多款反编译工具尝试均未成功,无法查看、修改真实的控制器代码,需要可直接落地的解决方案。
所有方案均无需修改后端代码、无需反编译dll,仅需编辑可直接访问的.cshtml视图文件即可生效,上传覆盖对应视图文件后不影响现有编译程序运行。
方案1:提交按钮加延迟跳转(改动最小)
由于购买逻辑本身可正常执行,无需等待后端返回
BuyOk通知,直接给提交按钮绑定延迟跳转逻辑即可。将原有提交按钮代码:<input type="submit" class="position: center !important" value="Confirm Purchase"/>替换为:
<input type="submit" class="position: center !important" value="Confirm Purchase" onclick="setTimeout(() => { window.location.href = '/Shop'; }, 1000);"/>点击按钮时会先正常触发表单POST请求完成购买,延迟1秒等待请求发送完成后自动跳转Shop页面。可根据服务器响应速度调整延迟时长,常规场景设置500ms-1500ms即可。
方案2:检测成功提示后跳转(容错最高)
如果担心购买失败时误跳转,可以沿用原有Layout的提示逻辑,在视图底部加JS判断,只有页面出现购买成功提示时才触发跳转:
<script> document.addEventListener('DOMContentLoaded', function() { const successTip = document.querySelector('.alert[style*="background: #00ff00"]'); if (successTip && successTip.textContent.includes('Purchase complete')) { // 停留1.5秒让用户看到成功提示,再执行跳转 setTimeout(() => { window.location.href = '/Shop'; }, 1500); } }); </script>该方案完全匹配原有业务逻辑,即便后续后端修复了
BuyOk通知的问题,代码也不会产生异常冲突。方案3:监听表单提交完成事件(稳定性最好)
如果担心固定延迟受网络波动影响,可以通过隐藏iframe监听表单提交完成状态,等请求真正处理结束后再跳转:
首先修改表单开头的BeginForm配置,加target属性指向隐藏iframe:@using (Html.BeginForm("Details", "Shop", FormMethod.Post, new { role = "form", target = "submit-hidden-frame"}))在表单下方添加隐藏iframe和监听代码:
<iframe name="submit-hidden-frame" style="display: none;"></iframe> <script> document.querySelector('iframe[name="submit-hidden-frame"]').addEventListener('load', () => { window.location.href = '/Shop'; }); </script>该方案无需预估请求耗时,POST请求处理完成、浏览器接收到返回内容后才会触发跳转,不会出现请求未发完就跳转的问题。
内容的提问来源于stack exchange,提问作者Invictus

