如何远程验证电子邮件或检查电子邮件是否存在

5
我正在尝试在注册时检查电子邮件是否存在,以便数据库中没有重复的电子邮件。我使用MVC4默认的Internet Application进行操作,但我已将电子邮件字段添加到RegisterviewModel中。我还注意到,这对于UserName字段已经很好地完成了,但我不知道他们是如何做到的。我尝试遵循下面的博客,但没有成功,因为当我单击创建时没有响应:Tug Berk。当我使用Firebug时,我得到Status: 302 Found,当Json action excutes时。这就是我所拥有的:UserProfile
[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string Email { get; set; }
}

RegisterViewModel

public class RegisterModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email")]
    [Remote("DoesUserEmailExist", "Account", HttpMethod = "POST", ErrorMessage = "Email address already exists. Please enter a different Email address.")]
    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")]
    [System.ComponentModel.DataAnnotations.Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

注册操作

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Register(RegisterModel model)
    {
        if (ModelState.IsValid)
        {
            try //CreateUserAndAccount
            {
                WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { model.Email });
                WebSecurity.Login(model.UserName, model.Password);
                return RedirectToAction("Index", "Home");

            }
            catch (MembershipCreateUserException e)
            {
                ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

Json操作

[HttpPost]
    public JsonResult DoesUserEmailExist(string email)
    {

        var user = Membership.GetUserNameByEmail(email);

        return Json(user == null);
    }

编辑:添加了注册视图

     @model Soccer.Models.RegisterModel

     @{
     ViewBag.Title = "Register";
     }

     <hgroup class="title">
     <h1>@ViewBag.Title.</h1>
     <h2>Create a new account.</h2>
     </hgroup>

 @using (Html.BeginForm()) {
 @Html.AntiForgeryToken()
 @Html.ValidationSummary()

 <fieldset>
    <legend>Registration Form</legend>
    <ol>
        <li>
            @Html.LabelFor(m => m.UserName)
            @Html.TextBoxFor(m => m.UserName)
        </li>
        <li>
            @Html.LabelFor(m => m.Email)
            @Html.TextBoxFor(m => m.Email)
        </li>
        <li>
            @Html.LabelFor(m => m.Password)
            @Html.PasswordFor(m => m.Password)
        </li>
        <li>
            @Html.LabelFor(m => m.ConfirmPassword)
            @Html.PasswordFor(m => m.ConfirmPassword)
        </li>
    </ol>
    <input type="submit" value="Register" />
</fieldset>
 }

 @section Scripts {
 @Scripts.Render("~/bundles/jqueryval")
 }

我是否有哪些不应该做的事情,或者这里是否还有其他更简单的选择?

2个回答

8
首先,我想对JOBG表示感谢,因为他通过此方式与我进行了交流。如果您在数据库中使用Database First,那么上面问题中展示的内容仍然有效,因为它要求您将电子邮件列设为UNIQUE。但是,为了使其与EF Code First一起工作,我必须对注册操作进行以下更改。请注意,使用此解决方案时,您无需在模型中使用Remote Annotation

注册操作

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Register(RegisterModel model)
    {
        if (ModelState.IsValid)
        {
            // Insert a new user into the database
            using (UsersContext db = new UsersContext())
            {
                UserProfile email = db.UserProfiles.FirstOrDefault(u => u.Email.ToLower() == model.Email.ToLower());
                try
                {
                    // Check if email already exists
                    if (email == null)
                    {
                        WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { Email = model.Email });
                        WebSecurity.Login(model.UserName, model.Password);
                        return RedirectToAction("Index", "Home");
                    }
                    else
                    {
                        ModelState.AddModelError("Email", "Email address already exists. Please enter a different email address.");
                    }
                }
                catch (MembershipCreateUserException e)
                {

                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

注意:请注意此操作在验证用户名之前会验证电子邮件地址,并要求您在创建对象之前至少访问一次数据库。


3
很难在没有View代码的情况下确定问题,但我怀疑是js的问题,请确保您已经设置了jQuery验证插件,它应该使用.blur()事件触发验证,在firebug(或类似工具)中检查页面,并查找失去焦点时命中DoesUserEmailExist的ajax POST请求,如果没有发生这种情况,则客户端缺少某些内容,因为Remote属性和服务DoesUserEmailExist看起来都没问题。
附注:确保数据库中的电子邮件字段具有唯一约束条件,这是确保没有重复电子邮件的唯一方法,即使进行DoesUserEmailExist验证也是如此,因为存在并发问题。

我已经添加了一个注册视图。至于UNIQUE约束,我不确定是否可以使用Code First实体框架实现。考虑到这一点,它已经被分配给UserId。 - Komengem
你说得对,EF5不支持Code First的UNIQUE约束,这也许是我不使用它的原因之一,我更喜欢Database First...至于问题,这个bundle“~/bundles/jqueryval”会渲染所需的js,所以那不是问题,你试过用Firebug检查请求了吗? - JOBG
我刚刚运行了它,结果显示“状态:302 Found”。这说明出现了问题。 - Komengem
好的,问题中所有内容都已经记录在上面了。我认为一切都在那里。 - Komengem
+1 鼓励你继续留下来,非常感谢。我所做的适用于“数据库优先”模式。我刚刚发布的解决方案适用于“EF Code First”模式,至少在我所知道的范围内是这样的。 - Komengem
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接