亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 ActionName 屬性時如何獲取操作名稱?

使用 ActionName 屬性時如何獲取操作名稱?

C#
qq_遁去的一_1 2021-12-05 17:10:25
隨著nameofC# 6 中運算符的引入,您可以通過編程方式獲取操作名稱,而無需魔法字符串:<p>@Html.ActionLink("Contact", nameof(HomeController.Contact), "Home")</p>如果您不更改視圖的名稱,這將非常有效。但是,如果操作方法正在使用該[ActionName]屬性,有沒有辦法獲得正確的操作名稱(并避免使用魔法字符串)?也許通過組合nameof()和擴展方法?[ActionName("Contact2")]public ActionResult Contact(){        // ...}在本例中,nameof(HomeController.Contact)將返回字符串“Contact”和 URL“ http://localhost:2222/Home/Contact ”,而正確的 URL 應該是“ http://localhost:2222/Home/Contact2 ”,因為[ActionName("Contact2")]屬性。
查看完整描述

3 回答

?
慕萊塢森

TA貢獻1810條經驗 獲得超4個贊

不,你不能。因為屬性名稱已經是一個魔法字符串,并且對于所有意圖和目的,控制器方法的名稱本身就是一個魔法字符串(在您使用隱式操作名稱的情況下)。魔術弦并不壞,只是經常被誤用。在這種情況下,您最好只使用常量。


internal const string ContactActionName2 = nameof(ContactActionName2);


[ActionName(ContactActionName2)]


HomeController.ContactActionName2

應該足以滿足您的用例。


但是,由于每個人都對此大發雷霆,我決定去尋找一個完全不依賴字符串的解決方案(除了您無法避免依賴的字符串 - 操作名稱)。我不喜歡這個解決方案,因為 1) 它太過分了,2) 它仍然只是訪問一個字符串值,這可以更簡單地使用一個常量來完成,3) 你實際上必須寫出整個方法調用作為一個表達式,并且4) 每次使用時它都會分配一個表達式。


public static class ActionNameExtensions<TController>

{

    public static string FindActionName<T>(Expression<Func<TController, T>> expression)

    {

        MethodCallExpression outermostExpression = expression.Body as MethodCallExpression;


        if (outermostExpression == null)

        {

            throw new ArgumentException("Not a " + nameof(MethodCallExpression));

        }


        return outermostExpression.Method.GetCustomAttribute<ActionNameAttribute>().Name;

    }

}

用法示例:


public class HomeController : Controller

{

    [ActionName("HelloWorld")]

    public string MyCoolAction(string arg1, string arg2, int arg4)

    {

        return ActionNameExtensions<HomeController>.FindActionName(

            controller => controller.MyCoolAction("a", "b", 3)

        );

    }

}

可以編寫一個重載來接受沒有void返回的方法。雖然這有點奇怪,因為它假設用于控制器方法,通常返回一個值。


查看完整回答
反對 回復 2021-12-05
?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

...如果操作方法使用 [ActionName] 屬性,有沒有辦法獲得正確的操作名稱(并避免使用魔法字符串)?也許通過 nameof() 和擴展方法的組合?


您可以使用反射。這是一個內聯版本:


<p>@(

    (

        (ActionNameAttribute)(

            typeof(HomeController)

            .GetMethod(nameof(HomeController.Contact))

            .GetCustomAttributes(typeof(ActionNameAttribute), false)[0]

        )

    ).Name

)</p>

這是與剃刀功能相同的操作:


@functions {

    public string GetActionName(Type controller, string methodName) {

        var method = controller.GetMethod(methodName);

        var attributeType = typeof(ActionNameAttribute);

        var attribute = method.GetCustomAttributes(attributeType, false)[0];

        return (attribute as ActionNameAttribute).Name;

    }

}


<p>@GetActionName(typeof(HomeController), nameof(HomeController.Contact))</p>

這是與通用剃刀函數相同的操作:


@functions {

    public string GetActionName<T>(string methodName) {

        var controllerType = typeof(T);

        var method = controllerType.GetMethod(methodName);

        var attributeType = typeof(ActionNameAttribute);

        var attribute = method.GetCustomAttributes(attributeType, false)[0];

        return (attribute as ActionNameAttribute).Name;

    }

}


<p>@(GetActionName<HomeController>(nameof(HomeController.Contact)))</p>

剩下的就是向函數添加防御性編程(例如null檢查)GetActionName。


您的問題專門詢問了擴展方法。據我所知,擴展方法不會提供太大的改進,因為我們正在使用類型和方法,而擴展方法適用于對象。


查看完整回答
反對 回復 2021-12-05
?
紅糖糍粑

TA貢獻1815條經驗 獲得超6個贊

如果你不喜歡你可以用泛型做一些非常奇特的邏輯:


public static class HtmlHelperExtensions

{

    public static IHtmlContent ActionLink<TController>(

        this IHtmlHelper htmlHelper, 

        string linkText, 

        string actionName)


      where TController : ControllerBase

    {

        var suffix = nameof(Controller);

        var controllerName = typeof(TController).Name.Replace(suffix, "");

        var method = typeof(TController).GetMethod(actionName);

        var attributeType = typeof(ActionNameAttribute);

        var attribute = method.GetCustomAttributes(attributeType, false);

        actionName = attribute.Length == 0

          ? actionName

          : (attribute[0] as ActionNameAttribute).Name;


        return htmlHelper.ActionLink(linkText, actionName);

    }

}

對此進行了測試,它可能會抱怨(很確定會)簽名已經存在,因此您可能必須重命名該方法。在任何情況下,您都可以像這樣使用它:


@(Html.ActionLink<HomeController>("Link Text", nameof(HomeController.Index)))


查看完整回答
反對 回復 2021-12-05
  • 3 回答
  • 0 關注
  • 404 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號