2017-10-12 88 views
2

我試圖從API控制器中獲取Attribute標記,以便我可以在運行時看到它允許的HTTP動詞。從下面的示例代碼中,我希望能夠獲得[HttpGet]標記。從MVC中的Controller方法獲取屬性標記?

[HttpGet] 
public void MyResource() 
{ 
    // Controller logic 
} 

我目前使用的System.Reflection在運行時收集有關我的API等信息,但到目前爲止,我已經無法檢索[HttpGet標籤和其他Http動詞標籤。我已經試過每個解決方案的下方,沒有運氣:

public void GetControllerMethodHttpAttribute() 
{ 
    MethodInfo controllerMethod = typeof(TestController).GetMethods().First(); 

    // Solution 1 
    var attrs = controllerMethod.Attributes; 

    // Solution 2 
    var httpAttr = Attribute.GetCustomAttributes(typeof(HttpGetAttribute)); 

    // Solution 3 
    var httpAttr2 = Attribute.GetCustomAttribute(controllerMethod, typeof(HttpGetAttribute)); 

    // Solution 4 
    var httpAttr3 = Attribute.IsDefined(controllerMethod, typeof(HttpGetAttribute)); 
} 

這一切都是我研究過這個話題不僅關係到Custom Attribute tags和拉動值超出那些以前的問題,但我找不到任何有關獲得框架的信息 - 包括Attribute tags

有誰知道我怎麼能得到[HttpGet]屬性標籤?

謝謝!

+0

您是否需要「此操作支持get/post/etc」,或者屬性(訂單,模板等)中的完整信息? – gunr2171

+1

您是否驗證過typeof(TestController).GetMethods()。First()'返回預期的方法? – thehennyy

+0

@ gunr2171完整的信息將是首選,但最重要的是,我希望能夠說出每種方法支持的動詞。 –

回答

3

建議的解決方案3和4工作。

您必須注意您引用的是正確的HttpGetAttributeSystem.Web.Http.HttpGetAttribute中有一個,System.Web.Mvc.HttpGetAttribute中有一個。

以下代碼列出了ValuesController API控制器的公共方法以及它們是否具有HttpGet或HttpPost屬性的信息。

var methods = typeof(ValuesController).GetMethods(); 
string infoString = ""; 

foreach(var method in methods) 
{ 
    // Only public methods that are not constructors 
    if(!method.IsConstructor && method.IsPublic) 
    { 
     // Don't include inherited methods 
     if(method.DeclaringType == typeof(ValuesController)) 
     { 

      infoString += method.Name; 

      if(Attribute.IsDefined(method, typeof(System.Web.Http.HttpGetAttribute))) 
      { 
       infoString += " GET "; 
      } 
      if(Attribute.IsDefined(method, typeof(System.Web.Http.HttpPostAttribute))) 
      { 
       infoString += " POST "; 
      } 


      infoString += Environment.NewLine; 
     } 
    } 
} 

您需要與System.Web.Mvc.交換System.Web.Http.當控制器是一個MVC控制器,而不是一個API控制器。

+0

非常感謝!我沒有意識到有兩個具有相同屬性名稱的名稱空間。 –

1

這是我最後只是:

public static IEnumerable<Attribute> GetSupportedVerbsForAction<T>(
    Expression<Func<T, IActionResult>> expression) 
    where T : Controller 
{ 
    //only consider a list of attributes 
    var typesToCheck = new[] { typeof(HttpGetAttribute), typeof(HttpPostAttribute), 
     typeof(HttpPutAttribute), typeof(HttpDeleteAttribute), typeof(HttpPatchAttribute)}; 

    var method = ((MethodCallExpression)expression.Body).Method; 

    var matchingAttributes = typesToCheck 
     .Where(x => method.IsDefined(x)) 
     .ToList(); 

    //if the method doesn't have any of the attributes we're looking for, 
    //assume that it does all verbs 
    if (!matchingAttributes.Any()) 
     foreach(var verb in typesToCheck) 
      yield return verb; 

    //else, return all the attributes we did find 
    foreach (var foundAttr in matchingAttributes) 
    { 
     yield return method.GetCustomAttribute(foundAttr); 
    } 
} 

假設你有以下控制器和行動:

public class HomeController : Controller 
{ 
    // implicit get 
    public IActionResult Index() => View(); 

    // explicit get 
    [HttpGet] 
    public IActionResult GetAction() => View(); 

    // extra info 
    [HttpPost(Name = "some name", Order = 5)] 
    public IActionResult PostAction() => View(); 

    [HttpPut] 
    [HttpDelete] 
    [HttpPatch("my template", Name = "patch name", Order = 333)] 
    public IActionResult MultiAction() => View(); 
} 

你可以打電話給他們這樣的:

var indexVerbs = GetSupportedVerbsForAction<HomeController>(x => x.Index()).ToList(); 
var getVerbs = GetSupportedVerbsForAction<HomeController>(x => x.GetAction()).ToList(); 
var postVerbs = GetSupportedVerbsForAction<HomeController>(x => x.PostAction()).ToList(); 
var multiVerbs = GetSupportedVerbsForAction<HomeController>(x => x.MultiAction()).ToList(); 

這將返回您設置的完整屬性,以防喲我已添加任何自定義數據。

enter image description here

有兩點需要注意:

  1. 你需要提供參數的函數調用。他們不需要是有效的,因爲方法本身不會被調用,但我不知道如何讓你做GetSupportedVerbsForAction<HomeController>(x => x.Index)
  2. 該方法將返回一個Attribute列表,因此請使用is關鍵字來確定它是否是您想要的類型。
+0

我可能是錯的,但我想如果它沒有任何屬性,這意味着它會接受任何東西,不只是得到? – Chris

+0

@Chris nope,默認是GET:http://www.tutorialsteacher.com/mvc/actionverbs-in-mvc。這裏有一個[更好的鏈接](https://forums.asp.net/t/1928761.aspx?What+is+default+http+verb+for+action+method),但我仍然在搜索官方文檔。 – gunr2171

+0

https://stackoverflow.com/questions/11767911/mvc-httppost-httpget-for-action是一個相關的堆棧溢出問題。正如您從測試中看到的(並且受文檔https://msdn.microsoft.com/en-us/library/system.web.mvc.httpgetattribute(v=vs.118).aspx支持),該屬性會限制什麼被允許。沒有屬性就沒有反應。我懷疑在這個例子中,你鏈接了MVC足夠聰明,可以說如果一個人不受限制,一個人只是發佈帖子,然後使用更受限制的帖子。 – Chris

相關問題