ASP.NET MVC 3 HttpPost action method not found

I have a simple form that submits to an HttpPost action method that returns the corresponding view. My problem is that I get a 404 Not Found error. Oddly enough, if I changed the form method and the attribute of the action method to GET , then it will work and the TestMethod view will be shown.

It seems that I am missing something to use POST , but my messages in other controllers work fine (for example, login to the account and registration). Note that the AllowAnonymous attribute is a custom attribute that allows you to specify controllers or actions that allow anonymous access, as opposed to specifying (through Authorize attr) controllers or actions that require authorization. I think nothing is impossible, but I do not think this has anything to do with my problem. Any thoughts on what's wrong?

FORM:

 @using (Html.BeginForm("TestMethod", "Test", FormMethod.Post, new { @id = "testForm" })) { <fieldset> <legend>Test Form</legend> <input type="submit" value="Submit" /> </fieldset> } 

CONTROLLER ACTION:

 [AllowAnonymous] [HttpPost] public ActionResult TestMethod() { return View(); } 

VIEW:

 <h2>TestMethod</h2> <p>HttpPost method was successful.</p> 

REGISTER THE ROUTE METHOD FROM Global.asax.cs:

 public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("favicon.ico"); routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // About routes.MapRoute( "About", // Route name "about", // URL with parameters new { controller = "Home", action = "About" } // Parameter defaults ); // Faq routes.MapRoute( "Faq", // Route name "faq", // URL with parameters new { controller = "Home", action = "Faq" } // Parameter defaults ); // Glossary routes.MapRoute( "Glossary", // Route name "glossary", // URL with parameters new { controller = "Home", action = "Glossary" } // Parameter defaults ); // Register routes.MapRoute( "Register", // Route name "register", // URL with parameters new { controller = "Account", action = "Register" } // Parameter defaults ); // LogIn routes.MapRoute( "LogIn", // Route name "login/{id}", // URL with parameters new { controller = "Account", action = "LogOn", id = UrlParameter.Optional } // Parameter defaults ); routes.MapRoute( "LogOn", // Route name "logon/{id}", // URL with parameters new { controller = "Account", action = "LogOn", id = UrlParameter.Optional } // Parameter defaults ); // Default routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); } 

ATTRIBUTE CODE AUTHORIZATION:

 // AllowAnonymousAttribute class [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public sealed class AllowAnonymousAttribute : Attribute { } // GlobalAuthorize class public sealed class GlobalAuthorize : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true); if (!skipAuthorization) base.OnAuthorization(filterContext); } } // RedirectAuthorizeAttribute class public class RedirectAuthorizeAttribute : AuthorizeAttribute { public string RedirectUrl { get; set; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { filterContext.Result = new RedirectResult(RedirectUrl); } } 

GLOBAL FILTERS:

 public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new RequireHttpsAttribute()); filters.Add(new GlobalAuthorize()); filters.Add(new HandleErrorAttribute()); } 

ROUTE SECURITY RULES:

 <rewrite> <rules> <!-- Block all requests made to a website that do not have the host header set. --> <rule name="Fail bad requests" stopProcessing="true"> <match url=".*" /> <conditions> <add input="{HTTP_HOST}" pattern="localhost" negate="true" /> </conditions> <action type="AbortRequest" /> </rule> <!-- Remove trailing slash from all incoming requests. --> <rule name="Remove trailing slash" stopProcessing="false"> <match url="(.*)/$" /> <conditions> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Redirect" redirectType="Permanent" url="{R:1}" /> </rule> <!-- Convert all requests to all lowercase. --> <rule name="Convert to lowercase" stopProcessing="false"> <match url=".*[AZ].*" ignoreCase="false" /> <action type="Redirect" url="{ToLower:{R:0}}" redirectType="Permanent" /> </rule> <!-- Any URL with (HTTPS == OFF) and (HTTP_HOST with colon) -> use for development testing. --> <rule name="Development redirect to HTTPS" enabled="true" stopProcessing="true"> <match url=".*" ignoreCase="true" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="true"> <add input="{HTTPS}" pattern="^OFF$" /> <add input="{HTTP_HOST}" pattern="([^/:]*?):[^/]*?" /> </conditions> <action type="Redirect" url="https://{C:1}:44300{URL}" /> </rule> <!-- Redirect any HTTP request to HTTPS. --> <rule name="Redirect to HTTPS" stopProcessing="true"> <match url="(.*)" /> <conditions> <add input="{HTTPS}" pattern="^OFF$" ignoreCase="true" /> </conditions> <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" /> </rule> </rules> </rewrite> 
+4
source share
2 answers

I think I finally found the culprit. First of all, I agree that, knowing now what the problem is, the name of this question is not very accurate. The problem was mainly about rewriting the rules in Web.config. Until I answered the comments of other people on this issue, I completely forgot about rewriting the rules, so I did not check them further to get started.

In any case, the problem was a rule that rewrote URLs to all lowercase. I knew that my accounts and login forms were working fine, so I checked them and noticed that their Html.BeginForm statements Html.BeginForm no parameters, which obviously leads to the generation of a lowercase letter. I tried the POST request for my test method without parameters, and it worked. Then I tried to use the parameters for the action and the controller in the Html.BeginForm , but this time I entered them as lowercase strings: Html.BeginForm("testmethod", "test"...) . Of course, it worked fine too, and the page source showed the form's action as lowercase.

To fix my problem, I just needed to set the condition so that it did not match POST requests: <add input="{REQUEST_METHOD}" matchType="Pattern" pattern="POST" negate="true" /> . Note that the problem was not with the line rule, but with the fact that the POST request was redirected. I found one blog that discusses the issue of converting POST converted to GET and leading to errors, which excludes what I was going through. This is a couple of years, but, apparently, this is still relevant information.

Anyway, now I'm working again. Thanks to everyone who threw their two cents.

PS. When I close the browser tabs and finish my search, I decided that I would attach myself to this SO question , as this is definitely related to my problem.

+5
source

I tested your code just now. I was initially redirected to use HTTPS, so I disabled this attribute, but after that your code worked.

Here is my logical subtraction ...

  • If HTTPS was a problem, you would not get 404.
  • If you are not logged in, you will be redirected to the login page.

The only thing I can think of is that your controller is either not named "TestController" or your controller is in a zone and you forgot to specify this area using BeginForm . Is this one of these factors?

0
source

All Articles