前言

前兩天 Stack Overflow 閒晃時,無意間發現這個問題:在 ASP.NET Core 程式內,如何回傳 Controller / Action 上的 DisplayName 內容,突然好奇在 .NET Framework 與 ASP.NET Core 之間會有什麼樣的差異,於是簡單撰寫程式進行測試。發現兩個版本差異在於取得方法不同,但程式流程其實很相似。本篇文章簡單記錄一下兩者差異,若有任何錯誤或建議,請各位先進不吝指教。

Examples are based on .NET Framework / ASP.NET Core WebAPI Project



介紹

在 .NET Framework ,我們分別可以透過 ControllerContext 與 ActionContext 分別取得ControllerDescriptor 與 ActionDescriptor,再透過 GetCustomAttributes 方法取得各自 attribute
ControllerContext.ControllerDescriptor.GetCustomAttributes<displaynameattribute>()
ActionContext.ActionDescriptor.GetCustomAttributes<displaynameattribute>()

將取得的 attribute 轉型為 DisplayNameAttribute,即可取得 DisplayName,整個範例程式如下:
.NET Framework
[DisplayName("Controller Display Name")]
public class ValuesController : ApiController
{
    // GET api/values
    [DisplayName("Action Display Name")]
    public IEnumerable<string> Get()
    {
        var ControllerDisplayName = string.Empty;
        var ActionsDisplayName = string.Empty;

        var ControllerAttributes = ControllerContext.ControllerDescriptor.GetCustomAttributes<DisplayNameAttribute>();
        if (ControllerAttributes.Count > 0)
        {
            ControllerDisplayName = ((DisplayNameAttribute)ControllerAttributes[0]).DisplayName;
        }

        var ActionAttributes = ActionContext.ActionDescriptor.GetCustomAttributes<DisplayNameAttribute>();
        if (ActionAttributes.Count > 0)
        {
            ActionsDisplayName = ((DisplayNameAttribute)ActionAttributes[0]).DisplayName;
        }

        return new string[] { ControllerDisplayName, ActionsDisplayName };
    }
}


而在 ASP.NET Core,我們皆是從 ControllerContext.ActionDescriptor 內分別取得 ControllerTypeInfo 與 MethodInfo,再使用 GetCustomAttributes(typeof(DisplayNameAttribute), true) 方法取得 DisplayNameAttribute
ControllerContext.ActionDescriptor.ControllerTypeInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true);
ControllerContext.ActionDescriptor.MethodInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false);

將取得的 attribute 轉型為 DisplayNameAttribute,即可取得 DisplayName,整個範例程式如下:
ASP.NET Core
[DisplayName("Controller Display Name")]
[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET api/values
    [HttpGet]
    [DisplayName("Action Display Name")]
    public IEnumerable<string> Get()
    {
        var ControllerDisplayName = string.Empty;
        var ActionsDisplayName = string.Empty;

        var ControllerAttributes = ControllerContext.ActionDescriptor.ControllerTypeInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true);
        if (ControllerAttributes.Length > 0)
        {
            ControllerDisplayName = ((DisplayNameAttribute)ControllerAttributes[0]).DisplayName;
        }

        var ActionAttributes = ControllerContext.ActionDescriptor.MethodInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false);
        if (ActionAttributes.Length > 0)
        {
            ActionsDisplayName = ((DisplayNameAttribute)ActionAttributes[0]).DisplayName;
        }

        return new string[] { ControllerDisplayName, ActionsDisplayName };
    }
}



參考資料

1. Return info of controller and actions with web api in asp core -  Stack Overflow