Utilizzo di ChildActionOnly in MVC


168

Quando useresti l'attributo ChildActionOnly? Che cos'è un ChildActione in quale circostanza vorresti limitare un'azione usando questo attributo?

Risposte:


161

L' ChildActionOnlyattributo garantisce che un metodo di azione possa essere chiamato solo come metodo figlio all'interno di una vista. Un metodo di azione non ha bisogno di avere questo attributo per essere usato come azione figlio, ma tendiamo a usare questo attributo per evitare che i metodi di azione vengano invocati a seguito di una richiesta dell'utente. Dopo aver definito un metodo di azione, dobbiamo creare ciò che verrà reso quando l'azione viene invocata. Le azioni dei bambini sono in genere associate a viste parziali, sebbene ciò non sia obbligatorio.

  1. [ChildActionOnly] che consente l'accesso limitato tramite codice in Visualizza

  2. Implementazione delle informazioni sullo stato per l'URL specifico della pagina. Esempio: l'URL della pagina di pagamento (pagando una sola volta) la sintassi del rasoio consente di chiamare determinate azioni condizionali


Esempio di utilizzo in una vista: <% Html.RenderAction ("MyChildAction", "MyController"); %>. Quindi non puoi chiamare un'azione figlio con GET e routing
Erik Bergstedt,

12
Codice di esempio: @ 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." Quindi si impedisce direttamente a un determinato controller di entrare, ma solo all'interno di un altro controller / azione. Probabile: _ Viste parziale.
Langeleppel,

1
Come catturare al meglio InvalidOperationExceptionquando <ChildActionOnly>viene chiamato un metodo contrassegnato tramite il browser?
Bernhard Döbler,

Ho dovuto usare @ Html.Action :)
chris c

125

Con l' attributo [ChildActionOnly] annotato, un metodo di azione può essere chiamato solo come metodo figlio all'interno di una vista. Ecco un esempio di [ChildActionOnly]. .

ci sono due metodi di azione: Index () e MyDateTime () e viste corrispondenti: Index.cshtml e MyDateTime.cshtml. questo è 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);
    } 
}

Ecco la vista per 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>

Ecco la vista parziale MyDateTime.cshtml .

@model DateTime

<p>
This is the child action result: @Model.ToLongTimeString()
<br />
@ViewBag.Message
</p>
 se esegui l'applicazione e fai questa richiesta http: // localhost: 57803 / home / mydatetime
 Il risultato sarà un errore del server in questo modo:

inserisci qui la descrizione dell'immagine

Ciò significa che non è possibile chiamare direttamente la vista parziale. ma può essere chiamato tramite la vista Index () come in Index.cshtml

     @ Html.Action ("MyDateTime") // Chiamata della vista parziale: MyDateTime ().
 

Se rimuovi [ChildActionOnly] e fai la stessa richiesta http: // localhost: 57803 / home / mydatetime ti consente di ottenere il risultato della vista parziale mydatetime:
This is the child action result. 12:53:31 PM 
This is from MyDateTime()

penso che questa spiegazione sia stata un "punto fermo", grazie uomini
TAHA SULTAN TEMURI

ma può essere raggiunto NonActionanche usando , che differenza fa?
Imad,

74

Lo useresti se lo stai usando RenderActionin una qualsiasi delle tue viste, solitamente per renderizzare una vista parziale.

Il motivo per cui è stato contrassegnato [ChildActionOnly]è che è necessario che il metodo del controller sia pubblico, in modo da poterlo chiamare RenderActionma non si desidera che qualcuno sia in grado di navigare verso un URL (ad es. / Controller / SomeChildAction) e vedere i risultati di quello azione direttamente.


2
simile a [NonAction]. è? qual è la differenza allora?
DarthVader il

10
@DarthVader - Simile, ma con [NonAction] non saresti in grado di chiamarlo usando RenderActionnessuno dei due
Eric Petroelje,

@EricPetroelje: quali possono essere i vantaggi di contrassegnare il metodo di azione come NonActionAttributenei progetti reali?
wuhcwdc,

1
@Pankaj - Onestamente, non riesco a pensare a nessuna ragione davvero valida. Se non si desidera accedere a un metodo su un controller tramite un URL, la soluzione migliore sarebbe quella di creare il metodo privateo protected. Non riesco davvero a pensare a nessuna buona ragione per cui vorresti creare un metodo controller publictranne se volessi essere in grado di chiamarlo direttamente o viaRenderAction
Eric Petroelje,

@Eric: alcune volte abbiamo bisogno di scrivere un piccolo codice per calcolare, quindi se questo è pubblico nel controller, allora è possibile accedervi dall'URL, se non vuoi che acceda tramite URL, allora contrassegnalo come [NonAction ]
Ali Adravi,

10

Cordiali saluti, [ChildActionOnly] non è disponibile in ASP.NET MVC Core. vedi alcune informazioni qui


8

Un po 'tardi alla festa, ma ...

Le altre risposte fanno un buon lavoro nel spiegare l'effetto [ChildActionOnly]dell'attributo. Tuttavia, nella maggior parte degli esempi, continuavo a chiedermi perché avrei creato un nuovo metodo di azione solo per rendere una vista parziale, all'interno di un'altra vista, quando si poteva semplicemente eseguire il rendering @Html.Partial("_MyParialView")direttamente nella vista. Sembrava uno strato inutile. Tuttavia, come ho studiato, ho scoperto che un vantaggio è che l'azione figlio può creare un modello diverso e passarlo alla vista parziale. Il modello necessario per il parziale potrebbe non essere disponibile nel modello della vista in cui viene visualizzata la vista parziale. Invece di modificare la struttura del modello per ottenere lì gli oggetti / le proprietà necessari solo per eseguire il rendering della vista parziale, è possibile chiamare l'azione figlio e fare in modo che il metodo di azione si occupi della creazione del modello necessario per la vista parziale.

Questo può tornare utile, ad esempio, in _Layout.cshtml. Se hai alcune proprietà comuni a tutte le pagine, un modo per farlo è usare un modello di vista di base e avere tutti gli altri modelli di vista ereditati da esso. Quindi, è _Layoutpossibile utilizzare il modello della vista di base e le proprietà comuni. Il rovescio della medaglia (che è soggettivo) è che tutti i modelli di vista devono ereditare dal modello di vista di base per garantire che tali proprietà comuni siano sempre disponibili. L'alternativa è rendere @Html.Actionin quei luoghi comuni. Il metodo di azione creerebbe un modello separato necessario per la vista parziale comune a tutte le pagine, che non influirebbe sul modello per la vista "principale". In questa alternativa, la _Layoutpagina non deve avere un modello. Ne consegue che tutti gli altri modelli di vista non devono ereditare da alcun modello di vista di base.

Sono sicuro che ci sono altri motivi per usare l' [ChildActionOnly]attributo, ma questo mi sembra buono, quindi ho pensato di condividere.


1
Un altro vantaggio è che se una chiamata parziale è racchiusa in una chiamata di azione, allora possiamo aggiungere un attributo cache ad esso.
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 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.