Bagaimana saya bisa mengembalikan tindakan saat ini dalam tampilan ASP.NET MVC?

291

Saya ingin mengatur kelas CSS di halaman master saya, yang tergantung pada kontroler dan tindakan saat ini. Saya dapat membuka pengontrol saat ini ViewContext.Controller.GetType().Name, tetapi bagaimana cara mendapatkan tindakan saat ini (mis . Index, ShowDll)?

kereta
sumber

Jawaban:

83

Gunakan ViewContextdan lihat RouteDatakoleksi untuk mengekstrak elemen controller dan action. Tapi saya pikir pengaturan beberapa variabel data yang menunjukkan konteks aplikasi (misalnya, "mode edit" atau "kesalahan") daripada pengontrol / tindakan mengurangi sambungan antara tampilan dan pengontrol Anda.

tvanfosson
sumber
Anda bisa mendapatkan data dalam pengontrol dan meneruskannya untuk dilihat dengan DTO. stackoverflow.com/a/31749391/4293929
MstfAsan
5
ini BUKAN jawaban yang diterima, lihat jawaban yang paling dipilih sebagai gantinya.
Hakan Fıstık
1
@ HakamFostok Saya masih berpikir saran untuk menambahkan informasi semantik ke model adalah metode yang lebih baik dalam semua kasus daripada mengandalkan data rute (pengontrol, tindakan) dalam pandangan Anda, bahkan jika jawaban lain memberikan lebih banyak detail tentang cara mendapatkan data tersebut.
tvanfosson
467

Dalam RC Anda juga dapat mengekstrak data rute seperti nama metode tindakan seperti ini

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

Pembaruan untuk MVC 3

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

Pembaruan untuk MVC 4

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

Pembaruan untuk MVC 4.5

ViewContext.RouteData.Values["action"]
ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["id"]
Christian Dalager
sumber
20
Saya tahu ini V2 pra-tanggal, tapi sekarang ViewContext.Controller.ValueProvider.GetValue("action").RawValuevariasi +
Chris S
7
Sintaks ini bekerja di V4: (string) ViewContext.RouteData.Values ​​["action"];
kiprainey
2
Solusi ini tidak berfungsi untuk saya (MVC4 + .NET Framework 4.5.1). Bagi saya, ini berfungsi dengan jawaban dari Viacheslav Smityukh: ViewContext.RouteData.Values ​​["action"], ViewContext.RouteData.Values ​​["controller"], ViewContext.RouteData.Values ​​["id"],
Tomas Kubes
@kiprainey Di V3.5 juga: msdn.microsoft.com/en-us/library/…
Pluto
2
Coba: (string) HttpContext.Request.RequestContext.RouteData.Values ​​["action"];
Martin Dawson
60

Untuk mendapatkan Id saat ini pada Tampilan:

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

Untuk mendapatkan pengontrol saat ini:

ViewContext.RouteData.Values["controller"].ToString() 
tsquillario
sumber
1
ViewContext.RouteData.Values ​​[<key>] .ToString () melempar pengecualian jika nilainya tidak ada di RouteData
Grizzly Peak Software
@ ShaneLarson Bandingkan dengan nol atau periksa ViewContext.RouteData.Values.ContainsKey(<key>)dulu.
Pluto
40

Saya tahu ini adalah pertanyaan yang lebih lama, tetapi saya melihatnya dan saya pikir Anda mungkin tertarik pada versi alternatif daripada membiarkan pandangan Anda menangani mengambil data yang diperlukan untuk melakukan pekerjaan itu.

Cara yang lebih mudah menurut saya adalah mengganti metode OnActionExecuting . Anda melewati ActionExecutingContext yang berisi anggota ActionDescriptor yang dapat Anda gunakan untuk mendapatkan informasi yang Anda cari, yang merupakan ActionName dan Anda juga dapat mencapai ControllerDescriptor dan berisi 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.
}

Semoga ini membantu. Jika ada, setidaknya itu akan menunjukkan alternatif bagi orang lain yang datang dengan pertanyaan Anda.

Dale Ragan
sumber
rekomendasi yang bagus; membantu saya dalam mengimplementasikan controller / action sensing secara cerdas. Terima kasih!
effkay
Mendapatkan tindakan desrciptor adalah apa yang saya butuhkan, saya tidak dapat menemukan solusi lain, jadi saya hanya melakukannya di sini dan kemudian mendorong apa yang saya inginkan ke dalam viewbag.
Chris Marisic
17

Saya melihat jawaban yang berbeda dan menghasilkan pembantu kelas:

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

Jadi dalam Tampilan (atau master / tata letak) Anda dapat menggunakannya seperti itu (Sintaks Razor):

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

Semoga ini bisa membantu.

Michael Vashchinsky
sumber
15

Anda bisa mendapatkan data ini dari RouteData dari ViewContext

ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["action"]
Viacheslav Smityukh
sumber
9

Di MVC Anda harus memberikan View dengan semua data, jangan biarkan View mengumpulkan datanya sendiri sehingga yang dapat Anda lakukan adalah mengatur kelas CSS dalam aksi controller Anda.

ViewData["CssClass"] = "bold";

dan pilih nilai ini dari ViewData Anda di View Anda

terjetyl
sumber
Ini akan menjadi metode pilihan saya juga untuk menjaga pandangan dari tergantung pada struktur pengontrol, tetapi dapat dilakukan sebaliknya.
tvanfosson
1
Tidak yakin saya akan menamainya "CssClass" karena tampaknya menunjukkan bahwa logika tampilan merayap ke controller Anda.
tvanfosson
Setuju, saya biasanya melakukan sesuatu seperti "Konteks", sehingga tidak terkait dengan lapisan presentasi, dan tidak pecah jika Anda mengubah nama tampilan juga.
RedFilter
6

Saya memilih 2 ini:

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

dan

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

Anda dapat mengambil kembali nama fisik tampilan saat ini dan tindakan yang memicunya. Ini dapat berguna di sebagian * halaman .acmx untuk menentukan wadah host.


sumber
2

Saya menggunakan ASP.NET MVC 4, dan ini yang bekerja untuk saya:

ControllerContext.Controller.ValueProvider.GetValue("controller").RawValue
ControllerContext.Controller.ValueProvider.GetValue("action").RawValue
kiewik
sumber
0

Memperluas jawaban Dale Ragan , contohnya untuk digunakan kembali, membuat kelas ApplicationController yang berasal dari Controller, dan pada gilirannya memiliki semua controller Anda yang lain berasal dari kelas ApplicationController daripada Controller.

Contoh:

public class MyCustomApplicationController : Controller {}

public class HomeController : MyCustomApplicationController {}

Di ApplicationController baru Anda, buat properti bernama ExecutingAction dengan tanda tangan ini:

protected ActionDescriptor ExecutingAction { get; set; }

Dan kemudian dalam metode OnActionExecuting (dari jawaban Dale Ragan), cukup tetapkan ActionDescriptor ke properti ini dan Anda dapat mengaksesnya kapan pun Anda membutuhkannya di salah satu pengontrol Anda.

string currentActionName = this.ExecutingAction.ActionName;
RunnerRick
sumber
0

Ganti fungsi ini di controller Anda

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}
Santosh Pandey
sumber