在MVC中使用ChildActionOnly


Answers:


161

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

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

  2. 特定页面URL的状态信息实现。示例:付款页面URL(仅支付一次)剃刀语法允许有条件地调用特定操作


在视图中使用的示例:<%Html.RenderAction(“ MyChildAction”,“ MyController”); %>。因此,您无法使用GET和路由调用子操作
Erik Bergstedt

12
示例代码:@ Clark-Kent // example from Music Store // GET: /ShoppingCart/CartSummary [ChildActionOnly] public ActionResult CartSummary() { // your stuff } /ShoppingCart/CartSummary will return "The action 'CartSummary' is accessible only by a child request." 因此,您可以直接从某个控制器/动作中阻止GET到某个控制器。可能:_局部视图。
Langeleppel

1
如何最好地捕捉通过浏览器调用InvalidOperationException带有方法标记的方法<ChildActionOnly>
2014年

我不得不使用@ Html.Action :)
chris c

125

[ChildActionOnly]注释的属性,动作方法可以被调用仅作为从一个视图内的子方法。这是[ChildActionOnly]的示例

有两种操作方法: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的视图。

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

我认为这个解释是“句号”,谢谢男人
TAHA SULTAN TEMURI

但是也可以使用它来实现NonAction,它有什么不同?
Imad

74

如果您要RenderAction在任何视图中使用它,则通常会使用它来渲染部分视图。

用标记的原因[ChildActionOnly]是您需要公开控制器方法,以便可以使用进行调用,RenderAction但是您不希望某人能够导航到URL(例如/ Controller / SomeChildAction)并查看其结果。直接行动。


2
类似于[NonAction]。是吗?那有什么区别呢?
DarthVader 2012年

10
@DarthVader -类似,但与[无为]你将无法使用称之为RenderAction要么
埃里克Petroelje

@EricPetroelje:将Action Method标记为NonActionAttribute真实项目有什么好处?
wuhcwdc

1
@Pankaj-老实说,我想不出任何真正好的理由。如果您不希望通过URL访问控制器上的方法,最好的解决方案就是将方法private或设置为protected。我真的想不出为什么要创建一个控制器方法的任何好理由,public除非您想直接或通过它来调用它RenderAction
Eric Petroelje

@Eric:有时我们需要编写一些小的代码来进行计算,因此,如果该代码在控制器中是公共的,则可以通过url访问,如果您根本不希望通过URL对其进行访问,则将其标记为[NonAction ]
Ali Adravi

10

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


8

派对晚了一点,但是...

其他答案很好地解释了该[ChildActionOnly]属性具有什么作用。但是,在大多数示例中,我一直在问自己为什么要创建一个新的动作方法,以便只@Html.Partial("_MyParialView")在视图中直接渲染时,才能在另一个视图中渲染部分视图。似乎是不必要的层。但是,当我进行调查时,发现一个好处是子操作可以创建一个不同的模型并将其传递给局部视图。在呈现局部视图的视图模型中,局部模型所需的模型可能不可用。您可以调用子操作并使该操作方法负责创建部分视图所需的模型,而无需修改模型结构以在那里获得仅用于呈现部分视图的必要对象/属性。

例如,这可以派上用场_Layout.cshtml。如果您具有所有页面共有的一些属性,则完成此操作的一种方法是使用基本视图模型,并使所有其他视图模型都继承自该视图模型。然后,_Layout可以使用基本视图模型和通用属性。不利的一面是(主观的)所有视图模型都必须继承自基本视图模型,以确保这些公共属性始终可用。另一种方法是@Html.Action在那些常见的地方渲染。操作方法将为所有页面共有的局部视图创建所需的单独模型,这不会影响“主”视图的模型。在这种替代方式中,_Layout页面不需要模型。随之而来的是,所有其他视图模型不需要从任何基本视图模型继承。

我确定还有其他原因可以使用该[ChildActionOnly]属性,但这对我来说似乎是一个不错的选择,所以我认为我愿意分享。


1
另一个优点是,如果将部分调用包装在动作调用中,则可以向其中添加缓存属性。
kamgman '19

0
    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 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.