asp.net MVC 5 - 分几页登记。我怎样才能使用[必需]注释?

时间:2016-06-06 14:36:59

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

我有一个用户对象:

namespace MySolution.Models
{
     public class MyUser
     {
        public Int32 Id { get; set; }
        [Required]
        public string CompanyName { get; set; }

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

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

        [Required]
        [EmailAddress]
        public string Email { get; set; }
     }
}

Id由SQL Server自动生成。我正在使用Dapper。

所有这些属性都是必需的。但是,我想将其分为两部分 - 因此首先要求用户提供电子邮件 - 然后在下一个“页面”上询问公司名称,名字和名称。姓氏。

[HttpPost]控制器如下所示:

[HttpPost]
public ActionResult SignUp(MyUser myuser)
{
    if (ModelState.IsValid)
    {
        // Insert returns success
        if (MyUserRepo.InsertEmailPass(myuser))
        {
            // Successfully added user, go to next user section
            return RedirectToAction("SignUp2", myuser);
        }
        else
        {
            // Adding prospect failed
            ViewBag.Error = "Email already registered";
        }
    }

    return View(myuser);
} 


[HttpPost]
public ActionResult SignUp2(MyUser myuser)
{
    if (ModelState.IsValid)
    {
        // Insert returns success
        if (MyUserRepo.UpdateNameCopany(myuser))
        {
            // Successfully added myuser, go to thank you page
            return RedirectToAction("SignUpEnd");
        }
        else
        {
            // Adding prospect failed
            ViewBag.Error = "Something went wrong";
        }
    }
}

我想要不显眼的验证和所有内置的MVC功能 - 例如if (ModelState.IsValid) - 但是,因为我将这个分为2页,所以模型永远不会在第一页上有效 - 除非我手动添加也可以通过电子邮件发送到第二页上的模型(而我需要做的就是对名字,姓氏和公司名称(不是电子邮件)进行SQL更新 - 所以不一定要向SQL添加电子邮件)。

这一切都感觉相当'hacky'。我怎么能这样做,仍然使用内置验证和ModelState等?

我在谷歌上找不到这个。

我的目标是以最少的代码以正确的方式“正确”执行此操作(以及最佳实践?)。

编辑: 我现在有这两个视图模型:

namespace MyNamespace.ViewModels
{
    public class SignUpViewModelPage1
    {
        public int Id { get; set; }

        [Required]
        [EmailAddress]
        public string Email { get; set; }

        [Required]
        [StringLength(50, MinimumLength = 8, ErrorMessage = "{0} must be at least {2} characters long")]
        [DataType(DataType.Password)]
        public string Password { get; set; }
    }

    public class SignUpViewModelPage2
    {
        public int Id { get; set; }

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

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

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

控制器:

[HttpPost]
public ActionResult SignUp(SignUpViewModelPage1 svmp1)
{
    if (ModelState.IsValid)
    {
        int Id = senderRepo.InsertEmailPass(svmp1);
        // Insert failure returns -1
        if (Id != -1)
        {
            // Successfully added user - go to page 2, pass Id
            return RedirectToAction("SignUp2", new { Id = Id });
        }
        else
        {
            // Adding user failed - probably duplicate email - tell user & pass invalid model back
            ViewBag.Error = "Email already registered";
        }
    }

    return View(svmp1);
}

public ActionResult SignUp2(int Id)
{
    return View();
}

[HttpPost]
public ActionResult SignUp2(SignUpViewModelPage2 svmp2)
{
    if (ModelState.IsValid)
    {
        // Insert success returns true
        if (senderRepo.UpdateNameCopany(svmp2))
        {
            // Successfully added user - go to success page
            return RedirectToAction("SignUpEnd");
        }
        else
        {
            // Adding user failed - tell user
            ViewBag.Error = "Email already registered";
        }
    }
    return View();
}

这一切看起来都好吗?任何明显的错误或糟糕的做事方式?

THX

3 个答案:

答案 0 :(得分:2)

您的模型应反映您网页上的内容。我会为每个页面创建一个模型,然后进行正常验证。如果需要,我会将结果合并到一个模型中。

答案 1 :(得分:1)

正如其他人所提到的,您应该考虑创建一个代表您的页面输入而不是您的域模型的ViewModel。

从那里,你有几个选择:

1)使用像bootstrap向导这样的东西,它基本上隐藏/显示页面的一部分,直到你提交为止。单个视图模型的所有属性都在您的页面上,但只是由向导隐藏。这也处理验证,非常好的东西。以下是它的示例:Bootstrap Form Wizard Example。您可以找到更多示例和download here

2)为表单的每一步分解几个较小的ViewModel。

我最近使用了选项1,它对我的​​项目很有用。

答案 2 :(得分:0)

有不同的方法。如果您希望/需要通过完整页面更新(而不是部分更新)来执行此操作,则需要在 n 部分上拆分模型,其中 n 等于向导你想向你呈现用户。然后,您需要在实际注册用户之前想出一种存储数据的方法。在WebForms时代,我通过保存会话相关数据做了很多事情,这些数据还没有为数据库做好准备但是在往返之间的隐藏字段中。

但是我不推荐这种方法,因为它有点笨拙和过时。更好的方法是将向导步骤设计为部分视图。然后在您的登录页面上指定一个弹出窗口和一个读取Signup的按钮。有很多JS库提供弹出窗口。我使用臭名昭着的Twitter Bootstrap或jQuery UI,但如果你愿意,还有其他的。因此,当用户点击Signup时,您将指定的弹出窗口显示第一个局部视图并显示它。您可以通过将AJAX回调到服务器来完成此操作。当然,当前步骤的UI需要提供加载下一步的按钮。您甚至可以为您的模型设计一个局部视图,一次加载它,但根据我们当前所处的步骤显示它的不同部分。

这一切都需要javascript。你可以 - 纠正 - 你应该使用jQuery并通过AJAX请求部分视图。您可以将每个步骤的数据存储在本地javascript变量中。在向导结束时,检查收集的数据并对注册方法进行另一次AJAX调用。在服务器端,您不必更改模型并留下注释。

您可以使用AJAX,jQuery,部分视图等进行谷歌搜索。互联网上充满了关于这个主题的信息。