Search code examples
c#asp.net-core-mvc

Post form to controller in ASP.NET Core MVC not working


I'm trying to POST a form to my controller the same way that I used to do with ASP.NET MVC 5 but it's not working.

The controller:

[HttpGet]
public IActionResult Login()
{
    return View();
}

[HttpPost]
public async Task<IActionResult> Login([FromBody] Login LoginModel)
{
    return View();
} 

And HTML

<form asp-action="Login" asp-controller="Home" method="post" class="mt-4">
    <div class="row">
        <div class="col-lg-12">
            <div class="form-group">
                <label class="text-dark" for="uname">E-mail</label>
                <input class="form-control" id="uname" type="text"
                       placeholder="digite e-mail">
            </div>
        </div>
        <div class="col-lg-12">
            <div class="form-group">
                <label class="text-dark" for="pwd">Senha</label>
                <input class="form-control" id="pwd" type="password"
                       placeholder="digite sua senha">
            </div>
        </div>
        <div class="col-lg-12 text-center">
            <button  type="submit" class="btn btn-block btn-dark" />
        </div>
    </div>
</form>

I tried to use the helper:

@using (Html.BeginForm("Login", "Login", FormMethod.Post))
{
}

But the HTML generated doesn't pass the controller path :

enter image description here

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages().AddRazorRuntimeCompilation();
    services.AddControllersWithViews();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Login}/{id?}");
        });
}

Solution

  • It shows action="/" instead of action="/Home/Login" on the form since you have set the default route as /Home/Login:

    app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Login}/{id?}");
        });
    

    If you change the default route, it will be displayed correctly.

    I have tried your code and the problem is in your model binding.

    Firstly, you need to remove [FromBody] since you are receiving data from a form instead of request body.

    Besides, your form does not post data correctly since you do not set the name attribute or use asp-for tag helper for your inputs which are used to bind inputs' data to model on action parameters.

    Finally, see my complete demo with my assumption Login model:

    public class Login
    {
        public string uname { get; set; }
        public string pwd { get; set; }
    }
    

    Login.cshtml( add name attribute which equal the Login model's property names):

    <form asp-action="Login" asp-controller="Home" method="post" class="mt-4">
        <div class="row">
            <div class="col-lg-12">
                <div class="form-group">
                    <label class="text-dark" for="uname">E-mail</label>
                    <input class="form-control" name="uname" id="uname" type="text"
                           placeholder="digite e-mail">
                </div>
            </div>
            <div class="col-lg-12">
                <div class="form-group">
                    <label class="text-dark" for="pwd">Senha</label>
                    <input class="form-control" name="pwd" id="pwd" type="password"
                           placeholder="digite sua senha">
                </div>
            </div>
            <div class="col-lg-12 text-center">
                <button type="submit" class="btn btn-block btn-dark" />
            </div>
    
        </div>
    </form>
    

    POST action:

    [HttpPost]
    public async Task<IActionResult> Login(Login LoginModel)