如何使用 ASP.NET Identity (Web Form) 在数据库中保存数据?
How to save data in database by using ASP.NET Identity (Web Form)?
这个问题是下一章:
在第一章中,我询问了如何在 ASP.NET 身份中创建自定义 table。
在本章中,我将询问如何将数据保存在数据库中。我试了很多方法都没有成功。
成功登录后,系统应该存储一些数据,如:
- [AccountLogID] PK
- [IPv4]
- 登录日期
- [UserId] FK(来自 User.ID)
我的代码是这样的:
IdentityModels.cs
namespace Web_WebApp.Models
{
// You can add User data for the user by adding more properties to your User class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public virtual ICollection<AccountLog> AccountLogs { get; set; }
public ClaimsIdentity GenerateUserIdentity(ApplicationUserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = manager.CreateIdentity(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
{
return Task.FromResult(GenerateUserIdentity(manager));
}
}
public class AccountLog
{
[Key]
public Guid AccountLogID { get; set; }
public string IPv4 { get; set; }
public DateTime LoginDate { get; set; }
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser User { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("Web_Identity", throwIfV1Schema: false)
{
}
public System.Data.Entity.DbSet<AccountLog> AccountLog { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
}
Login.aspx.cs
namespace Web_WebApp.Account
{
public partial class Login : Page
{
string GuidToken = System.Guid.NewGuid().ToString();
public static string GetExternalIP()
{
try
{
string externalIP;
externalIP = (new WebClient()).DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}
catch { return null; }
}
protected void LogIn(object sender, EventArgs e)
{
// Validate the user password
//var AccountLogs = Context.GetOwinContext().GetUserManager<AccountLog>();
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var signinManager = Context.GetOwinContext().GetUserManager<ApplicationSignInManager>();
// Require the user to have a confirmed email before they can log on.
var user = manager.FindByName(username.Text);
if (IsValid)
{
if (user != null)
{
{
// This doen't count login failures towards account lockout
// To enable password failures to trigger lockout, change to shouldLockout: true
var result = signinManager.PasswordSignIn(username.Text, Password.Text, RememberMe.Checked, shouldLockout: true);
if (!user.EmailConfirmed && result == SignInStatus.Success)
{
Response.Redirect("/Account/Confirmation?UserConfirmationID=" + user.Id);
}
switch (result)
{
case SignInStatus.Success:
var AccountLog = new AccountLog()
{
IPv4 = GetExternalIP(),
LoginDate = DateTime.Now,
UserId = user.Id,
};
user.AccountLogs.Add(AccountLog);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
//Response.Redirect("/Account/Lockout");
FailureText.Text = "This account has been locked, please try again later.";
ErrorMessage.Visible = true;
return;
case SignInStatus.RequiresVerification:
Response.Redirect(String.Format("/Account/TwoFactorAuthenticationSignIn?ReturnUrl={0}&RememberMe={1}",
Request.QueryString["ReturnUrl"],
RememberMe.Checked),
true);
break;
case SignInStatus.Failure:
default:
FailureText.Text = "Invalid password";
ErrorMessage.Visible = true;
break;
}
}
}
else
FailureText.Text = "Account not found.";
ErrorMessage.Visible = true;
}
}
}
}
使用这些代码,我的应用程序可以运行,我可以登录,但它不会像我在代码中提到的那样保存任何内容。我没有收到任何错误或警告。
我确定 "SaveChanges()" 之类的东西丢失了,但我不知道该放在哪里。
感谢您为解决我的问题所做的努力。
您正在通过 ApplicationUserManager
获取用户,在将新的 AccountLog
条目添加到集合 user.AccountLogs
后,您需要将用户保存回数据库.据我所知,您可以像获取其他实例一样从 OWIN 获取 Entity framework 上下文 (ApplicationDbContext
?)。
switch (result)
{
case SignInStatus.Success:
var AccountLog = new AccountLog()
{
IPv4 = GetExternalIP(),
LoginDate = DateTime.Now,
UserId = user.Id,
};
user.AccountLogs.Add(AccountLog);
// get the entity framework context.
var dbContext = Context.GetOwinContext().Get<ApplicationDbContext>();
// save the changes to objects tracked by this context
dbContext.SaveChanges();
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
// removed for brevity.
break;
}
注意:你可能需要直接从上下文中再次获取用户,但我认为没有必要,取决于用户是否分离.
这个问题是下一章:
在第一章中,我询问了如何在 ASP.NET 身份中创建自定义 table。 在本章中,我将询问如何将数据保存在数据库中。我试了很多方法都没有成功。
成功登录后,系统应该存储一些数据,如:
- [AccountLogID] PK
- [IPv4]
- 登录日期
- [UserId] FK(来自 User.ID)
我的代码是这样的:
IdentityModels.cs
namespace Web_WebApp.Models
{
// You can add User data for the user by adding more properties to your User class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public virtual ICollection<AccountLog> AccountLogs { get; set; }
public ClaimsIdentity GenerateUserIdentity(ApplicationUserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = manager.CreateIdentity(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
{
return Task.FromResult(GenerateUserIdentity(manager));
}
}
public class AccountLog
{
[Key]
public Guid AccountLogID { get; set; }
public string IPv4 { get; set; }
public DateTime LoginDate { get; set; }
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser User { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("Web_Identity", throwIfV1Schema: false)
{
}
public System.Data.Entity.DbSet<AccountLog> AccountLog { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
}
Login.aspx.cs
namespace Web_WebApp.Account
{
public partial class Login : Page
{
string GuidToken = System.Guid.NewGuid().ToString();
public static string GetExternalIP()
{
try
{
string externalIP;
externalIP = (new WebClient()).DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}
catch { return null; }
}
protected void LogIn(object sender, EventArgs e)
{
// Validate the user password
//var AccountLogs = Context.GetOwinContext().GetUserManager<AccountLog>();
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var signinManager = Context.GetOwinContext().GetUserManager<ApplicationSignInManager>();
// Require the user to have a confirmed email before they can log on.
var user = manager.FindByName(username.Text);
if (IsValid)
{
if (user != null)
{
{
// This doen't count login failures towards account lockout
// To enable password failures to trigger lockout, change to shouldLockout: true
var result = signinManager.PasswordSignIn(username.Text, Password.Text, RememberMe.Checked, shouldLockout: true);
if (!user.EmailConfirmed && result == SignInStatus.Success)
{
Response.Redirect("/Account/Confirmation?UserConfirmationID=" + user.Id);
}
switch (result)
{
case SignInStatus.Success:
var AccountLog = new AccountLog()
{
IPv4 = GetExternalIP(),
LoginDate = DateTime.Now,
UserId = user.Id,
};
user.AccountLogs.Add(AccountLog);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
//Response.Redirect("/Account/Lockout");
FailureText.Text = "This account has been locked, please try again later.";
ErrorMessage.Visible = true;
return;
case SignInStatus.RequiresVerification:
Response.Redirect(String.Format("/Account/TwoFactorAuthenticationSignIn?ReturnUrl={0}&RememberMe={1}",
Request.QueryString["ReturnUrl"],
RememberMe.Checked),
true);
break;
case SignInStatus.Failure:
default:
FailureText.Text = "Invalid password";
ErrorMessage.Visible = true;
break;
}
}
}
else
FailureText.Text = "Account not found.";
ErrorMessage.Visible = true;
}
}
}
}
使用这些代码,我的应用程序可以运行,我可以登录,但它不会像我在代码中提到的那样保存任何内容。我没有收到任何错误或警告。
我确定 "SaveChanges()" 之类的东西丢失了,但我不知道该放在哪里。
感谢您为解决我的问题所做的努力。
您正在通过 ApplicationUserManager
获取用户,在将新的 AccountLog
条目添加到集合 user.AccountLogs
后,您需要将用户保存回数据库.据我所知,您可以像获取其他实例一样从 OWIN 获取 Entity framework 上下文 (ApplicationDbContext
?)。
switch (result)
{
case SignInStatus.Success:
var AccountLog = new AccountLog()
{
IPv4 = GetExternalIP(),
LoginDate = DateTime.Now,
UserId = user.Id,
};
user.AccountLogs.Add(AccountLog);
// get the entity framework context.
var dbContext = Context.GetOwinContext().Get<ApplicationDbContext>();
// save the changes to objects tracked by this context
dbContext.SaveChanges();
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
// removed for brevity.
break;
}
注意:你可能需要直接从上下文中再次获取用户,但我认为没有必要,取决于用户是否分离.