【发布时间】:2021-03-27 16:52:32
【问题描述】:
我有两个局部视图,每个都包含一个表单。当我提交其中任何一个时,验证错误在两个部分中都显示为重复项。我错过了什么,或者可能有双重的。 我必须在单独的局部视图中移动每个表单,以便为每个表单提供自己的模型。 我的主要观点:
@inject Microsoft.Extensions.Localization.IStringLocalizer Localizer
@model LoginRegisterViewModel
@{
Layout = "_Layout_";
}
@if (Model.LoginViewModel.EnableLocalLogin)
{
<div class="loginRegister">
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header loginpage">
<main class="fullHeight">
<div class="flexValign" id="overview">
<section class="section--center mdl-grid mdl-grid--no-spacing mdl-shadow--8dp roundedWrapper">
@Html.Partial("_LoginPartial", Model.LoginViewModel)
@Html.Partial("_RegisterPartial", Model.RegisterViewModel)
</section>
</div>
</main>
</div>
</div>
} 我的部分:
@inject Microsoft.Extensions.Localization.IStringLocalizer Localizer
@model RegisterViewModel
<div class="mdl-card mdl-cell mdl-cell--6-col-desktop mdl-cell--6-col-tablet mdl-cell--4-col-phone darkBckrnd">
@using (Html.BeginForm("Register", "Account", FormMethod.Post))
{
<div class="fixedHeight mdl-grid mdl-card__supporting-text mdl-typography--text-center mdl-color-text--white">
<div class="innerWrapper">
@await Html.PartialAsync("_InputValidation")
<input type="hidden" asp-for="RegisterReturnUrl" />
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input type="password" class="mdl-textfield__input" asp-for="NewPassword" autocomplete="new-password">
<label class="mdl-textfield__label mdl-color-text--white" for="Password">@Localizer["password"]
*</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input type="password" autocomplete="off" class="mdl-textfield__input" asp-for="NewPasswordAgain">
<label class="mdl-textfield__label mdl-color-text--white"
for="PasswordAgain">@Localizer["repeatPassword"]
*</label>
</div>
</div>
</div>
<div class="btnContainer">
<button type="submit" value="register" name="button"
class="general mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--cyan-500 mdl-shadow--8dp"
id="RegisterButton">@Localizer["createAccount"]</button>
</div>
}
另一部分:
@inject Microsoft.Extensions.Localization.IStringLocalizer Localizer
@model LoginViewModel
<div class="mdl-card mdl-cell mdl-cell--6-col-desktop mdl-cell--6-col-tablet mdl-cell--4-col-phone white">
@using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
<div
class="fixedHeight mdl-grid mdl-card__supporting-text mdl-typography--text-center mdl-color-text--blue-grey-900">
<div class="innerWrapper">
<partial name="_InputValidation" />
<input type="hidden" asp-for="ReturnUrl" />
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" asp-for="Username">
<label class="mdl-textfield__label mdl-color-text--blue-grey-600"
for="Username">@Localizer["userNameOrEmail"]</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input type="password" class="mdl-textfield__input" asp-for="Password" autocomplete="off">
<label class="mdl-textfield__label mdl-color-text--blue-grey-600"
for="Password">@Localizer["password"]</label>
</div>
</div>
</div>
<div class="btnContainer">
<button type="submit" value="login" name="button"
class="general mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--cyan-500">
@Localizer["login"]</button>
</div>
}
型号:
using System;
using System.Collections.Generic;
using System.Linq;
namespace IdentityServer4.Quickstart.UI
{
public class LoginViewModel : LoginInputModel
{
public bool AllowRememberLogin { get; set; } = true;
public bool EnableLocalLogin { get; set; } = true;
public string LoginPage { get; set; } = "Login";
public IEnumerable<ExternalProvider> ExternalProviders { get; set; } = Enumerable.Empty<ExternalProvider>();
public IEnumerable<ExternalProvider> VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName));
public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;
public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;
}
}
第二个模型
using IdentityServer.DTOs;
using IdentityServer.Models;
namespace IdentityServer4.Quickstart.UI
{
public class RegisterViewModel
{
public string Email { get; set; }
public string NewPassword { get; set; }
public string NewPasswordAgain { get; set; }
public string RegisterReturnUrl { get; set; }
}
然后两个模型联合起来。我已经将这两个模型合并到控制器中来覆盖它们。
using System;
using System.Collections.Generic;
using System.Linq;
namespace IdentityServer4.Quickstart.UI
{
public class LoginRegisterViewModel
{
public LoginViewModel LoginViewModel { get; set; }
public RegisterViewModel RegisterViewModel { get; set; }
}
}
和控制器:
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.Username);
if (await _userManager.CheckPasswordAsync(user, model.Password))
{
var performAdditionalCheck = true;
// If the user has unknown provider let him pass
if (user.Provider == UserAuthentificationProvider.Unknown) performAdditionalCheck = false;
if (context != null)
{
var client = await _clientStore.FindEnabledClientByIdAsync(context.ClientId);
if (client.Properties["forceAuthentification"] == "false") performAdditionalCheck = false;
}
if (performAdditionalCheck)
{
return await RedirectToAuth(model);
}
else
{
return await SignInUserWithModel(user, model);
}
}
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId: context?.ClientId));
ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
}
// something went wrong, show form with error
var vm = await BuildLoginRegisterViewModelAsync(model);
return View(vm.LoginViewModel.LoginPage, vm);
}
【问题讨论】:
-
请参考部分视图和视图模型的正确实现。您可以在主页中保留一个包含多个部分视图的表单,如果您面临与模型(视图模型)相关的问题,则制作一个包含 LoginViewModel 和 RegisterViewModel 的所有属性的单个 ViewModel。
标签: asp.net-mvc validation asp.net-core razor asp.net-mvc-partialview