Search code examples
c#asp.net-mvcasp.net-mvc-5web-config

ASP.NET MVC 5 > AccountController > Login > HTTP 404


I'm using Adam Freeman's book called "Pro ASP.NET MVC", and trying to implement the chapter 12, a simple web application of Authentication.

This web application uses:

  1. Login.cshtml (~/Account/Login);
  2. AccountController.cs
  3. Web.config

You can see Login.cshtml here:

@model SportsStore.WebUI.Models.LoginViewModel

@{
    /*
    chapter 12 - SportsStore: Security & Finishing Touches
        Securing the Administration Controller
            Creating the View 312
                Listing 12-9. The Contents of the Login.cshtml File
   */

    ViewBag.Title = "Admin: Log In";
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

<div class="panel">
    <div class="panel-heading">
        <h3> Log In</h3>
    </div>
    <div class="panel-body">
        <p class="lead">Please log in to access the administration area:</p>
        @using (Html.BeginForm())
        {
            @Html.ValidationSummary()
            <div class="form-group">
                <label>User Name:</label>
                @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
            </div>
            <div class="form-group">
                <label>Password:</label>
                @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
            </div>
            <input type="submit" value="Log in" class="btn btn-primary" />
        }
    </div>
</div>

This is the AccountController class:

using System.Web.Mvc;
using SportsStore.WebUI.Infrastructure.Abstract;
using SportsStore.WebUI.Models;

namespace SportsStore.WebUI.Controllers
{
    /*
    chapter 12 - SportsStore: Security & Finishing Touches
        Securing the Administration Controller
            Creating the Account Controller 312
                Listing 12-8. The Contents of the AccountController.cs File
     */
    public class AccountController : Controller
    {
        IAuthProvider authProvider;

        public AccountController(IAuthProvider auth)
        {
            authProvider = auth;
        }

        [HttpPost]
        public ActionResult Login(LoginViewModel model, string returnUrl)
        {
            if (authProvider.Authenticate(model.UserName, model.Password))
            {
                return Redirect(returnUrl ?? Url.Action("Index", "Admin"));
            }
            else
            {
                return View();
            }
        }
    }
}

And here's the web.config file:

<system.web>
    <compilation debug="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2" />

    <!--
    chapter 12 - SportsStore: Security & Finishing Touches
        Securing the Administration Controller
            Creating a Basic Security Policy
                Listing 12-1. Configuring Forms Authentication in the Web.config File
                Listing 12-2. Defining a Username and Password in the Web.config File                   
    -->

    <authentication mode="Forms">
        <forms loginUrl="~/Account/Login" timeout="2880">
            <credentials passwordFormat="Clear">
                <user name="admin" password="secret" />
            </credentials>
        </forms>
    </authentication>
</system.web>

Maybe my mistake is here? RouteConfig/RegisterRoutes:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
    null,
        "",
        new { controller = "Product", action = "List", category = (string)null, page = 1 }
    );

routes.MapRoute(
    null,
    "Page{page}",
    new { controller = "Product", action = "List", category = (string)null },
    new { page = @"\d+" }
);

routes.MapRoute(
    null,
    "{category}",
    new { controller = "Product", action = "List", page = 1 }
);

routes.MapRoute(
    null,
    "{category}/Page{page}",
    new { controller = "Product", action = "List" },
    new { page = @"\d+" }
);

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

When I run the web application I get this HTTP 404 message

Server error in application '/'

The resource cannot be found.
Request URL: Account/Login

What's my mistake?


Solution

  • You have a Login method on the AccountController that takes an HttpPost but in order to get the view you also need an HttpGet endpoint:

    [HttpGet]
    public ActionResult Login(string returnUrl)
    {
        return View();
    }
    

    With the appropriate Login.cshtml to show the login form of course.

    Also make sure you have the following added to your RouteConfig

    routes.MapMvcAttributeRoutes();