ASP.NET MVC为什么不从视图中调用此post动作?

时间:2016-08-22 17:50:31

标签: c# asp.net asp.net-mvc asp.net-identity

在使用Identity framework进行身份验证的系统中,我分别使用以下Model,Controller操作和View来实现密码更改功能(我看到很多文章用于学习如何重置密码,但不知道如何更改密码密码,即使当前的密码已知):

型号:

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; }
}

AccountController.cs中的控制器操作:

[HttpPost]
public async Task<ActionResult> ChangePassword(ChangePasswordBindingModel loginChange)
{

    IdentityResult fffx = await UserManager.ChangePasswordAsync("userId", loginChange.OldPassword, loginChange.NewPassword);
    return View("Index");
}

查看密码更改表单,名为ChangePassword.cshtml

@model IdentityDevelopment.Models.ChangePasswordBindingModel
@{ ViewBag.Title = "ChangePassword";}
<h2>Change Password</h2>


@using (Html.BeginForm("ChangePassword","Account", FormMethod.Post))
{
    //@Html.AntiForgeryToken();
    <input type="hidden" name="returnUrl" value="@ViewBag.returnUrl" />

    <div class="form-group">
        <label>Current Password</label>
        @Html.PasswordFor(x => x.OldPassword, new { @class = "form-control" })
    </div>

    <div class="form-group">
        <label>New Password</label>
        @Html.PasswordFor(x => x.NewPassword, new { @class = "form-control" })
    </div>


    <div class="form-group">
        <label>Re-enter New Password</label>
        @Html.PasswordFor(x => x.ConfirmPassword, new { @class = "form-control" })
    </div>

    <button class="btn btn-primary" type="submit">Save</button>
}

为什么单击表单上的“保存”按钮不会调用post action方法?

编辑1:

我包含Login的控制器方法,其中场景导致ChangePassword表单出现。也许这里有什么问题?

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> 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);
        }

编辑2:

看起来问题的原因是全局自定义授权过滤器(感谢评论stephen.vakil)[AuthorizeSingleLogin]我已经提出AccountController.cs的定义

AuthorizeSingleLogin.cs

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);
        }
    }
}

SQLLoginrecord.cs

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 => 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 => l.Username == user && l.SessionId == session);

            if (logins.Any())
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool PriorSessionUpdated()
        {
            return this.PriorSessionActive;
        }


    }

}

谢谢。

2 个答案:

答案 0 :(得分:3)

<button class="btn btn-primary" type="submit">Save</button>

元素必须是

<input class="btn btn-primary" type="submit" value="Save"/>

元素。

答案 1 :(得分:3)

如果你的行动没有在帖子上被击中,而是转到其他地方,那将导致我相信发生了两件事之一:

  1. 您的路由表配置不正确

  2. 您有一个全局过滤器(尤其是全局授权过滤器),它通过拦截请求并禁止或覆盖请求来干扰您的预期行为。

  3. 通过调试和试错,你应该能够在任何一种情况下确定罪魁祸首。