Dapatkan nama pengontrol dan tindakan dari dalam pengontrol?

173

Untuk aplikasi web kami, saya harus menyimpan urutan item yang diambil dan ditampilkan tergantung pada tampilan - atau tepatnya - pengontrol dan tindakan yang menghasilkan tampilan (dan id pengguna tentu saja, tapi bukan itu intinya di sini).

Alih-alih hanya memberikan pengidentifikasi sendiri dalam setiap tindakan pengontrol (untuk menggunakannya untuk beberapa pengurutan keluaran DB), saya berpikir bahwa akan lebih aman dan lebih mudah untuk membuat pengidentifikasi ini secara otomatis dari pengontrol dan metode tindakan yang didapatnya. dipanggil dari.

Bagaimana saya bisa mendapatkan nama controller dan action dari dalam metode action di controller? Atau apakah saya perlu refleksi untuk itu? Saya kira itu sangat mudah, terima kasih sebelumnya!

Alex
sumber
1
Refleksi akan memberi Anda nama metode yang menangani tindakan, tetapi mungkin Anda lebih suka nama tindakan yang dikembalikan oleh kode Andrei.
citykid
Saya pada dasarnya hanya membutuhkan pengidentifikasi yang jelas untuk setiap tindakan yang memberikan tampilan, sehingga kedua cara akan melakukan pekerjaan. Tapi Anda benar, jawaban Andrei jelas lebih elegan.
Alex
@citykid Apakah ada kasus di mana ini berbeda dalam perilaku selain kasus dan akhiran "Controller" untuk nama kelas?
John
@ John, ActionNameAttribute memungkinkan metode ac # untuk memiliki nama tindakan apa pun: msdn.microsoft.com/en-us/library/…
citykid
@citykid Oh, ok. Itu semacam fitur usang mengingat Anda bisa menentukan rute dengan Routeatribut pada metode tindakan yang saya kumpulkan? Juga, apakah mungkin untuk mengganti nama pengontrol?
John

Jawaban:

345
string actionName = this.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = this.ControllerContext.RouteData.Values["controller"].ToString();
Andrei
sumber
13
Dalam beberapa kasus di mana Anda mungkin ingin memiliki nama controller di file View, maka Anda bisa menggunakan ini.ViewContext.RouteData.Values ​​["controller"]. ToString ();
Amogh Natu
Jika Anda akan melakukan ini (berikan nama tindakan dan pengontrol), mengapa tidak menetapkan mereka secara langsung ???
MetalPhoenix
1
@ MetalPhoenix, dapatkah Anda sedikit menjelaskan kasus penggunaan apa yang Anda bicarakan? OP tidak perlu menetapkan controller atau action - mereka hanya perlu memahami, secara umum, apa saja controller dan action yang sedang diproses.
Andrei
1
Pada bacaan kedua, apakah mungkin saya salah mengerti kode snippit di sini? ... Nilai ["aksi"] di mana "aksi" adalah kunci dan bukan nama tindakan yang akan diganti (seperti "'Pass123' tanpa tanda kutip" jenis barang)? Dengan kata lain: apakah masih akan Nilai ["tindakan"] alih-alih Nilai ["yourAction"]?
MetalPhoenix
@MetalPhoenix, tepatnya, "action" literal adalah kuncinya, dan Nilai ["action"] akan menampilkan "CurrentActionName"
Andrei
62

Berikut adalah beberapa metode ekstensi untuk mendapatkan informasi tersebut (termasuk 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;
    }
}

Pemakaian:

@Html.Controller();
@Html.Action();
@Html.Id();
John Bubriski
sumber
1
Solusi Terbaik & Lengkap, Terima Kasih Jhon
Umar Abbas
24

Mungkin bermanfaat. Saya membutuhkan tindakan dalam konstruktor controller, dan muncul pada titik siklus hidup MVC, thisbelum diinisialisasi, dan ControllerContext = null. Alih-alih mempelajari siklus hidup MVC dan menemukan nama fungsi yang tepat untuk menggantikan, saya hanya menemukan tindakan di RequestContext.RouteData.

Tetapi untuk melakukannya, seperti halnya HttpContextpenggunaan terkait dalam konstruktor, Anda harus menentukan namespace lengkap, karena this.HttpContextjuga belum diinisialisasi. Untungnya, itu tampak System.Web.HttpContext.Currentstatis.

// 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
}

CATATAN: kemungkinan bukan cara yang paling didukung untuk mengakses semua properti di HttpContext, tetapi untuk RequestContext dan Session tampaknya berfungsi dengan baik dalam aplikasi saya.

sonjz
sumber
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();
    }
}
Chris Ballance
sumber
5
 @this.ViewContext.RouteData.Values["controller"].ToString();
Hossein Hajizadeh
sumber
4

Inilah yang saya miliki sejauh ini:

var actionName = filterContext.ActionDescriptor.ActionName;
var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
pengguna3563149
sumber
3

Inilah jawaban paling sederhana dan paling praktis untuk mendapatkan nama:

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

Atau

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

Kode tes di atas dengan asp.net mvc 5.

Matheus Miranda
sumber
2

Tambahkan ini ke pengontrol dasar Anda di dalam metode 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;
    }

Terapkan pengendali Anda ke Basecontroller

Tambahkan sebagian tampilan _Breadcrumb.cshtml dan tambahkan di semua halaman yang diperlukan dengan @ Html.Partial ("_ Breadcrumb")

_Breadcrumb.cshtml

<span>
    <a href="../@ViewData["controllerName"]">
        @ViewData["controllerName"]
    </a> > @ViewData["actionName"]
</span>
Kurkula
sumber
(1): Apakah ini masih salah satu cara paling umum dalam MVC5? (2) Dari mana Anda mendapatkan filterContextvariabel dari dalam GetDefaults()?
chriszo111
1

Anda bisa mendapatkan nama pengontrol atau nama tindakan dari tindakan seperti variabel apa pun. Mereka hanya spesial (controller dan action) dan sudah didefinisikan sehingga Anda tidak perlu melakukan sesuatu yang istimewa untuk mendapatkannya kecuali mengatakan Anda membutuhkannya.

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

Atau Anda dapat memasukkan controller, aksi dalam model Anda untuk mendapatkan dua dari mereka dan data kustom Anda.

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;
    }
MstfAsan
sumber
1

Ini sepertinya bekerja dengan baik untuk saya (sejauh ini), juga berfungsi jika Anda menggunakan perutean atribut.

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");
    }
}
joepour
sumber
1

Untuk menghapus kebutuhan akan ToString()penggunaan panggilan

string actionName = ControllerContext.RouteData.GetRequiredString("action");
string controllerName = ControllerContext.RouteData.GetRequiredString("controller");
Vadim Ovchinnikov
sumber
1

Gunakan baris yang diberikan di OnActionExecuting for Action dan nama Controller.

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

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

Bilal Raj
sumber
-8

Mengapa tidak memiliki sesuatu yang lebih sederhana?

Panggil saja Request.Path, itu akan mengembalikan String Dipisahkan oleh "/"

dan kemudian Anda dapat menggunakan .Split('/')[1]untuk mendapatkan Nama Pengendali.

masukkan deskripsi gambar di sini

adie wong
sumber
1
-1: dengan kode Anda, aplikasi sub-level diabaikan begitu saja (misalnya:) http://www.example.com/sites/site1/controllerA/actionB/. MVC menyediakan banyak API untuk perutean, jadi mengapa Anda perlu mem-parsing (lagi) URL ?.
T-moty
Mengapa menemukan kembali roda dan selanjutnya, dengan reinvension yang buruk? ini tidak berfungsi untuk semua kasus.
jstuardo
selain dari subfolder, masalah sebenarnya adalah Anda dapat menyesuaikan rute agar tidak selalucontroller/action
drzaus