Мы недавно обновили нашу базу кода от .Net 4.0 до .Net 4.5.1 и от MVC 2.0 до MVC 5.2.2.Выполнение нескольких действий контроллера при одном вызове с MVC.Net 5
У нас есть собственный метод в нашем базовом классе контроллера, который позволил нам обновить несколько частей наших представлений в рамках одного запроса. Начиная с обновления, это больше не работает.
Оригинальный код:
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[])
Для этой функции, как я могу сохранить первоначальное поведение, без ошибок, что у нас было под .Net 4.0 и 2.0 MVC, используя более новую структуру и MVC?
Трудно сказать, не видя остальную часть базы кода, но моя реакция на кишок заключается в том, что вы добавляете слишком много бизнес-логики в свои контроллеры, если вы отправляете людей на несколько действий контроллера. – Paul
@Paul Некоторые из нашего кода довольно сложны и, вероятно, слишком много продолжаются. В этом случае, однако, мы хотим обновить некоторые общие частичные представления, включая их внутреннюю обработку, а также выполнить действие конечного контроллера. Вышеприведенный код является частью страницы соглашения об Условиях обслуживания на нашем сайте и должен возвращать людей к различным действиям контроллера в зависимости от того, с чего они начались. Дополнительные частичные представления всегда должны обновляться при выходе из страницы TOS, но редко в результате конечных действий. – Zarepheth
Этот код дает мне завещания - * особенно * любое упоминание о Server.Transfer в приложении MVC.Похоже, что у вас есть что-то принципиально ошибочное с вашим подходом - вы должны либо нажимать на действие * single * controller, либо на функции обертывания, общие для нескольких страниц в дочерних действиях или частичных, или вы должны использовать AJAX для асинхронного обновления частей представления. Если вам нужно возвращать пользователей в разные места условно, используйте перенаправления и передавайте параметры GET для условного рендеринга. –