Отображение представления из другого контроллера в ASP.NET MVC

248

Можно ли отобразить вид с другого контроллера?

Скажем, например, у меня есть CategoriesControllerи Category/NotFound.aspxмнение. Находясь в CategoriesController, я могу легко вернуться View("NotFound").

Теперь скажите, что у меня есть ProductsControllerи действие, и вид, чтобы добавить товар. Тем не менее, это действие требует, чтобы у нас была Категория для добавления Продукта. Например, Products/Add/?catid=10.

Если я не могу найти категорию на основе catid, я хочу показать NotFoundпредставление из контроллера категорий вместо создания CategoryNotFoundпредставления под контроллером продуктов.

Возможно ли это или я неправильно структурирую вещи? Есть ли хороший способ сделать это?

DTC
источник

Ответы:

283

Да. По умолчанию ASP.NET MVC сначала регистрируется \Views\[Controller_Dir]\, но после этого, если он не находит представление, он регистрируется \Views\Shared.

Общий каталог предназначен для совместного использования представлений на нескольких контроллерах. Просто добавьте ваш вид в подкаталог Shared, и все готово.

Если вы это сделаете, return View("~/Views/Wherever/SomeDir/MyView.aspx")вы можете вернуть любой вид, который вы хотите.

WOMP
источник
Спасибо, это похоже на решение, которое я должен использовать. Я все еще задаюсь вопросом, возможно ли отобразить View с другого контроллера. Я предполагаю, что это нарушает какое-то правило в MVC?
DTC
1
В ситуации, которую вы описали выше, да, вы должны использовать общую папку.
Джонатан Фриленд
69
Да, это также возможно. Если вы вернете View («~ / Views / Wherever / SomeDir / MyView.aspx»), вы можете вернуть любой View, который захотите. Это не нарушает какого-либо конкретного правила как такового, однако ASP.Net MVC полностью посвящен «соглашению над конфигурацией». Другими словами, фреймворк создан для автоматической работы с использованием определенных соглашений, и вы должны использовать его там, где это возможно.
womp
1
Спасибо за объяснение. Я не знал, что Взгляды можно так назвать. Общий каталог, конечно, работает отлично :)
DTC
1
Я не был в контроллере, поэтому мне пришлось использовать, new ViewResult { ViewName = "~/Views/Error/Unauthorised.cshtml" };и это сработало
Nacht
162

Ты можешь использовать:

return View("../Category/NotFound", model);

Он был протестирован в ASP.NET MVC 3, но также должен работать в ASP.NET MVC 2.

Guillaume86
источник
3
Работает в MVC 2 и оказался самым чистым решением для необычной ситуации, с которой я сталкиваюсь.
Тодд Менье
3
Resharper сообщит об этой ссылке как об ошибке, но она все еще работает.
CodeMonkeyKing
1
@CodeMonkeyKing - Resharper 7 (в VS2012) правильно определяет путь в формате "~/Views/Category/NotFound.cshtml".
Ричард Эв
Стоит отметить: это решение работает с режимами отображения, например, если у вас было представление «/Category/NotFound.Mobile.cshtml».
BenWillkommen
55

Да, это возможно. Вернуть RedirectToAction()метод, подобный этому:

return RedirectToAction("ActionOrViewName", "ControllerName");
doncadavona
источник
1
Я считаю, что это должно быть RedirectToAction ("ActionOrView", "Controller", null), в противном случае вторым параметром является routeValues
Zoran P.
Но в этом случае вы фактически должны написать действие в контроллере, в отличие от решения View.
tobbenb3
@ tobbenb3 Это гораздо лучшее решение, чем жесткое кодирование результата. В любом случае вы не должны передавать строку пути.
perustaja
34

Ты пробовал RedirectToAction?

Пол Джонсон
источник
1
Я бы сказал, что это MVC для тех, кому не нужен вид в общих папках. Обратите внимание, что для всех других решений (например, с использованием прямых путей) любому, кто пытается рефакторизовать виды, не придется принимать во внимание что он также используется в другом контроллере, что приводит к непредсказуемому поведению
yoel halb
4
как насчет без перенаправления?
Счастливчик
гораздо лучшее решение, чем перемещение представления в общие папки
juFo
Это решение требует действия на контроллере, View (directPath) отображает вывод без каких-либо действий. Когда вы добавляете действие, вам нужно подумать, чтобы скрыть его от прямого доступа через URL, это сгенерирует шаг в истории браузера и т. Д. Но да, это мой путь.
Ян Захрадник,
3
RedirectToAction отправляет код ответа 302 в браузер. Это не подходит, когда вы пытаетесь показать страницу 404 не найдена. Таким образом, это решение, кажется, работает, но запутает поисковые системы.
NightOwl888
20

Да, ты можешь. Верните действие как это:

return RedirectToAction("View", "Name of Controller");

Пример:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees");

Этот подход вызовет метод GET

Также вы можете передать значения действию следующим образом:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees", new {id = id.ToString(), viewtype = "extended" });
игнасио кьяццо
источник
Как бы я отправить объект с этим подходом?
Джероен
Посмотрите @Djeroen
Игнасио chiazzo
5
Вы не возвращаете представление, вы вызываете действие.
0014
Прежде всего было полезно для меня.
Анил Шреста
5

Вы также можете вызвать любой контроллер из JavaScript / jQuery . Скажем, у вас есть контроллер, возвращающий 404, или другой пользовательский элемент управления / страницу. Затем, по какому-либо действию, из вашего клиентского кода вы можете вызвать некоторый адрес, который запустит ваш контроллер и вернуть результат в формате HTML , ваш клиентский код может взять этот возвращенный результат и поместить его туда, куда вы хотите, на свою страницу ...

Marko
источник
Я не знал этого. Похоже, это то, что я мог бы использовать в будущем. Да, MVC скалы :)
DTC
1

С помощью этого кода вы можете получить любой контроллер:

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, 
controller);
Яир ГР
источник
Перевод: С помощью этого кода вы можете получить любой контроллер: [code], С уважением,
Роберт Колумбия,
3
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.
Nic3500