.NET Framework 4.6.1中Post方法失败后重定向至另一个Post方法的问题
解决Post方法重定向到区域Post方法的问题
在.NET Framework 4.6.1里,RedirectToAction默认返回302重定向,浏览器会自动把原Post请求改成Get请求,而你的目标方法是Post,所以会出现NotFound错误。下面是几个可行的解决办法:
方法1:返回307临时重定向(保留请求方法)
HTTP 307状态码会告诉浏览器保留原请求方法访问新地址,这样就能带着Post请求跳转到目标方法。你可以自定义重定向结果,或者手动设置响应头:
自定义重定向结果类
public class RedirectToActionPreserveMethodResult : ActionResult { public string ActionName { get; set; } public string ControllerName { get; set; } public RouteValueDictionary RouteValues { get; set; } public RedirectToActionPreserveMethodResult(string actionName, string controllerName, RouteValueDictionary routeValues) { ActionName = actionName; ControllerName = controllerName; RouteValues = routeValues; } public override void ExecuteResult(ControllerContext context) { var urlHelper = new UrlHelper(context.RequestContext); var url = urlHelper.Action(ActionName, ControllerName, RouteValues); context.HttpContext.Response.StatusCode = 307; context.HttpContext.Response.RedirectLocation = url; } }
在你的Post方法A()中使用
[HttpPost] [Route("{customerName}/Home/A")] public ActionResult A(string customerName, string id) { try { // 你的业务逻辑,执行失败则进入catch return View(); } catch (Exception) { // 重定向到FirstCustomer区域的Home/A Post方法 return new RedirectToActionPreserveMethodResult("A", "Home", new { area = "FirstCustomer", id = id }); } }
注意:307重定向会让浏览器重复提交原请求的表单数据,要避免用户重复提交产生副作用(比如重复下单),同时部分旧浏览器对307支持有限,需要测试兼容性。
方法2:前端自动提交表单(更稳妥)
如果担心307的兼容性问题,可以返回一个临时视图,通过隐藏表单自动提交到目标地址:
在你的Post方法A()中返回临时视图
[HttpPost] [Route("{customerName}/Home/A")] public ActionResult A(string customerName, string id) { try { // 业务逻辑 return View(); } catch (Exception) { // 传递需要的参数 TempData["Id"] = id; return View("RedirectToCustomerPost"); } }
创建RedirectToCustomerPost视图
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Redirecting...</title> <script> window.onload = function() { document.getElementById("redirectForm").submit(); }; </script> </head> <body> <form id="redirectForm" action="@Url.Action("A", "Home", new { area = "FirstCustomer" })" method="post"> @Html.Hidden("id", TempData["Id"]) <!-- 其他需要传递的隐藏字段 --> <p>Redirecting, please wait...</p> </form> </body> </html>
这个方法兼容性拉满,所有浏览器都支持,还能清晰控制传递的参数,可按需添加防重复提交逻辑。
方法3:直接调用目标方法的逻辑(服务器内部处理)
如果不需要浏览器跳转,只是想复用目标方法的业务逻辑,可以直接实例化区域的HomeController并调用其方法:
[HttpPost] [Route("{customerName}/Home/A")] public ActionResult A(string customerName, string id) { try { // 业务逻辑 return View(); } catch (Exception) { // 实例化FirstCustomer区域的HomeController var targetController = new FirstCustomer.Controllers.HomeController(); // 复制当前请求上下文到目标控制器 targetController.ControllerContext = new ControllerContext(this.ControllerContext.RequestContext, targetController); // 调用目标方法并传递参数 return targetController.A(id); } }
注意:这种方式是服务器内部转发,不会改变浏览器地址栏,要确保目标控制器的依赖注入(如果有)能正常工作,避免空引用问题。
内容的提问来源于stack exchange,提问作者Linesh Lanjewar
相关产品推荐
相关产品推荐

