3

I have an MVC application with different user accounts and passwords. The log in feature works fine, but when I click the log out button I get a 404 error saying:

Server Error in '/' Application.

The resource cannot be found. Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had >its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled >correctly.

Requested URL: /Account/LogOff

This is the code for the log out button:

        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li>@Html.ActionLink("Log Off", "LogOff", "Account")</li>
                
            </ul>
        </div>

This is the code in the AccountController

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        Session.Clear();
        FormsAuthentication.SignOut();
        return RedirectToAction("Index", "Home");
    }
Community
  • 1
  • 1
Kevin
  • 198
  • 3
  • 6
  • 17

4 Answers4

10

Html.ActionLink renders a regular hyperlink, which causes a GET request.

Your LogOff has the HttpPost attribute, which means it'll only answer to POST requests. Remove the attribute and your action will work. The ValidateAntiForgeryToken is also not needed, it is for forms.


Note: I no longer stand by my original answer. Although it fixes the problem at hand, logging out should really be a POST instead, due to browser prefetching and potential malicious behaviour. So instead of using a hyperlink, there should be a form with a submit button styled as a hyperlink.

user247702
  • 23,641
  • 15
  • 110
  • 157
4

Just adding to answer given by @Stijn: ActionLink sends a get request to the server and your LogOff Action is expecting a post request which contains AntiForgeryToken

You need to create a form, with a submit button like this:

 @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { role = "form" }))
 {
     @Html.AntiForgeryToken()
     <input type="submit" value="Logout" class="btn btn-primary"/>
 }

This would hit your LogOff Action, in Account Controller:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    AuthenticationManager.SignOut(
        DefaultAuthenticationTypes.ApplicationCookie);
    return RedirectToAction("Index", "Home");
}
Hooman Bahreini
  • 14,480
  • 11
  • 70
  • 137
2

I had the same issue and I handled it by creating a hidden form, then on click of the Log Out link, it submits the form. Like this

<form method="post" action="@Url.Action("LogOff", "Account")" id="signoutfrm" style="display:none;">
@Html.AntiForgeryToken()
</form>

<a href="" onclick="$('#signoutfrm').submit(); return false;">LOGOUT</a>

It worked perfectly

njmwas
  • 1,111
  • 14
  • 15
0

As per Microsoft MVC project template,

// Note: Action Name, Controller Name
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm"))
{
    @Html.AntiForgeryToken()

    <ul>            
    <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
    </ul>
}
  • Since logoff require AntiForgeryToken it is not allowed in get method. You have to use POST method.

  • RedirectToAction cannot be used for post method.

Aravin
  • 6,605
  • 5
  • 42
  • 58