MVC数据验证Membership使用常见错误

     在做注册界面的时候,出现了两个错误,让我纠结得想死,幸好最后都解决了,只能怪自己对MVC的Membership了解得不深,尤其是有关Web.Config的配置问题。

问题一:Membership.IsValid返回为false

     这个问题一开始让我很无语,因为在之前也有做过注册界面,但并不会出现这样的问题,代码如下:

[HttpPost]
        public ActionResult Register(RegisterModel model)
        {
            if(ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus;
                Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);
                if (createStatus == MembershipCreateStatus.Success)
                {

                    FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
                    return RedirectToAction("LogOn", "Account");
                }
                else
                {
                    ModelState.AddModelError("test", ErrorCodeToString(createStatus));
                    return RedirectToAction("Index", "Home");
                }
            }
            

            // If we got this far, something failed, redisplay form

            return View(model);
        }

     这是RegisterModel的代码:

 public class RegisterModel
    {

       [Required(ErrorMessage = "姓名不能为空!")]
        [Display(Name = "学生名")]
        [StringLength(160)]
        public string UserName { get; set; }

       [Required(ErrorMessage = "密码不能为空!")]
        [StringLength(160, ErrorMessage = "{0}至少是{2}位数以上!", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "密码")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "确认密码")]
        [Compare("Password", ErrorMessage = "密码不一致,请重新输入!")]
        public string ConfirmPassword { get; set; }

       [Required(ErrorMessage = "电话不能为空!")]
        [StringLength(160)]
        [DisplayName("电话")]
        public String Phone { get; set; }

       [Required(ErrorMessage = "QQ不能为空!")]
        [StringLength(160)]
        [DisplayName("QQ")]
        public String QQ { get; set; }

       [Required(ErrorMessage = "邮箱不能为空!")]
        [StringLength(160)]
        [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+[A-Za-z]{2,4}", ErrorMessage = "Email is not valid")]
        [DataType(DataType.EmailAddress)]
        [DisplayName("电子邮箱")]
        public String Email { get; set; }

       [Required(ErrorMessage = "学号不能为空!")]
        [DisplayName("学号")]
        [StringLength(160)]
        public String Number { get; set; }
    }

     然后是我的视图代码:

 <div class="editor-label">
                <%: Html.LabelFor(model => model.UserName)%>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.UserName)%>
                <%: Html.ValidationMessageFor(model => model.UserName)%>
            </div>

            <div class="editor-label">
                <%: Html.LabelFor(model => model.Number)%>
            </div>
            <div class="editor-field">
               <%: Html.TextBoxFor(model => model.Number)%>
               <%: Html.ValidationMessageFor(model => model.Number)%>
            </div>

            <div class="editor-label">
                <%: Html.LabelFor(model => model.Password)%>
            </div>
            <div class="editor-field">
               <%: Html.PasswordFor(model => model.Password)%>
               <%: Html.ValidationMessageFor(model => model.Password)%>
            </div>

            <div class="editor-label">
                <%: Html.LabelFor(model => model.ConfirmPassword)%> 
            </div>
            <div class="editor-field">
                <%: Html.PasswordFor(model => model.ConfirmPassword) %>
                <%: Html.ValidationMessageFor(model => model.ConfirmPassword) %>
            </div>

      如果运行就会出现这样的错误。原因很简单,就是Model所有字段都有Reguired,也就是要求视图验证,但视图中能赋值的只是其中几个值,也就是说,能够验证的值只有视图页显示的那几个,其他要求验证的属性字段就会返回错误信息给ModelState,因为ModelState绑定的是整个Model。
      如果只是想要让用户输入几个值而已,可以去掉其他属性字段的Required,否则就要老老实实的在视图页中提供其他属性字段的输入。

问题二:MembershipCreateStatus的值并不等于Success

      这个问题涉及到Membership的配置。我们想要使用Membership,必须在我们的Web.config中添加下面的配置代码:

<system.web>
    <profile defaultProvider="DefaultProfileProvider">
      <providers>
        <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
      </providers>
    </profile>
    <membership defaultProvider="DefaultMembershipProvider">
      <providers>
        <add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
      </providers>
    </membership>
    <roleManager enabled="true" defaultProvider="DefaultRoleProvider">
      <providers>
        <add connectionStringName="DefaultConnection" applicationName="/" name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      </providers>
    </roleManager>
    <sessionState mode="InProc" customProvider="DefaultSessionProvider">
      <providers>
        <add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
      </providers>
    </sessionState>
</system.web/>

      如果运行还有错误,说明没有引入System.Web.Providers这个包,需要使用Nuget命令:

Install-Package System.Web.Providers

      导入后,问题就解决了。
      在解决上面的问题中,我也大概摸索出一些调试方法。

      想要获得ModelState某个属性字段的错误信息,可以使用TempData:

TempData["UserName"] = ModelState["UserName"];

      然后在视图中添加:

    <p>
        <%= TempData["UserName"] == null ? "" : TempData["UserName"].ToString() %>
    </p>

      ModelState就是错误信息的字典值,只要提供相应的键值就能获得对应的错误信息。TempData有个好处就是它不需要传递给视图就可以直接使用。
      同样也可以获得MembershipCreateStatus的错误信息:

TempData["test"] = ErrorCodeToString(createStatus);

      我们也可以将错误信息添加进ModelState中:

  ModelState.AddModelError("test", ErrorCodeToString(createStatus));

       调试代码的第一步就是获得错误信息,连错误信息都得不到,又怎能解决问题呢?这时就要想方设法获得错误信息,然后再进行改正。

posted @ 2013-06-02 00:18  文酱  阅读(3792)  评论(5编辑  收藏  举报