ASP.NET MVC:从视图访问控制器实例

49

我如何从视图中访问控制器实例?例如,我有一个HomeController,它返回我的Index视图。在该视图中,我想访问创建视图的HomeController实例。我该如何做到这一点?


为什么这个问题的答案不是“你不应该这样做”?(参考 https://dev59.com/aWHVa4cB1Zd3GeqPkCpw) - NH.
2个回答

79

你需要访问 ViewContext.Controller,并且你需要进行强制转换。

<% var homeController = ViewContext.Controller as HomeController; %>

Asp.Net MVC:如何获取当前控制器/视图的虚拟URL?中,这个问题还有一些额外的细节。

编辑:这是为了补充Mark Seemann的建议,尽可能将功能从视图中分离出来。如果您正在使用控制器来帮助确定呈现页面的标记,则可以使用Html.RenderAction(actionName, controllerName)方法。此调用将触发操作,就像它是一个单独的请求,并将其视图作为主页面的一部分包含。

这种方法将有助于强制执行关注点分离,因为重定向到的操作方法可以完成所有与表示规则相关的繁重工作。它需要返回一个Partial View才能在父视图中正常工作。


@David:RenderAction只在Futures包中可用,对吗? - Alex
是的,但如果您的视图已经可以访问相关的模型,您可以调用Html.RenderPartial。另外,请查看http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/。 - Iain Galloway
@Alex,这个可以在Futures库中找到。抱歉没有包含那个细节。 - David Andres
@Iain,你是正确的。我提倡使用RenderAction而不是RenderPartial的原因是需要控制器实例意味着超出了视图范围的逻辑处理。RenderPartial只是将问题移动到另一个视图,而RenderAction则走了另一条路(具体来说是到另一个操作方法)。 - David Andres

31

在我看来,你应该考虑一种设计,其中视图不需要了解控制器。这个想法是,控制器处理请求,创建一个模型并将该模型交给视图。此时,控制器的工作完成了。

如果视图需要了解控制器的任何内容,我认为这表明存在设计缺陷。你能分享更多关于你尝试实现的目标吗?

我经常发现,在处理良好设计的框架(如MVC框架)时,如果感觉框架在跟你对抗,那么你可能正在错误的方式下进行任务。这种情况经常发生在我身上,退后一步并询问自己我真正想要达到什么通常会带来新的见解。


1
如果需要实用程序类,它们通常应该放在ViewModel或完全独立的实体中,因为控制器的生命周期应该随着“返回”而结束。 - Michael Stum
马克:我在我的帖子中增加了一点你的论点。+1 - David Andres
我也点赞。我考虑的是,我有一个部分视图,类似于ASP.NET MVC常规启动项目中的LogOnUserControl。它显示用户名(但不是来自Page上下文/IPrincipal -- 它是自定义的)。我的控制器已经有了一个能够提供用户名的服务,所以我宁愿从控制器中获取实例,而不是在视图中重新实例化。我没有使用模型,因为我想利用常规的return View(),而不会遇到问题(记住,这是共享的,所以我需要一个VM基类等)。 - Alex
@Alex:在我看来,这似乎是使用名称属于ViewModel。你可以使用继承,但你应该更倾向于组合优于继承,因此在这种情况下,我会定义一个“根”ViewModel,其中包含一个UserName属性和另一个包含特定页面的ViewModel的属性。然后,当您调用RenderPartial方法时,可以将UserName属性的值作为model参数传递。 - Mark Seemann
1
@Alex, Mark: 我支持一个“根”ViewModel随时间变化的论点。是的,这会增加复杂性,但是一旦你需要额外的属性传递到模型中,你就必须更新你的视图来匹配。这个ViewModel可能会在不同的视图之间共享,所以这可能会变得很繁琐。 - David Andres
显示剩余2条评论

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