diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-09-03 17:37:40 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-09-03 17:37:40 -0700 |
commit | ab797eabc37fd3b1a2b77ff5114ff2e00a0f2e39 (patch) | |
tree | 184012f9a67a7c93d1f2c29208f116941c3cf2b7 | |
parent | a93777789e267045e836531fa0b149f6df5a4031 (diff) | |
parent | e65eb7cff86b438d863e24d551d585cda0759116 (diff) | |
download | DotNetOpenAuth-ab797eabc37fd3b1a2b77ff5114ff2e00a0f2e39.zip DotNetOpenAuth-ab797eabc37fd3b1a2b77ff5114ff2e00a0f2e39.tar.gz DotNetOpenAuth-ab797eabc37fd3b1a2b77ff5114ff2e00a0f2e39.tar.bz2 |
Merge branch 'master' into contracts
Conflicts:
src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
8 files changed, 215 insertions, 92 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index 7e92cb5..1cfeb9c 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -265,6 +265,7 @@ <Compile Include="OpenId\RelyingParty\AuthenticationRequestTests.cs" /> <Compile Include="OpenId\RelyingParty\FailedAuthenticationResponseTests.cs" /> <Compile Include="OpenId\RelyingParty\NegativeAuthenticationResponseTests.cs" /> + <Compile Include="OpenId\RelyingParty\OpenIdTextBoxTests.cs" /> <Compile Include="OpenId\RelyingParty\PositiveAnonymousResponseTests.cs" /> <Compile Include="OpenId\RelyingParty\PositiveAuthenticationResponseTests.cs" /> <Compile Include="OpenId\RelyingParty\OpenIdRelyingPartyTests.cs" /> diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs new file mode 100644 index 0000000..67255e3 --- /dev/null +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------- +// <copyright file="OpenIdTextBoxTests.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.OpenId.RelyingParty { + using DotNetOpenAuth.OpenId.RelyingParty; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class OpenIdTextBoxTests : OpenIdTestBase { + /// <summary> + /// Verifies that the Text and Identifier properties interact correctly. + /// </summary> + [TestMethod] + public void IdentifierTextInteraction() { + var box = new OpenIdTextBox(); + Assert.AreEqual(string.Empty, box.Text); + Assert.IsNull(box.Identifier); + + box.Text = "=arnott"; + Assert.AreEqual("=arnott", box.Text); + Assert.AreEqual("=arnott", box.Identifier.ToString()); + + box.Identifier = "=bob"; + Assert.AreEqual("=bob", box.Text); + Assert.AreEqual("=bob", box.Identifier.ToString()); + + box.Text = string.Empty; + Assert.AreEqual(string.Empty, box.Text); + Assert.IsNull(box.Identifier); + + box.Text = null; + Assert.AreEqual(string.Empty, box.Text); + Assert.IsNull(box.Identifier); + + // Invalid identifier case + box.Text = "/"; + Assert.AreEqual("/", box.Text); + Assert.IsNull(box.Identifier); + + // blank out the invalid case + box.Identifier = null; + Assert.AreEqual(string.Empty, box.Text); + Assert.IsNull(box.Identifier); + } + } +} diff --git a/src/DotNetOpenAuth/OpenId/Identifier.cs b/src/DotNetOpenAuth/OpenId/Identifier.cs index 0475db1..e32251b 100644 --- a/src/DotNetOpenAuth/OpenId/Identifier.cs +++ b/src/DotNetOpenAuth/OpenId/Identifier.cs @@ -27,6 +27,7 @@ namespace DotNetOpenAuth.OpenId { /// <param name="originalString">The original string before any normalization.</param> /// <param name="isDiscoverySecureEndToEnd">Whether the derived class is prepared to guarantee end-to-end discovery /// and initial redirect for authentication is performed using SSL.</param> + [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "string", Justification = "Emphasis on string instead of the strong-typed Identifier.")] protected Identifier(string originalString, bool isDiscoverySecureEndToEnd) { this.OriginalString = originalString; this.IsDiscoverySecureEndToEnd = isDiscoverySecureEndToEnd; diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs index 3b7b78f..a1ecc24 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs @@ -231,12 +231,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { #endregion - /// <summary> - /// A dictionary of extension response types and the javascript member - /// name to map them to on the user agent. - /// </summary> - private Dictionary<Type, string> clientScriptExtensions = new Dictionary<Type, string>(); - #region Events /// <summary> @@ -628,6 +622,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// <summary> /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed. /// </summary> + [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Preserve signature of interface we're implementing.")] protected virtual void RaisePostDataChangedEvent() { this.OnTextChanged(); } diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs index b0dce61..3e13ef0 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs @@ -551,8 +551,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { [DefaultValue(RememberMeDefault)] [Description("Whether a successful authentication should result in a persistent cookie being saved to the browser.")] public bool RememberMe { - get { return this.UsePersistentCookie != LoginPersistence.Session; } - set { this.UsePersistentCookie = value ? LoginPersistence.PersistentAuthentication : LoginPersistence.Session; } + get { return this.UsePersistentCookie != LogOnPersistence.Session; } + set { this.UsePersistentCookie = value ? LogOnPersistence.PersistentAuthentication : LogOnPersistence.Session; } } /// <summary> @@ -568,6 +568,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { set { unchecked { + EnsureChildControls(); base.TabIndex = (short)(value + TextBoxTabIndexOffset); this.loginButton.TabIndex = (short)(value + LoginButtonTabIndexOffset); this.rememberMeCheckBox.TabIndex = (short)(value + RememberMeTabIndexOffset); @@ -634,7 +635,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// cookie should persist across user sessions. /// </summary> [Browsable(false), Bindable(false)] - public override LoginPersistence UsePersistentCookie { + public override LogOnPersistence UsePersistentCookie { get { return base.UsePersistentCookie; } @@ -644,7 +645,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { // use conditional here to prevent infinite recursion // with CheckedChanged event. - bool rememberMe = value != LoginPersistence.Session; + bool rememberMe = value != LogOnPersistence.Session; if (this.rememberMeCheckBox.Checked != rememberMe) { this.rememberMeCheckBox.Checked = rememberMe; } @@ -672,6 +673,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } /// <summary> + /// Raises the <see cref="E:System.Web.UI.Control.PreRender"/> event. + /// </summary> + /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> + protected override void OnPreRender(EventArgs e) { + base.OnPreRender(e); + + EnsureChildControls(); + EnsureID(); + this.requiredValidator.ControlToValidate = this.ID; + this.identifierFormatValidator.ControlToValidate = this.ID; + } + + /// <summary> /// Initializes the child controls. /// </summary> protected void InitializeControls() { @@ -721,7 +735,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { this.requiredValidator.ErrorMessage = RequiredTextDefault + RequiredTextSuffix; this.requiredValidator.Text = RequiredTextDefault + RequiredTextSuffix; this.requiredValidator.Display = ValidatorDisplay.Dynamic; - this.requiredValidator.ControlToValidate = this.ID; this.requiredValidator.ValidationGroup = ValidationGroupDefault; cell.Controls.Add(this.requiredValidator); this.identifierFormatValidator = new CustomValidator(); @@ -730,7 +743,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { this.identifierFormatValidator.ServerValidate += this.IdentifierFormatValidator_ServerValidate; this.identifierFormatValidator.Enabled = UriValidatorEnabledDefault; this.identifierFormatValidator.Display = ValidatorDisplay.Dynamic; - this.identifierFormatValidator.ControlToValidate = this.ID; this.identifierFormatValidator.ValidationGroup = ValidationGroupDefault; cell.Controls.Add(this.identifierFormatValidator); this.errorLabel = new Label(); diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs index 8a4c94e..bf883f4 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs @@ -32,12 +32,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// <summary> /// The name of the javascript function that will initiate a synchronous callback. /// </summary> - protected const string CallbackJsFunction = "window.dnoa_internal.callback"; + protected const string CallbackJSFunction = "window.dnoa_internal.callback"; /// <summary> /// The name of the javascript function that will initiate an asynchronous callback. /// </summary> - protected const string CallbackJsFunctionAsync = "window.dnoa_internal.callbackAsync"; + protected const string CallbackJSFunctionAsync = "window.dnoa_internal.callbackAsync"; /// <summary> /// The "dnoa.op_endpoint" string. @@ -98,7 +98,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { base.Popup = PopupBehavior.Always; // The expected use case for the AJAX login box is for comments... not logging in. - this.LoginMode = LoginSiteNotification.None; + this.LogOnMode = LogOnSiteNotification.None; } /// <summary> @@ -216,8 +216,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// <returns>The result of the callback.</returns> /// <value>A whitespace delimited list of URLs that can be used to initiate authentication.</value> string ICallbackEventHandler.GetCallbackResult() { - this.Page.Response.ContentType = "text/javascript"; - return this.discoveryResult; + return this.GetCallbackResult(); } /// <summary> @@ -225,10 +224,32 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// AJAX callback mechanisms. /// </summary> /// <param name="eventArgument">The identifier to perform discovery on.</param> + [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "We want to preserve the signature of the interface.")] void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument) { - ErrorUtilities.VerifyNonZeroLength(eventArgument, "eventArgument"); + this.RaiseCallbackEvent(eventArgument); + } + + #endregion + + /// <summary> + /// Returns the results of a callback event that targets a control. + /// </summary> + /// <returns>The result of the callback.</returns> + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "We want to preserve the signature of the interface.")] + protected virtual string GetCallbackResult() { + this.Page.Response.ContentType = "text/javascript"; + return this.discoveryResult; + } + + /// <summary> + /// Processes a callback event that targets a control. + /// </summary> + /// <param name="eventArgument">A string that represents an event argument to pass to the event handler.</param> + [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "We want to preserve the signature of the interface.")] + protected virtual void RaiseCallbackEvent(string eventArgument) { string userSuppliedIdentifier = eventArgument; + ErrorUtilities.VerifyNonZeroLength(userSuppliedIdentifier, "userSuppliedIdentifier"); Logger.OpenId.InfoFormat("AJAX discovery on {0} requested.", userSuppliedIdentifier); // We prepare a JSON object with this interface: @@ -277,8 +298,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { this.discoveryResult = discoveryResultBuilder.ToString(); } - #endregion - /// <summary> /// Fires the <see cref="UnconfirmedPositiveAssertion"/> event. /// </summary> @@ -334,8 +353,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { StringBuilder initScript = new StringBuilder(); - initScript.AppendLine(CallbackJsFunctionAsync + " = " + this.GetJsCallbackConvenienceFunction(true)); - initScript.AppendLine(CallbackJsFunction + " = " + this.GetJsCallbackConvenienceFunction(false)); + initScript.AppendLine(CallbackJSFunctionAsync + " = " + this.GetJsCallbackConvenienceFunction(true)); + initScript.AppendLine(CallbackJSFunction + " = " + this.GetJsCallbackConvenienceFunction(false)); this.Page.ClientScript.RegisterClientScriptBlock(typeof(OpenIdRelyingPartyControlBase), "initializer", initScript.ToString(), true); } diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs index 0e054ac..d8f0269 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs @@ -27,6 +27,50 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { using DotNetOpenAuth.OpenId.Extensions.UI; /// <summary> + /// Methods of indicating to the rest of the web site that the user has logged in. + /// </summary> + [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "OnSite", Justification = "Two words intended.")] + public enum LogOnSiteNotification { + /// <summary> + /// The rest of the web site is unaware that the user just completed an OpenID login. + /// </summary> + None, + + /// <summary> + /// After the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event is fired + /// the control automatically calls <see cref="System.Web.Security.FormsAuthentication.RedirectFromLoginPage(string, bool)"/> + /// with the <see cref="IAuthenticationResponse.ClaimedIdentifier"/> as the username + /// unless the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event handler sets + /// <see cref="OpenIdEventArgs.Cancel"/> property to true. + /// </summary> + FormsAuthentication, + } + + /// <summary> + /// How an OpenID user session should be persisted across visits. + /// </summary> + public enum LogOnPersistence { + /// <summary> + /// The user should only be logged in as long as the browser window remains open. + /// Nothing is persisted to help the user on a return visit. Public kiosk mode. + /// </summary> + Session, + + /// <summary> + /// The user should only be logged in as long as the browser window remains open. + /// The OpenID Identifier is persisted to help expedite re-authentication when + /// the user visits the next time. + /// </summary> + SessionAndPersistentIdentifier, + + /// <summary> + /// The user is issued a persistent authentication ticket so that no login is + /// necessary on their return visit. + /// </summary> + PersistentAuthentication, + } + + /// <summary> /// A common base class for OpenID Relying Party controls. /// </summary> [DefaultProperty("Identifier"), ValidationProperty("Identifier")] @@ -76,7 +120,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// The parameter name to include in the formulated auth request so that javascript can know whether /// the OP advertises support for the UI extension. /// </summary> - protected const string PopupUISupportedJsHint = OpenIdUtilities.CustomParameterPrefix + "popupUISupported"; + protected const string PopupUISupportedJSHint = OpenIdUtilities.CustomParameterPrefix + "popupUISupported"; /// <summary> /// The callback parameter for use with persisting the <see cref="UsePersistentCookie"/> property. @@ -105,12 +149,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// <summary> /// Default value of <see cref="UsePersistentCookie"/>. /// </summary> - private const LoginPersistence UsePersistentCookieDefault = LoginPersistence.Session; + private const LogOnPersistence UsePersistentCookieDefault = LogOnPersistence.Session; /// <summary> - /// Default value of <see cref="LoginMode"/>. + /// Default value of <see cref="LogOnMode"/>. /// </summary> - private const LoginSiteNotification LoginModeDefault = LoginSiteNotification.FormsAuthentication; + private const LogOnSiteNotification LogOnModeDefault = LogOnSiteNotification.FormsAuthentication; /// <summary> /// The default value for the <see cref="RealmUrl"/> property. @@ -142,9 +186,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { private const string UsePersistentCookieViewStateKey = "UsePersistentCookie"; /// <summary> - /// The viewstate key to use for the <see cref="LoginMode"/> property. + /// The viewstate key to use for the <see cref="LogOnMode"/> property. /// </summary> - private const string LoginModeViewStateKey = "LoginMode"; + private const string LogOnModeViewStateKey = "LogOnMode"; /// <summary> /// The viewstate key to use for the <see cref="RealmUrl"/> property. @@ -222,50 +266,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { [Description("Fired when an authentication attempt is canceled at the OpenID Provider."), Category(OpenIdCategory)] public event EventHandler<OpenIdEventArgs> Canceled; - #endregion - /// <summary> - /// Methods of indicating to the rest of the web site that the user has logged in. + /// Occurs when the <see cref="Identifier"/> property is changed. /// </summary> - public enum LoginSiteNotification { - /// <summary> - /// The rest of the web site is unaware that the user just completed an OpenID login. - /// </summary> - None, + protected event EventHandler IdentifierChanged; - /// <summary> - /// After the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event is fired - /// the control automatically calls <see cref="System.Web.Security.FormsAuthentication.RedirectFromLoginPage(string, bool)"/> - /// with the <see cref="IAuthenticationResponse.ClaimedIdentifier"/> as the username - /// unless the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event handler sets - /// <see cref="OpenIdEventArgs.Cancel"/> property to true. - /// </summary> - FormsAuthentication, - } - - /// <summary> - /// How an OpenID user session should be persisted across visits. - /// </summary> - public enum LoginPersistence { - /// <summary> - /// The user should only be logged in as long as the browser window remains open. - /// Nothing is persisted to help the user on a return visit. Public kiosk mode. - /// </summary> - Session, - - /// <summary> - /// The user should only be logged in as long as the browser window remains open. - /// The OpenID Identifier is persisted to help expedite re-authentication when - /// the user visits the next time. - /// </summary> - SessionAndPersistentIdentifier, - - /// <summary> - /// The user is issued a persistent authentication ticket so that no login is - /// necessary on their return visit. - /// </summary> - PersistentAuthentication, - } + #endregion /// <summary> /// Gets or sets the <see cref="OpenIdRelyingParty"/> instance to use. @@ -380,19 +386,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { [Bindable(true), DefaultValue(UsePersistentCookieDefault), Category(BehaviorCategory)] [Description("Whether to send a persistent cookie upon successful " + "login so the user does not have to log in upon returning to this site.")] - public virtual LoginPersistence UsePersistentCookie { - get { return (LoginPersistence)(this.ViewState[UsePersistentCookieViewStateKey] ?? UsePersistentCookieDefault); } + public virtual LogOnPersistence UsePersistentCookie { + get { return (LogOnPersistence)(this.ViewState[UsePersistentCookieViewStateKey] ?? UsePersistentCookieDefault); } set { this.ViewState[UsePersistentCookieViewStateKey] = value; } } /// <summary> /// Gets or sets the way a completed login is communicated to the rest of the web site. /// </summary> - [Bindable(true), DefaultValue(LoginModeDefault), Category(BehaviorCategory)] + [Bindable(true), DefaultValue(LogOnModeDefault), Category(BehaviorCategory)] [Description("The way a completed login is communicated to the rest of the web site.")] - public virtual LoginSiteNotification LoginMode { - get { return (LoginSiteNotification)(this.ViewState[LoginModeViewStateKey] ?? LoginModeDefault); } - set { this.ViewState[LoginModeViewStateKey] = value; } + public virtual LogOnSiteNotification LogOnMode { + get { return (LogOnSiteNotification)(this.ViewState[LogOnModeViewStateKey] ?? LogOnModeDefault); } + set { this.ViewState[LogOnModeViewStateKey] = value; } } /// <summary> @@ -424,9 +430,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { [Bindable(true), Category(OpenIdCategory)] [Description("The OpenID Identifier that this button will use to initiate login.")] [TypeConverter(typeof(IdentifierConverter))] - public Identifier Identifier { - get { return (Identifier)ViewState[IdentifierViewStateKey]; } - set { ViewState[IdentifierViewStateKey] = value; } + public virtual Identifier Identifier { + get { + return (Identifier)ViewState[IdentifierViewStateKey]; + } + + set { + ViewState[IdentifierViewStateKey] = value; + this.OnIdentifierChanged(); + } } /// <summary> @@ -541,7 +553,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { // This is so the window can be made the correct size for the extension. // If the OP doesn't advertise support for the extension, the javascript will use // a bigger popup window. - req.SetCallbackArgument(PopupUISupportedJsHint, "1"); + req.SetCallbackArgument(PopupUISupportedJSHint, "1"); } } @@ -593,6 +605,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } /// <summary> + /// Called when the <see cref="Identifier"/> property is changed. + /// </summary> + protected virtual void OnIdentifierChanged() { + var identifierChanged = this.IdentifierChanged; + if (identifierChanged != null) { + identifierChanged(this, EventArgs.Empty); + } + } + + /// <summary> /// Processes the response. /// </summary> /// <param name="response">The response.</param> @@ -602,7 +624,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } string persistentString = response.GetCallbackArgument(UsePersistentCookieCallbackKey); if (persistentString != null) { - this.UsePersistentCookie = (LoginPersistence)Enum.Parse(typeof(LoginPersistence), persistentString); + this.UsePersistentCookie = (LogOnPersistence)Enum.Parse(typeof(LogOnPersistence), persistentString); } switch (response.Status) { @@ -651,15 +673,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } if (!args.Cancel) { - if (this.UsePersistentCookie == LoginPersistence.SessionAndPersistentIdentifier) { + if (this.UsePersistentCookie == LogOnPersistence.SessionAndPersistentIdentifier) { Page.Response.SetCookie(CreateIdentifierPersistingCookie(response)); } - switch (this.LoginMode) { - case LoginSiteNotification.FormsAuthentication: - FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie == LoginPersistence.PersistentAuthentication); + switch (this.LogOnMode) { + case LogOnSiteNotification.FormsAuthentication: + FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie == LogOnPersistence.PersistentAuthentication); break; - case LoginSiteNotification.None: + case LogOnSiteNotification.None: default: break; } diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs index 1fb227d..dc39dbb 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs @@ -158,6 +158,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// </summary> private const string NameViewStateKey = "Name"; + /// <summary> + /// The viewstate key to use for the <see cref="Text"/> property. + /// </summary> + private const string TextViewStateKey = "Text"; + #endregion #region Property defaults @@ -282,8 +287,21 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { [Bindable(true), DefaultValue(""), Category(AppearanceCategory)] [Description("The content of the text box.")] public string Text { - get { return this.Identifier != null ? this.Identifier.OriginalString : string.Empty; } - set { this.Identifier = value; } + get { + return this.Identifier != null ? this.Identifier.OriginalString : (this.ViewState[TextViewStateKey] as string ?? string.Empty); + } + + set { + // Try to store it as a validated identifier, + // but failing that at least store the text. + Identifier id; + if (Identifier.TryParse(value, out id)) { + this.Identifier = id; + } else { + this.Identifier = null; + this.ViewState[TextViewStateKey] = value; + } + } } /// <summary> @@ -549,6 +567,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } /// <summary> + /// Called when the <see cref="Identifier"/> property is changed. + /// </summary> + protected override void OnIdentifierChanged() { + this.ViewState.Remove(TextViewStateKey); + base.OnIdentifierChanged(); + } + + /// <summary> /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client. /// </summary> /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param> @@ -597,11 +623,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { // If the control was temporarily hidden, it won't be in the Form data, // and we'll just implicitly keep the last Text setting. if (postCollection[this.Name] != null) { - Identifier identifier = postCollection[this.Name].Length == 0 ? null : postCollection[this.Name]; - if (identifier != this.Identifier) { - this.Identifier = identifier; - return true; - } + this.Text = postCollection[this.Name]; + return true; } return false; @@ -610,6 +633,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// <summary> /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed. /// </summary> + [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Preserve signature of interface we're implementing.")] protected virtual void RaisePostDataChangedEvent() { this.OnTextChanged(); } |