Verwenden von ChildActionOnly in MVC

168

Wann würden Sie das Attribut verwenden ChildActionOnly? Was ist eine ChildActionund unter welchen Umständen möchten Sie eine Aktion mit diesem Attribut einschränken?

Rafael Carvalho
quelle

Antworten:

161

Das ChildActionOnlyAttribut stellt sicher, dass eine Aktionsmethode nur als untergeordnete Methode in einer Ansicht aufgerufen werden kann. Für eine Aktionsmethode muss dieses Attribut nicht als untergeordnete Aktion verwendet werden. Wir verwenden dieses Attribut jedoch in der Regel, um zu verhindern, dass die Aktionsmethoden aufgrund einer Benutzeranforderung aufgerufen werden. Nachdem wir eine Aktionsmethode definiert haben, müssen wir erstellen, was beim Aufrufen der Aktion gerendert wird. Untergeordnete Aktionen sind normalerweise mit Teilansichten verbunden, obwohl dies nicht obligatorisch ist.

  1. [ChildActionOnly] Ermöglicht den eingeschränkten Zugriff über Code in View

  2. Implementierung von Statusinformationen für eine bestimmte Seiten-URL. Beispiel: Mit der Rasiersyntax der Zahlungsseiten-URL (nur einmal bezahlen) können bestimmte Aktionen unter bestimmten Bedingungen aufgerufen werden

Tomasz Jaskuλa
quelle
Beispiel für die Verwendung in einer Ansicht: <% Html.RenderAction ("MyChildAction", "MyController"); %>. Daher können Sie mit GET und Routing keine untergeordnete Aktion aufrufen
Erik Bergstedt
12
Beispielcode: @ 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." Sie verhindern also ein GET zu einem bestimmten Controller direkt, jedoch nur innerhalb eines anderen Controllers / einer anderen Aktion. Wahrscheinlich: Teilansichten.
Langeleppel
1
Wie kann man am besten feststellen, InvalidOperationExceptionwann eine markierte Methode <ChildActionOnly>über den Browser aufgerufen wird?
Bernhard Döbler
Ich musste @ Html.Action verwenden :)
Chris C
125

Mit [ChildActionOnly] Attribut kommentiert, kann eine Aktion Methode nur als Kind Methode aus einer Ansicht aufgerufen werden. Hier ist ein Beispiel für [ChildActionOnly]. .

Es gibt zwei Aktionsmethoden: Index () und MyDateTime () sowie die entsprechenden Ansichten: Index.cshtml und MyDateTime.cshtml. Dies ist 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);
    } 
}

Hier ist die Ansicht für 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>

Hier ist die Teilansicht MyDateTime.cshtml .

@model DateTime

<p>
This is the child action result: @Model.ToLongTimeString()
<br />
@ViewBag.Message
</p>
 Wenn Sie die Anwendung ausführen und diese Anforderung ausführen, http: // localhost: 57803 / home / mydatetime
 Das Ergebnis ist ein Serverfehler wie folgt :

Geben Sie hier die Bildbeschreibung ein

Dies bedeutet, dass Sie die Teilansicht nicht direkt aufrufen können. Es kann jedoch über die Index () - Ansicht wie in der Index.cshtml aufgerufen werden

     @ Html.Action ("MyDateTime") // Aufrufen der Teilansicht: MyDateTime ().
 

Wenn Sie [ChildActionOnly] entfernen und dieselbe Anforderung http: // localhost: 57803 / home / mydatetime ausführen, können Sie das Ergebnis der Teilansicht mydatetime abrufen:
This is the child action result. 12:53:31 PM 
This is from MyDateTime()
yantaq
quelle
Ich denke, diese Erklärung war ein "
Punkt
Aber es kann auch erreicht werden NonAction, welchen Unterschied macht es?
Imad
74

Sie würden es verwenden, wenn Sie es RenderActionin einer Ihrer Ansichten verwenden, normalerweise um eine Teilansicht zu rendern.

Der Grund für das Markieren mit [ChildActionOnly]ist, dass die Controller-Methode öffentlich sein muss, damit Sie sie aufrufen können. RenderActionSie möchten jedoch nicht, dass jemand zu einer URL (z. B. / Controller / SomeChildAction) navigieren und die Ergebnisse anzeigen kann Aktion direkt.

Eric Petroelje
quelle
2
ähnlich wie [NonAction]. ist es? Was ist dann der Unterschied?
DarthVader
10
@DarthVader - Ähnlich, aber mit [Nichthandeln] Sie würden nicht in der Lage sein , es zu nennen mit RenderActionentweder
Eric Petroelje
@EricPetroelje: Welche Vorteile kann die Kennzeichnung der Aktionsmethode als NonActionAttributein realen Projekten haben?
wuhcwdc
1
@Pankaj - Ehrlich gesagt, ich kann mir keine wirklich guten Gründe vorstellen. Wenn Sie nicht möchten, dass auf eine Methode auf einem Controller über eine URL zugegriffen wird, besteht die beste Lösung darin, die Methode privateoder zu erstellen protected. Ich kann mir keinen guten Grund publicRenderAction
vorstellen,
@Eric: Manchmal müssen wir kleinen Code schreiben, um zu berechnen. Wenn dieser also im Controller öffentlich ist, kann über die URL darauf zugegriffen werden. Wenn Sie nicht möchten, dass überhaupt über die URL darauf zugegriffen wird, markieren Sie ihn als [NonAction ]
Ali Adravi
10

Zu Ihrer Information, [ChildActionOnly] ist in ASP.NET MVC Core nicht verfügbar. siehe einige Infos hier

Joseph Wu
quelle
8

Ein bisschen spät zur Party, aber ...

Die anderen Antworten erklären gut, welche Wirkung das [ChildActionOnly]Attribut hat. In den meisten Beispielen habe ich mich jedoch immer wieder gefragt, warum ich eine neue Aktionsmethode erstellen würde, um eine Teilansicht in einer anderen Ansicht zu rendern, wenn Sie einfach @Html.Partial("_MyParialView")direkt in der Ansicht rendern könnten . Es schien eine unnötige Schicht zu sein. Als ich nachforschte, stellte ich jedoch fest, dass ein Vorteil darin besteht, dass die untergeordnete Aktion ein anderes Modell erstellen und dieses an die Teilansicht übergeben kann. Das für den Teil benötigte Modell ist möglicherweise nicht im Modell der Ansicht verfügbar, in der die Teilansicht gerendert wird. Anstatt die Modellstruktur zu ändern, um die erforderlichen Objekte / Eigenschaften dort nur zum Rendern der Teilansicht abzurufen, können Sie die untergeordnete Aktion aufrufen und die Aktionsmethode das für die Teilansicht erforderliche Modell erstellen lassen.

Dies kann beispielsweise in nützlich sein _Layout.cshtml. Wenn Sie einige Eigenschaften haben, die allen Seiten gemeinsam sind, können Sie dies erreichen, indem Sie ein Basisansichtsmodell verwenden und alle anderen Ansichtsmodelle davon erben lassen. Anschließend _Layoutkönnen Sie das Basisansichtsmodell und die allgemeinen Eigenschaften verwenden. Der Nachteil (der subjektiv ist) ist, dass alle Ansichtsmodelle vom Basisansichtsmodell erben müssen, um sicherzustellen, dass diese gemeinsamen Eigenschaften immer verfügbar sind. Die Alternative besteht darin, @Html.Actionan diesen gemeinsamen Orten zu rendern . Die Aktionsmethode würde ein separates Modell erstellen, das für die Teilansicht benötigt wird, die allen Seiten gemeinsam ist, was sich nicht auf das Modell für die "Hauptansicht" auswirken würde. Bei dieser Alternative muss die _LayoutSeite kein Modell haben. Daraus folgt, dass alle anderen Ansichtsmodelle kein Basisansichtsmodell erben müssen.

Ich bin mir sicher, dass es andere Gründe gibt, das [ChildActionOnly]Attribut zu verwenden, aber dies scheint mir ein guter Grund zu sein, also dachte ich, ich würde es teilen.

Neizan
quelle
1
Ein weiterer Vorteil ist, dass wir einen Cache-Attribut hinzufügen können, wenn ein Teilaufruf in einen Aktionsaufruf eingeschlossen ist.
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 
Hamid Nawaz
quelle