MVC:两个表单标记和一个ViewModel

时间:2016-10-26 21:46:33

标签: c# asp.net-mvc asp.net-mvc-5

我的MVC应用程序上有一个页面。在此页面上,用户可以输入用户名和密码并单击登录按钮,或者用户可以输入他们的名字,电子邮件地址并单击注册按钮。

我最初的想法是创建一个包含UserNamePasswordFirstNameEmail属性的ViewModel,所有属性都具有[Required]属性。然后有两个Html.BeginForm()的视图。虽然这可能会有效,但我觉得当我将数据发布回控制器时,ModelState.IsValid将始终返回false,因为ViewModel确实无效。

那么有人可以告诉我处理这种情况的正确方法吗?

4 个答案:

答案 0 :(得分:2)

我已经在我的项目中实现了非常类似的场景我认为实现这一目标的最佳方法是创建一个视图模型,其中包含2个子视图模型:

public class AuthModelView
{
    public MemberLoginViewModel LoginModel { get; set; }
    public MemberRegisterViewModel RegisterModel { get; set; }

    [HiddenInput]
    public string ReturnUrl { get; set; }
}

MemberLoginViewModel:

public class MemberLoginViewModel
{
    [Required(ErrorMessage = "")]
    [Display(Name = "")]
    [EmailAddress]
    public string Email { get; set; }


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

    [Display(Name = "")]
    public bool RememberMe { get; set; }
}

MemberRegisterViewModel:

public class MemberRegisterViewModel
{
    [Required(ErrorMessage = "")]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }

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

    [Required]
    public string RepeatPassword { get; set; }

    [HiddenInput(DisplayValue = false)]
    public string ReturnUrl { get; set; }
}

然后创建将呈现2个部分视图的视图

  @Html.Partial("MemberLoginSummary", Model)
  @Html.Partial("MemberRegisterSummary", Model)

"模型"是您的父Viewmodel,那么您将有2个单独的表单 在一个视图中。在部分视图中,您只需执行以下操作:

@Html.TextBoxFor(m => m.LoginModel.Email, null, new { @class = "form-control", placeholder = "email", id="Email" })

答案 1 :(得分:1)

您可以定义2个视图模型。

登录视图模型:

public class LoginViewModel
{
    [Requried]
    public string UserName { get; set; }

    [Requried]
    public string Password { get; set; }
}

注册视图模型:

public class RegisterViewModel
{
    [Requried]
    public string UserName { get; set; }

    [Requried]
    public string Password { get; set; }

    [Requried]
    public string FirstName{ get; set; }

    [Requried]
    public string Email { get; set; }
}

登录视图:

@Html.BeginForm("Login", "Account", FormMethod.Post)
{
    <!-- login form implements... -->
}

注册视图:

@Html.BeginForm("Register", "Account", FormMethod.Post)
{
    <!-- register form implements... -->
}

控制器:

public IActionResult Login(LoginViewModel model)
{
    if (ModelState.IsValid)
    {

    }
}

public IActionResult Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {

    }
}

或者,如果您只想要1个型号。尝试删除[Required]属性。您可以在操作中查看它。像这样:

public IActionResult Login(YourViewModel model)
{
    if (!string.IsNullOrEmpty(model.UserName) && !string.IsNullOrEmpty(model.Password))
    {

    }
}

public IActionResult Register(YourViewModel model)
{
    if (!string.IsNullOrEmpty(model.UserName) &&
        !string.IsNullOrEmpty(model.Password) &&
        !string.IsNullOrEmpty(model.FirstName) &&
        !string.IsNullOrEmpty(model.Email))
    {

    }
}

希望这有帮助!

答案 2 :(得分:1)

如果您想尝试不同的库,那么您可以使用FluentValidation

FluentValidation提供了为不同方法自定义单个类验证的优雅方法。

例如

[Validator(typeof(LoginRegisterModelValidator))]
public class LoginRegisterViewModel
{
    public string UserName { get; set; }

    public string Password { get; set; }

    public string FirstName{ get; set; }

    public string Email { get; set; }
}

您可以为不同的操作定义多个规则 验证器类看起来像这样

public class LoginRegisterModelValidator : AbstractValidator<LoginRegisterViewModel>
    {
        public RegistryAddEditModelValidator()
        {
            /* Define the rule set to call them specifically inside contrller action parameter with CustomizeValidator Attribute */
            RuleSet("LoginRuleSet", LoginRuleSet);
            RuleSet("RegisterRuleSet", RegisterRuleSet);            
        }

protected void LoginRuleSet()
        {
           RuleFor(x => x.UserName).NotEmpty();
           RuleFor(x => x.Password).NotEmpty();
        }

        protected void RegisterRuleSet()
        {
           RuleFor(x => x.Email).NotEmpty();
           RuleFor(x => x.FirstName).NotEmpty();
        }
}

Controller Action看起来像这样

 [HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login([CustomizeValidator(RuleSet = "LoginRuleSet")] LoginRegisterViewModel model)
        { ...
        }

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register([CustomizeValidator(RuleSet = "RegisterRuleSet")] LoginRegisterViewModel model)
        { ...
        }
}

希望这可以帮助您验证具有相同类别的不同规则。

答案 3 :(得分:0)

我认为正确的方法是为每个人提供一个ViewModel。如果需要,您的基础业务逻辑和/或与数据库通信的代码仍然可以使用单个模型。

我们很好地讨论了您的选项here

虽然我想补充说在MVC页面上有多个ViewModel是一件痛苦的事。 Some guidance here on how