В ASP.NET MVC вы можете легко вернуть ActionResult перенаправления:
return RedirectToAction("Index");
or
return RedirectToRoute(new { controller = "home", version = Math.Random() * 10 });
Это фактически приведет к перенаправлению HTTP, что обычно нормально. Однако при использовании аналитики Google это вызывает большие проблемы, потому что исходный референт теряется, поэтому Google не знает, откуда вы пришли. При этом теряется полезная информация, например, любые термины поисковых систем.
В качестве примечания: этот метод имеет то преимущество, что он удаляет любые параметры, которые могли быть получены из кампаний, но все же позволяет мне фиксировать их на стороне сервера. Если оставить их в строке запроса, люди добавят в закладки, добавят в твиттер или блог ссылку, которую им не следует использовать. Я несколько раз видел это, когда люди размещали в твиттере ссылки на наш сайт, содержащие идентификаторы кампании.
В любом случае, я пишу контроллер «шлюза» для всех входящих посещений сайта, который я могу перенаправить в другие места или альтернативные версии.
На данный момент меня больше волнует Google (чем случайное добавление в закладки), и я хочу иметь возможность отправлять кого-то, кто посещает /
страницу, которую они получили бы, если бы перешли на нее /home/7
, а это версия 7 домашней страницы.
Как я уже говорил ранее, если я сделаю это, я потеряю способность Google анализировать реферер:
return RedirectToAction(new { controller = "home", version = 7 });
Я действительно хочу
return ServerTransferAction(new { controller = "home", version = 7 });
что даст мне это представление без перенаправления на стороне клиента. Хотя я не думаю, что такое существует.
На данный момент лучшее, что я могу придумать, - это продублировать всю логику контроллера HomeController.Index(..)
в моем GatewayController.Index
Action. Это означает , что я должен был двигаться 'Views/Home'
в 'Shared'
так что это было доступно. Должен быть способ получше ?? ..
источник
ServerTransferAction
вы пытались воспроизвести? Это актуально? (не смог найти никакой информации об этом ... спасибо за вопрос, кстати, ответ ниже превосходен)if
утверждение просто слишком заманчиво.RouteBase
чтобы вы могли поместитьif
туда свой оператор, вместо того, чтобы сгибать все назад, чтобы перейти от одного контроллера к другому?Ответы:
Как насчет класса TransferResult? (на основе ответа Станса )
Обновлено: теперь работает с MVC3 (с использованием кода из сообщения Саймона ). Он должен (не смог его протестировать) также работать в MVC2, проверяя, работает ли он в интегрированном конвейере IIS7 +.
Для полной прозрачности; В нашей производственной среде мы никогда не используем TransferResult напрямую. Мы используем TransferToRouteResult, который, в свою очередь, вызывает TransferResult. Вот что на самом деле работает на моих производственных серверах.
И если вы используете T4MVC (если нет ... используйте!), Это расширение может пригодиться.
Используя этот маленький драгоценный камень, вы можете сделать
источник
Изменить: обновлено для совместимости с ASP.NET MVC 3
При условии, что вы используете IIS7, следующая модификация, похоже, работает для ASP.NET MVC 3. Спасибо @nitin и @andy за указание на то, что исходный код не работал.
Изменить 4/11/2011: TempData ломается с Server.TransferRequest с MVC 3 RTM
Изменил приведенный ниже код, чтобы создать исключение, но на данный момент другого решения нет.
Вот моя модификация, основанная на модифицированной версии Маркуса оригинального сообщения Стэна. Я добавил дополнительный конструктор, чтобы взять словарь значений маршрута - и переименовал его в MVCTransferResult, чтобы избежать путаницы, что это может быть просто перенаправление.
Теперь я могу сделать следующее для перенаправления:
Мой модифицированный класс:
источник
Вместо этого вы можете использовать Server.TransferRequest в IIS7 +.
источник
Недавно я узнал, что ASP.NET MVC не поддерживает Server.Transfer (), поэтому я создал метод-заглушку (вдохновленный Default.aspx.cs).
источник
Не могли бы вы просто создать экземпляр контроллера, на который вы хотите перенаправить, вызвать метод действия, который вы хотите, а затем вернуть результат? Что-то вроде:
источник
otherController.ControllerContext = this.ControllerContext;
Я хотел перенаправить текущий запрос на другой контроллер / действие, сохраняя при этом путь выполнения точно таким же, как если бы был запрошен этот второй контроллер / действие. В моем случае Server.Request не работал, потому что я хотел добавить больше данных. Фактически это эквивалентно тому, что текущий обработчик выполняет другой HTTP GET / POST, а затем передает результаты клиенту. Я уверен, что будут лучшие способы добиться этого, но вот что мне подходит:
Ваше предположение верно: я поместил этот код в
и я использую его для отображения ошибок разработчикам, в то время как в производственной среде он будет использовать обычное перенаправление. Обратите внимание, что я не хотел использовать сеанс ASP.NET, базу данных или некоторые другие способы передачи данных об исключениях между запросами.
источник
Вместо того, чтобы имитировать передачу сервера, MVC по-прежнему способен выполнять Server.TransferRequest :
источник
Просто создайте экземпляр другого контроллера и выполните его метод действия.
источник
Вы можете обновить другой контроллер и вызвать метод действия, возвращающий результат. Однако это потребует от вас поместить свое представление в общую папку.
Я не уверен, что вы имели в виду дубликат, но:
редактировать
Другой вариант - создать собственный ControllerFactory, таким образом вы сможете определить, какой контроллер создать.
источник
Разве маршрутизация не позаботится об этом сценарии за вас? т.е. для сценария, описанного выше, вы можете просто создать обработчик маршрута, который реализует эту логику.
источник
Для тех, кто использует маршрутизацию на основе выражений и использует только класс TransferResult, описанный выше, вот метод расширения контроллера, который помогает и сохраняет TempData. Нет необходимости в TransferToRouteResult.
источник
Server.TransferRequest
является совершенно ненужным в MVC . Это устаревшая функция, которая была необходима только в ASP.NET, потому что запрос поступал непосредственно на страницу, и должен был существовать способ передачи запроса на другую страницу. Современные версии ASP.NET (включая MVC) имеют инфраструктуру маршрутизации, которую можно настроить для маршрутизации непосредственно к желаемому ресурсу. Нет смысла позволять запросу достигать контроллера только для того, чтобы передать его другому контроллеру, когда вы можете просто сделать так, чтобы запрос направлялся непосредственно к контроллеру и действию, которое вы хотите.Более того, поскольку вы отвечаете на исходный запрос, нет необходимости что-либо засовывать в
TempData
или другое хранилище только для того, чтобы направить запрос в нужное место. Вместо этого вы перейдете к действию контроллера с неизменным исходным запросом. Вы также можете быть уверены, что Google одобрит этот подход, поскольку он полностью реализуется на стороне сервера.Хотя вы можете многое сделать с обоими
IRouteConstraint
иIRouteHandler
, наиболее мощной точкой расширения для маршрутизации являетсяRouteBase
подкласс. Этот класс может быть расширен для обеспечения как входящих маршрутов, так и генерации исходящих URL-адресов, что делает его универсальным магазином для всего, что связано с URL-адресом и действием, выполняемым URL-адресом.Итак, чтобы следовать вашему второму примеру, чтобы добраться от
/
до/home/7
, вам просто нужен маршрут, который добавляет соответствующие значения маршрута.Но возвращаясь к исходному примеру, где у вас есть случайная страница, он более сложен, потому что параметры маршрута не могут измениться во время выполнения. Итак, это можно сделать с помощью
RouteBase
подкласса следующим образом.Что можно прописать в маршрутизации, например:
Обратите внимание, что в приведенном выше примере может иметь смысл также сохранить файл cookie, записывающий версию домашней страницы, на которой зашел пользователь, чтобы при возвращении они получали ту же версию домашней страницы.
Также обратите внимание, что, используя этот подход, вы можете настроить маршрутизацию, чтобы учитывать параметры строки запроса (он полностью игнорирует их по умолчанию) и соответствующим образом направлять к соответствующему действию контроллера.
Дополнительные примеры
источник
Server.TransferRequest
это, в конце концов, не «совершенно ненужно в MVC».Это не ответ сам по себе, но очевидно, что требуется не только для фактической навигации, чтобы «выполнять» эквивалентную функциональность Webforms Server.Transfer (), но и для полной поддержки всего этого в рамках модульного тестирования.
Следовательно, ServerTransferResult должен "выглядеть" как RedirectToRouteResult и быть как можно более похожим с точки зрения иерархии классов.
Я подумываю сделать это, глядя на Reflector и делая все, что делают класс RedirectToRouteResult, а также различные методы базового класса Controller, а затем «добавляю» последний к Controller через методы расширения. Может быть, это статические методы в одном классе для простоты / лени загрузки?
Если я вернусь к этому, я опубликую это, иначе, может быть, кто-то другой опередит меня!
источник
Я добился этого, используя
Html.RenderAction
помощника в представлении:И в моем контроллере:
источник