MVC 4 - LogOff controller action giving 404 not found

15,952

Solution 1

You use a link (<a/> tag) to log off which results in HTTP GET request when user clicks on it, but your action is constrained to serve POST request only (because it is decorated with [HttpPost] attribute).

You either need to put your link into a form and generate POST request, or remove [HttpPost] and [ValidateAntiForgeryToken] (credits to GalacticCowboy) from your action.

Solution 2

Since logout modifies server state, I wouldnt remove [HttpPost] and [ValidateAntiForgeryToken] Instead I will replace the link (anchor tag) with the following

@using (Html.BeginForm("Log Out", "Account", FormMethod.Post,
 new { id = "logoutForm" }))
{

    @Html.AntiForgeryToken()
    <a href="javascript:document.getElementById('logoutForm').submit()">Log Out</a>

}
Share:
15,952

Related videos on Youtube

MattSull
Author by

MattSull

Founder at early-stage Irish tech start-up Verivoo /// Check us out in The Irish Times Full stack developer with experience across the .NET stack and more recently Angular/Ionic/Node. Open to hearing about short-term, part-time, remote contracting positions.

Updated on June 04, 2022

Comments

  • MattSull
    MattSull almost 2 years

    I'm just wrapping up a college project, I'm not sure if I've been staring at my computer for too long and am missing something obvious, but when I try to log a user out, I'm getting a 404 not found for the URL /Account/LogOff.

    I have a navbar that shows Log in/Log out depending on whether a user is, logged in, or, logged out:

    <div class="nav-collapse collapse">
        <ul class="nav pull-right">
            <li class="dropdown" id="dropdown-login-div">
                @if (!Request.IsAuthenticated)
                {
                    <a class="dropdown-toggle" href="#" data-toggle="dropdown">Sign In <strong class="caret"></strong></a>
                }
                else
                {
                    @Html.ActionLink("Log Off", "LogOff", "Account")
                }
                <div class="dropdown-menu" id="dropdown-login">
                    @Html.Partial("~/Views/Account/_LoginPartial.cshtml", new ViewDataDictionary<LetLord.Models.LoginModel>())
                </div>
            </li>
        </ul>
    </div>
    

    In my Account controller the default LogOff action that comes with the Internet template:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        WebSecurity.Logout();
    
        return View("Index");
    }
    

    Could someone tell me why this happening - before I throw my laptop against the wall. Cheers.

  • Nate Dudek
    Nate Dudek about 11 years
    This is correct - and my recommendation would be to remove the HttpPost rather than creating a form to logout. Since you're not submitting any data to the server, a GET is most appropriate for a logout action.
  • GalacticCowboy
    GalacticCowboy about 11 years
    ValidateAntiForgeryToken will fail since it's not a form post, also.
  • MattSull
    MattSull about 11 years
    Completely went over my head. Thanks.
  • Dan Hunex
    Dan Hunex about 11 years
    Dont use Get for logout ( logout it modifies sever state
  • Gent
    Gent over 10 years
    very good solution dude, easy to implement and explains the problem. Thanks!
  • Cas Bloem
    Cas Bloem about 8 years
    @JeanJimenez There is no correct solution. A solution can only be correct if the other options are not correct.
  • THX-1138
    THX-1138 about 8 years
    @CasBloem: x * x = 4 => x = 2, x = -2 QED
  • Aravin
    Aravin over 5 years
    This is not a solution. It is work around. Without ValidateAntiForgeryToken anyone can hit that get request.