One way to solve this problem is to use the GetMethods() method GetMethods() System.Type object to return a list of methods on the System.Type object. Use the LINQ query to filter the list of methods only for methods that match a specific action name.
Add this approach by replacing the code in the code:
var method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
with the following if condition, which checks for several methods matching the actionName variable from your code. Define a string variable that identifies the type of action (ie, "HttpGet" or "HttpPost") and compares it with the attributes of each method in the filtered list.
System.Reflection.MethodInfo[] matchedMethods = controllerType.GetMethods( System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public) .Where(m => m.Name == actionName).ToArray<System.Reflection.MethodInfo>(); if (matchedMethods.Length > 1) { string attributeTypeString = "HttpGet"; // Change this to "HttpPut" or the text of any custom attribute filter foreach (System.Reflection.MethodInfo methodInfo in matchedMethods) { if (methodInfo.CustomAttributes.Count() == 0) { continue; } // An alternative below is to explicitly check against a defined attribute type (eg `ca.AttributeType == ...`). if (methodInfo.CustomAttributes.FirstOrDefault(ca => ca.ToString().IndexOf(attributeTypeString) == 0) !=null) { method = methodInfo; break; // Break out of the 'foreach' loop since a match was found } } } else { method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); }
Code Notes
I used strongly typed variable declarations (compared to "var"), so itβs easier to keep track of what the code is doing.
Add using System.Reflection; and using System.Linq at the beginning of the class file. I have listed the complete assembly declaration of the / type / flag variable in the above code so that it is easier to follow again (at least for me) in this answer.
The first line of code in the solution above can be broken down into separate lines so that it is easier to follow:
System.Reflection.MethodInfo[] allMethods = controllerType.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); System.Reflection.MethodInfo[] matchedMethods = allMethods.Where(m => m.Name == actionName).ToArray<System.Reflection.MethodInfo>();
Note the if condition in the foreach .
if (methodInfo.CustomAttributes.FirstOrDefault(ca => ca.ToString().IndexOf(attributeTypeString) == 0) !=null)
The if condition does not require the conversion of a custom attribute to a string. An alternative is to explicitly check for a particular type of attribute (for example, ca.AttributeType == ... ). If the condition checks the text of the attribute name, make sure that the string comparison method (for example, IndexOf() used here) satisfies the conditions of your application. For example, I used IndexOf() > -1 to determine if the text of the attributeTypeString variable is specified anywhere in the user attribute, because I suggested that there should not be another custom attribute that contains the text "HttpGet".