Dapatkan Nama Area Saat Ini di View atau Controller

126

Bagaimana Anda mendapatkan nama area saat ini dalam tampilan atau pengontrol?

Apakah ada yang seperti ViewContext.RouteData.Values["controller"]untuk area?

pengguna202448
sumber

Jawaban:

217

Dari MVC2 dan seterusnya, Anda dapat menggunakan ViewContext.RouteData.DataTokens["area"]

artvolk
sumber
22
Jika tidak di suatu area, ViewContext.RouteData.DataTokens ["area"] == null.
user202448
23
... dan di MVC5 :)
Stefan
4
Lol .. lelucon ada pada Anda @ante ... baik untuk adil itu disebut ASP.NET Core 1.0bukan MVC6.. :-)
Rosdi Kasim
FYI - menemukan apa yang salah dengan POST ajax saya tidak berfungsi ... silakan periksa permintaan ajax Anda memiliki area di URL ... mereka mungkin masih menemukan !!! tampilan, tetapi mereka tidak akan mempertahankan daerah ... jika url tidak ada daerah ketika permintaan dibuat.
Seabizkit
43
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]
Slava
sumber
3
Ini adalah cara universal terbaik untuk mendapatkan info area, jika Anda tidak berada dalam tampilan atau pengontrol. Terima kasih telah memposting ini!
bdrelling
19

Anda bisa mendapatkannya dari controller menggunakan:

ControllerContext.RouteData.DataTokens["area"]
Matt Penner
sumber
@ user202338 Area diperkenalkan di MVC2 jadi saya akan curiga, tapi saya tidak yakin apakah mereka telah mengubah cara mereka mengisi koleksi DataTokens. Saya memang melihat posting seperti ini: tautan yang berbicara tentang menggunakannya di MVC2.
Matt Penner
10

Di ASP.NET Core 1.0 nilainya ditemukan di

ViewContext.RouteData.Values ​​["area"];

zerox981
sumber
Apakah kamu yakin Sejauh yang saya ingat itu berhasil ketika kami menjalankan aplikasi kami di ASP.NET Core 2.0 dan masih bekerja sekarang di ASP.NET Core 2.1 (diuji beberapa saat yang lalu).
zerox981
Anda benar, tidak hanya bekerja untuk Razor Pages (tidak ada ViewContext - pageModel.RouteData.Values.TryGetValue("area", out object area)harus digunakan sebagai gantinya)
Roman Pokrovskij
9

Saya baru saja menulis entri log ab tentang ini , Anda dapat mengunjungi itu untuk lebih jelasnya, tetapi jawaban saya adalah membuat Metode Ekstensi, yang ditunjukkan di bawah ini.

Penendang kuncinya adalah Anda menarik Area MVC dari .DataTokens dan pengontrol / aksi dari .Values ​​dari RouteData.

public static MvcHtmlString TopMenuLink(this HtmlHelper htmlHelper, string linkText, string controller, string action, string area, string anchorTitle)
    {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
        var url = urlHelper.Action(action, controller, new { @area = area });

        var anchor = new TagBuilder("a");
        anchor.InnerHtml = HttpUtility.HtmlEncode(linkText);
        anchor.MergeAttribute("href", url);
        anchor.Attributes.Add("title", anchorTitle);

        var listItem = new TagBuilder("li");
        listItem.InnerHtml = anchor.ToString(TagRenderMode.Normal);

        if (CheckForActiveItem(htmlHelper, controller, action, area))
            listItem.GenerateId("menu_active");

        return MvcHtmlString.Create(listItem.ToString(TagRenderMode.Normal));
    }

    private static bool CheckForActiveItem(HtmlHelper htmlHelper, string controller, string action, string area)
    {
        if (!CheckIfTokenMatches(htmlHelper, area, "area"))
            return false;

        if (!CheckIfValueMatches(htmlHelper, controller, "controller"))
            return false;

        return CheckIfValueMatches(htmlHelper, action, "action");
    }

    private static bool CheckIfValueMatches(HtmlHelper htmlHelper, string item, string dataToken)
    {
        var routeData = (string)htmlHelper.ViewContext.RouteData.Values[dataToken];

        if (routeData == null) return string.IsNullOrEmpty(item);

        return routeData == item;
    }

    private static bool CheckIfTokenMatches(HtmlHelper htmlHelper, string item, string dataToken)
    {
        var routeData = (string)htmlHelper.ViewContext.RouteData.DataTokens[dataToken];

        if (dataToken == "action" && item == "Index" && string.IsNullOrEmpty(routeData))
            return true;

        if (dataToken == "controller" && item == "Home" && string.IsNullOrEmpty(routeData))
            return true;

        if (routeData == null) return string.IsNullOrEmpty(item);

        return routeData == item;
    }

Kemudian Anda bisa menerapkannya seperti di bawah ini:

<ul id="menu">
@Html.TopMenuLink("Dashboard", "Home", "Index", "", "Click here for the dashboard.")
@Html.TopMenuLink("Courses", "Home", "Index", "Courses", "List of our Courses.")
</ul>
christesene
sumber
Untuk beberapa alasan saya tidak dapat menemukan areatoken di Valuestetapi perlu mencari di DataTokens... tidak tahu kenapa.
Syska
8

Saya membuat metode ekstensi untuk RouteDatamengembalikan nama area saat ini.

public static string GetAreaName(this RouteData routeData)
{
    object area;
    if (routeData.DataTokens.TryGetValue("area", out area))
    {
        return area as string;
    }

    return null;
}

Karena RouteDatatersedia di keduanya ControllerContextdanViewContext dapat diakses di controller dan tampilan Anda.

Ini juga sangat mudah untuk diuji:

[TestFixture]
public class RouteDataExtensionsTests
{
    [Test]
    public void GetAreaName_should_return_area_name()
    {
        var routeData = new RouteData();
        routeData.DataTokens.Add("area", "Admin");
        routeData.GetAreaName().ShouldEqual("Admin");
    }

    [Test]
    public void GetAreaName_should_return_null_when_not_set()
    {
        var routeData = new RouteData();
        routeData.GetAreaName().ShouldBeNull();
    }
}

Tidak perlu memeriksa apakah RouteData.DataTokensnol karena ini selalu diinisialisasi secara internal.

Ben Foster
sumber
3

MVC Futures memiliki metode AreaHelpers.GetAreaName (). Namun, berhati-hatilah jika Anda menggunakan metode ini. Menggunakan area saat ini untuk membuat keputusan runtime tentang aplikasi Anda dapat menyebabkan kode sulit-untuk-debug atau tidak aman.

Retribusi
sumber
1
Apakah ada metode seperti itu untuk pengontrol? Saya benci menggunakan string literal ke dalam koleksi.
Erick T
untuk penggunaan pengontrol this.GetName()dan untuk penggunaan Metode saat iniMethodBase.GetCurrentMethod().Name
Nerdroid
3

Saya tahu ini sudah tua, tetapi juga, ketika dalam filter seperti ActionFilter, konteksnya tidak mudah memberi Anda informasi area.

Itu dapat ditemukan dalam kode berikut:

var routeData = filterContext.RequestContext.RouteData;

if (routeData.DataTokens["area"] != null)
    area = routeData.DataTokens["area"].ToString();

Jadi filterContext diteruskan pada override dan RouteData yang benar ditemukan di bawah RequestContext. Ada RoutData di tingkat Basis, tetapi DataTokens TIDAK memiliki area dalam kamus itu.

gcoleman0828
sumber
2

Untuk mendapatkan nama area dalam tampilan, di ASP.NET Core MVC 2.1:

@Context.GetRouteData().Values["area"]
Netstep
sumber
2

Dapatkan nama area di View (.NET Core 2.2):

ViewContext?.ActionDescriptor?.RouteValues["area"]
SZL
sumber
0

Saya tahu ini adalah posting yang sangat sangat lama tetapi kita dapat menggunakan Properti Nilai persis dengan cara yang sama seperti DataTokens

Url.RequestContext.RouteData.Values ​​["action"] bekerja untuk saya.

Joao Nunes da Silva
sumber
0

Saya tidak tahu mengapa tetapi jawaban yang diterima tidak berfungsi. Mengembalikan null dengan misalnya (mungkin tentang MVC, saya menggunakan .net core)

http: // localhost: 5000 / Admin / CustomerGroup

Saya selalu men-debug variabel dan mengambil data dari dalamnya.

Coba ini. Ini bekerja untuk saya

var area = ViewContext.RouteData.Values["area"]

Contoh logis terperinci

Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";
fthopkins
sumber