简体   繁体   中英

Asp.Net Mvc multiple forms in single strongly typed view and validate using data annotation

I am developing an Asp.Net mvc application. In my project there are two forms in a single view like this:

在此处输入图片说明

To use multiple forms in a single view, there is a problem for validation using data annotation. First I found this link for using multiple forms in single view asp.net MVC 4 multiple post via different forms . Following answer of that link, I can add multiple forms. But I cannot validate using data annotation with that approach. So I googled for another solution.

This link ( http://geekswithblogs.net/MightyZot/archive/2013/11/11/html.validationsummary-and-multiple-forms.aspx ) also just the same, I have to add validation logic in controller. I found another solution ( http://bluetubeinc.com/blog/2012/10/validating-multiple-forms-the-asp-dot-net-mvc3-way-using-strongly-typed-views ). I thought this solution will solve my problem to validation using data annotation. But one thing to notice is that it is working with Ajax Form. But I followed that link and I am still having problem.

These are my view models:

public class AuthVM
    {
        public LoginViewModel LoginForm { get; set; }
        public RegisterViewModel RegisterForm { get; set; }
    }
public class LoginViewModel
    {
        [Required]
        [Display(Name = "Email")]
        public string Email { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }
    }

    public class RegisterViewModel
    {
        [Required]
        [Display(Name = "User name")]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [MaxLength(70)]
        public string Email { 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 = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    }

This is my controller and actions for login and register:

public class AccountController: Controller
{

[AllowAnonymous]
        public ActionResult Create(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            AuthVM model = new AuthVM
            {
                RegisterForm = new RegisterViewModel(),
                LoginForm = new LoginViewModel()
            };
            return View("Auth",model);
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
           //check modelstate and continue
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Register(RegisterViewModel model)
        {
            //check modelstate and continue
        }

}

This is my view:

<section id="form">
    <!--form-->
    <div class="container">
        <div class="row">
            <div class="col-sm-4 col-sm-offset-1">
                <div class="login-form">
                    <!--login form-->
                    <h2>Login to your account</h2>
                    @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, null))
                    {
                        @Html.AntiForgeryToken()
                        @Html.ValidationSummary()
                        @Html.TextBoxFor(x => x.LoginForm.Email, new { placeholder = "Email" })
                        @Html.PasswordFor(x => x.LoginForm.Password, new { placeholder = "Password" })
                        <button type="submit" class="btn btn-default">Login</button>
                    }
                </div><!--/login form-->
            </div>
            <div class="col-sm-1">
                <h2 class="or">OR</h2>
            </div>
            <div class="col-sm-4">
                <div class="signup-form">
                    <!--sign up form-->
                    <h2>New User Signup!</h2>
                    @using (Html.BeginForm("Register", "Account", FormMethod.Post))
                    {
                        @Html.AntiForgeryToken()
                        @Html.ValidationSummary()
                        @Html.TextBoxFor(x => x.RegisterForm.UserName, new { placeholder = "Display Name" })
                        @Html.TextBoxFor(x => x.RegisterForm.Email, new { placeholder = "Email" })
                        @Html.PasswordFor(x => x.RegisterForm.Password, new { placeholder = "Password" })
                        @Html.PasswordFor(x => x.RegisterForm.ConfirmPassword, new { placeholder = "Retype password" })
                        <button class="btn btn-primary">Register</button>
                    }
                </div><!--/sign up form-->
            </div>
        </div>
    </div>
</section><!--/form-->
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

But when I submit the form, model state is always invalid because values are always null even if I input correct values. For example, I login, then form will submit to post login action, but value are always null.

在此处输入图片说明

Why is that always null? How can I bind to get correct values? How can I validate multiple forms in a single view (strongly typed view) using data annotation?

As @stephen-muecke says doing this will work:

public async Task<ActionResult> Register([Bind(Prefix="RegisterForm")]RegisterViewModel model)
        {
            //check modelstate and continue
        }

If you don't want to do that then you can create a partial view for each form and pass the model required for that form to that partial view.

<section id="form">
    <!--form-->
    <div class="container">
        <div class="row">
            <div class="col-sm-4 col-sm-offset-1">
                <div class="login->
                     @Html.Partial("_LoginForm", Model.LoginForm)
                </div><!--/login form-->
            </div>
            <div class="col-sm-1">
                <h2 class="or">OR</h2>
            </div>
            <div class="col-sm-4">
                <div class="signup-form">
                     @Html.Partial("_RegisterForm", Model.RegisterForm)
                </div><!--/sign up form-->
            </div>
        </div>
    </div>
</section><!--/form-->

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