ASP.Net 带有电子邮件确认的 WebForms(InvalidApiRequestException 错误)
ASP.Net WebForms with Email Confirmation (InvalidApiRequestException error)
我正在尝试使用 SendGrid 在用户注册后向他们发送一封确认电子邮件,这样一旦他们单击它,他们的帐户就会得到确认,他们可以访问该网站。
我遵循了本教程:http://www.asp.net/webforms/overview/security/create-a-secure-aspnet-web-forms-app-with-user-registration-email-confirmation-and-password-reset
甚至下载了源代码,但在我注册用户后仍然出现错误。错误正是: 'Exceptions.InvalidApiRequestException' 类型的异常发生在 mscorlib.dll 但未在用户代码中处理
附加信息:错误请求检查 Errors
以获得 API 返回的错误列表。
我今天已经为此工作了 8 个小时,我真的迷路了。我将展示相关文件,我们将不胜感激任何帮助或指导!
Register.aspx.cs
public partial class Register : Page
{
protected void CreateUser_Click(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text };
IdentityResult result = manager.Create(user, Password.Text);
if (result.Succeeded)
{
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
string code = manager.GenerateEmailConfirmationToken(user.Id);
string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
if (user.EmailConfirmed)
{
IdentityHelper.SignIn(manager, user, isPersistent: false);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else
{
ErrorMessage.Text = "An email has been sent to your account. Please view the email and confirm your account to complete the registration process.";
}
}
else
{
ErrorMessage.Text = result.Errors.FirstOrDefault();
}
}
}
appSetting 在 Web.config
内
<appSettings>
<!-- SendGrid Credentials-->
<add key="emailServiceUserName" value="[mySendGridUsername]" />
<add key="emailServicePassword" value="[MySendGridPassword]" />
<!-- Twilio Credentials-->
<add key="SMSSID" value="[APab1ee340509424be311b64bc673b5885]" />
<add key="SMSAuthToken" value="[5320-5345]" />
<add key="SMSPhoneNumber" value="+[441752414370]" />
</appSettings>
Login.aspx.cs
public partial class Login : Page
{
protected void Page_Load(object sender, EventArgs e)
{
RegisterHyperLink.NavigateUrl = "Register";
// Enable this once you have account confirmation enabled for password reset functionality
ForgotPasswordHyperLink.NavigateUrl = "Forgot";
OpenAuthLogin.ReturnUrl = Request.QueryString["ReturnUrl"];
var returnUrl = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]);
if (!String.IsNullOrEmpty(returnUrl))
{
RegisterHyperLink.NavigateUrl += "?ReturnUrl=" + returnUrl;
}
}
protected void LogIn(object sender, EventArgs e)
{
if (IsValid)
{
// Validate the user password
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(Email.Text);
if (user != null)
{
if (!user.EmailConfirmed)
{
FailureText.Text = "Invalid login attempt. You must have a confirmed email address. Enter your email and password, then press 'Resend Confirmation'.";
ErrorMessage.Visible = true;
ResendConfirm.Visible = true;
}
else
{
// This doen't count login failures towards account lockout
// To enable password failures to trigger lockout, change to shouldLockout: true
var result = signinManager.PasswordSignIn(Email.Text, Password.Text, RememberMe.Checked, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
Response.Redirect("/Account/Lockout");
break;
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 login attempt";
ErrorMessage.Visible = true;
break;
}
}
}
}
}
protected void SendEmailConfirmationToken(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindByName(Email.Text);
if (user != null)
{
if (!user.EmailConfirmed)
{
string code = manager.GenerateEmailConfirmationToken(user.Id);
string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
FailureText.Text = "Confirmation email sent. Please view the email and confirm your account.";
ErrorMessage.Visible = true;
ResendConfirm.Visible = false;
}
}
}
}
错误出现在代码行:
manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
IdentityConfig.cs
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
await configSendGridasync(message);
}
// Use NuGet to install SendGrid (Basic C# client lib)
private async Task configSendGridasync(IdentityMessage message)
{
var myMessage = new SendGridMessage();
myMessage.AddTo(message.Destination);
myMessage.From = new System.Net.Mail.MailAddress(
"Royce@contoso.com", "Royce Sellars (Contoso Admin)");
myMessage.Subject = message.Subject;
myMessage.Text = message.Body;
myMessage.Html = message.Body;
var credentials = new NetworkCredential(
ConfigurationManager.AppSettings["emailServiceUserName"],
ConfigurationManager.AppSettings["emailServicePassword"]
);
// Create a Web transport for sending email.
var transportWeb = new Web(credentials);
// Send the email.
if (transportWeb != null)
{
await transportWeb.DeliverAsync(myMessage);
}
else
{
Trace.TraceError("Failed to create Web transport.");
await Task.FromResult(0);
}
}
}
public class SmsService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
var Twilio = new TwilioRestClient(
ConfigurationManager.AppSettings["SMSSID"],
ConfigurationManager.AppSettings["SMSAuthToken"]
);
var result = Twilio.SendMessage(
ConfigurationManager.AppSettings["SMSPhoneNumber"],
message.Destination, message.Body);
// Status is one of Queued, Sending, Sent, Failed or null if the number is not valid
Trace.TraceInformation(result.Status);
// Twilio doesn't currently have an async API, so return success.
return Task.FromResult(0);
}
}
// Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application.
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
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
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) :
base(userManager, authenticationManager) { }
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
}
public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
{
return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
}
}
在您的 web.config 文件中将其从
add key="emailServiceUserName" value="[mySendGridUsername]"
add key="emailServicePassword" value="[MySendGridPassword]"
对此:
add key="emailServiceUserName" value="mySendGridUsername"
add key="emailServicePassword" value="MySendGridPassword"
删除 []。问题解决了! :)
我正在尝试使用 SendGrid 在用户注册后向他们发送一封确认电子邮件,这样一旦他们单击它,他们的帐户就会得到确认,他们可以访问该网站。
我遵循了本教程:http://www.asp.net/webforms/overview/security/create-a-secure-aspnet-web-forms-app-with-user-registration-email-confirmation-and-password-reset
甚至下载了源代码,但在我注册用户后仍然出现错误。错误正是: 'Exceptions.InvalidApiRequestException' 类型的异常发生在 mscorlib.dll 但未在用户代码中处理
附加信息:错误请求检查 Errors
以获得 API 返回的错误列表。
我今天已经为此工作了 8 个小时,我真的迷路了。我将展示相关文件,我们将不胜感激任何帮助或指导!
Register.aspx.cs
public partial class Register : Page
{
protected void CreateUser_Click(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text };
IdentityResult result = manager.Create(user, Password.Text);
if (result.Succeeded)
{
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
string code = manager.GenerateEmailConfirmationToken(user.Id);
string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
if (user.EmailConfirmed)
{
IdentityHelper.SignIn(manager, user, isPersistent: false);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else
{
ErrorMessage.Text = "An email has been sent to your account. Please view the email and confirm your account to complete the registration process.";
}
}
else
{
ErrorMessage.Text = result.Errors.FirstOrDefault();
}
}
}
appSetting 在 Web.config
内<appSettings>
<!-- SendGrid Credentials-->
<add key="emailServiceUserName" value="[mySendGridUsername]" />
<add key="emailServicePassword" value="[MySendGridPassword]" />
<!-- Twilio Credentials-->
<add key="SMSSID" value="[APab1ee340509424be311b64bc673b5885]" />
<add key="SMSAuthToken" value="[5320-5345]" />
<add key="SMSPhoneNumber" value="+[441752414370]" />
</appSettings>
Login.aspx.cs
public partial class Login : Page
{
protected void Page_Load(object sender, EventArgs e)
{
RegisterHyperLink.NavigateUrl = "Register";
// Enable this once you have account confirmation enabled for password reset functionality
ForgotPasswordHyperLink.NavigateUrl = "Forgot";
OpenAuthLogin.ReturnUrl = Request.QueryString["ReturnUrl"];
var returnUrl = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]);
if (!String.IsNullOrEmpty(returnUrl))
{
RegisterHyperLink.NavigateUrl += "?ReturnUrl=" + returnUrl;
}
}
protected void LogIn(object sender, EventArgs e)
{
if (IsValid)
{
// Validate the user password
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(Email.Text);
if (user != null)
{
if (!user.EmailConfirmed)
{
FailureText.Text = "Invalid login attempt. You must have a confirmed email address. Enter your email and password, then press 'Resend Confirmation'.";
ErrorMessage.Visible = true;
ResendConfirm.Visible = true;
}
else
{
// This doen't count login failures towards account lockout
// To enable password failures to trigger lockout, change to shouldLockout: true
var result = signinManager.PasswordSignIn(Email.Text, Password.Text, RememberMe.Checked, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
Response.Redirect("/Account/Lockout");
break;
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 login attempt";
ErrorMessage.Visible = true;
break;
}
}
}
}
}
protected void SendEmailConfirmationToken(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindByName(Email.Text);
if (user != null)
{
if (!user.EmailConfirmed)
{
string code = manager.GenerateEmailConfirmationToken(user.Id);
string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
FailureText.Text = "Confirmation email sent. Please view the email and confirm your account.";
ErrorMessage.Visible = true;
ResendConfirm.Visible = false;
}
}
}
}
错误出现在代码行:
manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
IdentityConfig.cs
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
await configSendGridasync(message);
}
// Use NuGet to install SendGrid (Basic C# client lib)
private async Task configSendGridasync(IdentityMessage message)
{
var myMessage = new SendGridMessage();
myMessage.AddTo(message.Destination);
myMessage.From = new System.Net.Mail.MailAddress(
"Royce@contoso.com", "Royce Sellars (Contoso Admin)");
myMessage.Subject = message.Subject;
myMessage.Text = message.Body;
myMessage.Html = message.Body;
var credentials = new NetworkCredential(
ConfigurationManager.AppSettings["emailServiceUserName"],
ConfigurationManager.AppSettings["emailServicePassword"]
);
// Create a Web transport for sending email.
var transportWeb = new Web(credentials);
// Send the email.
if (transportWeb != null)
{
await transportWeb.DeliverAsync(myMessage);
}
else
{
Trace.TraceError("Failed to create Web transport.");
await Task.FromResult(0);
}
}
}
public class SmsService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
var Twilio = new TwilioRestClient(
ConfigurationManager.AppSettings["SMSSID"],
ConfigurationManager.AppSettings["SMSAuthToken"]
);
var result = Twilio.SendMessage(
ConfigurationManager.AppSettings["SMSPhoneNumber"],
message.Destination, message.Body);
// Status is one of Queued, Sending, Sent, Failed or null if the number is not valid
Trace.TraceInformation(result.Status);
// Twilio doesn't currently have an async API, so return success.
return Task.FromResult(0);
}
}
// Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application.
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
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
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) :
base(userManager, authenticationManager) { }
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
}
public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
{
return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
}
}
在您的 web.config 文件中将其从
add key="emailServiceUserName" value="[mySendGridUsername]"
add key="emailServicePassword" value="[MySendGridPassword]"
对此:
add key="emailServiceUserName" value="mySendGridUsername"
add key="emailServicePassword" value="MySendGridPassword"
删除 []。问题解决了! :)