Menggunakan ChildActionOnly di MVC

168

Kapan Anda akan menggunakan atribut ChildActionOnly? Apa itu ChildActiondan dalam keadaan apa Anda ingin membatasi tindakan menggunakan atribut ini?

Rafael Carvalho
sumber

Jawaban:

161

The ChildActionOnlyatribut memastikan bahwa metode tindakan bisa disebut hanya sebagai metode anak dari dalam pandangan. Metode tindakan tidak perlu memiliki atribut ini untuk digunakan sebagai tindakan anak, tetapi kami cenderung menggunakan atribut ini untuk mencegah metode tindakan tidak dipanggil sebagai hasil dari permintaan pengguna. Setelah menetapkan metode tindakan, kita perlu membuat apa yang akan diberikan ketika tindakan dipanggil. Tindakan anak biasanya dikaitkan dengan pandangan sebagian, meskipun ini tidak wajib.

  1. [ChildActionOnly] memungkinkan akses terbatas melalui kode di View

  2. Nyatakan implementasi Informasi untuk URL halaman tertentu. Contoh: URL Halaman Pembayaran (hanya membayar sekali) sintaks silet memungkinkan untuk memanggil tindakan tertentu bersyarat

Tomasz Jaskuλa
sumber
Contoh penggunaan dalam tampilan: <% Html.RenderAction ("MyChildAction", "MyController"); %>. Dengan demikian Anda tidak dapat memanggil tindakan anak dengan GET dan perutean
Erik Bergstedt
12
Contoh kode: @ 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." Jadi Anda mencegah GET ke controller tertentu secara langsung, tetapi hanya dari dalam controller / action lain. Kemungkinan: _Penampilan bela diri.
Langeleppel
1
Bagaimana cara terbaik menangkap InvalidOperationExceptionketika Metode ditandai <ChildActionOnly>dipanggil melalui browser?
Bernhard Döbler
Saya harus menggunakan @ Html.Action :)
chris c
125

Dengan atribut [ChildActionOnly] dijelaskan, metode tindakan dapat dipanggil hanya sebagai metode anak dari dalam tampilan. Ini adalah contoh untuk [ChildActionOnly]. .

ada dua metode tindakan: Indeks () dan MyDateTime () dan Tampilan yang sesuai: Index.cshtml dan MyDateTime.cshtml. ini adalah 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);
    } 
}

Berikut ini adalah tampilan untuk 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>

Berikut ini adalah tampilan parsial MyDateTime.cshtml .

@model DateTime

<p>
This is the child action result: @Model.ToLongTimeString()
<br />
@ViewBag.Message
</p>
 jika Anda menjalankan aplikasi dan melakukan permintaan ini http: // localhost: 57803 / home / mydatetime
 Hasilnya akan menjadi Server Error seperti:

masukkan deskripsi gambar di sini

Ini berarti Anda tidak dapat secara langsung memanggil tampilan parsial. tetapi bisa dipanggil melalui tampilan Index () seperti pada Index.cshtml

     @ Html.Action ("MyDateTime") // Memanggil tampilan parsial: MyDateTime ().
 

Jika Anda menghapus [ChildActionOnly] dan melakukan permintaan yang sama http: // localhost: 57803 / home / mydatetime itu memungkinkan Anda untuk mendapatkan hasil tampilan parsial mydatetime:
This is the child action result. 12:53:31 PM 
This is from MyDateTime()
yantaq
sumber
saya pikir penjelasan ini adalah "Pemberhentian penuh", terima kasih laki
TAHA SULTAN TEMURI
tetapi itu bisa dicapai dengan menggunakan NonActionjuga, apa bedanya?
Imad
74

Anda akan menggunakannya jika Anda menggunakan RenderActiondalam salah satu tampilan Anda, biasanya untuk membuat tampilan parsial.

Alasan untuk menandainya [ChildActionOnly]adalah karena Anda memerlukan metode pengontrol untuk dipublikasikan sehingga Anda dapat memanggilnya RenderActiontetapi Anda tidak ingin seseorang dapat menavigasi ke URL (mis. / Kontroler / SomeChildAction) dan lihat hasilnya tindakan langsung.

Eric Petroelje
sumber
2
mirip dengan [NonAction]. Apakah itu? lalu apa bedanya?
DarthVader
10
@DarthVader - Mirip, tetapi dengan [NonAction] Anda tidak akan dapat memanggilnya menggunakan RenderActionjuga
Eric Petroelje
@EricPetroelje: Apa manfaat menandai Metode Aksi seperti NonActionAttributedalam proyek nyata?
wuhcwdc
1
@Pankaj - Jujur, saya tidak bisa memikirkan alasan yang sangat bagus. Jika Anda tidak ingin metode pada pengontrol diakses melalui URL, solusi terbaik hanya dengan membuat metode privateatau protected. Saya benar-benar tidak dapat memikirkan alasan bagus mengapa Anda ingin membuat metode pengontrol publickecuali jika Anda ingin dapat memanggilnya secara langsung atau melaluiRenderAction
Eric Petroelje
@ Eric: beberapa kali kita perlu menulis kode kecil untuk menghitung, jadi jika itu publik di controller maka dapat diakses oleh url, jika Anda tidak ingin itu diakses oleh URL sama sekali kemudian tandai sebagai [NonAction ]
Ali Adravi
10

FYI, [ChildActionOnly] tidak tersedia di ASP.NET MVC Core. lihat beberapa info di sini

Joseph Wu
sumber
8

Sedikit terlambat ke pesta, tapi ...

Jawaban lain melakukan pekerjaan dengan baik untuk menjelaskan apa efek [ChildActionOnly]atribut tersebut. Namun, dalam sebagian besar contoh, saya terus bertanya pada diri sendiri mengapa saya akan membuat metode tindakan baru hanya untuk membuat tampilan parsial, dalam tampilan lain, ketika Anda bisa membuat @Html.Partial("_MyParialView")langsung dalam tampilan. Sepertinya lapisan yang tidak perlu. Namun, ketika saya menyelidiki, saya menemukan bahwa satu manfaat adalah bahwa tindakan anak dapat membuat model yang berbeda dan meneruskannya ke pandangan sebagian. Model yang diperlukan untuk parsial mungkin tidak tersedia dalam model tampilan tempat tampilan parsial dibuat. Alih-alih memodifikasi struktur model untuk mendapatkan objek / properti yang diperlukan di sana hanya untuk membuat tampilan parsial, Anda dapat memanggil tindakan anak dan meminta metode tindakan berhati-hati menciptakan model yang diperlukan untuk tampilan parsial.

Ini bisa berguna, misalnya di _Layout.cshtml. Jika Anda memiliki beberapa properti yang umum untuk semua halaman, salah satu cara untuk mencapai ini adalah menggunakan model tampilan dasar dan semua model tampilan lain mewarisi dari itu. Kemudian, _Layoutdapat menggunakan model tampilan dasar dan properti umum. The downside (yang subjektif) adalah bahwa semua model tampilan harus mewarisi dari model tampilan dasar untuk menjamin bahwa properti-properti umum selalu tersedia. Alternatifnya adalah membuat @Html.Actiondi tempat-tempat umum itu. Metode tindakan akan membuat model terpisah yang diperlukan untuk tampilan parsial yang umum untuk semua halaman, yang tidak akan memengaruhi model untuk tampilan "utama". Dalam alternatif ini, _Layouthalaman tidak perlu memiliki model. Oleh karena itu semua model tampilan lain tidak perlu diwarisi dari model tampilan dasar apa pun.

Saya yakin ada alasan lain untuk menggunakan [ChildActionOnly]atribut ini, tetapi ini sepertinya bagus untuk saya, jadi saya pikir saya akan membagikannya.

Neizan
sumber
1
Keuntungan lain adalah, jika panggilan parsial dibungkus dengan panggilan tindakan, maka kita dapat menambahkan atribut cache ke dalamnya.
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
sumber