简体   繁体   中英

View with Multiple Models and Posting only one

The situation is that I have a complex model with a lots of data to view and aside to it, control panel with for example password change.

One big model with another property model which will be submitted.
The information inside the big model requires loading and is not required upon POSTing

The Model

public class ProfileModel {
    // This is the submitted model:
    public PasswordChangeModel Password = new PasswordChangeModel();

    // Personal Info
    public string Name {get; set;}
    public string LastName {get; set;}
    // 15~ more fields
}

The password model w/ validation

public class PasswordChangeModel {
    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "OldPassword")]
    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 = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Repeat password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string RepeatPassword { get; set; }
}

Controller Catching-Action

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ChangePassword(PasswordChangeModel model) {
    if (!ModelState.IsValid) //validate the model
        return View(model);

    //do stuff ...
    return Index();
}

The Html to generate the form

<form asp-controller="Profile" asp-action="ChangePassword" asp-antiforgery="true">
    <div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div>        
    <label asp-for="Password.OldPassword">Old Password</label>
    <input asp-for="Password.OldPassword"/>
    <label asp-for="Password.Password">New Password</label>
    <input asp-for="Password.Password"/>
    <label asp-for="Password.RepeatPassword">New Password Repeat</label>
    <input asp-for="Password.RepeatPassword"/>
    <input type="submit" class="btn" name="submit" value="Change"/>
</form>

The Question

Now after reviewing the code, my question is - is it possible to submit it that way, if not whats the most convenient and clean way to do it.

Note: I always can just include 3 fields inside the model ProfileModel of the password changing but A-It's ugly and B-It still makes the entire ProfileModel data to load.

I would say that the cleanest way to do this is to have a separate update password view. This or switching to a ajax post so you can post without reloading the page. If you can't make a model that could do a roundtrip to the server without repopulating it then don't do standard form posting. It can be done but when I've seen it usually there are subtle errors when rerendering the page on validation error. It's just easy to shoot yourself in the foot.

This is what I've ended up doing. Worked just fine.

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ChangePassword([Bind(Prefix = "Password.OldPassword")]string Password_OldPassword, 
    [Bind(Prefix = "Password.Password")] string Password_Password, 
    [Bind(Prefix = "Password.RepeatPassword")] string Password_RepeatPassword) {
    //Change the password
}

Bind attribute redirected the value of Password.OldPassword to Password_OldPassword .

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM