【问题标题】:How to make a customized profile information UNIQUE in ASP.NET Identity如何在 ASP.NET 标识中使自定义配置文件信息唯一
【发布时间】:2014-10-27 12:47:36
【问题描述】:

我在 Visual Studio 2013 上使用带有 asp.net Identity 2.0 的 Web 项目。我已按照 page 上的说明创建了一个名为 screenName 的自定义新字段。一切似乎都运作良好。

但是,我想更进一步,让 screenName 在数据库中是唯一的。这意味着 ApplicationUserManager 必须在注册用户之前检查是否使用了屏幕名称。我怎样才能需要一个唯一的 screenName 并完成它?

这是我的代码:

AccountControler.cs(添加 screenName = model.screenName)

public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email, screenName = model.screenName };

            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                await UserManager.SendEmailAsync(user.Id, "bla bla bla", "Thank you for your bla bla bla registration. Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");
                ViewBag.Link = callbackUrl;
                return View("DisplayEmail");
            }
            AddErrors(result);
        }

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

AccountViewModel.cs

public class RegisterViewModel
{
 [Required]
 [StringLength(20, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [Display(Name = "screenName")]
    public string screenName { get; set; }
}

IdentityModel.cs(添加公共字符串 screenName { get; set; })

public class ApplicationUser : IdentityUser
{
    public string screenName { get; set; }
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here

        return userIdentity;
    }
}

Register.cshtml

<div class="form-group">
@Html.LabelFor(m => m.screenName, new { @class = "col-md-2 control-label" }) 
<div class="col-md-10"> @Html.TextBoxFor(m => m.screenName, new { @class = "form-control" }) 
</div>
</div>

SQL 服务器

 GO
 CREATE UNIQUE NONCLUSTERED INDEX [screenNameIndex]
 ON [dbo].[AspNetUsers]([screenName] ASC);

例如,ApplicationUserManager 需要在 identityConfig.cs 上具有以下代码的唯一电子邮件。如何对自定义 screenName 执行相同操作?

var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

【问题讨论】:

    标签: asp.net visual-studio-2013 asp.net-mvc-5 asp.net-identity


    【解决方案1】:

    您需要手动检查数据库中是否存在具有此屏幕名称的记录:

    类似这样的:

    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            // somehow obtain your DbContext object
            var existsDuplicate = dbContext.Users.Any(u => u.screenName == model.screenName);
            if(existsDuplicate)
            {
                ModelState.AddModelError("screenName", "Screen Name is already taken, please choose another one");
                return View(model);
            }
    
    
            // the rest of controller is unchanged
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email, screenName = model.screenName };
    
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                await UserManager.SendEmailAsync(user.Id, "bla bla bla", "Thank you for your bla bla bla registration. Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");
                ViewBag.Link = callbackUrl;
                return View("DisplayEmail");
            }
            AddErrors(result);
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    }
    

    【讨论】:

    • 感谢您的回答。我正在尝试实现您的代码,但由于某种原因,尽管我安装了 EntityFramework 6.1.1,但找不到 dbContext。我正在使用 MVC5。我是否缺少命名空间?
    • 好的,我通过添加 System.Data.Entity 解决了这个问题。但现在我收到另一条错误消息; “System.Data.Entity.DbContext”不包含“用户”的定义......
    • 您需要使用自己的数据库上下文,即继承自IdentityDbContext 的数据库上下文。上面的代码是示例,不要按字面意思理解。
    • 不幸的是它变得非常糟糕。我无法弄清楚如何解决它。我根本不熟悉 MVC 和 DbContext。像老鼠一样在恶性循环中四处走动。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 2010-10-21
    相关资源
    最近更新 更多