partial的ActionResult让Layout消失

ActionResult of partial makes Layout disappear

我正在尝试在“管理”部分的“索引”页面中验证更改后的密码部分视图。像这样,

@inject UserManager<ApplicationUser> UserManager
@model IndexViewModel
@{
   ViewData["Title"] = "Manage your account";
}

<div class="row settings">
<div class="col-sm-6">
    <h4>Basic information</h4>
    @await Html.PartialAsync("BasicInformation", new BasicInformationViewModel(UserManager))
</div>
<div class="col-sm-6">
    <h4>Change Password</h4>
    @await Html.PartialAsync("ChangePassword", new ChangePasswordViewModel())
</div>

控制器代码

    [HttpPost("ChangePassword")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model)
    {
        if (!ModelState.IsValid)
        {
            return PartialView(model);
        }
        var user = await GetCurrentUserAsync();
        if (user != null)
        {
            var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
            if (result.Succeeded)
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                _logger.LogInformation(3, "User changed their password successfully.");
                ViewData["StatusMessage"] = TranslationService.TranslateManageMessage(_context, ManageMessageId.ChangePasswordSuccess, "Your password has been changed.");
                return PartialView();
            }
            AddErrors(result);
            return PartialView(model);
        }

        ViewData["StatusMessage"] = TranslationService.TranslateManageMessage(_context, ManageMessageId.Error, "An error has occured.");
        return PartialView();
    }

所以当用户更改他的密码时,我真正想要发生的事情是操作完成并且局部视图 ges 的状态消息更新了发生的事情(成功、错误等)。所以我现在是如何实现它的,它按我想要的方式工作,但这个设置唯一不好的地方就是会发生这种情况。

我的布局就这样消失了,我不知道为什么。我原以为返回局部视图只会重新加载页面,但似乎并非如此。

谁能指出我正确的方向?或者给出如何更好地做到这一点的建议?

编辑:

更改密码部分

@model ChangePasswordViewModel

<form asp-controller="Manage" asp-action="ChangePassword" method="post" class="form-horizontal">
<p class="text-success">@ViewData["StatusMessage"]</p>
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
    <label asp-for="OldPassword" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="OldPassword" class="form-control" />
        <span asp-validation-for="OldPassword" class="text-danger"></span>
    </div>
</div>
<div class="form-group">
    <label asp-for="NewPassword" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="NewPassword" class="form-control" />
        <span asp-validation-for="NewPassword" class="text-danger"></span>
    </div>
</div>
<div class="form-group">
    <label asp-for="ConfirmPassword" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="ConfirmPassword" class="form-control" />
        <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
    </div>
</div>
<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <button type="submit" class="btn btn-default">Change password</button>
    </div>
</div>

@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

问题是您最初是在获取请求时在索引视图中加载部分视图,当您 post 更改密码操作时,它不是 ajax 部分 post 它是完整 post 并且它不是 Index 操作,因此它没有使用索引视图,并且您返回的是不在任何其他视图内的局部视图,因此没有外部视图也没有布局

更新:因为您在评论中要求展示如何使用 ajax:

在你的索引视图中用一个 id 包裹一个 div 像这样:

<div id="changepassword">
    @await Html.PartialAsync("ChangePassword", new ChangePasswordViewModel())
</div>

并且您需要包括 jquery unobtrusive ajax 在应该在索引视图中的脚本部分中,而不是在部分

@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
<script src="~/path-to-jqueryajaxunobtrusive"></script>
}

在您的 ChangePassword 视图中更改如下:

@model ChangePasswordViewModel

<form asp-controller="Manage" asp-action="ChangePassword" method="post" class="form-horizontal"
    data-ajax="true" 
    data-ajax-method="POST" 
    data-ajax-mode="replace" 
    data-ajax-update="#changepassword">

<p class="text-success">@ViewData["StatusMessage"]</p>
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
    <label asp-for="OldPassword" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="OldPassword" class="form-control" />
        <span asp-validation-for="OldPassword" class="text-danger"></span>
    </div>
</div>
<div class="form-group">
    <label asp-for="NewPassword" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="NewPassword" class="form-control" />
        <span asp-validation-for="NewPassword" class="text-danger"></span>
    </div>
</div>
<div class="form-group">
    <label asp-for="ConfirmPassword" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="ConfirmPassword" class="form-control" />
        <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
    </div>
</div>
<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <button type="submit" class="btn btn-default">Change password</button>
    </div>
</div>

通过包含 jquery 不引人注目的 ajax 脚本并添加 data-* 属性,如图所示,应该连接表单以执行 ajax post 和结果应使用指示的 id

更新 div 的内容