在ASP.NET MVC中显示另一个控制器的视图

276

是否可以展示另一个控制器的视图?

例如,我有一个CategoriesController和一个Category/NotFound.aspx视图。在CategoriesController中,我可以轻松地返回View("NotFound")

现在,假设我有一个ProductsController和一个用于添加产品的操作和视图。但是,该操作需要我们拥有要将产品添加到的类别。例如:Products/Add/?catid=10

如果我无法基于catid找到类别,我想从Categories控制器中显示NotFound视图,而不是在Products控制器下创建CategoryNotFound视图。

这是否可能,或者我的结构方式不对?有没有好的方法来实现这个需求?

7个回答

326

是的。默认情况下,ASP.NET MVC首先检查\Views\[Controller_Dir]\,但如果在该目录中找不到视图,则会检查\Views\Shared

共享目录是专门用于在多个控制器之间共享视图的。只需将您的视图添加到共享子目录中即可。

如果您执行return View("~/Views/Wherever/SomeDir/MyView.aspx"),则可以返回任何视图。


谢谢,这听起来像是我应该使用的解决方案。不过我还在想是否有可能从另一个控制器中显示视图。我猜这违反了MVC的某些规则? - dtc
1
在您上述描述的情况下,是的,您应该使用共享文件夹。 - Jonathan Freeland
75
是的,这也是可能的。如果你执行return View("~/Views/Wherever/SomeDir/MyView.aspx")你可以返回任何视图。这并没有违反任何特定的规则,但 ASP.NET MVC 遵循“约定优于配置”的原则。换句话说,该框架是建立在一些约定上自动运行的,你应该尽可能利用它。 - womp
2
谢谢你的解释。我不知道Views可以这样调用。Shared目录当然完美运作 :) - dtc
2
我不在控制器中,所以我必须使用 new ViewResult { ViewName = "~/Views/Error/Unauthorised.cshtml" };,这样它就可以工作了。 - Nacht
1
这个解决方案不会改变URL(将呈现的视图与浏览器中显示的URL不对应)! - Mr. L

174

你可以使用:

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

它已在ASP.NET MVC 3中进行了测试,但也应该适用于ASP.NET MVC 2。


4
在MVC 2中运作,对我正在处理的一个不寻常的情况来说,证明是最清晰的解决方案。 - Todd Menier
3
Resharper会将该链接报告为错误,但它仍然能够正常工作。 - CodeMonkeyKing
1
@CodeMonkeyKing - Resharper 7(在VS2012中)可以正确识别格式为“~/Views/Category/NotFound.cshtml”的路径。 - Richard Ev
值得注意的是:此解决方案适用于显示模式,例如如果您有一个“/Category/NotFound.Mobile.cshtml”视图。 - BenWillkommen

74

是的,这是可能的。 返回一个像这样的RedirectToAction()方法:

return RedirectToAction("ActionOrViewName", "ControllerName");

1
我认为这应该作为RedirectToAction("ActionOrView", "Controller", null)进行,否则第二个参数就是routeValues。 - Zoran P.
但在这种情况下,您必须实际在控制器中编写操作,而不像使用视图解决方案那样。 - tobbenb3
@tobbenb3 这是一个比硬编码结果更好的解决方案。无论如何,你都不应该传递路径字符串。 - perustaja

35

你尝试过使用 RedirectToAction 吗?


1
我认为这是适用于不想在共享文件夹中使用视图的人的MVC。请注意,对于所有其他解决方案(例如使用直接路径),任何试图重构视图的人都不必考虑它也被另一个控制器使用,从而导致不可预测的行为。 - yoel halb
4
不进行重定向,怎么样? - Luckyy
比将视图移动到共享文件夹更好的解决方案 - juFo
3
RedirectToAction 会向浏览器发送 302 响应代码。但在尝试显示 404 页面未找到时,这是不合适的。换句话说,这个解决方案看起来有效,但会混淆搜索引擎。 - NightOwl888
你能否在视图中修改Response.StatusCode为正确的状态码呢?或者这个修改会在搜索引擎读取状态码之前发生吗? - nulltron
显示剩余4条评论

24

可以,您可以返回这样的Action:

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
请看 @Djeroen - Ignacio Chiazzo
6
你没有返回一个视图,而是调用了一个动作。 - 0014

5
你可以从JavaScript/jQuery调用任何控制器。假设你有一个返回404或其他用户控件/页面的控制器。然后,在某个动作中,从你的客户端代码,你可以调用一些地址来触发你的控制器并以HTML格式返回结果。你的客户端代码可以获取这个返回的结果并把它放在你想要的页面上...

我不知道那个。听起来这是我将来可能会用到的东西。是的,MVC很棒 :) - dtc

1
使用这段代码,您可以获取任何控制器:
var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, 
controller);

使用此代码,您可以获取任何控制器:[code],敬礼。 - Robert Columbia
3
虽然这段代码可能回答了问题,但提供关于它如何以及/或者为什么解决问题的额外上下文信息会增加答案的长期价值。 - Nic3500

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接