Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ChildActionOnly in MVC

Tags:

c#

asp.net-mvc

People also ask

What are non action methods in MVC?

Non-Action is another built-in attribute which indicates that a public method of a Controller is not an action method. It is used when we don't want that method to be treated as an action method. Please read my previous articles to learn more about Selectors in ASP.NET MVC.

What is render action in MVC?

RenderAction(HtmlHelper, String) Invokes the specified child action method and renders the result inline in the parent view. RenderAction(HtmlHelper, String, Object) Invokes the specified child action method using the specified parameters and renders the result inline in the parent view.

What is partial view in MVC C#?

A partial view is a Razor markup file ( . cshtml ) without an @page directive that renders HTML output within another markup file's rendered output. The term partial view is used when developing either an MVC app, where markup files are called views, or a Razor Pages app, where markup files are called pages.


The ChildActionOnly attribute ensures that an action method can be called only as a child method from within a view. An action method doesn’t need to have this attribute to be used as a child action, but we tend to use this attribute to prevent the action methods from being invoked as a result of a user request. Having defined an action method, we need to create what will be rendered when the action is invoked. Child actions are typically associated with partial views, although this is not compulsory.

  1. [ChildActionOnly] allowing restricted access via code in View

  2. State Information implementation for specific page URL. Example: Payment Page URL (paying only once) razor syntax allows to call specific actions conditional


With [ChildActionOnly] attribute annotated, an action method can be called only as a child method from within a view. Here is an example for [ChildActionOnly]..

there are two action methods: Index() and MyDateTime() and corresponding Views: Index.cshtml and MyDateTime.cshtml. this is 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);
    } 
}

Here is the view for 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>

Here is MyDateTime.cshtml partial view.

@model DateTime

<p>
This is the child action result: @Model.ToLongTimeString()
<br />
@ViewBag.Message
</p>
 if you run the application and do this request http://localhost:57803/home/mydatetime
 The result will be Server Error like so: 

enter image description here

This means you can not directly call the partial view. but it can be called via Index() view as in the Index.cshtml

     @Html.Action("MyDateTime")  // Calling the partial view: MyDateTime().
 
If you remove [ChildActionOnly] and do the same request http://localhost:57803/home/mydatetime it allows you to get the mydatetime partial view result:
This is the child action result. 12:53:31 PM 
This is from MyDateTime()

You would use it if you are using RenderAction in any of your views, usually to render a partial view.

The reason for marking it with [ChildActionOnly] is that you need the controller method to be public so you can call it with RenderAction but you don't want someone to be able to navigate to a URL (e.g. /Controller/SomeChildAction) and see the results of that action directly.


FYI, [ChildActionOnly] is not available in ASP.NET MVC Core. see some info here


A little late to the party, but...

The other answers do a good job of explaining what effect the [ChildActionOnly] attribute has. However, in most examples, I kept asking myself why I'd create a new action method just to render a partial view, within another view, when you could simply render @Html.Partial("_MyParialView") directly in the view. It seemed like an unnecessary layer. However, as I investigated, I found that one benefit is that the child action can create a different model and pass that to the partial view. The model needed for the partial might not be available in the model of the view in which the partial view is being rendered. Instead of modifying the model structure to get the necessary objects/properties there just to render the partial view, you can call the child action and have the action method take care of creating the model needed for the partial view.

This can come in handy, for example, in _Layout.cshtml. If you have a few properties common to all pages, one way to accomplish this is use a base view model and have all other view models inherit from it. Then, the _Layout can use the base view model and the common properties. The downside (which is subjective) is that all view models must inherit from the base view model to guarantee that those common properties are always available. The alternative is to render @Html.Action in those common places. The action method would create a separate model needed for the partial view common to all pages, which would not impact the model for the "main" view. In this alternative, the _Layout page need not have a model. It follows that all other view models need not inherit from any base view model.

I'm sure there are other reasons to use the [ChildActionOnly] attribute, but this seems like a good one to me, so I thought I'd share.