在MVC中使用ChildActionOnly
使用[ChildActionOnly]属性注释的动作方法只能作为视图内的子方法调用。这里有一个关于[ChildActionOnly]的示例。
HomeController.cs中有两个动作方法:Index()和MyDateTime(),对应的视图为Index.cshtml和MyDateTime.cshtml。
这是HomeController.cs的代码:
public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "This is from Index()"; var model = DateTime.Now; return View(model); } [ChildActionOnly] public PartialViewResult MyDateTime() { ViewBag.Message = "This is from MyDateTime()"; var model = DateTime.Now; return PartialView(model); } }
这是Index.cshtml视图:
@{ ViewBag.Title = "Index"; }Index
This is the index view for Home : @Model.ToLongTimeString()@Html.Action("MyDateTime") // 调用部分视图:MyDateTime()@ViewBag.Message
这是MyDateTime.cshtml部分视图:
This is the child action result: @Model.ToLongTimeString() @ViewBag.Message
如果你运行该应用程序并发送请求http://localhost:57803/home/mydatetime,结果将是Server Error,如下图所示:
![Error](https://i.stack.imgur.com/TzGex.png)
这意味着你不能直接调用部分视图,但可以通过Index()视图调用,如Index.cshtml中的代码所示:
@Html.Action("MyDateTime") // 调用部分视图:MyDateTime()
如果你移除[ChildActionOnly]并发送相同的请求http://localhost:57803/home/mydatetime,它允许你获取mydatetime部分视图的结果:
This is the child action result. 12:53:31 PM This is from MyDateTime()
我认为这个解释就是“完整的解释”,谢谢。
但是,也可以使用NonAction来实现相同的效果,它有什么区别呢?
在MVC中使用ChildActionOnly的原因是,当你在任何视图中使用RenderAction来呈现一个部分视图时,你会使用它。标记为[ChildActionOnly]的原因是,你需要使控制器方法公开,以便你可以使用RenderAction来调用它,但你不希望有人能够通过URL(例如/Controller/SomeChildAction)访问并直接查看该动作的结果。
与[NonAction]类似,那有什么区别呢?
- 相似,但是使用[NonAction]的话,你也不能使用RenderAction来调用它。
在真实项目中,将动作方法标记为NonActionAttribute有什么好处呢?
- 老实说,我想不出任何真正好的理由。如果你不希望通过URL访问控制器上的某个方法,最好的解决方法就是将该方法设置为private或protected。我真的想不出为什么你想要将控制器方法设置为public,除非你希望能够直接调用它或者通过RenderAction来调用它。
有时我们需要编写一些小代码来计算,如果该方法在控制器中是public的,那么可以通过URL进行访问,如果你根本不希望它被URL访问到,那么将其标记为[NonAction]。
在MVC中使用ChildActionOnly的问题出现的原因是为了限制一个操作方法只能作为视图中的子方法被调用。这个属性并不是必需的,但我们通常使用这个属性来防止操作方法在用户请求时被调用。
一旦定义了一个操作方法,我们需要创建在调用该操作方法时将被呈现的内容。子操作通常与部分视图关联,尽管这不是强制性的。
ChildActionOnly的使用场景有:
1. 允许在视图中通过代码进行受限访问
2. 为特定页面URL实现状态信息。例如,支付页面URL(只支付一次),Razor语法允许有条件地调用特定的操作方法。
在视图中的使用示例:<% Html.RenderAction("MyChildAction", "MyController"); %>。因此,您无法使用GET和路由调用子操作。
下面是一个示例代码:
// example from Music Store // GET: /ShoppingCart/CartSummary [ChildActionOnly] public ActionResult CartSummary() { // your stuff }
通过这样的方式,您可以防止直接使用GET请求在某个控制器上进行访问,而只能通过另一个控制器/操作方法进行访问。通常使用在部分视图中。
那么,如果通过浏览器调用了一个标记为ChildActionOnly的方法,如何最好地捕获InvalidOperationException呢?我必须使用.Action 🙂