title: ASP.NET MVC Why doesn't this post action get called from the view?
body: <p>In a system that uses Identity framework for authentication, I have the following Model, Controller action, and View respectively to implement a password change feature (I saw many articles for learning how to reset a password, but not how to change a password even though the current one is known):</p>
  
  <p><strong>Model:</strong></p>
  
  <pre><code>public class ChangePasswordBindingModel
      {
          [Required]
          [DataType(DataType.Password)]
          public string OldPassword { get; set; }
  
          [Required]
          [DataType(DataType.Password)]
          [Display(Name = "New password")]
          public string NewPassword { get; set; }
  
          [Required]
          [DataType(DataType.Password)]
          [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
          public string ConfirmPassword { get; set; }
  }
  </code></pre>
  
  <p><strong>Controller action in <code>AccountController.cs</code>:</strong></p>
  
  <pre><code>[HttpPost]
  public async Task&lt;ActionResult&gt; ChangePassword(ChangePasswordBindingModel loginChange)
  {
  
      IdentityResult fffx = await UserManager.ChangePasswordAsync("userId", loginChange.OldPassword, loginChange.NewPassword);
      return View("Index");
  }
  </code></pre>
  
  <p><strong>View for password change form, called <code>ChangePassword.cshtml</code>:</strong></p>
  
  <pre><code>@model IdentityDevelopment.Models.ChangePasswordBindingModel
  @{ ViewBag.Title = "ChangePassword";}
  &lt;h2&gt;Change Password&lt;/h2&gt;
  
  
  @using (Html.BeginForm("ChangePassword","Account", FormMethod.Post))
  {
      //@Html.AntiForgeryToken();
      &lt;input type="hidden" name="returnUrl" value="@ViewBag.returnUrl" /&gt;
  
      &lt;div class="form-group"&gt;
          &lt;label&gt;Current Password&lt;/label&gt;
          @Html.PasswordFor(x =&gt; x.OldPassword, new { @class = "form-control" })
      &lt;/div&gt;
  
      &lt;div class="form-group"&gt;
          &lt;label&gt;New Password&lt;/label&gt;
          @Html.PasswordFor(x =&gt; x.NewPassword, new { @class = "form-control" })
      &lt;/div&gt;
  
  
      &lt;div class="form-group"&gt;
          &lt;label&gt;Re-enter New Password&lt;/label&gt;
          @Html.PasswordFor(x =&gt; x.ConfirmPassword, new { @class = "form-control" })
      &lt;/div&gt;
  
      &lt;button class="btn btn-primary" type="submit"&gt;Save&lt;/button&gt;
  }
  </code></pre>
  
  <p>Why would clicking on the "Save" button on the form not call the post action method? </p>
  
  <p><strong>EDIT 1:</strong></p>
  
  <p>I am including the controller method for Login, in where a scenario causes the ChangePassword form to appear. Maybe there is something here that is a problem?</p>
  
  <pre><code>[HttpPost]
  [AllowAnonymous]
  [ValidateAntiForgeryToken]
  public async Task&lt;ActionResult&gt; Login(LoginModel details, string returnUrl)
  {
    if (ModelState.IsValid)
      {
         AppUser user = await UserManager.FindAsync(details.Name,
                      details.Password);
          if (user == null)
           {
                      ModelState.AddModelError("", "Invalid name or password.");
            }
        else
         {
  
      //Check if this is initial login of user, force password change if so
                      PasswordChangeChecker PassCheck = new PasswordChangeChecker();
                      string userId = user.Id.ToString();
                      bool proceed = PassCheck.IsPasswordChangedFromInitial(userId);
                      if (proceed)
                      {
                          ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user,
                                               DefaultAuthenticationTypes.ApplicationCookie);
                          ident.AddClaims(LocationClaimsProvider.GetClaims(ident));
                          ident.AddClaims(ClaimsRoles.CreateRolesFromClaims(ident));
                          AuthManager.SignOut();
                          AuthManager.SignIn(new AuthenticationProperties
                          {
                              IsPersistent = false
                          }, ident);
  
  
                          //persist login into db
                          Loginobject login = new Loginobject();
                          login.Username = user.UserName;
                          login.SessionId = HttpContext.Session.SessionID;
                          Session["sessionid"] = HttpContext.Session.SessionID;
                          login.Date = DateTime.Now;
                          SQLLoginrecord sqlLogin = new SQLLoginrecord();
                          sqlLogin.PutOrPostLogin(login);
  
                          TempData["LoginMsg"] = "Any existing sessions are now deactivated.";
  
                          return Redirect(returnUrl);
                      }
                      else
                      {
                          return View("ChangePassword", new ChangePasswordBindingModel());
                      }
                  }
              }
              ViewBag.returnUrl = returnUrl;
              return View(details);
          }
  </code></pre>
  
  <p><strong>EDIT 2:</strong></p>
  
  <p>It looks like the cause of the issue is a global custom authorization filter (thanks for the comment stephen.vakil) <code>[AuthorizeSingleLogin]</code> that I have put over the definition of <code>AccountController.cs</code></p>
  
  <p><strong>AuthorizeSingleLogin.cs</strong></p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using System.Web.Mvc;
  
  namespace IdentityDevelopment.Infrastructure
  {
      public class AuthorizeSingleLogin : AuthorizeAttribute
      {
          private AppIdentityDbContext db = new AppIdentityDbContext();
          protected override bool AuthorizeCore(HttpContextBase httpContext)
          {
              bool isAuthorized = base.AuthorizeCore(httpContext);
  
              string user = httpContext.User.Identity.Name;
  
              string access = httpContext.Session.SessionID;
  
              if (String.IsNullOrEmpty(user) || String.IsNullOrEmpty(access))
              {
                  return isAuthorized;
              }
  
              SQLLoginrecord sqlLogin = new SQLLoginrecord();
  
              return sqlLogin.IsLoggedIn(user, access);
          }
      }
  }
  </code></pre>
  
  <p><strong>SQLLoginrecord.cs</strong></p>
  
  <pre><code>using IdentityDevelopment.Models;
  using System;
  using System.Collections.Generic;
  using System.Data.Entity;
  using System.Linq;
  using System.Web;
  using static IdentityDevelopment.Models.Loginobject;
  
  namespace IdentityDevelopment.Infrastructure
  {
      public class SQLLoginrecord
      {
  
          private LoginobjectDBContext db = new LoginobjectDBContext();
          private bool PriorSessionActive = false;
          public void PutOrPostLogin(Loginobject login)
          {
              var logins = db.Loginobjects.Where(l =&gt; l.Username == login.Username);
  
              if (logins.Any())
              {
                  Loginobject tempLogin = logins.First();
                  tempLogin.SessionId = login.SessionId;
                  tempLogin.Date = login.Date;
                  db.Entry(tempLogin).State = EntityState.Modified;
                  PriorSessionActive = true;
              }
              else
              {
                  db.Loginobjects.Add(login);
              }
              db.SaveChanges();
  
  
          }
  
          public bool IsLoggedIn(string user, string session)
          {
              var logins = db.Loginobjects.Where(l =&gt; l.Username == user &amp;&amp; l.SessionId == session);
  
              if (logins.Any())
              {
                  return true;
              }
              else
              {
                  return false;
              }
          }
  
          public bool PriorSessionUpdated()
          {
              return this.PriorSessionActive;
          }
  
  
      }
  
  }
  </code></pre>
  
  <p>Thank you.</p>