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 的内容
我正在尝试在“管理”部分的“索引”页面中验证更改后的密码部分视图。像这样,
@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 的内容