コントローラ内からコントローラとアクション名を取得しますか?


173

私たちのWebアプリケーションでは、ビューに応じて、または正確に、ビューに応じてコントローラーとアクション(およびユーザーIDはもちろん、ここでは重要ではありません)に応じて、フェッチおよび表示されたアイテムの順序を保存する必要があります。

各コントローラーアクションで自分自身に識別子を与えるだけでなく(ビューに依存するDB出力の並べ替えに使用するため)、コントローラーと取得するアクションメソッドからこの識別子を自動的に作成する方が安全で簡単だと思いましたから呼ばれた。

コントローラーのアクションメソッド内からコントローラーとアクションの名前を取得するにはどうすればよいですか?それとも反射が必要ですか?私はそれがかなり簡単であると思います、事前に感謝します!


1
Reflectionはアクションを処理するメソッド名を提供しますが、おそらくAndreiのコードによって返されるアクション名を好みます。
シティキッド2013

基本的には、ビューを提供するすべてのアクションに明確な識別子が必要なので、どちらの方法でも機能します。しかし、あなたの言う通り、アンドレイの答えは間違いなくエレガントです。
アレックス

@citykidケースとクラス名の「コントローラー」サフィックス以外の方法でこれらが異なるケースはありますか?
John

@ジョン、ActionNameAttributeはAC#メソッドは、任意のアクション名を持つことができます:msdn.microsoft.com/en-us/library/...を
citykid

@citykidああ、わかりました。Route収集したアクションメソッドの属性でルートを指定できるので、これは古い機能の一種ですか?また、コントローラの名前を変更することもできますか?
ジョン

回答:


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

13
コントローラーの名前をビューファイルに含める必要がある場合は、this.ViewContext.RouteData.Values ["controller"]。ToString();を使用できます。
Amogh Natu 14

これを行う(アクションとコントローラー名を提供する)場合は、それらを直接割り当てるだけではどうですか。
MetalPhoenix

1
@MetalPhoenix、あなたが話しているユースケースを少し明確にできますか?OPはコントローラーまたはアクションを割り当てる必要はありません。現在処理されているコントローラーとアクションを一般的な方法で理解する必要があるだけです。
Andrei

1
2回目の読み取りで、ここでコードの抜粋を誤解した可能性はありますか?... 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
最高の完全なソリューション、ありがとうJhon
Umar Abbas

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

コントローラーをBasecontrollerに実装する

部分ビュー_Breadcrumb.cshtmlを追加し、@ Html.Partial( "_ Breadcrumb")を使用して必要なすべてのページに追加します。

_Breadcrumb.cshtml

<span>
    <a href="../@ViewData["controllerName"]">
        @ViewData["controllerName"]
    </a> > @ViewData["actionName"]
</span>

(1):これはまだMVC5内で最も一般的な方法の1つですか?(2)filterContext変数はどこから取得しますGetDefaults()か?
chriszo111 2017年

1

変数と同様に、アクションからコントローラー名またはアクション名を取得できます。それらは特別なもの(コントローラーとアクション)であり、すでに定義されているので、それらを取得するために特別なことをする必要はありません。

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

または、モデルにコントローラとアクションを含めて、そのうちの2つとカスタムデータを取得することもできます。

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 16

なぜ車輪を再発明し、さらには再発明が不十分なのでしょうか?これはすべてのケースで機能するわけではありません。
jstuardo 2017

サブフォルダーの側にある場合、本当の問題は、ルートが常にカスタマイズされないようにルートをカスタマイズできることですcontroller/action
drzaus
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.