MVC3: using ActionMethodSelectorAttribute ignores HttpPostAttribute

The following attribute is used to limit the use of an action to an ajax request:

public class AjaxRequestAttribute : ActionMethodSelectorAttribute { public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo) { return controllerContext.HttpContext.Request.IsAjaxRequest(); } } 

I have the following controller action methods:

 [AjaxRequest] public ActionResult Login() { ... } [HttpPost, AjaxRequest] public ActionResult Login(LoginModel model, string returnUrl) { ... } 

The following error occurs when creating an ajax message:

The current Login action request for the AgentController controller type is ambiguous between the following action methods: System.Web.Mvc.ActionResult Login () as NappWebsiteMvc.Controllers.AgentController System.Web.Mvc.ActionResult Login (NappWebsiteMvc.Models.Agent. LoginModel, System.String) by type NappWebsiteMvc.Controllers.AgentController

The HttpPost attribute seems to be ignored when using the optional attribute. If I remove the AjaxRequest attribute from the two methods, then the code will work.

What should be the correct implementation? Thanks!

+4
source share
3 answers

At the request of Pavel, here is the code:

 public class AjaxGetAttribute : ActionMethodSelectorAttribute { public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { var isHttpGet = new AcceptVerbsAttribute(HttpVerbs.Get).IsValidForRequest(controllerContext, methodInfo); return isHttpGet && controllerContext.HttpContext.Request.IsAjaxRequest(); } } public class AjaxPostAttribute : ActionMethodSelectorAttribute { public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { var isHttpPost = new AcceptVerbsAttribute(HttpVerbs.Post).IsValidForRequest(controllerContext, methodInfo); return isHttpPost && controllerContext.HttpContext.Request.IsAjaxRequest(); } } 
+2
source

I believe that you can also include the HttpGet attribute in the first action method:

 [HttpGet, AjaxRequest] public ActionResult Login() { ... } [HttpPost, AjaxRequest] public ActionResult Login(LoginModel model, string returnUrl) { ... } 

It seems that all the attributes of an ActionMethodSelector should return true in order for the action method to be valid. Making this change means that the first method will not be used for POST, even if it is an Ajax request.

My script is a little different, but this solution worked for me.

+1
source

This is because HttpPost also extends ActionMethodSelectorAttribute with its own Override IsValidForRequest . Have you tried splitting your attribute into AjaxRequestAttribute and AjaxPostRequestAttribute ?

 public class AjaxPostRequestAttribute : HttpPostAttribute { public override bool IsValidForRequest( ControllerContext controllerContext, MethodInfo methodInfo) { var isHttpPost = base.IsValidForRequest(controllerContext, methodInfo); return isHttpPost && controllerContext.HttpContext.Request.IsAjaxRequest(); } } 

Then you would simply be decorated like this:

 [AjaxPostRequest] public ActionResult Login(LoginModel model, string returnUrl) { ... } 

Update

Sorry, I didn’t notice the private keyword in the HttpPostAttribute source.

0
source

Source: https://habr.com/ru/post/1389705/


All Articles