ใช้ ChildActionOnly ใน MVC


168

คุณจะใช้คุณลักษณะเมื่อChildActionOnlyใด อะไรคือChildActionสิ่งที่คุณต้องการ จำกัด การกระทำโดยใช้คุณลักษณะนี้และในสถานการณ์ใด

คำตอบ:


161

ChildActionOnlyแอตทริบิวต์เพื่อให้แน่ใจว่าวิธีการดำเนินการสามารถเรียกว่าเป็นเพียงวิธีการที่เด็กจากภายในมุมมอง เมธอดการกระทำไม่จำเป็นต้องมีแอททริบิวนี้เพื่อใช้เป็นแอคชันลูก แต่เรามักจะใช้แอททริบิวนี้เพื่อป้องกันไม่ให้มีการเรียกใช้แอคชันวิธีนี้เนื่องจากคำขอของผู้ใช้ ต้องกำหนดวิธีการกระทำเราต้องสร้างสิ่งที่จะแสดงผลเมื่อมีการเรียกการกระทำ การกระทำของเด็กมักจะเกี่ยวข้องกับมุมมองบางส่วนแม้ว่าจะไม่ได้รับคำสั่ง

  1. [ChildActionOnly] อนุญาตการเข้าถึงที่ จำกัด ผ่านรหัสในมุมมอง

  2. การใช้ข้อมูลสถานะสำหรับ URL หน้าเฉพาะ ตัวอย่าง: URL หน้าการชำระเงิน (จ่ายเพียงครั้งเดียว) ไวยากรณ์ของมีดโกนอนุญาตให้เรียกใช้การกระทำที่มีเงื่อนไข


ตัวอย่างการใช้งานในมุมมอง: <% Html.RenderAction ("MyChildAction", "MyController"); %> ดังนั้นคุณไม่สามารถเรียกการดำเนินการลูกด้วย GET และการกำหนดเส้นทาง
Erik Bergstedt

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 ไปยังตัวควบคุมบางตัวได้โดยตรง แต่จากภายในคอนโทรลเลอร์ / แอ็คชั่นอื่นเท่านั้น แนวโน้ม: _Partial views
Langeleppel

1
วิธีการจับInvalidOperationExceptionเมื่อวิธีการทำเครื่องหมาย<ChildActionOnly>ถูกเรียกผ่านเบราว์เซอร์ที่ดีที่สุด?
Bernhard Döbler

ฉันต้องใช้ @ Html.Action :)
chris c

125

ด้วย แอตทริบิวต์[ChildActionOnly]คำอธิบายประกอบวิธีการดำเนินการสามารถเรียกได้ว่าเป็นวิธีการของเด็กจากภายในมุมมอง นี่คือตัวอย่างสำหรับ[ChildActionOnly] .

มีวิธีการดำเนินการสองวิธี: ดัชนี () และ 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.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มันแตกต่างกันอย่างไร
Imad

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: บางครั้งเราจำเป็นต้องเขียนโค้ดขนาดเล็กเพื่อคำนวณดังนั้นถ้ามันเป็น public ใน controller ก็สามารถเข้าถึงได้โดย url ถ้าคุณไม่ต้องการให้มันเข้าถึงด้วย URL เลยให้ทำเครื่องหมายเป็น [NonAction ]
Ali Adravi


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 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.