Asp.net mvc Type.GetMethod when two actions with the same name but get and post

in asp.net mvc 4, I am writing a custom Exception handler, working as an attribute called HandleCustomError.

In this handler, I need to know what action the current request is executing, then I can find out what type of return for this action. I will return various data for the "return type () and json type".

But now I have two actions with the same name, but one for "Get", the other for "Post". The "GetMethod" method returns an error: "System.Reflection.AmbiguousMatchException"

public class HandleCustomError : System.Web.Mvc.HandleErrorAttribute { public override void OnException(System.Web.Mvc.ExceptionContext filterContext) { //base.OnException(filterContext); if (filterContext.ExceptionHandled) { return; } else { //Determine the return type of the action string actionName = filterContext.RouteData.Values["action"].ToString(); Type controllerType = filterContext.Controller.GetType(); var method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); var returnType = method.ReturnType; } ....(Omitted) 
+7
post get asp.net-mvc-4
source share
3 answers

As you already mentioned, you have two actions with the same name, but one for "Get", the other for "Post", you can try [HttpGet] to the first action and [HttpPost] to the section action, or you can try that something like this if your action serves requests from multiple verbs

 [HttpGet, HttpPost] or [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)] 

For example, if your function name is GetMethod, then try doing this.

 [HttpGet] Public ActionResult GetMethod() { //do something ... } [HttpPost] Public ActionResult GetMethod() { //do something ... } 
0
source share

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".

0
source share

I also ran into this problem that below the line gave an Ambigeous problem

controllerType.GetMethod (actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

The reason was that the controller has two methods with the same name:

[HttpGet]

and other iis

[HttpPost]

.

To get the exact method, I use GetMethods and LINQ. Note: when writing the controller [HTTPGet] **, the action is not required for the get method, i.e. In action, if HTTpGet is not written by default .net will treat it as ** [HttpGet] . But for post-action, this is a must. Will use this property to find the correct method.

Actions 1. Search Query Type 2. Locate the action using reflection

  • Search request type:

var actionName = filterContext.RouteData.Values ​​["action"] ToString (). Type typeOfRequest = filterContext.HttpContext.Request.RequestType.ToLower () == "get" TypeOf (HttpGetAttribute): TypeOf (HttpPostAttribute);

  1. Search Method:
 var cntMethods = controllerType.GetMethods() .Where(m => m.Name == actionName && ( ( typeOfRequest == typeof(HttpPostAttribute) && m.CustomAttributes.Where(a => a.AttributeType == typeOfRequest).Count()>0 ) || ( typeOfRequest == typeof(HttpGetAttribute) && m.CustomAttributes.Where(a => a.AttributeType == typeof(HttpPostAttribute)).Count() == 0 ) ) ); MethodInfo actionMethodInfo = actionMethodInfo = cntMethods != null && cntMethods.Count() == 1 ? cntMethods.ElementAt(0):null; 

Link: https://technologyatfingertips.wordpress.com/2016/06/14/session-state-on-action/

0
source share

All Articles