รับชื่อคอนโทรลเลอร์และแอ็คชันจากภายในคอนโทรลเลอร์?


173

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

แทนที่จะให้ตัวระบุในการดำเนินการควบคุมแต่ละตัว (เพื่อใช้สำหรับการเรียงลำดับมุมมองบางส่วนของเอาต์พุต DB) ฉันคิดว่ามันจะปลอดภัยและง่ายกว่าในการสร้างตัวระบุนี้โดยอัตโนมัติจากตัวควบคุมและวิธีการกระทำที่ได้รับ เรียกจาก

ฉันจะได้รับชื่อของตัวควบคุมและการกระทำจากภายในวิธีการดำเนินการในตัวควบคุมได้อย่างไร หรือฉันต้องการภาพสะท้อนเพื่อสิ่งนั้น? ฉันคิดว่ามันค่อนข้างง่ายขอบคุณล่วงหน้า!


1
Reflection จะให้ชื่อวิธีที่จัดการกับการกระทำของคุณ แต่สมมุติว่าคุณต้องการชื่อการกระทำที่ส่งคืนโดยรหัสของ Andrei
citykid

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

@citykid มีกรณีที่สิ่งเหล่านี้แตกต่างกันในลักษณะอื่นนอกเหนือจากกรณีและส่วนต่อท้าย "ควบคุม" สำหรับชื่อชั้น?
จอห์น

@John, ActionNameAttribute อนุญาตให้ ac # method มีชื่อการกระทำใด ๆ : msdn.microsoft.com/en-us/library/…
citykid

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

คำตอบ:


345
string actionName = this.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = this.ControllerContext.RouteData.Values["controller"].ToString();

13
ในบางกรณีที่คุณอาจต้องการชื่อของตัวควบคุมในไฟล์มุมมองจากนั้นคุณสามารถใช้ไฟล์นี้ได้ ViewContext.RouteData.Values ​​["controller"] ToString ();
Amogh Natu

หากคุณกำลังจะทำสิ่งนี้ (ระบุการดำเนินการและชื่อคอนโทรลเลอร์) ทำไมไม่เพียงกำหนดให้พวกเขาโดยตรง?
MetalPhoenix

1
@ MetalPhoenix คุณช่วยอธิบายให้ฟังหน่อยเกี่ยวกับกรณีที่คุณกำลังพูดถึงอะไร? OP ไม่จำเป็นต้องกำหนดตัวควบคุมหรือการกระทำ - พวกเขาเพียงแค่ต้องเข้าใจในแบบทั่วไปสิ่งที่เป็นตัวควบคุมและการกระทำที่กำลังประมวลผล
Andrei

1
ในการอ่านครั้งที่สองเป็นไปได้หรือไม่ที่ฉันเข้าใจผิดโค้ดที่นี่? ... คุณค่า ["การกระทำ"] โดยที่ "การกระทำ" เป็นกุญแจสำคัญและไม่ใช่ชื่อของการกระทำที่จะถูกแทนที่ (เช่น "'Pass123' โดยไม่มีเครื่องหมายคำพูด" เป็นประเภทของสิ่ง) หรือไม่ กล่าวคือจะยังคงเป็นค่า ["การกระทำ"] แทนที่จะเป็นค่า ["yourAction"] หรือไม่
MetalPhoenix

@MetalPhoenix ตรงตามตัวอักษร "action" เป็นกุญแจสำคัญและ Values ​​["action"] จะแสดงผล "CurrentActionName"
Andrei

62

ต่อไปนี้เป็นวิธีส่วนขยายบางส่วนสำหรับการรับข้อมูล (รวมถึง ID ด้วย):

public static class HtmlRequestHelper
{
    public static string Id(this HtmlHelper htmlHelper)
    {
        var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

        if (routeValues.ContainsKey("id"))
            return (string)routeValues["id"];
        else if (HttpContext.Current.Request.QueryString.AllKeys.Contains("id"))
            return HttpContext.Current.Request.QueryString["id"];

        return string.Empty;
    }

    public static string Controller(this HtmlHelper htmlHelper)
    {
        var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

        if (routeValues.ContainsKey("controller"))
            return (string)routeValues["controller"];

        return string.Empty;
    }

    public static string Action(this HtmlHelper htmlHelper)
    {
        var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

        if (routeValues.ContainsKey("action"))
            return (string)routeValues["action"];

        return string.Empty;
    }
}

การใช้งาน:

@Html.Controller();
@Html.Action();
@Html.Id();

1
ทางออกที่ดีที่สุด & สมบูรณ์ขอบคุณ Jhon
Umar Abbas

24

อาจจะมีประโยชน์ ผมจำเป็นต้องมีการดำเนินการในการคอนสตรัคของตัวควบคุมและจะปรากฏที่จุดของวงจรชีวิต MVC นี้ยังไม่ได้เริ่มต้นและthis ControllerContext = nullแทนการขุดคุ้ยวงจร MVC RequestContext.RouteDataและการหาชื่อฟังก์ชั่นที่เหมาะสมเพื่อแทนที่ฉันเพิ่งพบการกระทำที่

แต่เพื่อที่จะทำเช่นเดียวกับการHttpContextใช้งานที่เกี่ยวข้องใด ๆในตัวสร้างคุณต้องระบุเนมสเปซเต็มรูปแบบเพราะthis.HttpContextยังไม่ได้เริ่มต้น โชคดีที่มันดูเหมือนว่าSystem.Web.HttpContext.Currentคงที่

// controller constructor
public MyController() {
    // grab action from RequestContext
    string action = System.Web.HttpContext.Current.Request.RequestContext.RouteData.GetRequiredString("action");

    // grab session (another example of using System.Web.HttpContext static reference)
    string sessionTest = System.Web.HttpContext.Current.Session["test"] as string
}

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


11
var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;
if (routeValues != null) 
{
    if (routeValues.ContainsKey("action"))
    {
        var actionName = routeValues["action"].ToString();
                }
    if (routeValues.ContainsKey("controller"))
    {
        var controllerName = routeValues["controller"].ToString();
    }
}


4

นี่คือสิ่งที่ฉันมี:

var actionName = filterContext.ActionDescriptor.ActionName;
var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;

3

นี่คือคำตอบที่ง่ายและปฏิบัติได้จริงที่สุดในการตั้งชื่อ:

var actionName = RouteData.Values["action"];
var controllerName = RouteData.Values["controller"];

หรือ

string actionName = RouteData.Values["action"].ToString();
string controllerName = RouteData.Values["controller"].ToString();

โค้ดข้างต้นทดสอบกับ asp.net mvc 5


2

เพิ่มสิ่งนี้ไปยังตัวควบคุมฐานของคุณภายในวิธี GetDefaults ()

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
         GetDefaults();
         base.OnActionExecuting(filterContext);
    }

    private void GetDefaults()
    {
    var actionName = filterContext.ActionDescriptor.ActionName;
    var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
    }

นำคอนโทรลเลอร์ของคุณไปใช้กับBasecontroller

เพิ่ม _Breadcrumb.cshtml มุมมองบางส่วนและเพิ่มลงในหน้าเว็บที่จำเป็นทั้งหมดด้วย @ Html.Partial ("_ Breadcrumb")

_Breadcrumb.cshtml

<span>
    <a href="../@ViewData["controllerName"]">
        @ViewData["controllerName"]
    </a> > @ViewData["actionName"]
</span>

(1): นี่เป็นหนึ่งในวิธีที่พบได้บ่อยที่สุดใน MVC5 หรือไม่ (2) คุณได้filterContextตัวแปรจากภายในGetDefaults()ที่ไหน
chriszo111

1

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

public string Index(string controller,string action)
   {
     var names=string.Format("Controller : {0}, Action: {1}",controller,action);
     return names;
   }

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

public class DtoModel
    {
        public string Action { get; set; }
        public string Controller { get; set; }
        public string Name { get; set; }
    }

public string Index(DtoModel baseModel)
    {
        var names=string.Format("Controller : {0}, Action: {1}",baseModel.Controller,baseModel.Action);
        return names;
    }

1

ดูเหมือนว่าจะใช้งานได้ดีสำหรับฉัน (จนถึงตอนนี้) สามารถใช้งานได้หากคุณใช้การกำหนดเส้นทางแอตทริบิวต์

public class BaseController : Controller
{
    protected string CurrentAction { get; private set; }
    protected string CurrentController { get; private set; }

    protected override void Initialize(RequestContext requestContext)
    {
        this.PopulateControllerActionInfo(requestContext);
    }

    private void PopulateControllerActionInfo(RequestContext requestContext)
    {
        RouteData routedata = requestContext.RouteData;

        object routes;

        if (routedata.Values.TryGetValue("MS_DirectRouteMatches", out routes))
        {
            routedata = (routes as List<RouteData>)?.FirstOrDefault();
        }

        if (routedata == null)
            return;

        Func<string, string> getValue = (s) =>
        {
            object o;
            return routedata.Values.TryGetValue(s, out o) ? o.ToString() : String.Empty;
        };

        this.CurrentAction = getValue("action");
        this.CurrentController = getValue("controller");
    }
}

1

ในการลบความต้องการToString()ใช้การโทรออก

string actionName = ControllerContext.RouteData.GetRequiredString("action");
string controllerName = ControllerContext.RouteData.GetRequiredString("controller");

1

ใช้บรรทัดที่กำหนดใน OnActionExecuting สำหรับชื่อ Action และ Controller

สตริง actionName = this.ControllerContext.RouteData.Values ​​["action"] ToString ();

สตริง controllerName = this.ControllerContext.RouteData.Values ​​["คอนโทรลเลอร์"] ToString ();


-8

ทำไมไม่มีอะไรที่ง่ายกว่านี้?

เพียงแค่โทรRequest.Pathมันจะส่งกลับสตริงคั่นด้วย "/"

จากนั้นคุณสามารถใช้.Split('/')[1]เพื่อรับชื่อคอนโทรลเลอร์

ป้อนคำอธิบายรูปภาพที่นี่


1
-1: ด้วยรหัสการใช้งานระดับย่อยของคุณจะถูกละเว้นเพียง (เช่นhttp://www.example.com/sites/site1/controllerA/actionB/) MVC มี API จำนวนมากสำหรับการกำหนดเส้นทางดังนั้นทำไมคุณต้องแยกวิเคราะห์ URL อีกครั้ง
T-moty

ทำไมต้องบูรณาการล้อและนอกจากนี้ยังมี reinvension ที่ไม่ดี? สิ่งนี้ไม่สามารถใช้ได้กับทุกกรณี
jstuardo

นอกเหนือจากโฟลเดอร์ย่อยปัญหาที่แท้จริงคือคุณสามารถกำหนดเส้นทางของคุณเองเพื่อไม่ให้เป็นเช่นนั้นอีกต่อไปcontroller/action
drzaus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.