ฉันจะคืนค่าการกระทำปัจจุบันในมุมมอง ASP.NET MVC ได้อย่างไร


291

ฉันต้องการตั้งคลาส CSS ในหน้าต้นแบบของฉันซึ่งขึ้นอยู่กับตัวควบคุมและการกระทำในปัจจุบัน ฉันจะได้รับไปยังตัวควบคุมปัจจุบันผ่านViewContext.Controller.GetType().Nameแต่ฉันจะได้รับการดำเนินการปัจจุบัน (เช่นIndex, Showฯลฯ )?

คำตอบ:


83

ใช้ViewContextและดูที่RouteDataคอลเล็กชันเพื่อแยกทั้งองค์ประกอบคอนโทรลเลอร์และแอ็คชัน แต่ฉันคิดว่าการตั้งค่าตัวแปรข้อมูลบางอย่างที่บ่งบอกถึงบริบทของแอปพลิเคชัน (เช่น "editmode" หรือ "ข้อผิดพลาด") แทนที่จะควบคุม / การกระทำลดข้อต่อระหว่างมุมมองและตัวควบคุมของคุณ


คุณสามารถรับข้อมูลในคอนโทรลเลอร์และส่งต่อให้ดูด้วย DTO stackoverflow.com/a/31749391/4293929
MstfAsan

5
สิ่งนี้จะต้องไม่ใช่คำตอบที่ยอมรับให้ดูคำตอบที่โหวตมากที่สุดแทน
Hakan Fıstık

1
@ HakamFostok ฉันยังคงคิดว่าคำแนะนำในการเพิ่มข้อมูลความหมายให้กับโมเดลเป็นวิธีที่ดีกว่าในทุกกรณีมากกว่าการใช้ข้อมูลเส้นทาง (คอนโทรลเลอร์, การกระทำ) ในมุมมองของคุณแม้ว่าคำตอบอื่น ๆ จะให้รายละเอียดเพิ่มเติมเกี่ยวกับวิธีการรับข้อมูล
tvanfosson

467

ใน RC คุณสามารถดึงข้อมูลเส้นทางเช่นชื่อวิธีการกระทำเช่นนี้ได้

ViewContext.Controller.ValueProvider["action"].RawValue
ViewContext.Controller.ValueProvider["controller"].RawValue
ViewContext.Controller.ValueProvider["id"].RawValue

อัพเดทสำหรับ MVC 3

ViewContext.Controller.ValueProvider.GetValue("action").RawValue
ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
ViewContext.Controller.ValueProvider.GetValue("id").RawValue

อัพเดทสำหรับ MVC 4

ViewContext.Controller.RouteData.Values["action"]
ViewContext.Controller.RouteData.Values["controller"]
ViewContext.Controller.RouteData.Values["id"]

อัพเดทสำหรับ MVC 4.5

ViewContext.RouteData.Values["action"]
ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["id"]

20
ฉันรู้ว่ารุ่นก่อนหน้านี้ V2 แต่ตอนนี้มันเป็นViewContext.Controller.ValueProvider.GetValue("action").RawValue+ การเปลี่ยนแปลง
Chris S

7
ไวยากรณ์นี้ทำงานใน V4: (สตริง) ViewContext.RouteData.Values ​​["action"];
kiprainey

2
วิธีนี้ไม่ทำงานสำหรับฉัน (MVC4 + .NET Framework 4.5.1) สำหรับฉันมันทำงานได้คำตอบจาก Viacheslav Smityukh: ViewContext.RouteData.Values ​​["action"], ViewContext.RouteData.Values ​​["คอนโทรลเลอร์"], ViewContext.RouteData.Values ​​["id"],
Tomas Kubes

@kiprainey ใน V3.5 เช่นกัน: msdn.microsoft.com/en-us/library/…
พลูโต

2
ลอง: (สตริง) HttpContext.Request.RequestContext.RouteData.Values ​​["action"];
Martin Dawson

60

วิธีรับรหัสปัจจุบันบนมุมมอง:

ViewContext.RouteData.Values["id"].ToString()

ในการรับคอนโทรลเลอร์ปัจจุบัน:

ViewContext.RouteData.Values["controller"].ToString() 

1
ViewContext.RouteData.Values ​​[<key>] .ToString () ส่งข้อยกเว้นหากไม่มีค่าใน RouteData
Grizzly Peak Software

@ShaneLarson เพียงเปรียบเทียบกับ null หรือตรวจสอบViewContext.RouteData.Values.ContainsKey(<key>)ก่อน
พลูโต

40

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

วิธีที่ง่ายกว่าในความคิดของฉันคือการแทนที่วิธีOnActionExecuting คุณถูกส่งผ่านActionExecutingContextที่ประกอบด้วยสมาชิกActionDescriptorซึ่งคุณสามารถใช้เพื่อรับข้อมูลที่คุณกำลังค้นหาซึ่งเป็น ActionName และคุณยังสามารถเข้าถึง ControllerDescriptor และประกอบด้วย ControllerName

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    ActionDescriptor actionDescriptor = filterContext.ActionDescriptor;
    string actionName = actionDescriptor.ActionName;
    string controllerName = actionDescriptor.ControllerDescriptor.ControllerName;
    // Now that you have the values, set them somewhere and pass them down with your ViewModel
    // This will keep your view cleaner and the controller will take care of everything that the view needs to do it's job.
}

หวังว่านี่จะช่วยได้ หากมีอะไรอย่างน้อยก็จะแสดงทางเลือกให้กับคนอื่นที่มาจากคำถามของคุณ


คำแนะนำที่ดี; ช่วยฉันในการใช้การตรวจจับคอนโทรลเลอร์ / แอ็คชั่นอย่างชาญฉลาด ขอบคุณ!
effkay

การได้รับ desrciptor จากการกระทำคือสิ่งที่ฉันต้องการฉันไม่สามารถหาวิธีแก้ปัญหาอื่น ๆ ได้จริงๆดังนั้นฉันจึงทำที่นี่จากนั้นดันสิ่งที่ฉันต้องการลงใน viewbag
Chris Marisic

17

ฉันเห็นคำตอบที่แตกต่างและเกิดขึ้นกับผู้ช่วยในชั้นเรียน:

using System;
using System.Web.Mvc;

namespace MyMvcApp.Helpers {
    public class LocationHelper {
        public static bool IsCurrentControllerAndAction(string controllerName, string actionName, ViewContext viewContext) {
            bool result = false;
            string normalizedControllerName = controllerName.EndsWith("Controller") ? controllerName : String.Format("{0}Controller", controllerName);

            if(viewContext == null) return false;
            if(String.IsNullOrEmpty(actionName)) return false;

            if (viewContext.Controller.GetType().Name.Equals(normalizedControllerName, StringComparison.InvariantCultureIgnoreCase) &&
                viewContext.Controller.ValueProvider.GetValue("action").AttemptedValue.Equals(actionName, StringComparison.InvariantCultureIgnoreCase)) {
                result = true;
            }

            return result;
        }
    }
}

ดังนั้นใน View (หรือ master / layout) คุณสามารถใช้มันได้ (ไวยากรณ์ของมีดโกนหนวด):

            <div id="menucontainer">

                <ul id="menu">
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home", "index", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("account","logon", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("Logon", "Logon", "Account")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home","about", ViewContext)) {
                            @:class="selected"
                        }>@Html.ActionLink("About", "About", "Home")</li>
                </ul>

            </div>

หวังว่ามันจะช่วย


15

คุณสามารถรับข้อมูลเหล่านี้ได้จาก RouteData ของ ViewContext

ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["action"]

9

ใน MVC คุณควรจัดเตรียมมุมมองพร้อมข้อมูลทั้งหมดอย่าปล่อยให้มุมมองรวบรวมข้อมูลของตัวเองเพื่อที่คุณสามารถทำได้คือตั้งค่าคลาส CSS ในแอคชั่นควบคุมของคุณ

ViewData["CssClass"] = "bold";

และเลือกค่านี้จาก ViewData ของคุณในมุมมองของคุณ


นี่จะเป็นวิธีที่ฉันชอบและป้องกันไม่ให้มุมมองขึ้นอยู่กับโครงสร้างของตัวควบคุม แต่ก็สามารถทำได้เช่นกัน
tvanfosson

1
ไม่แน่ใจว่าฉันจะตั้งชื่อมันว่า "CssClass" ตามที่ดูเหมือนจะระบุว่าตรรกะการแสดงผลกำลังคืบคลานเข้าสู่คอนโทรลเลอร์ของคุณ
tvanfosson

เห็นด้วยฉันมักจะทำอะไรบางอย่างเช่น "บริบท" ดังนั้นจึงไม่เชื่อมโยงกับเลเยอร์การนำเสนอและไม่แตกถ้าคุณเปลี่ยนชื่อมุมมอง
RedFilter

6

ฉันลงคะแนนให้ 2:

string currentActionName = ViewContext.RouteData.GetRequiredString("action");

และ

string currentViewName = ((WebFormView)ViewContext.View).ViewPath;

คุณสามารถเรียกคืนทั้งชื่อฟิสิคัลของมุมมองปัจจุบันและแอ็คชันที่เรียกใช้ มันสามารถเป็นประโยชน์ในหน้า * .acmx บางส่วนเพื่อกำหนดโฮสต์คอนเทนเนอร์


2

ฉันกำลังใช้ ASP.NET MVC 4 และสิ่งนี้ใช้ได้กับฉัน:

ControllerContext.Controller.ValueProvider.GetValue("controller").RawValue
ControllerContext.Controller.ValueProvider.GetValue("action").RawValue

0

ขยายคำตอบของ Dale Raganตัวอย่างของเขาสำหรับการนำมาใช้ใหม่สร้างคลาส ApplicationController ซึ่งมาจากตัวควบคุมและในทางกลับกันให้คอนโทรลเลอร์อื่น ๆ ของคุณได้รับมาจากคลาส ApplicationController นั้นแทนที่จะเป็นตัวควบคุม

ตัวอย่าง:

public class MyCustomApplicationController : Controller {}

public class HomeController : MyCustomApplicationController {}

บน ApplicationController ใหม่ของคุณสร้างคุณสมบัติชื่อ ExecutingAction พร้อมลายเซ็นนี้:

protected ActionDescriptor ExecutingAction { get; set; }

และจากนั้นในวิธีการ OnActionExecuting (จากคำตอบของ Dale Ragan) เพียงแค่กำหนด ActionDescriptor ให้กับคุณสมบัตินี้และคุณสามารถเข้าถึงได้ทุกเมื่อที่คุณต้องการในตัวควบคุมใด ๆ ของคุณ

string currentActionName = this.ExecutingAction.ActionName;

0

แทนที่ฟังก์ชั่นนี้ในคอนโทรลเลอร์ของคุณ

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.