To be short, I have 2 View Models, one is for creating and another for editing. The problem is to bypass ModelState validation for one of them. For example, I want to edit a user. When I post it will say validation is invalid for the Input Model which I do not want to use when I trigger the OnPostEdit handler. I tried to remove the key from ModelState but does not work because using debugger all the properties appear without the class which means I would have to remove all properties one by one by their names. The point is, how can I handle all of this without having to remove keys one by one? I know I could just create another page but it's better UX to have it all on one.
Also I found a similar post but has no solution, but should explain what I need better too. Razor Pages - Model validation fails due to multiple objects sharing parameters
@if (Model.EditInput != null)
{
<form method="post" asp-page-handler="Edit">
<!-- Modal -->
<div class="modal fade" id="modalEditUser" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header bg-warning">
<h5 class="modal-title" id="exampleModalLabel"><i class="fas fa-edit"></i> Editar Utilizador</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true"><i class="fas fa-times"></i></span>
</button>
</div>
<div class="modal-body">
<input type="hidden" asp-for="EditInput.Id" />
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="EditInput.UserName"></label>
<input asp-for="EditInput.UserName" class="form-control rounded-0" />
<span asp-validation-for="EditInput.UserName" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="EditInput.Name"></label>
<input asp-for="EditInput.Name" class="form-control rounded-0" />
<span asp-validation-for="EditInput.Name" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="EditInput.Email"></label>
<input asp-for="EditInput.Email" class="form-control rounded-0" />
<span asp-validation-for="EditInput.Email" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="EditInput.Password"></label>
<input asp-for="EditInput.Password" class="form-control rounded-0" />
<span asp-validation-for="EditInput.Password" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="EditInput.ConfirmPassword"></label>
<input asp-for="EditInput.ConfirmPassword" class="form-control rounded-0" />
<span asp-validation-for="EditInput.ConfirmPassword" class="text-danger"></span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-warning">Guardar</button>
</div>
</div>
</div>
</div>
</form>
}
<form method="post">
<!-- Modal -->
<div class="modal fade" id="modalAddUser" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header bg-lightblue">
<h5 class="modal-title" id="exampleModalLabel">Adicionar Artigo a Kit</h5>
<button type="button" class="close text-white" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true"><i class="fas fa-times"></i></span>
</button>
</div>
<div class="modal-body">
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="Input.UserName"></label>
<input asp-for="Input.UserName" class="form-control rounded-0" />
<span asp-validation-for="Input.UserName" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="Input.Name"></label>
<input asp-for="Input.Name" class="form-control rounded-0" />
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control rounded-0" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control rounded-0" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control rounded-0" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancelar</button>
<button type="submit" class="btn bg-lightblue">Adicionar</button>
</div>
</div>
</div>
</div>
</form>
Page Model
[BindProperty]
public EditUserVM EditInput { get; set; }
[BindProperty]
public UserVM Input { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
GetData();
_toast.AddErrorToastMessage("Dados inválidos.");
return Page();
}
// add user
_toast.AddSuccessToastMessage("Utilizador alterado.");
return RedirectToPage("Index");
}
public async Task<IActionResult> OnPostEditAsync()
{
ModelState.Remove(nameof(UserVM));
if (!ModelState.IsValid)
{
GetData();
_toast.AddErrorToastMessage("Dados inválidos.");
return Page();
}
var user = await _userManager.FindByIdAsync(EditInput.Id.ToString());
user.UserName = EditInput.UserName;
user.Name = EditInput.Name;
user.Email = EditInput.Email;
user.IsBlocked = EditInput.IsBlocked;
user.ModifiedAt = DateTime.Now;
var hashedPassword = _userManager.PasswordHasher.HashPassword(user, EditInput.Password);
user.PasswordHash = hashedPassword;
await _userManager.UpdateAsync(user);
_toast.AddSuccessToastMessage("Utilizador alterado.");
return RedirectToPage("Index");
}
So the solution is to wrap both models into one
For example instead of having this
[BindProperty]
public EditUserVM EditInput { get; set; }
[BindProperty]
public UserVM Input { get; set; }
I would create another class in my page and change the properties around the page accordingly. With this If I hit the Edit Handler, the UserVM won't appear on the ModelState and the same vice-versa
[BindProperty]
public FormModel Form { get; set; }
public class FormModel
{
public UserVM Input { get; set; }
public EditUserVM EditInput { get; set; }
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.