c# - ASP.NET MVC 为什么不从 View 中调用此发布操作?

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

在一个使用Identity framework进行身份验证的系统中,我分别有如下Model,Controller action,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 中的 Controller 操作:

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

为什么单击表单上的“保存”按钮不会调用发布操作方法?

编辑 1:

我包括了用于登录的 Controller 方法,其中一个场景导致 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;
        }


    }

}

谢谢。

最佳答案

如果你的 Action 没有被击中,而是转移到其他地方,那会让我相信正在发生以下两种情况之一:

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

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

通过调试和试错,您应该能够确定两种情况下的罪魁祸首。

关于c# - ASP.NET MVC 为什么不从 View 中调用此发布操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39085744/

相关文章:

c# - Try - Catch 返回策略

c# - 处理 for-each 循环中项目的异常

c# - 为什么 Replace() 字符串方法不修改我的字符串变量?

c# - 使用 ASP.NET C# 解析 JSON 中的数组

c# - Json.net:如何从 [WebMethod] 返回 JObject?

c# - 在不安装 visual studio 的情况下发布 asp.net mvc5

jquery - json数据中可以有group by吗?

c# - 如何在启动到非桌面 shell 后从 C# 代码加载/显示桌面?

javascript - 进度条使用样式更新进度

c# - 我可以在 PostAuthorizeRequest 方法中启动 MVC Mini Profiler 吗?