컨트롤러 내에서 컨트롤러 및 작업 이름을 가져 오시겠습니까?


173

우리의 웹 응용 프로그램의 경우 뷰에 따라 가져 오기 및 표시 된 항목의 순서를 저장해야합니다. 또는 뷰를 생성 한 컨트롤러 및 작업 (및 사용자 ID는 물론 여기서 중요한 것은 아닙니다).

각 컨트롤러 작업에서 식별자를 직접 제공하는 대신 (보기에 따라 DB 출력의 일부 정렬에 사용하기 위해) 컨트롤러와 가져 오는 작업 방법 에서이 식별자를 자동으로 만드는 것이 더 안전하고 쉽다고 생각했습니다. 에서 전화했다.

컨트롤러의 액션 메소드 내에서 컨트롤러 이름과 액션을 어떻게 얻을 수 있습니까? 아니면 그것에 대해 반성이 필요합니까? 미리 감사드립니다.


1
리플렉션은 액션을 처리하는 메소드 이름을 제공하지만 Andrei의 코드가 반환하는 액션 이름을 선호 할 것입니다.
citykid

기본적으로보기를 제공하는 모든 작업에 대해 명확한 식별자가 필요하므로 두 가지 방법으로 작업을 수행 할 수 있습니다. 그러나 당신이 옳습니다. Andrei의 대답은 분명히 더 우아합니다.
Alex

@citykid 클래스 이름에 대해 대소 문자와 "컨트롤러"접미사 이외의 방식이 다른 경우가 있습니까?
John

@John, ActionNameAttribute를 사용하면 ac # 메서드가 모든 작업 이름을 가질 수 있습니다. msdn.microsoft.com/en-us/library/…
citykid

@citykid 오, 알겠습니다. Route내가 수집 한 작업 방법에 속성을 사용하여 경로를 지정할 수 있다는 점에서 쓸모없는 기능 입니까? 또한 컨트롤러의 이름을 바꿀 수도 있습니까?
John

답변:


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

13
View 파일에서 컨트롤러 이름을 원할 경우 this.ViewContext.RouteData.Values ​​[ "controller"]. ToString ();
Amogh Natu

이 작업을 수행하려면 (작업 및 컨트롤러 이름 제공) 직접 할당하지 않는 이유는 무엇입니까 ???
MetalPhoenix

1
@MetalPhoenix, 무슨 유스 케이스에 대해 설명해 주실 수 있습니까? OP는 컨트롤러 또는 작업을 할당 할 필요가 없습니다. 일반적으로 현재 처리중인 컨트롤러 및 작업이 무엇인지 이해하면됩니다.
Andrei

1
두 번째로 읽을 때 여기에서 코드 조각을 잘못 이해할 수 있습니까? ... Values ​​[ "action"] 여기서 "action"은 키이며 대체 할 조치의 이름이 아닙니다 (예 : "따옴표없는 'Pass123'"유형)? 다시 말해, Values ​​[ "yourAction"] 대신 Values ​​[ "action"]이 될 것입니까?
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
Best & Complete Solution, Thanks Jhon
우마르 압바스

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 및 Session의 경우 내 응용 프로그램에서 제대로 작동하는 것으로 보입니다.


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

컨트롤러를 베이스 컨트롤러로 구현

_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에서 제공된 행을 사용하십시오.

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

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


-8

왜 더 간단한 것이 없습니까?

그냥 호출 Request.Path하면 "/"로 구분 된 문자열이 반환됩니다.

그런 다음 .Split('/')[1]컨트롤러 이름을 얻는 데 사용할 수 있습니다 .

여기에 이미지 설명을 입력하십시오


1
-1 : 코드를 사용하면 하위 수준 응용 프로그램은 무시됩니다 (예 :) http://www.example.com/sites/site1/controllerA/actionB/. MVC는 라우팅을위한 많은 API를 제공하므로 URL을 구문 분석해야하는 이유는 무엇입니까?
T-moty

강화가 좋지 않은 상태에서 휠을 재발 명하는 이유는 무엇입니까? 모든 경우에 해당되는 것은 아닙니다.
jstuardo

잡담 하위 폴더에서, 진짜 문제는 그들이 항상하지 않도록 당신이 당신의 경로를 사용자 정의 할 수 있다는 것입니다controller/action
drzaus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.