Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form not hitting the controller

Edited the question as I've found out that the issue isn't inside the razor, but instead in the route

I have a very simple login form, but somehow, when the user presses Login the page goes tot Error404 and it simply does not hit the controller breakpoints for some reason.

   @using (Html.BeginRouteForm("MyCustomRoute", new { controller = "login", action = "verify", FormMethod.Post }))
                 {
                <fieldset class="clearfix">
                    <p><span style="float:none;color:black; font-size:20pt;"></span></p>
                    <p><span style="float:none;color:black; font-size:20pt;"></span></p>
                    <p><span class="fa fa-user"></span>@Html.TextBoxFor(m => m.UserName, new { @class = "form-control", placeholder = "Username", onkeydown = "convertTabtoEnter(this, event)", autofocus = "" })</p> <!-- JS because of IE support; better: placeholder="Username" -->
                    <p>
                        <span class="fa fa-lock"></span>@Html.PasswordFor(m => m.Password, new { @class = "form-control", placeholder = "Password", onkeyup = "convertTabtoEnter()" })
                    </p> <!-- JS because of IE support; better: placeholder="Password" -->

                    <div>
                        <span style="width:48%; text-align:left;  display: inline-block;">
                            <a class="small-text" href="#">
                                @*Forgot
                    password?*@
                            </a>
                        </span>
                        <span style="width:50%; text-align:right;  display: inline-block;"><input type="submit" value="Sign In"></span>
                    </div>
                </fieldset>
                <div class="clearfix"></div>
                }    

And Inside my login controller I have a simple ActionResult named Verify with the 2 params.

    [RoutePrefix("Login")]

public class LoginController : Controller
{
    // GET: Login
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    [Route("Verify")] //Matches GET login/verify

    public ActionResult Verify(string username, string password)
    {...}

What exactly am I doing wrong here? It's not like this is rocket science.

Edit2: I've noticed that whenever I change the RouteConfig.cs back to default it works correctly. So, the problem isn't inside the form tags but within the routings. So I've been trying to add a custom route in order to get this working using this sample: Using Html.BeginForm() with custom routes

public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "TrailersOverview",
                url: "{TrailersOverview}/{action}/{vendid}",
                defaults: new { controller = "TrailersOverview", action = "Index", vendId = UrlParameter.Optional }
            );

             routes.MapRoute(
                "MyCustomRoute", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "login", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

            routes.MapRoute(
                name: "Default",
                url: "{*anything}",
                defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
            );
        }
    }

When I remove the routings and I simply bring everything back to default, the controller does get hit. Unfortunately I really need those routings for the rest of the app :(

like image 764
Катерина Avatar asked May 17 '19 07:05

Катерина


2 Answers

There are several things that seems to be wrong:

  • Your Controller is missing in the route Config.
  • Action and Controller names are in wrong order.

RouteConfig:

A default route looks like that:

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}/",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Form:

If you want to use Tag Helpers, then you have to change your code from:

<form action="@Url.Action("Login", "Verify")" method="post">

to:

<form asp-controller="Login" asp-action="Verify" method="post">

Have a look here.

like image 100
Marc Avatar answered Sep 21 '22 23:09

Marc


Your custom route (the second in your RegisterRoutes code above) seems to be incorrect... based on what you stated above, it can/should be this:

routes.MapRoute(
    "MyCustomRoute", // Route name
    "Login/Verify", // (No parameters needed)
    new { controller = "Login", action = "Verify" } // Parameter defaults
);

With this setup, alter the first line of your razor code to be this:

@using (Html.BeginRouteForm("MyCustomRoute", FormMethod.Post }))
{
    <fieldset class="clearfix">
    ...
}

Using Html.BeginRouteForm will automatically use the defaults specified in your custom route; no need to add the defaults in Razor. Using FormMethod.Post as the second parameter will render your form's method as a POST.

Edit: Let's fix your general Route problem. You're attempting to use Attribute Routing, which is described well here: https://www.dotnettricks.com/learn/mvc/understanding-attribute-routing-in-aspnet-mvc. I'd contend that it isn't necessary here.

First, fix your default Route (last route in your RegisterRoutes code) like so:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional });
    // Change the 'controller' and 'action' parameters here to point to the Main page in your application.

Your default Route is very important, and should be configured as a catch-all for any requests can be simply mapped to a Controller/Action combination. I suspect that you experienced problems because your default Route was altered.

Next, comment out the Route and RoutePrefix attributes in your Login Controller... there's hardly a need for the [Route("Verify")] directive if you're using 'RegisterRoutes' properly.

// [RoutePrefix("Login")]
public class LoginController : Controller
{
    // GET: Login
    public ActionResult Index()
    {
        return View();
    }
    [HttpPost]
    // [Route("Verify")] //Matches GET login/verify
    public ActionResult Verify(string username, string password)
    {...}
}

Now that the default Route is set up properly, the url '/Login' should take you to your Login screen, because the default action is "Index" (it's the default in your default Route above.)

like image 40
cyrotello Avatar answered Sep 20 '22 23:09

cyrotello