【问题标题】:Add object as property in ASP.Net identity在 ASP.Net 标识中添加对象作为属性
【发布时间】:2015-11-13 19:23:47
【问题描述】:

我正在使用 MVC 5 ASP.net Identity 实体框架代码优先来创建在线申请表。我已经使用 ASP.net 标识脚手架创建了一个新项目,并且需要能够添加其他属性。其中一些是简单的属性——手机号码等,这很好用。但是我需要向用户添加一个更复杂的对象来存储应用程序表单信息。我试过这样做:

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();
    }
}

并创建了这样的 appform 模型:

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; }
}

申请表很大,有很多问题,这就是为什么我没有把它全部放在 applicationuser 类中。还需要使用表格上传文件。

现在,当我创建用户并将 AppForm 的实例和 AppFormAnswers 的一些实例附加到它,然后保存它时,数据已成功存储,但是当我在登录后再次尝试访问数据时,它是未找到。用户的其他简单属性是可用的,包括手机号码和标题。这是我的代码:

[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);
    }

现在,当 uManager.UpdateAsync(user) 行运行时,数据会很好地保存到数据库中,并添加新的 appForm 记录。数据库也会自动为所有表创建主键和外键。

那么,我是否需要编写登录方法的重载来从其他表中检索数据?还是我需要向 ApplicationDbContext 类添加一些东西?

这是我的第一个 MVC 应用程序,所以现在不知道该转向哪里。尝试阅读许多论坛帖子和博客,但没有找到真正符合我需求的内容。许多信息与早期版本的 mvc 相关,这些信息不适用于较新的 asp.net 身份系统。

【问题讨论】:

  • 如果您将 int AppFormId 属性添加到您的 AppUser。
  • 除了导航属性,尝试添加外键属性。例如,AppFormDocument 应该具有 int AppFormId 作为属性
  • 此外,无论您选择什么,都可能需要一个“包含”。示例:stackoverflow.com/questions/13047845/…
  • 我会重新考虑 AppForm 是用户的属性还是用户有权访问的一些数据。您应该将 AppForm 和其他数据存储在某个表中,并且该数据应该有一个用户 ID
  • @andy - 宁愿不向 AppUser 添加 appFormId 属性,因为我希望将来保留该选项以允许单个用户使用多个应用程序表单。

标签: c# model-view-controller asp.net-mvc-5 identity


【解决方案1】:

我终于弄明白了。我向 applicationuser 类添加了一个 appformid 属性,如下所示:

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

然后创建另一个类来加载 appform 对象,如下所示:

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;
    }

}

所以在控制器中,代码更加简洁:

// 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);
    }

我可以调用 AppFormManager.SaveCurrentUser() 方法将数据保存在 post 操作中。

感谢所有提出建议的人,这些建议帮助我找到了解决办法。可能不是最好的方法,但它现在对我有用。

【讨论】:

    猜你喜欢
    • 2022-11-02
    • 2020-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-21
    • 1970-01-01
    • 2017-09-20
    相关资源
    最近更新 更多