简体   繁体   English

使用导航属性扩展ASP.Net Identity

[英]Extend ASP.Net Identity with navigation property

Just recently started out to play with ASP.Net Identity in VS2013. 刚开始使用VS2013中的ASP.Net Identity。 I fired up a MVC5 project and are using the default template for it, with individual account. 我启动了一个MVC5项目,并使用其默认模板(具有单独的帐户)。 I am trying to extend the ApplicationUser class which is inherited from IdentityUser withe the following fields: 我正在尝试使用以下字段扩展从IdentityUser继承的ApplicationUser类:

//this is my code first entity
public class ApplicationUser : IdentityUser
{
    public string Name { get; set; }
    public string EmailAddress { get; set; }
    public virtual SellingLocation Location { get; set; }
}

I have extended the Register.cshtml with textboxes for Name and EmailAddress, updated the registerviewmodel and added a list with all SellingLocation to populate a drop down list with it. 我用名称和电子邮件地址的文本框扩展了Register.cshtml,更新了registerviewmodel并添加了一个包含所有SellingLocation的列表,以使用它填充下拉列表。

public class RegisterViewModel
{
    [Required]
    [Display(Name = "Användarnamn")]
    public string UserName { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Lösenord")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Bekräfta lösenord")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }

    [Required]
    [Display(Name = "Säljarens namn")]
    public string Name { get; set; }

    [Required]
    [Display(Name = "Epostadress")]
    public string EmailAddress { get; set; }

    [Display(Name = "Försäljningställe")]
    public int SellingLocationId { get; set; }

    public List<SellingLocationViewModel> SellingLocations { get; set; }
}

And the Register.cshtml code for the drop down: 以及下拉菜单的Register.cshtml代码:

<div class="form-group">
    @Html.LabelFor(m => m.SellingLocationId, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.DropDownListFor(m => m.SellingLocationId, new SelectList(Model.SellingLocations, "Id", "Name"))
    </div>
</div>

The problem is in the account controller. 问题出在帐户控制器中。 When I try to add this new user a new copy of the SellingLocation is created (a new row in the database) instead of just adding a reference (foreign key) to the row which the selected value in the dropdown list was pointing to. 当我尝试添加此新用户时,将创建SellingLocation的新副本(数据库中的新行),而不仅仅是在下拉列表中所选值指向的行中添加引用(外键)。 What am I doing wrong? 我究竟做错了什么?

// GET: /Account/Register
    [AllowAnonymous]
    public ActionResult Register()
    {
        var regvm = new RegisterViewModel();
        regvm.SellingLocations = GetSellingLocations();
        return View(regvm);
    }
    private List<SellingLocationViewModel> GetSellingLocations()
    {
        return Mapper.Map<List<SellingLocation>, List<SellingLocationViewModel>>(db.SellingLocations.ToList());
    }

        //
    // POST: /Account/Register
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            //get the SellingLocation from the id from the selected value in dropdown
            var sellingloc = db.SellingLocations.Find(model.SellingLocationId);
            //creating user object, adding new data
            var user = new ApplicationUser() { UserName = model.UserName, Name = model.Name, EmailAddress = model.EmailAddress, Location = sellingloc };
            var result = await UserManager.CreateAsync(user, model.Password);
            //this will create a new row in SellingLocations, not just add a reference in AspNetUsers to the old row as expected.
            if (result.Succeeded)
            {
                await SignInAsync(user, isPersistent: false);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                AddErrors(result);
            }
        }

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

You need a SellingLocationId in ApplicationUser and configure your foreign key relationship. 您需要ApplicationUser中SellingLocationId并配置您的外键关系。 When you create a new ApplicationUser you just fill in the SellingLocationId and not the virtual object Location . 创建新的ApplicationUser时 ,只需填写SellingLocationId而不是虚拟对象Location即可 Location is filled in by EF after the Insert or when you query for a new ApplicationUser . 在插入后或查询新的ApplicationUser时, 位置由EF填充。

Also, for the SellingLocation to be duplicated in the database that must mean that SellingLocationID is not a unique ID. 同样,要在数据库中复制SellingLocation ,这必须意味着SellingLocationID不是唯一ID。 It needs to be. 它一定是。

I found the problem. 我发现了问题。 I was using two different context objects, one for the UserManager and one for looking up the SellingLocation object in my Register post method. 我使用了两种不同的上下文对象,一种用于UserManager,一种用于在Register post方法中查找SellingLocation对象。

Changing the constructor of the AccountController and catching the reference to the context passed into the UserStore which is passed into the UserManager fixed the problem. 更改AccountController的构造函数并捕获对传递给UserStore的上下文的引用,该上下文又传递给UserManager,从而解决了该问题。 The code in the question works now when the db object is the reference to the context in UserManager. 当db对象是UserManager中上下文的引用时,问题中的代码现在可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM