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

C# MVC:两个表单标记和一个ViewModel,c#,asp.net-mvc,asp.net-mvc-5,C#,Asp.net Mvc,Asp.net Mvc 5,我的MVC应用程序只有一个页面。在此页面上,用户可以输入用户名和密码并单击登录按钮,或者用户可以输入其名字、电子邮件地址并单击注册按钮 我最初的想法是创建一个带有UserName、Password、FirstName和Email属性的视图模型,所有这些属性都带有[必需]属性。然后有一个包含两个Html.BeginForm()的视图。虽然这可能会起作用,但我感觉当我将数据发回控制器时,ModelState.IsValid将始终返回false,因为ViewModel确实是无效的 那么,有人能告诉我处

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

我最初的想法是创建一个带有
UserName
Password
FirstName
Email
属性的视图模型,所有这些属性都带有
[必需]
属性。然后有一个包含两个
Html.BeginForm()
的视图。虽然这可能会起作用,但我感觉当我将数据发回控制器时,
ModelState.IsValid
将始终返回
false
,因为ViewModel确实是无效的


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

我认为正确的方法是为每种情况设置一个ViewModel。如果需要,与数据库对话的底层业务逻辑和/或代码仍然可以使用单个模型

你的选择讨论得很好


尽管我想补充一点,在MVC页面上有多个ViewModel是一种痛苦

我认为正确的方法是为每个视图都设置一个ViewModel。如果需要,与数据库对话的底层业务逻辑和/或代码仍然可以使用单个模型

你的选择讨论得很好


尽管我想补充一点,在MVC页面上有多个ViewModel是一种痛苦

您可以定义两个视图模型

登录视图模型:

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; }
}
注册视图模型:

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... -->
}
或者,如果您只需要一个模型。尝试删除
[必需]
属性。你可以在动作中检查它。像这样:

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

    }
}

希望这有帮助

您可以定义两个视图模型

登录视图模型:

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; }
}
注册视图模型:

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... -->
}
或者,如果您只需要一个模型。尝试删除
[必需]
属性。你可以在动作中检查它。像这样:

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

    }
}

希望这有帮助

我在我的项目中实现了非常类似的场景,我认为实现这一点的最佳方法是创建一个viewmodel,其中包含两个子viewmodel,如下所示:

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

    [HiddenInput]
    public string ReturnUrl { get; set; }
}
MemberLoginView模型:

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

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; }
}
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)
如果“模型”是您的父视图模型,那么您将有两个单独的表单 在一种观点中。在你的局部观点中,你只需做如下事情:

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

我在我的项目中实现了非常类似的场景,我认为实现这一点的最佳方法是创建一个viewmodel,其中包含两个子viewmodel,如下所示:

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

    [HiddenInput]
    public string ReturnUrl { get; set; }
}
MemberLoginView模型:

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

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; }
}
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)
如果“模型”是您的父视图模型,那么您将有两个单独的表单 在一种观点中。在你的局部观点中,你只需做如下事情:

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

如果你想尝试不同的图书馆,那么你可以选择

FluentValidation提供了一种优雅的方式,可以为不同方法的单个类定制验证

例如

[验证器(typeof(LoginRegisterModelValidator))]
公共类LoginRegisterViewModel
{
公共字符串用户名{get;set;}
公共字符串密码{get;set;}
公共字符串名{get;set;}
公共字符串电子邮件{get;set;}
}
可以为不同的操作定义多个规则 验证器类如下所示

public类LoginRegisterModelValidator:AbstractValidator
{
公共注册表AddeditModelValidator()
{
/*定义规则集,以便在具有CustomizeEvalidator属性的contrller操作参数内专门调用它们*/
规则集(“登录规则集”,登录规则集);
规则集(“RegisterRuleSet”,RegisterRuleSet);
}
受保护的无效登录规则集()
{
RuleFor(x=>x.UserName).NotEmpty();
RuleFor(x=>x.Password).NotEmpty();
}
受保护的无效注册表规则集()
{
RuleFor(x=>x.Email).NotEmpty();
RuleFor(x=>x.FirstName).NotEmpty();
}
}
控制器操作如下所示

[HttpPost]
[ValidateAntiForgeryToken]
公共操作结果登录([CustomizeValidator(RuleSet=“LoginRuleSet”)]LoginRegisterViewModel模型)
{ ...
}
[HttpPost]
[ValidateAntiForgeryToken]
公共操作结果寄存器([CustomizeValidator(RuleSet=“RegisterRuleSet”)]LoginRegisterViewModel模型)
{ ...
}
}

希望这有助于您在同一类中验证不同的规则。

如果您想尝试不同的库,则可以使用

FluentValidation提供了一种优雅的方式,可以为不同方法的单个类定制验证

例如

[验证器(typeof(LoginRegisterModelValidator))]
公共类LoginRegisterViewModel
{
公共字符串用户名{get;set;}
公共字符串密码{get;set;}
公共字符串名{get;set;}
公共字符串电子邮件{get;set;}
}
可以为不同的操作定义多个规则 验证器类如下所示

public类LoginRegisterModelValidator:AbstractValidator
{
公共注册表AddeditModelValidator()
{
/*定义规则集,以便在具有CustomizeEvalidator属性的contrller操作参数内专门调用它们*/
规则集(“登录规则集”,登录规则集);
规则集(“RegisterRuleSet”,RegisterRuleSet);
}
受保护的无效登录规则集()
{
RuleFor(x=>x.UserName).NotEmpty();
RuleFor(x=>x.Password).NotEmpty();
}
受保护的无效注册表规则集()
{
RuleFor(x=>x.Email).NotEmpty();
RuleFor(x=>x.FirstName).NotEmpty();
}
}
控制器操作如下所示

[HttpPost]
[ValidateAntiForgeryToken