Використання ChildActionOnly в MVC


168

Коли ви використовуєте атрибут ChildActionOnly? Що таке a ChildActionі за яких обставин ви хочете обмежити дію, використовуючи цей атрибут?

Відповіді:


161

ChildActionOnlyАтрибут гарантує , що метод дії можна назвати тільки як метод дитини зсередини зору. Для методу дії не потрібно, щоб цей атрибут використовувався як дочірня дія, але ми схильні використовувати цей атрибут для запобігання виклику методів дії в результаті запиту користувача. Визначивши метод дії, нам потрібно створити те, що буде надано, коли дія буде викликана. Діти дитини зазвичай пов'язані з частковими поглядами, хоча це не є обов'язковим.

  1. [ChildActionOnly], що дозволяє обмежений доступ через код у View

  2. Впровадження державної інформації для конкретної URL-адреси сторінки. Приклад: URL-адреса сторінки платежу (сплачуючи лише один раз) синтаксис бритви дозволяє називати конкретні дії умовними


Приклад використання в перегляді: <% Html.RenderAction ("MyChildAction", "MyController"); %>. Таким чином, ви не можете назвати дочірню дію за допомогою GET та маршрутизації
Ерік Бергштедт,

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 безпосередньо до певного контролера, але тільки зсередини іншого контролера / дії. Ймовірно: _Простотні види.
Лангелеппель

1
Як найкраще зрозуміти, InvalidOperationExceptionколи викликається позначений метод <ChildActionOnly>через браузер?
Бернхард Дьоблер

Мені довелося користуватися @ 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 (), як у 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()

Я думаю, що це пояснення було "повною зупинкою", спасибі чоловікам
TAHA SULTAN TEMURI

але це можна досягти, використовуючи NonActionтакож, яка різниця це робить?
Імад

74

Ви б використовували його, якщо ви використовуєте RenderActionбудь-який із своїх переглядів, як правило, для часткового подання.

Причиною для позначення цього [ChildActionOnly]є те, що вам потрібен метод контролера, щоб він був загальнодоступним, щоб його можна було викликати, RenderActionале ви не хочете, щоб хтось мав можливість переходити до URL-адреси (наприклад, / Controller / SomeChildAction) і бачити результати дії безпосередньо.


2
схожий на [NonAction]. є це? у чому різниця тоді?
DarthVader

10
@DarthVader - Схоже, але з [NonAction] ви не зможете назвати це за допомогою RenderActionбудь-якого
Eric Petroelje

@EricPetroelje: Якими можуть бути переваги позначення Методу дій як NonActionAttributeу реальних проектах?
wuhcwdc

1
@Pankaj - Чесно кажучи, я не можу придумати жодних дійсно хороших причин. Якщо ви не хочете, щоб метод на контролері був доступний за допомогою URL-адреси, найкращим рішенням було б просто зробити метод privateабо protected. Я насправді не можу придумати жодної вагомої причини, чому б ви хотіли зробити метод контролера, publicза винятком випадків, коли ви хотіли б або зателефонувати йому безпосередньо, або черезRenderAction
Eric Petroelje

@Eric: інколи нам потрібно писати невеликий код для обчислення, тому, якщо це відкрито в контролері, тоді до нього може отримати доступ URL-адреса, якщо ви не хочете, щоб це був доступ за URL-адресою, тоді позначте його як [NonAction ]
Алі Адраві


8

Трохи запізнюємось на вечірку, але ...

Інші відповіді добре допомагають пояснити, який ефект [ChildActionOnly]має атрибут. Однак у більшості прикладів я постійно запитував себе, чому я б створив новий метод дії просто для надання часткового перегляду в іншому представленні, коли ви можете просто відобразити його @Html.Partial("_MyParialView")безпосередньо у поданні. Це здавалося зайвим шаром. Однак, коли я досліджував, я виявив, що одна перевага полягає в тому, що дія дитини може створити іншу модель і передати її частковому погляду. Модель, необхідна для часткового, може бути недоступною в моделі подання, в якому частковий вигляд надається. Замість того, щоб змінювати структуру моделі, щоб отримати необхідні об’єкти / властивості просто для надання часткового виду, ви можете викликати дочірню дію та змусити метод дії подбати про створення моделі, необхідної для часткового перегляду.

Це може стати в нагоді, наприклад, в _Layout.cshtml. Якщо у вас є декілька властивостей, спільних для всіх сторінок, один із способів досягти цього - використовувати модель базового перегляду та передати успадковані від нього всі інші моделі подання. Потім _Layoutможна використовувати базову модель перегляду та загальні властивості. Мінусом (який є суб'єктивним) є те, що всі моделі перегляду повинні успадковувати від базової моделі перегляду, щоб гарантувати, що ці загальні властивості завжди доступні. Альтернативою є надання @Html.Actionв цих загальних місцях. Метод дії створить окрему модель, необхідну для часткового перегляду, спільного для всіх сторінок, що не вплине на модель для "головного" перегляду. У цій альтернативі на _Layoutсторінці не потрібно мати моделі. Звідси випливає, що всі інші моделі подання не повинні успадковувати жодну модель базового виду.

Я впевнений, що є інші причини використовувати [ChildActionOnly]атрибут, але це здається мені гарним, тому я подумав, що поділюсь.


1
Ще одна перевага - якщо частковий виклик завернуто в виклик дії, то ми можемо додати до нього атрибут кеша.
kamgman

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 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.