重定向到区域而不更改URL和TempData

时间:2018-01-20 13:02:42

标签: c# asp.net asp.net-mvc asp.net-mvc-5 tempdata

在我的项目中,我必须从一个控制器重定向到另一个控制器,该控制器位于名为SIP的区域内。如果使用以下方法,重定向将成功运行,并且TempData值也将传递给另一个控制器:

TempData["sipModel"] = 1;
return RedirectToAction("Index", "Home", new { area = "SIP" });

但是在这种情况下,URL会被更改,而我的要求是保持相同的URL,以实现我通过其他答案并使用提到的方法TransferToAction()

in this answer 这非常有效,我可以使用以下代码重定向到其他区域而无需更改URL:

TempData["sipModel"] = 1;
return this.TransferToAction("Index", "Home", new { area = "SIP"});

但是,在这种情况下,TempData值不会保留,并且在尝试读取时会得到Null Reference Exception。

我尝试使用其他答案中提到的以下代码:

public static TransferToRouteResult TransferToAction(this System.Web.Mvc.Controller controller, string actionName, string controllerName, object routeValues)
        {
            controller.TempData.Keep();
            controller.TempData.Save(controller.ControllerContext, controller.TempDataProvider);
            return new TransferToRouteResult(controller.Request.RequestContext, actionName, controllerName, routeValues);
        }

但这并没有成功。有人可以建议我如何解决这个或任何其他更好的方法来实现这个结果。感谢。

编辑:

网址如下:

  

https://myproject/Home/Index?cid=ABC-1234&pid=xyz123456abc

我在一个类中有一个复杂的数据,它也需要从一个控制器传递到另一个控制器(存在于区域SIP中),因为我一直在使用TempData,我已经这里使用整数作为样本。

在第一种控制器方法中,我是if-else条件,所以:

if (companyCode = 'X')
 return View();
else
 TempData["sipModel"] = 1;
 return RedirectToAction("Index", "Home", new { area = "SIP" }); OR (this.TransferToAction("Index", "Home", new { area = "SIP"});)

1 个答案:

答案 0 :(得分:1)

Server.TransferRequest 在MVC中完全没必要。这是一个过时的功能,只有在ASP.NET中才需要,因为请求直接来到页面,需要有一种方法将请求传输到另一个页面。现代版本的ASP.NET(包括MVC)具有路由基础结构,可以自定义以直接路由到所需的资源。当您只需将请求直接发送到控制器并执行您想要的操作时,没有必要让请求到达控制器只将其传输到另一个控制器。

因此,鉴于您的示例不是一整套要求,我将做出以下假设。根据您的要求调整这些。

  1. 如果没有传递给主页的查询字符串参数,它将保留在主页上。
  2. 如果主页上有查询参数cidpid,我们会将请求发送到Index的{​​{1}}操作区域。
  3. 我们将在后一种情况下传递值为HomeController的元数据参数SID,并在第一种情况下省略参数。
  4. 首先,我们将"sipModel"子类化并将我们的自定义逻辑放在那里。更完整的场景可能具有通过构造函数传递的依赖服务和选项,甚至还有自己的1扩展方法将它们连接在一起。

    RouteBase

    要将其连接到MVC,我们只需编辑MapRoute,如下所示:

    public class CustomHomePageRoute : RouteBase
    {
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            RouteData result = null;
    
            // Only handle the home page route
            if (httpContext.Request.Path == "/")
            {
                var cid = httpContext.Request.QueryString["cid"];
                var pid = httpContext.Request.QueryString["pid"];
    
                result = new RouteData(this, new MvcRouteHandler());
    
                if (string.IsNullOrEmpty(cid) && string.IsNullOrEmpty(pid))
                {
                    // Go to the HomeController.Index action of the non-area
                    result.Values["controller"] = "Home";
                    result.Values["action"] = "Index";
    
                    // NOTE: Since the controller names are ambiguous between the non-area
                    // and area route, this extra namespace info is required to disambiguate them.
                    // This is not necessary if the controller names differ.
                    result.DataTokens["Namespaces"] = new string[] { "WebApplication23.Controllers" };
                }
                else
                {
                    // Go to the HomeController.Index action of the SID area
                    result.Values["controller"] = "Home";
                    result.Values["action"] = "Index";
    
                    // This tells MVC to change areas to SID
                    result.DataTokens["area"] = "SID";
    
                    // Set additional data for sipModel.
                    // This can be read from the HomeController.Index action by 
                    // adding a parameter "int sipModel".
                    result.Values["sipModel"] = 1;
    
                    // NOTE: Since the controller names are ambiguous between the non-area
                    // and area route, this extra namespace info is required to disambiguate them.
                    // This is not necessary if the controller names differ.
                    result.DataTokens["Namespaces"] = new string[] { "WebApplication23.Areas.SID.Controllers" };
                }
            }
    
            // If this isn't the home page route, this should return null
            // which instructs routing to try the next route in the route table.
            return result;
        }
    
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            var controller = Convert.ToString(values["controller"]);
            var action = Convert.ToString(values["action"]);
    
            if (controller.Equals("Home", StringComparison.OrdinalIgnoreCase) &&
                action.Equals("Index", StringComparison.OrdinalIgnoreCase))
            {
                // Route to the Home page URL
                return new VirtualPathData(this, "");
            }
    
            return null;
        }
    }
    

    这会将额外的路由值RouteConfig传递给public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // Add the custom route to the static routing collection routes.Add(new CustomHomePageRoute()); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, namespaces: new string[] { "WebApplication23.Controllers" } ); } } 区域的sipModel方法。因此,我们需要调整方法签名以接受该参数。

    PID

    正如您所看到的,也没有理由使用HomeController.Indexnamespace WebApplication23.Areas.SID.Controllers { public class HomeController : Controller { // GET: SID/Home public ActionResult Index(int sipModel) { return View(); } } } 默认依赖会话状态。它有它的用途,但你应该总是think twice about using session state在MVC中,因为它通常可以完全避免。