在MVC中使用ChildActionOnly

你什么时候使用ChildActionOnly属性? 什么是ChildAction ,在什么情况下你想要使用这个属性限制一个动作?

ChildActionOnly属性确保操作方法只能从视图中作为子方法调用。 一个动作方法不需要把这个属性用作一个子动作,但是我们倾向于使用这个属性来防止由于用户请求而调用动作方法。 定义了一个动作方法后,我们需要创build一个动作被调用时将会呈现的内容。 子动作通常与部分视图相关联,但这不是强制性的。

  1. [ChildActionOnly]允许通过View中的代码进行受限访问

  2. 针对特定网页url的状态信息实施。 示例:付款页面URL(仅支付一次)razor语法允许以条件方式调用特定的操作

通过注释[ChildActionOnly]属性,操作方法只能在视图内被调用为子方法。 这里是[ChildActionOnly]的例子

有两个操作方法:Index()和MyDateTime()以及相应的Views: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的视图。

 @model DateTime @{ ViewBag.Title = "Index"; } <h2> Index</h2> <div> This is the index view for Home : @Model.ToLongTimeString() </div> <div> @Html.Action("MyDateTime") // Calling the partial view: MyDateTime(). </div> <div> @ViewBag.Message </div> 

这里是MyDateTime.cshtml局部视图。

 @model DateTime <p> This is the child action result: @Model.ToLongTimeString() <br /> @ViewBag.Message </p> 
 如果您运行应用程序并执行此请求http:// localhost:57803 / home / mydatetime
 结果将是服务器错误,如下所示: 

在这里输入图像描述

这意味着你不能直接调用局部视图。 但是可以像Index.cshtml中那样通过Index()视图来调用它

      @ 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() 

如果您在任何视图中使用RenderAction ,通常会渲染局部视图。

[ChildActionOnly]标记它的原因是你需要控制器方法是公开的,所以你可以用RenderAction调用它,但是你不希望有人能够导航到一个URL(例如/ Controller / SomeChildAction),并看到该行动的结果直接。

仅供参考,[ChildActionOnly]在ASP.NET MVC Core中不可用。 在这里看到一些信息

晚会有点迟,但…

其他答案很好地解释了[ChildActionOnly]属性的作用。 然而,在大多数例子中,我一直在问自己为什么要创build一个新的动作方法来渲染一个局部视图,在另一个视图中,直接在视图中渲染@Html.Partial("_MyParialView") 。 这似乎是一个不必要的层。 然而,正如我调查,我发现一个好处是,孩子的行动可以创build一个不同的模型,并将其传递到局部视图。 在局部视图被渲染的视图的模型中,局部所需的模型可能不可用。 不是修改模型结构来获取必要的对象/属性,而是渲染局部视图,您可以调用子操作并使用操作方法来创build局部视图所需的模型。

这可以派上用场,例如, _Layout.cshtml 。 如果您对所有页面都有一些共同的属性,则完成此操作的一种方法是使用基本视图模型,并从其中inheritance所有其他视图模型。 然后, _Layout可以使用基本视图模型和公共属性。 缺点(这是主观的)是所有视图模型都必须从基本视图模型inheritance,以保证这些公共属性始终可用。 另一种方法是在这些常见的地方渲染@Html.Action 。 action方法将为所有页面共有的局部视图创build一个单独的模型,这不会影响“主”视图的模型。 在这个select中, _Layout页面不需要模型。 因此,所有其他视图模型不需要从任何基本视图模型inheritance。

我相信还有其他的理由来使用[ChildActionOnly]属性,但是这对我来说似乎是一个很好的,所以我想我会分享。

  public class HomeController : Controller { public ActionResult Index() { ViewBag.TempValue = "Index Action called at HomeController"; return View(); } [ChildActionOnly] public ActionResult ChildAction(string param) { ViewBag.Message = "Child Action called. " + param; return View(); } } The code is initially invoking an Index action that in turn returns two Index views and at the View level it calls the ChildAction named “ChildAction”. @{ ViewBag.Title = "Index"; } <h2> Index </h2> <!DOCTYPE html> <html> <head> <title>Error</title> </head> <body> <ul> <li> @ViewBag.TempValue </li> <li>@ViewBag.OnExceptionError</li> @*<li>@{Html.RenderAction("ChildAction", new { param = "first" });}</li>@**@ @Html.Action("ChildAction", "Home", new { param = "first" }) </ul> </body> </html> Copy and paste the code to see the result .thanks