รับชื่อพื้นที่ปัจจุบันในมุมมองหรือตัวควบคุม


126

คุณได้รับชื่อพื้นที่ปัจจุบันในมุมมองหรือคอนโทรลเลอร์ได้อย่างไร?

มีอะไรที่ต้องการViewContext.RouteData.Values["controller"]สำหรับพื้นที่หรือไม่?

คำตอบ:


218

ตั้งแต่ MVC2 เป็นต้นไปคุณสามารถใช้ไฟล์ ViewContext.RouteData.DataTokens["area"]


22
หากไม่ได้อยู่ในพื้นที่ ViewContext.RouteData.DataTokens ["area"] == null
user202448

23
... และใน MVC5 :)
Stefan

4
ฮ่า ๆ .. เรื่องตลกอยู่ที่คุณ @ ดันเต้ ... ดีจะเรียกว่าASP.NET Core 1.0แทนMVC6.. :-)
Rosdi Kasim

FYI - พบว่าเกิดอะไรขึ้นกับ ajax POST ของฉันไม่ทำงาน ... โปรดตรวจสอบคำขอ ajax ของคุณมีพื้นที่ใน URL ... พวกเขาอาจยังพบ !!! มุมมอง แต่พวกเขาจะไม่รักษาพื้นที่ ... หาก url ไม่มีพื้นที่เมื่อมีการร้องขอ
Seabizkit

44
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["area"]

3
นี่เป็นวิธีที่ดีที่สุดและเป็นสากลในการรับข้อมูลพื้นที่หากคุณไม่ได้อยู่ในมุมมองหรือตัวควบคุม ขอบคุณสำหรับการโพสต์สิ่งนี้!
bdrelling

20

คุณสามารถรับได้จากคอนโทรลเลอร์โดยใช้:

ControllerContext.RouteData.DataTokens["area"]

@ user202338 พื้นที่ถูกนำมาใช้ใน MVC2 ดังนั้นฉันจึงสงสัยเช่นนั้น แต่ฉันไม่แน่ใจว่าพวกเขาเปลี่ยนวิธีการเติมข้อมูลคอลเลกชัน DataTokens หรือไม่ ฉันเห็นโพสต์แบบนี้: ลิงก์ที่พูดถึงการใช้ใน MVC2
Matt Penner

10

ใน ASP.NET Core 1.0 พบค่าใน

ViewContext.RouteData.Values ​​[ "พื้นที่"];


คุณแน่ใจไหม? เท่าที่ฉันจำได้มันใช้งานได้เมื่อเรารันแอพของเราบน ASP.NET Core 2.0 และตอนนี้ยังใช้งานได้ใน ASP.NET Core 2.1 (ทดสอบเมื่อครู่ที่ผ่านมา)
zerox981

คุณพูดถูกไม่ได้ทำงานเฉพาะกับ Razor Pages (ไม่มี ViewContext - pageModel.RouteData.Values.TryGetValue("area", out object area)ควรใช้แทน)
Roman Pokrovskij

9

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

สิ่งสำคัญคือคุณดึง MVC Area จาก. DataTokens และตัวควบคุม / การกระทำจาก. Value ของ 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;
    }

จากนั้นคุณสามารถใช้งานได้ดังนี้:

<ul id="menu">
@Html.TopMenuLink("Dashboard", "Home", "Index", "", "Click here for the dashboard.")
@Html.TopMenuLink("Courses", "Home", "Index", "Courses", "List of our Courses.")
</ul>

ด้วยเหตุผลบางอย่างฉันไม่พบareaโทเค็นในValuesแต่จำเป็นต้องดูในDataTokens... ไม่รู้ว่าทำไม
Syska

8

ฉันสร้างวิธีการขยายสำหรับRouteDataที่ส่งคืนชื่อพื้นที่ปัจจุบัน

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

    return null;
}

เนื่องจากRouteDataมีให้ใช้งานทั้งสองอย่างControllerContextและViewContextสามารถเข้าถึงได้ในคอนโทรลเลอร์และมุมมองของคุณ

นอกจากนี้ยังง่ายมากที่จะทดสอบ:

[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();
    }
}

ไม่จำเป็นต้องตรวจสอบว่าRouteData.DataTokensเป็นโมฆะหรือไม่เนื่องจากสิ่งนี้จะเริ่มต้นภายในเสมอ


3

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


1
มีวิธีการเช่นนั้นสำหรับคอนโทรลเลอร์หรือไม่? ฉันเกลียดการใช้ตัวอักษรสตริงในคอลเลกชัน
Erick T

สำหรับการใช้คอนโทรลเลอร์this.GetName()และสำหรับวิธีการใช้งานปัจจุบันMethodBase.GetCurrentMethod().Name
Nerdroid

3

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

สามารถพบได้ในรหัสต่อไปนี้:

var routeData = filterContext.RequestContext.RouteData;

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

ดังนั้น filterContext จะถูกส่งผ่านไปบนการแทนที่และพบ RouteData ที่ถูกต้องภายใต้ RequestContext มี RoutData ที่ระดับ Base แต่ DataTokens ไม่มีพื้นที่ในพจนานุกรม


2

ในการรับชื่อพื้นที่ในมุมมองใน ASP.NET Core MVC 2.1:

@Context.GetRouteData().Values["area"]


0

ฉันรู้ว่านี่เป็นโพสต์เก่ามาก แต่เราสามารถใช้คุณสมบัติค่าในลักษณะเดียวกับ DataTokens

Url.RequestContext.RouteData.Values ​​["action"] ใช้ได้ผลสำหรับฉัน


0

ฉันไม่รู้ว่าทำไม แต่คำตอบที่ได้รับการยอมรับไม่ได้ผล มันคืนค่า null ด้วยเช่น (อาจเกี่ยวกับ mvc ฉันใช้. net core)

http: // localhost: 5000 / ธุรการ / CustomerGroup

ฉันมักจะดีบักตัวแปรและดึงข้อมูลจากในนั้น

ลองทำตามนี้ มันใช้ได้กับฉัน

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

ตัวอย่างตรรกะโดยละเอียด

Layout = ViewContext.RouteData.Values["area"] == null ? "_LayoutUser" : "_LayoutAdmin";
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.