简体   繁体   English

从MVC中的Controller方法获取Attribute标签?

[英]Get the Attribute tag from a Controller Method in MVC?

I'm trying to get the Attribute tag from an API Controller so that I can see what HTTP verb it allows at runtime. 我正在尝试从API控制器获取属性标记,以便我可以看到它在运行时允许的HTTP谓词。 From the sample code below, I want to be able to get the [HttpGet] tag. 从下面的示例代码中,我希望能够获得[HttpGet]标记。

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

I am currently using System.Reflection to gather other information about my API while it is running, but so far I have been unable to retrieve the [HttpGet tag and other Http verb tags. 我目前正在使用System.Reflection来收集有关我的API运行时的其他信息,但到目前为止我一直无法检索[HttpGet标记和其他Http动词标记。 I've tried each of the solutions below with no luck: 我已经尝试了下面的每个解决方案而没有运气:

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

All of the previous questions that I've researched about this topic only related to Custom Attribute tags and pulling values out of those, but I couldn't find any information about getting the framework-included Attribute tags . 我之前研究过的关于这个主题的所有问题只涉及Custom Attribute tags和从中提取值,但我找不到任何有关获取包含框架的Attribute tags

Does anyone know how I can get the [HttpGet] Attribute tag? 有谁知道如何获得[HttpGet]属性标签?

Thanks! 谢谢!

The proposed solutions 3 and 4 work. 建议的解决方案3和4工作。

You must look out that you are referencing the correct HttpGetAttribute . 您必须注意您正在引用正确的HttpGetAttribute There is one in System.Web.Http.HttpGetAttribute and there is one in System.Web.Mvc.HttpGetAttribute . 有一个在System.Web.Http.HttpGetAttribute并有一个在System.Web.Mvc.HttpGetAttribute

The following code lists the public methods of the ValuesController API controller with the information on whether they have HttpGet or HttpPost attributes. 以下代码列出了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;
        }
    }
}

You need to exchange System.Web.Http. 您需要交换System.Web.Http. with System.Web.Mvc. 使用System.Web.Mvc. when the controller is an MVC controller instead of an API controller. 当控制器是MVC控制器而不是API控制器时。

This is how I ended up doing it: 这就是我最终做到的方式:

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

Say you have the following Controller and Actions: 假设您有以下控制器和操作:

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

You can call them like this: 你可以像这样打电话给他们:

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();

This will return the full attribute that you've set in case you've added any custom data. 如果您添加了任何自定义数据,这将返回您设置的完整属性。

在此输入图像描述

Two things to note: 有两点需要注意:

  1. You'll need to supply parameters to the function call. 您需要为函数调用提供参数。 They don't need to be valid as the method itself won't be called, but I couldn't figure out how to allow you to do GetSupportedVerbsForAction<HomeController>(x => x.Index) . 它们不需要有效,因为方法本身不会被调用,但我无法弄清楚如何允许你做GetSupportedVerbsForAction<HomeController>(x => x.Index)
  2. The method will pass back a list of Attribute , so use the is keyword to figure out if it's the type you want. 该方法将传回Attribute列表,因此使用is关键字来确定它是否是您想要的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM