从部分视图返回的模型字段包含空值

时间:2014-11-03 11:24:34

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

我有一个当前登录用户的Manage页面。此视图加载两个部分视图。一个用于更新用户注册的电子邮件地址,另一个用于更新密码。 Manage视图看起来像

@using VisasysNET.Models;
@using Microsoft.AspNet.Identity;
@model VisasysNET.Models.ManageUserViewModel
@{
    ViewBag.Title = "Manage Account";
}

<h2>@ViewBag.Title</h2>
<p class="text-success">@ViewBag.StatusMessage</p>
<div class="row">
    <div class="col-md-12">
        @Html.Partial("_ChangeEmailAddressPartial", Model)
    </div>
</div>
<div class="row">
    <div class="col-md-12">
        @if (ViewBag.HasLocalPassword)
        {
            @Html.Partial("_ChangePasswordPartial")
        }
        else
        {
            @Html.Partial("_SetPasswordPartial")
        }
    </div>
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

我有一个&#34;更新电子邮件/密码&#34;我的更新电子邮件局部视图中的按钮和更新密码局部视图。现在,我通过

从控制器的管理视图处理帖子
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Manage(ManageUserViewModel model)
{
    bool hasPassword = HasPassword();
    ViewBag.HasLocalPassword = hasPassword;
    ViewBag.ReturnUrl = Url.Action("Manage");
    if (hasPassword)
    {
        if (ModelState.IsValid)
        {
            IdentityResult result = await UserManager.ChangePasswordAsync(
                User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
            if (result.Succeeded)
            {
                return RedirectToAction("Manage",
                    new { Message = ManageMessageId.ChangePasswordSuccess });
            }
            else
                AddErrors(result);
        }
    }
    else
    {
        // User does not have a password so remove any validation 
        // errors caused by a missing OldPassword field.
        ...
    }
    // If we got this far, something failed, redisplay form.
    return View(model);
}

其中

public class ManageUserViewModel
{
    [Required]
    [EmailAddress(ErrorMessage = "Invalid email address.")]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email address")]
    public string EmailAddress { get; set; }

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

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

问题是如果用户点击按钮

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

在更新密码视图中,ManageUserViewModel.EmailAddress返回为null,反之亦然(如果用户单击&#34;更新电子邮件地址&#34;按钮,则密码字段返回null )。这是一个问题,因为我随后收到验证错误消息

Validation Error

在上面我试图更新密码。如果&#34;更新密码&#34;如何阻止执行电子邮件的验证?按下按钮,反之亦然?

感谢您的时间。


请求部分观点

电子邮件更新部分视图

@using Microsoft.AspNet.Identity
@model VisasysNET.Models.ManageUserViewModel
<p>You're logged in as <strong>@User.Identity.GetUserName()</strong></p>
@using (Html.BeginForm("Manage", "Account", FormMethod.Post,
    new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Change Email Address</h4>
    <hr />
    @Html.ValidationSummary()
    <div class="form-group">
        @Html.LabelFor(m => m.EmailAddress, 
            new 
            { 
                @class = "col-md-2 control-label" 
            })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.EmailAddress, 
                new 
                { 
                    @class = "col-md-10 form-control", 
                    @type = "text",
                    @placeholder = "Email Address",
                    @value = Model.EmailAddress
                })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Update Email Address" class="btn btn-primary" />
        </div>
    </div>
}

更新密码部分是

@using Microsoft.AspNet.Identity
@model VisasysNET.Models.ManageUserViewModel

@*<p>You're logged in as <strong>@User.Identity.GetUserName()</strong></p>*@

@using (Html.BeginForm("Manage", "Account", FormMethod.Post, 
    new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Change Password</h4>
    <hr />
    @Html.ValidationSummary()
    <div class="form-group">
        @Html.LabelFor(m => m.OldPassword, 
        new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.OldPassword, 
            new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.NewPassword, 
        new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.NewPassword, 
            new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, 
        new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, 
            new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Change password" class="btn btn-primary" />
        </div>
    </div>
}

编辑#2。答案问题

Get方法是

// GET: /Account/Manage.
public ActionResult Manage(ManageMessageId? message)
{
    ViewBag.StatusMessage =
        message == ManageMessageId.ChangePasswordSuccess ? 
            "Your password has been changed": 
        message == ManageMessageId.SetPasswordSuccess ? 
            "Your password has been set" : 
        message == ManageMessageId.RemoveLoginSuccess ? 
            "The external login was removed" : 
        message == ManageMessageId.ChangeEmailAddressSuccess ?
            "Your email address was successfully updated" :
        message == ManageMessageId.Error ? 
            "An error has occurred." : "";
    ViewBag.HasLocalPassword = HasPassword();
    ViewBag.ReturnUrl = Url.Action("Manage");

    // Get current email address.
    var user = UserManager.FindById(User.Identity.GetUserId());
    ManageUserViewModel model = new ManageUserViewModel();
    model.EmailAddress = user.EmailAddress;
    return View(model);
}

但是视图似乎知道OldPassword是什么,它放在TextBox中,显然是null,所以这个Firefox是聪明的吗?

你是说我应该传递一个object[]包含两个视图模型,一个用于密码,另一个用于电子邮件的东西?

1 个答案:

答案 0 :(得分:2)

我认为您最好考虑使用单独的视图模型,尤其是客户端验证,但是您可以使用

清除特定属性的ModelState错误
if (ModelState.ContainsKey("Email"))
{
   ModelState["Email"].Errors.Clear();
}