Как смоделировать Server.Transfer в ASP.NET MVC? - PullRequest
121 голосов
/ 28 апреля 2009

В ASP.NET MVC вы можете довольно легко вернуть перенаправленный ActionResult:

 return RedirectToAction("Index");

 or

 return RedirectToRoute(new { controller = "home", version = Math.Random() * 10 });

Это фактически даст перенаправление HTTP, что обычно нормально. Однако при использовании Google Analytics это вызывает большие проблемы, потому что первоначальный реферер потерян, поэтому Google не знает, откуда вы пришли. Это теряет полезную информацию, такую ​​как любые термины поисковой системы.

Как примечание, этот метод имеет преимущество, заключающееся в удалении любых параметров, которые могут быть получены из кампаний, но все же позволяет мне захватывать их на стороне сервера. Если оставить их в строке запроса, люди будут добавлять в закладки, в твиттере или в блоге ссылку, которой они не должны. Я видел это несколько раз, когда люди твитнули ссылки на наш сайт, содержащие идентификаторы кампаний.

В любом случае, я пишу контроллер «шлюза» для всех входящих посещений сайта, который я могу перенаправить в разные места или альтернативные версии.

На данный момент меня больше интересует Google (чем случайные закладки), и я хочу иметь возможность отправлять тех, кто посещает /, на страницу, которую они получат, если перейдут на /home/7, которая является версией 7 из домашней страницы.

Как я уже говорил, если я сделаю это, я потеряю способность Google анализировать реферера:

 return RedirectToAction(new { controller = "home", version = 7 });

Что я действительно хочу, так это

 return ServerTransferAction(new { controller = "home", version = 7 });

, что даст мне это представление без перенаправления на стороне клиента. Я не думаю, что такая вещь существует, хотя.

В настоящее время лучшее, что я могу придумать, это продублировать всю логику контроллера для HomeController.Index(..) в моем GatewayController.Index действии. Это означает, что мне пришлось переместить 'Views/Home' в 'Shared', чтобы он был доступен. Должен быть лучший способ ?? ..

Ответы [ 14 ]

1 голос
/ 18 октября 2012

Для тех, кто использует маршрутизацию на основе выражений и использует только вышеприведенный класс TransferResult, вот метод расширения контроллера, который добивается цели и сохраняет TempData. Нет необходимости в TransferToRouteResult.

public static ActionResult TransferRequest<T>(this Controller controller, Expression<Action<T>> action)
    where T : Controller
{
     controller.TempData.Keep();
     controller.TempData.Save(controller.ControllerContext, controller.TempDataProvider);
     var url = LinkBuilder.BuildUrlFromExpression(controller.Request.RequestContext, RouteTable.Routes, action);
     return new TransferResult(url);
}
1 голос
/ 28 апреля 2009

Разве маршрутизация не позаботится об этом сценарии для вас? то есть для сценария, описанного выше, вы можете просто создать обработчик маршрута, который реализует эту логику.

0 голосов
/ 06 марта 2018

Я добился этого, используя помощника Html.RenderAction в представлении:

@{
    string action = ViewBag.ActionName;
    string controller = ViewBag.ControllerName;
    object routeValues = ViewBag.RouteValues;
    Html.RenderAction(action, controller, routeValues);
}

И в моем контроллере:

public ActionResult MyAction(....)
{
    var routeValues = HttpContext.Request.RequestContext.RouteData.Values;    
    ViewBag.ActionName = "myaction";
    ViewBag.ControllerName = "mycontroller";
    ViewBag.RouteValues = routeValues;    
    return PartialView("_AjaxRedirect");
}
0 голосов
/ 29 декабря 2009

Не является ответом как таковым, но очевидно, что требовалось бы, чтобы фактическая навигация «не делала» эквивалентную функциональность Webforms Server.Transfer (), но также и для того, чтобы все это полностью поддерживалось в модульном тестировании.

Поэтому ServerTransferResult должен «выглядеть» как RedirectToRouteResult и быть максимально похожим с точки зрения иерархии классов.

Я думаю сделать это, посмотрев на Reflector и сделав все, что делает класс RedirectToRouteResult, а также различные методы базового класса Controller, а затем «добавив» последний в Controller с помощью методов расширения. Может быть, это могут быть статические методы в одном классе для простоты / лени загрузки?

Если я займусь этим, я опубликую это, иначе, может быть, кто-то другой может побить меня этим!

...