简体   繁体   English

在ASP.Net身份中将对象添加为属性

[英]Add object as property in ASP.Net identity

I'm using MVC 5 ASP.net Identity entity framework code-first to create an online application form. 我先使用MVC 5 ASP.net Identity实体框架创建在线应用程序表单。 I have created a new project with the ASP.net identity scaffold, and need to be able to add additional properties. 我已经使用ASP.net身份支架创建了一个新项目,并且需要能够添加其他属性。 Some of them are simple properties- mobile phone number etc, and this works fine. 其中一些是简单的属性-手机号码等,这很好用。 however I need to add a more complex object to the user to store the application form information. 但是我需要向用户添加一个更复杂的对象来存储申请表信息。 I tried doing this: 我尝试这样做:

public class ApplicationUser : IdentityUser 
{
    public string Title { get; set; }
    public string FirstName { get; set; }
    public string  Surname { get; set; }
    public override string PhoneNumber { get; set; }
    public string  PracticeName { get; set; }
    public string  Address { get; set; }
    public string  Mobile { get; set; }
    public string  GMCNumber { get; set; }
    public AppForm ApplicationForm { 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;
    }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public DbSet<AppForm> AppForms { get; set; }
    public DbSet<AppFormDocument> AppFormDocuments { get; set; }
    public DbSet<AppFormAnswer> AppFormAnswers { get; set; }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

and have created the appform models like this: 并创建了如下的应用程序模型:

public class AppForm {

    public int Id { get; set; }
    public int PercentComplete { get; set; }
    public string Status {get; set; }
    public bool Completed { get; set; }
    public bool Reviewed { get; set; }
    public bool SignedOff { get; set; }
    public int LastPageCompleted { get; set; }

    public List<AppFormDocument> Documents { get; set; }
    public List<AppFormAnswer> Answers { get; set; }

}

public class AppFormDocument {
    public int Id { get; set; }
    public DateTime DateSubmitted { get; set; }
    public string Name { get; set; }
    public DateTime? ExpiryDate { get; set; }
    public bool Accepted { get; set; }
    public string ScannedFile { get; set; }
}


public class AppFormAnswer {
    public int Id { get; set; }
    public string QuestionNumber { get; set; }
    public string Question { get; set; }
    public string Answer { get; set; }
}

The application form is very large and has many questions which is why I didnt just put it all in the applicationuser class. 申请表很大,有很多问题,这就是为什么我不把全部都放在applicationuser类中。 There is also the requirement to upload documents with the form. 还需要使用表格上传文档。

Now, when I create the user and attach an instance of the AppForm and some instances of AppFormAnswers to it, then save it, the data gets stored successfully, but when I try to access the data again after logging in, it is not found. 现在,当我创建用户并将一个AppForm实例和一些AppFormAnswers实例附加到该实例,然后将其保存时,数据将成功存储,但是当我尝试登录后再次访问该数据时,找不到它。 The additional simple properties of the user are available though, including mobile number and title. 用户的其他简单属性仍然可用,包括手机号码和标题。 here's my code: 这是我的代码:

[Route("appform/{action}")]
[Authorize]
public class AppFormController:Controller {
    // GET: AppForm
    public ActionResult Index() {
        ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());

        var model = new AppFormIndexViewModel();
        if (user != null) {
            if (user.ApplicationForm != null) {
                model.PercentComplete = user.ApplicationForm.PercentComplete;
                model.NextPage = "Page" + user.ApplicationForm.LastPageCompleted + 1;
                model.Status = user.ApplicationForm.Status;
            } else {
                // if appform is not available for user for some reason, create a new one.
                user.ApplicationForm = new AppForm { PercentComplete = 0, Reviewed = false, Status = "Incomplete", SignedOff = false, Completed = false, LastPageCompleted = 0 };
                var uManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
                uManager.UpdateAsync(user);

                model.PercentComplete = 0;
                model.Status = "Incomplete";
                model.NextPage = "Page1";
            }
        }
        return View(model);
    }

Now when the uManager.UpdateAsync(user) line runs, the data is saved to the database fine and a new appForm record is added. 现在,当uManager.UpdateAsync(user)行运行时,数据将保存到数据库中,并添加新的appForm记录。 The database automatically creates primary keys and foreign keys for all the tables too. 数据库也会自动为所有表创建主键和外键。

So, do I need to write an overload of the login method to retrieve the data from the other tables? 因此,我是否需要编写login方法的重载以从其他表中检索数据? Or do I need to add something to the ApplicationDbContext class? 还是我需要在ApplicationDbContext类中添加一些内容?

This is my first MVC application so not really sure where to turn now. 这是我的第一个MVC应用程序,因此不确定现在应该转到哪里。 Have tried reading many forum posts and blogs but not found anything that really matches my needs. 曾尝试阅读许多论坛帖子和博客,但没有找到真正符合我需求的内容。 A lot of information relates to earlier version of mvc which do not work with the newer asp.net identity system. 很多信息与早期版本的mvc有关,而早期版本的mvc不适用于较新的asp.net身份系统。

I finally managed to figure it out. 我终于设法弄清楚了。 I added an appformid property to the applicationuser class like this: 我将如下appformid属性添加到applicationuser类:

[ForeignKey("AppForm")]
public int AppFormId { get; set; }

Then created another class to load the appform object like this: 然后创建另一个类来加载应用程序对象,如下所示:

public static class AppFormManager {

    public static ApplicationUser GetCurrentUser() {
        ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
        if (user != null) {
            AppForm form = new AppForm();
            ApplicationDbContext db = new ApplicationDbContext();
            AppForm ap = db.AppForms.Where(af => af.Id == user.AppFormId).Include("Answers").Include("Documents").SingleOrDefault();
            if (ap == null) {
                var AppForm = new AppForm { PercentComplete = 0, Reviewed = false, Status = "Incomplete", SignedOff = false, Completed = false, LastPageCompleted = 0 };
                user.AppForm = AppForm;
            } else {
                user.AppForm = ap;
            }
            return user;
        }
        return null;
    }

    public static bool SaveCurrentUser() {
        ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
        if (user == null) { return false; }
        var uManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        uManager.UpdateAsync(user);
        return true;
    }

}

So in the controller, the code is much cleaner: 因此在控制器中,代码更加简洁:

// GET: AppForm
    public ActionResult Index() {

        ApplicationUser user = AppFormManager.GetCurrentUser();

        var model = new AppFormIndexViewModel();
        if (user != null) {
                model.PercentComplete = user.AppForm.PercentComplete;
                model.NextPage = "Page" + user.AppForm.LastPageCompleted + 1;
                model.Status = user.AppForm.Status;
        }
        return View(model);
    }

and I can call the AppFormManager.SaveCurrentUser() method to save the data in the post action. 并且我可以调用AppFormManager.SaveCurrentUser()方法将数据保存在后期操作中。

Thanks for all those who made suggestions which helped me figure out a way to do it. 感谢所有提出建议的人,这些帮助我找到了解决方法。 Possibly not the best way to do it, but it works for me for now. 可能不是最好的方法,但目前它对我有效。

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

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