Asp.Net Mvc在单个强类型视图中有多种形式,并使用数据注释进行验证

时间:2016-07-09 10:49:18

标签: asp.net-mvc forms validation data-annotations model-binding

我正在开发一个Asp.Net mvc应用程序。在我的项目中,在这样的单个视图中有两种形式。

enter image description here

要在单个视图中使用多个表单,使用数据批注进行验证时会出现问题。首先,我在单个视图asp.net MVC 4 multiple post via different forms中找到了使用多个表单的链接。在回答该链接后,我可以添加多个表单。但我无法使用该方法验证数据注释。所以我用Google搜索了另一种解决方案。

这个链接(http://geekswithblogs.net/MightyZot/archive/2013/11/11/html.validationsummary-and-multiple-forms.aspx)也一样,我必须在控制器中添加验证逻辑。我找到了另一个解决方案(http://bluetubeinc.com/blog/2012/10/validating-multiple-forms-the-asp-dot-net-mvc3-way-using-strongly-typed-views)。我认为这个解决方案将解决我使用数据注释进行验证的问题。但有一点需要注意的是它正在使用Ajax Form。但我遵循了这个链接,我仍然有问题。

这些是我的观点模型

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; }
    }

这是我的控制器和登录和注册的行动

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
        }

}

这是我的观点

<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")
}

但是当我提交表单时,模型状态始终无效,因为即使输入正确的值,值也始终为null。例如,我登录,然后表单将提交到发布登录操作,但值始终为空。

enter image description here

为什么总是空?如何绑定以获取正确的值?如何使用数据注释在单个视图(强类型视图)中验证多个表单?

1 个答案:

答案 0 :(得分:1)

就像@ stephen-muecke所说的那样,可以这样做:

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

如果您不想这样做,则可以为每个表单创建一个局部视图,并将该表单所需的模型传递给该局部视图。

<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-->