调用POST方法时,ASP.NET MVC Model属性为null

时间:2016-08-23 14:59:24

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

在控制器操作中,我有以下调用,其中userId是已知的非空值:

return View("ChangePassword", new ChangePasswordBindingModel(userId));

以下是ChangePasswordBindingModel的定义:

public class ChangePasswordBindingModel
{
    private string currentUserId;
    [Required]
    [DataType(DataType.Password)]
    //[Display(Name = "Current password")]
    public string OldPassword { get; set; }

    [Required]
    //[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "New password")]
    public string NewPassword { get; set; }

    [Required]
    [DataType(DataType.Password)]
    //[Display(Name = "Confirm new password")]
    [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }

    public ChangePasswordBindingModel()
    {

    }
    public ChangePasswordBindingModel(string userId)
    {
        this.currentUserId = userId;
    }

    public string GetUserId()
    {
        return this.currentUserId;
    }
}

以下是此模型与ChangePassword绑定的视图:

@model IdentityDevelopment.Models.ChangePasswordBindingModel
@{ ViewBag.Title = "ChangePassword";
}

@Html.ValidationSummary(false)
<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> -->
    <input class="btn btn-primary" type="submit" value="Save" />
}

最后,这是在上面的表单上单击Save的Post方法:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ChangePassword(ChangePasswordBindingModel loginChange)
{
    if (ModelState.IsValid)
    {
        IdentityResult result = null;
        try
        {
            string userid = loginChange.GetUserId();
            result = await UserManager.ChangePasswordAsync(userid, loginChange.OldPassword, loginChange.NewPassword);

        }
        catch (Exception ex)
        {

        }
        if (result != null && result.Succeeded)
        {
            return RedirectToAction("Index");
        }
        else
        {
            if(result != null)
            {
                AddErrorsFromResult(result);
            }

        }
    }

    return View(loginChange);
}

问题是userid没有设置为非空值,正如我认为GetUserId()会做的那样。为什么发送到post方法的Model的currentUserId属性不包含值?我通过调试期间调用GetUserId()来确认这是如此。

3 个答案:

答案 0 :(得分:2)

由于以下两个原因,

currentUserId未提交给帖子操作方法:

  1. currentUserId不是公共财产。
  2. using (Html.BeginForm<input><textarea>标记中的<select>块内不存在。
  3. 删除currentUserId并在模型中创建名为CurrentUserId的新公共属性。您也不需要GetUserId()方法。您的模型应如下所示

    public class ChangePasswordBindingModel
    {
        [Required]
        [DataType(DataType.Password)]
        //[Display(Name = "Current password")]
        public string OldPassword { get; set; }
    
        [Required]
        //[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "New password")]
        public string NewPassword { get; set; }
    
        [Required]
        [DataType(DataType.Password)]
        //[Display(Name = "Confirm new password")]
        [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    
        public string CurrentUserId { get; set; }
    
        public ChangePasswordBindingModel()
        {
    
        }
        public ChangePasswordBindingModel(string userId)
        {
            this.CurrentUserId = userId;
        }
    
    }
    

    并使用HiddenField在您的视图中包含CurrentUserId

    @using (Html.BeginForm("ChangePassword","Account", FormMethod.Post))
    {
       @Html.AntiForgeryToken();
        @Html.HiddenFor(x => x.CurrentUserId)
        <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> -->
        <input class="btn btn-primary" type="submit" value="Save" />
    }
    

    在您的帖子操作方法中,您可以获得CurrentUserId属性的值,如下所示

    result = await UserManager.ChangePasswordAsync(loginChange.CurrentUserId, loginChange.OldPassword, loginChange.NewPassword);
    

答案 1 :(得分:2)

首先将currentUserId设为public,然后将其放入View中的隐藏字段中。

I\sam\s(.+)

答案 2 :(得分:1)

currentUserId是私人会员,不是财产。并且它不受视图中任何表单字段的约束。因此,当您通过传递具有非空值currentUserId的模型来呈现视图时,在客户端上呈现视图时该值会立即丢失,因为它仅存在于服务器上的模型中。所以没有办法让它回来。

您可以使用CurrentUserId创建Html.HiddenFor()属性,并在视图中显示隐藏字段,以便将值发送到客户端,然后在POST期间将其恢复。