我们最近将代码库从 .Net 4.0 升级到了 .Net 4.5.1,从 MVC 2.0 升级到了 MVC 5.2.2。
我们的基本控制器类中有一个自定义方法,它允许我们在单个请求中更新视图的多个部分。自升级以来,这不再有效。
原始代码:
protected void IncludeAction(string actionName, string controllerName, object routeValues)
{
//Get Url
RouteValueDictionary routes = null;
if (routeValues != null)
routes = new RouteValueDictionary(routeValues);
else
routes = new RouteValueDictionary();
routes.Add("Action", actionName);
if (!string.IsNullOrEmpty(controllerName))
routes.Add("Controller", controllerName);
else
routes.Add("Controller", this.ControllerContext.RouteData.Values["Controller"].ToString());
var url = RouteTable.Routes.GetVirtualPath(this.ControllerContext.RequestContext, routes).VirtualPath;
//Rewrite path
System.Web.HttpContext.Current.RewritePath(url, false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(System.Web.HttpContext.Current);
}
httpHandler.ProcessRequest
我们在通话中收到错误。我们在很多地方都使用了这种技术。经过大量谷歌搜索后,我们似乎应该使用它Server.TransferRequest
。
新代码
protected void IncludeAction(string actionName, string controllerName, object routeValues)
{
//Get Url
RouteValueDictionary routes = null;
if (routeValues != null)
routes = new RouteValueDictionary(routeValues);
else
routes = new RouteValueDictionary();
routes.Add("Action", actionName);
if (!string.IsNullOrEmpty(controllerName))
routes.Add("Controller", controllerName);
else
routes.Add("Controller", this.ControllerContext.RouteData.Values["Controller"].ToString());
var url = RouteTable.Routes.GetVirtualPath(this.ControllerContext.RequestContext, routes).VirtualPath;
//Rewrite path
System.Web.HttpContext.Current.RewritePath(url, false);
System.Web.HttpContext.Current.Server.TransferRequest(url, true);
}
从这样的代码调用时:
IncludeAction("OptInBanner", "Person");
IncludeAction("NavMenu", "Person");
return Transfer(returnurl);
我们的新代码会产生这个错误:
Type:
System.InvalidOperationException
Message:
TransferRequest cannot be invoked more than once.
Stack Trace:
at System.Web.HttpServerUtility.TransferRequest(String path, Boolean preserveForm)
at MyProject.MyNamspace.MyBaseController.IncludeAction(String actionName, String controllerName, Object routeValues)
at MyProject.MyNamspace.MyBaseController.IncludeAction(String actionName, String controllerName)
at MyProject.MyNamspace.MyController.MyAction(Boolean myChoice, String returnurl)
at .lambda_method(Closure , ControllerBase , Object[] )
由于消息明确表示我不能多次调用 TransferRequest,但我的代码除了重定向和执行第三个操作之外还需要执行两个控制器操作,我想我会恢复到旧代码。但是,这会产生此错误:
Type:
System.InvalidOperationException
Message:
'HttpContext.SetSessionStateBehavior' can only be invoked before 'HttpApplication.AcquireRequestState' event is raised.
Stack Trace:
at System.Web.Routing.UrlRoutingHandler.ProcessRequest(HttpContextBase httpContext)
at MyProject.MyNamspace.MyBaseController.IncludeAction(String actionName, String controllerName, Object routeValues)
at MyProject.MyNamspace.MyBaseController.IncludeAction(String actionName, String controllerName)
at MyProject.MyNamspace.MyController.MyAction(Boolean myChoice, String returnurl)
at .lambda_method(Closure , ControllerBase , Object[] )
对于此功能,我如何在使用较新的框架和 MVC 时保留我们在 .Net 4.0 和 MVC 2.0 下的原始行为,而不会出现错误?