Использование ChildActionOnly в MVC

168

Когда бы вы использовали атрибут ChildActionOnly? Что такое ChildActionи при каких обстоятельствах вы хотите ограничить действие, используя этот атрибут?

Рафаэль Карвалью
источник

Ответы:

161

ChildActionOnlyАтрибут гарантирует , что метод действия можно назвать только как метод ребенка изнутри зрения. Метод действия не обязательно должен иметь этот атрибут для использования в качестве дочернего действия, но мы склонны использовать этот атрибут для предотвращения вызова методов действия в результате запроса пользователя. Определив метод действия, мы должны создать то, что будет отображаться при вызове действия. Дочерние действия обычно связаны с частичными представлениями, хотя это не является обязательным.

  1. [ChildActionOnly], разрешающий ограниченный доступ с помощью кода в представлении

  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 :)
Крис с
125

С аннотированным атрибутом [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 (), как в 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()
yantaq
источник
я думаю, что это объяснение было "полной остановкой", спасибо мужчинам
TAHA SULTAN TEMURI
но это может быть достигнуто с помощью NonActionтакже, какая разница?
Имад
74

Вы бы использовали его, если вы используете RenderActionв любом из ваших представлений, обычно для визуализации частичного представления.

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

Эрик Петроэль
источник
2
похож на [NonAction]. это? какая разница тогда?
DarthVader
10
@DarthVader - Похоже, но с [делания] Вы не могли бы назвать его , используя RenderActionлибо
Эрик Petroelje
@EricPetroelje: Каковы преимущества маркировки метода действия NonActionAttributeв реальных проектах?
wuhcwdc
1
@Pankaj - Честно говоря, я не могу придумать никаких веских причин. Если вы не хотите, чтобы метод на контроллере был доступен через URL, лучшим решением было бы просто создать метод privateили protected. Я не могу придумать какой-либо веской причины, по которой вы хотели бы создать метод контроллера, publicза исключением случаев, когда вы хотели бы иметь возможность вызывать его напрямую или черезRenderAction
Eric Petroelje
@Eric: иногда нам нужно написать небольшой код для вычисления, поэтому, если он общедоступен в контроллере, он может быть доступен по URL, если вы вообще не хотите, чтобы к нему обращался по URL, пометьте его как [NonAction ]
Али Адрави
10

К вашему сведению, [ChildActionOnly] недоступно в ASP.NET MVC Core. см. некоторую информацию здесь

Джозеф Ву
источник
8

Немного опоздал на вечеринку, но ...

Другие ответы хорошо объясняют, какой эффект [ChildActionOnly]имеет атрибут. Тем не менее, в большинстве примеров я продолжал спрашивать себя, зачем создавать новый метод действия только для визуализации частичного представления в другом представлении, когда вы можете просто выполнить визуализацию @Html.Partial("_MyParialView")непосредственно в представлении. Это казалось ненужным слоем. Однако, как я выяснил, я обнаружил, что одним из преимуществ является то, что дочернее действие может создать другую модель и передать ее в частичное представление. Модель, необходимая для частичного представления, может быть недоступна в модели представления, в котором отображается частичное представление. Вместо того, чтобы изменять структуру модели, чтобы получить необходимые объекты / свойства для визуализации частичного представления, вы можете вызвать дочернее действие, а метод действия позаботится о создании модели, необходимой для частичного представления.

Это может пригодиться, например, в _Layout.cshtml. Если у вас есть несколько свойств, общих для всех страниц, один из способов сделать это - использовать базовую модель представления и наследовать от нее все другие модели представления. Затем _Layoutможно использовать модель базового вида и общие свойства. Недостатком (который является субъективным) является то, что все модели представлений должны наследоваться от модели базовых представлений, чтобы гарантировать, что эти общие свойства всегда доступны. Альтернатива состоит в том, чтобы сделать @Html.Actionв этих общих местах. Метод действия создаст отдельную модель, необходимую для частичного представления, общего для всех страниц, что не повлияет на модель для «основного» представления. В этой альтернативе _Layoutстранице не нужно иметь модель. Отсюда следует, что все другие модели представлений не должны наследоваться от какой-либо базовой модели представлений.

Я уверен, что есть и другие причины для использования [ChildActionOnly]атрибута, но мне он кажется хорошим, поэтому я решил поделиться.

neizan
источник
1
Другое преимущество состоит в том, что если частичный вызов обернут в вызов действия, то мы можем добавить к нему атрибут кэша.
Камгман
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 
Хамид Наваз
источник