1 //------------------------------------------------------------------------------
2 // <copyright file="PasswordRecovery.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 namespace System.Web.UI.WebControls {
9 using System.Collections;
10 using System.Collections.Specialized;
11 using System.ComponentModel;
12 using System.Diagnostics;
13 using System.Diagnostics.CodeAnalysis;
15 using System.Drawing.Design;
16 using System.Globalization;
17 using System.Security.Permissions;
19 using System.Web.Configuration;
20 using System.Web.Management;
21 using System.Web.Security;
25 /// Displays UI that allows a user to recover his/her password. Prompts for username and possibly answer
26 /// to security question. If successful, the user's password is sent to him/her via email. Uses
27 /// a Membership provider. UI can be customized using control properties or a template.
31 DefaultEvent("SendingMail"),
32 Designer("System.Web.UI.Design.WebControls.PasswordRecoveryDesigner, " + AssemblyRef.SystemDesign)
34 public class PasswordRecovery : CompositeControl, IBorderPaddingControl, IRenderOuterTableControl {
35 public static readonly string SubmitButtonCommandName = "Submit";
37 // Needed for user template feature
38 private const string _userNameID = "UserName";
39 private const string _questionID = "Question";
40 private const string _answerID = "Answer";
41 private const string _failureTextID = "FailureText";
43 // Needed only for "convert to template" feature, otherwise unnecessary
44 private const string _userNameRequiredID = "UserNameRequired";
45 private const string _answerRequiredID = "AnswerRequired";
46 private const string _pushButtonID = "SubmitButton";
47 private const string _imageButtonID = "SubmitImageButton";
48 private const string _linkButtonID = "SubmitLinkButton";
49 private const string _helpLinkID = "HelpLink";
51 private const string _userNameContainerID = "UserNameContainerID";
52 private const string _questionContainerID = "QuestionContainerID";
53 private const string _successContainerID = "SuccessContainerID";
54 private const ValidatorDisplay _requiredFieldValidatorDisplay = ValidatorDisplay.Static;
55 private const string _userNameReplacementKey = "<%\\s*UserName\\s*%>";
56 private const string _passwordReplacementKey = "<%\\s*Password\\s*%>";
58 private string _answer;
59 private View _currentView = View.UserName;
60 private string _question;
61 private string _userName;
62 private bool _convertingToTemplate = false;
63 private bool _renderDesignerRegion = false;
65 private ITemplate _userNameTemplate;
66 private UserNameContainer _userNameContainer;
67 private ITemplate _questionTemplate;
68 private QuestionContainer _questionContainer;
69 private ITemplate _successTemplate;
70 private SuccessContainer _successContainer;
72 private const int _viewStateArrayLength = 11;
73 private Style _submitButtonStyle;
74 private TableItemStyle _labelStyle;
75 private Style _textBoxStyle;
76 private TableItemStyle _hyperLinkStyle;
77 private TableItemStyle _instructionTextStyle;
78 private TableItemStyle _titleTextStyle;
79 private TableItemStyle _failureTextStyle;
80 private TableItemStyle _successTextStyle;
81 private MailDefinition _mailDefinition;
82 private Style _validatorTextStyle;
84 private static readonly object EventVerifyingUser = new object();
85 private static readonly object EventUserLookupError = new object();
86 private static readonly object EventVerifyingAnswer = new object();
87 private static readonly object EventAnswerLookupError = new object();
88 private static readonly object EventSendMailError = new object();
89 private static readonly object EventSendingMail = new object();
93 /// Answer to the security question.
99 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
101 public virtual string Answer {
103 return (_answer == null) ? String.Empty : _answer;
107 private string AnswerInternal {
109 string answer = Answer;
110 if (String.IsNullOrEmpty(answer) && _questionContainer != null) {
111 ITextControl answerTextBox = (ITextControl)_questionContainer.AnswerTextBox;
112 if (answerTextBox != null && answerTextBox.Text != null) {
113 return answerTextBox.Text;
121 /// The text that identifies the answer textbox.
125 WebCategory("Appearance"),
126 WebSysDefaultValue(SR.PasswordRecovery_DefaultAnswerLabelText),
127 WebSysDescription(SR.PasswordRecovery_AnswerLabelText)
129 public virtual string AnswerLabelText {
131 object obj = ViewState["AnswerLabelText"];
132 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultAnswerLabelText) : (string)obj;
135 ViewState["AnswerLabelText"] = value;
141 /// The text to be shown in the validation summary when the answer is empty.
145 WebCategory("Validation"),
146 WebSysDefaultValue(SR.PasswordRecovery_DefaultAnswerRequiredErrorMessage),
147 WebSysDescription(SR.LoginControls_AnswerRequiredErrorMessage)
149 public virtual string AnswerRequiredErrorMessage {
151 object obj = ViewState["AnswerRequiredErrorMessage"];
152 return (obj == null) ?
153 SR.GetString(SR.PasswordRecovery_DefaultAnswerRequiredErrorMessage) : (string)obj;
156 ViewState["AnswerRequiredErrorMessage"] = value;
162 WebCategory("Appearance"),
164 WebSysDescription(SR.Login_BorderPadding),
165 SuppressMessage("Microsoft.Security", "CA2119:SealMethodsThatSatisfyPrivateInterfaces",
166 Justification = "Interface denotes existence of property, not used for security.")
168 public virtual int BorderPadding {
170 object obj = ViewState["BorderPadding"];
171 return (obj == null) ? 1 : (int)obj;
175 throw new ArgumentOutOfRangeException("value", SR.GetString(SR.PasswordRecovery_InvalidBorderPadding));
177 ViewState["BorderPadding"] = value;
183 /// The style of the submit button.
186 WebCategory("Styles"),
188 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
189 NotifyParentProperty(true),
190 PersistenceMode(PersistenceMode.InnerProperty),
191 WebSysDescription(SR.PasswordRecovery_SubmitButtonStyle)
193 public Style SubmitButtonStyle {
195 if (_submitButtonStyle == null) {
196 _submitButtonStyle = new Style();
197 if (IsTrackingViewState) {
198 ((IStateManager)_submitButtonStyle).TrackViewState();
201 return _submitButtonStyle;
207 /// The type of the submit button.
210 WebCategory("Appearance"),
211 DefaultValue(ButtonType.Button),
212 WebSysDescription(SR.PasswordRecovery_SubmitButtonType)
214 public virtual ButtonType SubmitButtonType {
216 object obj = ViewState["SubmitButtonType"];
217 return (obj == null) ? ButtonType.Button : (ButtonType)obj;
220 if (value < ButtonType.Button || value > ButtonType.Link) {
221 throw new ArgumentOutOfRangeException("value");
223 ViewState["SubmitButtonType"] = value;
227 private bool ConvertingToTemplate {
229 return (DesignMode && _convertingToTemplate);
234 /// Internal because used from PasswordRecoveryAdapter.
236 internal View CurrentView {
241 if (value < View.UserName || value > View.Success) {
242 throw new ArgumentOutOfRangeException("value");
244 if (value != CurrentView) {
245 _currentView = value;
253 /// The style of the failure text.
256 WebCategory("Styles"),
258 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
259 NotifyParentProperty(true),
260 PersistenceMode(PersistenceMode.InnerProperty),
261 WebSysDescription(SR.WebControl_FailureTextStyle)
263 public TableItemStyle FailureTextStyle {
265 if (_failureTextStyle == null) {
266 _failureTextStyle = new ErrorTableItemStyle();
267 if (IsTrackingViewState) {
268 ((IStateManager)_failureTextStyle).TrackViewState();
271 return _failureTextStyle;
277 /// The text to be shown when there is an unexpected failure.
281 WebCategory("Appearance"),
282 WebSysDefaultValue(SR.PasswordRecovery_DefaultGeneralFailureText),
283 WebSysDescription(SR.PasswordRecovery_GeneralFailureText)
285 public virtual string GeneralFailureText {
287 object obj = ViewState["GeneralFailureText"];
288 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultGeneralFailureText) : (string)obj;
291 ViewState["GeneralFailureText"] = value;
297 /// The text to be shown for the help link.
301 WebCategory("Links"),
303 WebSysDescription(SR.ChangePassword_HelpPageText)
305 public virtual string HelpPageText {
307 object obj = ViewState["HelpPageText"];
308 return (obj == null) ? String.Empty : (string)obj;
311 ViewState["HelpPageText"] = value;
316 WebCategory("Links"),
318 WebSysDescription(SR.LoginControls_HelpPageIconUrl),
319 Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
322 public virtual string HelpPageIconUrl {
324 object obj = ViewState["HelpPageIconUrl"];
325 return (obj == null) ? String.Empty : (string)obj;
328 ViewState["HelpPageIconUrl"] = value;
334 /// The URL of the help page.
337 WebCategory("Links"),
339 WebSysDescription(SR.LoginControls_HelpPageUrl),
340 Editor("System.Web.UI.Design.UrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
343 public virtual string HelpPageUrl {
345 object obj = ViewState["HelpPageUrl"];
346 return (obj == null) ? String.Empty : (string)obj;
349 ViewState["HelpPageUrl"] = value;
355 /// The style of the hyperlinks.
358 WebCategory("Styles"),
360 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
361 NotifyParentProperty(true),
362 PersistenceMode(PersistenceMode.InnerProperty),
363 WebSysDescription(SR.WebControl_HyperLinkStyle)
365 public TableItemStyle HyperLinkStyle {
367 if (_hyperLinkStyle == null) {
368 _hyperLinkStyle = new TableItemStyle();
369 if (IsTrackingViewState) {
370 ((IStateManager)_hyperLinkStyle).TrackViewState();
373 return _hyperLinkStyle;
379 /// The style of the instructions.
382 WebCategory("Styles"),
384 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
385 NotifyParentProperty(true),
386 PersistenceMode(PersistenceMode.InnerProperty),
387 WebSysDescription(SR.WebControl_InstructionTextStyle)
389 public TableItemStyle InstructionTextStyle {
391 if (_instructionTextStyle == null) {
392 _instructionTextStyle = new TableItemStyle();
393 if (IsTrackingViewState) {
394 ((IStateManager)_instructionTextStyle).TrackViewState();
397 return _instructionTextStyle;
403 /// The style of the textbox labels.
406 WebCategory("Styles"),
408 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
409 NotifyParentProperty(true),
410 PersistenceMode(PersistenceMode.InnerProperty),
411 WebSysDescription(SR.LoginControls_LabelStyle)
413 public TableItemStyle LabelStyle {
415 if (_labelStyle == null) {
416 _labelStyle = new TableItemStyle();
417 if (IsTrackingViewState) {
418 ((IStateManager)_labelStyle).TrackViewState();
427 /// The content and format of the e-mail message that contains the new password.
430 WebCategory("Behavior"),
431 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
432 NotifyParentProperty(true),
433 PersistenceMode(PersistenceMode.InnerProperty),
435 WebSysDescription(SR.PasswordRecovery_MailDefinition)
437 public MailDefinition MailDefinition {
439 if (_mailDefinition == null) {
440 _mailDefinition = new MailDefinition();
441 if (IsTrackingViewState) {
442 ((IStateManager)_mailDefinition).TrackViewState();
445 return _mailDefinition;
451 /// Gets or sets the name of the membership provider. If null or empty, the default provider is used.
457 WebSysDescription(SR.MembershipProvider_Name)
459 public virtual string MembershipProvider {
461 object obj = ViewState["MembershipProvider"];
462 return (obj == null) ? String.Empty : (string)obj;
465 ViewState["MembershipProvider"] = value;
471 /// The security question.
477 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
479 public virtual string Question {
481 return (_question != null) ? _question : String.Empty;
490 /// The text to be shown when the answer is incorrect.
494 WebCategory("Appearance"),
495 WebSysDefaultValue(SR.PasswordRecovery_DefaultQuestionFailureText),
496 WebSysDescription(SR.PasswordRecovery_QuestionFailureText)
498 public virtual string QuestionFailureText {
500 object obj = ViewState["QuestionFailureText"];
501 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultQuestionFailureText) : (string)obj;
504 ViewState["QuestionFailureText"] = value;
510 /// Text that is displayed to give instructions for answering the question.
514 WebCategory("Appearance"),
515 WebSysDefaultValue(SR.PasswordRecovery_DefaultQuestionInstructionText),
516 WebSysDescription(SR.PasswordRecovery_QuestionInstructionText)
518 public virtual string QuestionInstructionText {
520 object obj = ViewState["QuestionInstructionText"];
521 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultQuestionInstructionText) : (string)obj;
524 ViewState["QuestionInstructionText"] = value;
530 /// The text that identifies the question.
534 WebCategory("Appearance"),
535 WebSysDefaultValue(SR.PasswordRecovery_DefaultQuestionLabelText),
536 WebSysDescription(SR.PasswordRecovery_QuestionLabelText)
538 public virtual string QuestionLabelText {
540 object obj = ViewState["QuestionLabelText"];
541 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultQuestionLabelText) : (string)obj;
544 ViewState["QuestionLabelText"] = value;
550 /// The text to be shown for the title when answering the question.
554 WebCategory("Appearance"),
555 WebSysDefaultValue(SR.PasswordRecovery_DefaultQuestionTitleText),
556 WebSysDescription(SR.PasswordRecovery_QuestionTitleText)
558 public virtual string QuestionTitleText {
560 object obj = ViewState["QuestionTitleText"];
561 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultQuestionTitleText) : (string)obj;
564 ViewState["QuestionTitleText"] = value;
570 /// Template rendered to prompt the user for an answer to the security question.
574 PersistenceMode(PersistenceMode.InnerProperty),
575 TemplateContainer(typeof(PasswordRecovery)),
576 WebSysDescription(SR.PasswordRecovery_QuestionTemplate)
578 public virtual ITemplate QuestionTemplate {
580 return _questionTemplate;
583 _questionTemplate = value;
584 ChildControlsCreated = false;
589 /// Internal because used from PasswordRecoveryAdapter.
593 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
594 WebSysDescription(SR.PasswordRecovery_QuestionTemplateContainer)
596 public Control QuestionTemplateContainer {
598 EnsureChildControls();
599 return _questionContainer;
605 /// The URL of an image to be displayed for the submit button.
608 WebCategory("Appearance"),
610 WebSysDescription(SR.ChangePassword_ChangePasswordButtonImageUrl),
611 Editor("System.Web.UI.Design.ImageUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
614 public virtual string SubmitButtonImageUrl {
616 object obj = ViewState["SubmitButtonImageUrl"];
617 return (obj == null) ? String.Empty : (string)obj;
620 ViewState["SubmitButtonImageUrl"] = value;
626 /// The text to be shown for the submit button.
630 WebCategory("Appearance"),
631 WebSysDefaultValue(SR.PasswordRecovery_DefaultSubmitButtonText),
632 WebSysDescription(SR.ChangePassword_ChangePasswordButtonText)
634 public virtual string SubmitButtonText {
636 object obj = ViewState["SubmitButtonText"];
637 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultSubmitButtonText) : (string)obj;
640 ViewState["SubmitButtonText"] = value;
646 /// The URL that the user is directed to after the password e-mail has been sent.
647 /// If non-null, always redirect the user to this page after successful password recovery. Else, perform the refresh action.
650 WebCategory("Behavior"),
652 WebSysDescription(SR.LoginControls_SuccessPageUrl),
653 Editor("System.Web.UI.Design.UrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
657 public virtual string SuccessPageUrl {
659 object obj = ViewState["SuccessPageUrl"];
660 return (obj == null) ? String.Empty : (string)obj;
663 ViewState["SuccessPageUrl"] = value;
669 /// Template rendered after the e-mail is sent.
673 PersistenceMode(PersistenceMode.InnerProperty),
674 WebSysDescription(SR.PasswordRecovery_SuccessTemplate),
675 TemplateContainer(typeof(PasswordRecovery))
677 public virtual ITemplate SuccessTemplate {
679 return _successTemplate;
682 _successTemplate = value;
683 ChildControlsCreated = false;
688 /// Internal because used from PasswordRecoveryAdapter.
692 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
693 WebSysDescription(SR.PasswordRecovery_SuccessTemplateContainer)
695 public Control SuccessTemplateContainer {
697 EnsureChildControls();
698 return _successContainer;
704 /// The text to be shown after the password e-mail has been sent.
708 WebCategory("Appearance"),
709 WebSysDefaultValue(SR.PasswordRecovery_DefaultSuccessText),
710 WebSysDescription(SR.PasswordRecovery_SuccessText)
712 public virtual string SuccessText {
714 object obj = ViewState["SuccessText"];
715 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultSuccessText) : (string)obj;
718 ViewState["SuccessText"] = value;
724 /// The style of the success text.
727 WebCategory("Styles"),
729 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
730 NotifyParentProperty(true),
731 PersistenceMode(PersistenceMode.InnerProperty),
732 WebSysDescription(SR.PasswordRecovery_SuccessTextStyle)
734 public TableItemStyle SuccessTextStyle {
736 if (_successTextStyle == null) {
737 _successTextStyle = new TableItemStyle();
738 if (IsTrackingViewState) {
739 ((IStateManager)_successTextStyle).TrackViewState();
742 return _successTextStyle;
747 WebCategory("Layout"),
749 WebSysDescription(SR.LoginControls_RenderOuterTable),
750 SuppressMessage("Microsoft.Security", "CA2119:SealMethodsThatSatisfyPrivateInterfaces",
751 Justification = "Interface denotes existence of property, not used for security.")
753 public virtual bool RenderOuterTable {
755 object obj = ViewState["RenderOuterTable"];
756 return (obj == null) ? true : (bool)obj;
759 ViewState["RenderOuterTable"] = value;
763 protected override HtmlTextWriterTag TagKey {
765 return HtmlTextWriterTag.Table;
771 /// The style of the textboxes.
774 WebCategory("Styles"),
776 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
777 NotifyParentProperty(true),
778 PersistenceMode(PersistenceMode.InnerProperty),
779 WebSysDescription(SR.LoginControls_TextBoxStyle)
781 public Style TextBoxStyle {
783 if (_textBoxStyle == null) {
784 _textBoxStyle = new Style();
785 if (IsTrackingViewState) {
786 ((IStateManager)_textBoxStyle).TrackViewState();
789 return _textBoxStyle;
795 /// The layout of the labels in relation to the textboxes.
798 WebCategory("Layout"),
799 DefaultValue(LoginTextLayout.TextOnLeft),
800 WebSysDescription(SR.LoginControls_TextLayout)
802 public virtual LoginTextLayout TextLayout {
804 object obj = ViewState["TextLayout"];
805 return (obj == null) ? LoginTextLayout.TextOnLeft : (LoginTextLayout)obj;
808 if (value < LoginTextLayout.TextOnLeft || value > LoginTextLayout.TextOnTop) {
809 throw new ArgumentOutOfRangeException("value");
811 ViewState["TextLayout"] = value;
812 ChildControlsCreated = false;
818 /// The style of the title.
821 WebCategory("Styles"),
823 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
824 NotifyParentProperty(true),
825 PersistenceMode(PersistenceMode.InnerProperty),
826 WebSysDescription(SR.LoginControls_TitleTextStyle)
828 public TableItemStyle TitleTextStyle {
830 if (_titleTextStyle == null) {
831 _titleTextStyle = new TableItemStyle();
832 if (IsTrackingViewState) {
833 ((IStateManager)_titleTextStyle).TrackViewState();
836 return _titleTextStyle;
842 /// The initial value in the user name textbox.
846 WebCategory("Appearance"),
848 WebSysDescription(SR.UserName_InitialValue)
850 public virtual string UserName {
852 return (_userName == null) ? String.Empty : _userName;
859 internal string UserNameInternal {
861 string userName = UserName;
862 if (String.IsNullOrEmpty(userName) && _userNameContainer != null) {
863 ITextControl textbox = _userNameContainer.UserNameTextBox as ITextControl;
864 if (textbox != null) {
874 /// The text to be shown when the user name is invalid.
878 WebCategory("Appearance"),
879 WebSysDefaultValue(SR.PasswordRecovery_DefaultUserNameFailureText),
880 WebSysDescription(SR.PasswordRecovery_UserNameFailureText)
882 public virtual string UserNameFailureText {
884 object obj = ViewState["UserNameFailureText"];
885 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultUserNameFailureText) : (string)obj;
888 ViewState["UserNameFailureText"] = value;
894 /// Text that is displayed to give instructions for entering the user name.
898 WebCategory("Appearance"),
899 WebSysDefaultValue(SR.PasswordRecovery_DefaultUserNameInstructionText),
900 WebSysDescription(SR.PasswordRecovery_UserNameInstructionText)
902 public virtual string UserNameInstructionText {
904 object obj = ViewState["UserNameInstructionText"];
905 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultUserNameInstructionText) : (string)obj;
908 ViewState["UserNameInstructionText"] = value;
914 /// The text that identifies the user name.
918 WebCategory("Appearance"),
919 WebSysDefaultValue(SR.PasswordRecovery_DefaultUserNameLabelText),
920 WebSysDescription(SR.PasswordRecovery_UserNameLabelText)
922 public virtual string UserNameLabelText {
924 object obj = ViewState["UserNameLabelText"];
925 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultUserNameLabelText) : (string)obj;
928 ViewState["UserNameLabelText"] = value;
934 /// The text to be shown in the validation summary when the user name is empty.
938 WebCategory("Validation"),
939 WebSysDefaultValue(SR.PasswordRecovery_DefaultUserNameRequiredErrorMessage),
940 WebSysDescription(SR.ChangePassword_UserNameRequiredErrorMessage)
942 public virtual string UserNameRequiredErrorMessage {
944 object obj = ViewState["UserNameRequiredErrorMessage"];
945 return (obj == null) ?
946 SR.GetString(SR.PasswordRecovery_DefaultUserNameRequiredErrorMessage) : (string)obj;
949 ViewState["UserNameRequiredErrorMessage"] = value;
955 /// Template rendered to prompt the user to enter a user name.
959 PersistenceMode(PersistenceMode.InnerProperty),
960 TemplateContainer(typeof(PasswordRecovery)),
961 WebSysDescription(SR.PasswordRecovery_UserNameTemplate)
963 public virtual ITemplate UserNameTemplate {
965 return _userNameTemplate;
968 _userNameTemplate = value;
969 ChildControlsCreated = false;
974 /// Internal because used from PasswordRecoveryAdapter.
978 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
979 WebSysDescription(SR.PasswordRecovery_UserNameTemplateContainer)
981 public Control UserNameTemplateContainer {
983 EnsureChildControls();
984 return _userNameContainer;
990 /// The text to be shown for the title when entering the user name.
994 WebCategory("Appearance"),
995 WebSysDefaultValue(SR.PasswordRecovery_DefaultUserNameTitleText),
996 WebSysDescription(SR.PasswordRecovery_UserNameTitleText)
998 public virtual string UserNameTitleText {
1000 object obj = ViewState["UserNameTitleText"];
1001 return (obj == null) ? SR.GetString(SR.PasswordRecovery_DefaultUserNameTitleText) : (string)obj;
1004 ViewState["UserNameTitleText"] = value;
1009 WebCategory("Styles"),
1011 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
1012 NotifyParentProperty(true),
1013 PersistenceMode(PersistenceMode.InnerProperty),
1014 WebSysDescription(SR.ChangePassword_ValidatorTextStyle)
1016 public Style ValidatorTextStyle {
1018 if (_validatorTextStyle == null) {
1019 _validatorTextStyle = new ErrorStyle();
1020 if (IsTrackingViewState) {
1021 ((IStateManager)_validatorTextStyle).TrackViewState();
1024 return _validatorTextStyle;
1031 /// Raised when the answer provided is incorrect.
1034 WebCategory("Action"),
1035 WebSysDescription(SR.PasswordRecovery_AnswerLookupError)
1037 public event EventHandler AnswerLookupError {
1039 Events.AddHandler(EventAnswerLookupError, value);
1042 Events.RemoveHandler(EventAnswerLookupError, value);
1048 /// Raised before the answer is validated.
1051 WebCategory("Action"),
1052 WebSysDescription(SR.PasswordRecovery_VerifyingAnswer)
1054 public event LoginCancelEventHandler VerifyingAnswer {
1056 Events.AddHandler(EventVerifyingAnswer, value);
1059 Events.RemoveHandler(EventVerifyingAnswer, value);
1065 /// Raised before the e-mail is sent.
1068 WebCategory("Action"),
1069 WebSysDescription(SR.PasswordRecovery_SendingMail)
1071 public event MailMessageEventHandler SendingMail {
1073 Events.AddHandler(EventSendingMail, value);
1076 Events.RemoveHandler(EventSendingMail, value);
1081 WebCategory("Action"),
1082 WebSysDescription(SR.CreateUserWizard_SendMailError)
1084 public event SendMailErrorEventHandler SendMailError {
1086 Events.AddHandler(EventSendMailError, value);
1089 Events.RemoveHandler(EventSendMailError, value);
1095 /// Raised before the username is looked up.
1098 WebCategory("Action"),
1099 WebSysDescription(SR.PasswordRecovery_VerifyingUser)
1101 public event LoginCancelEventHandler VerifyingUser {
1103 Events.AddHandler(EventVerifyingUser, value);
1106 Events.RemoveHandler(EventVerifyingUser, value);
1112 /// Raised when the user name is invalid.
1115 WebCategory("Action"),
1116 WebSysDescription(SR.PasswordRecovery_UserLookupError)
1118 public event EventHandler UserLookupError {
1120 Events.AddHandler(EventUserLookupError, value);
1123 Events.RemoveHandler(EventUserLookupError, value);
1128 /// Called when the answer text box changes.
1130 private void AnswerTextChanged(object source, EventArgs e) {
1131 _answer = ((ITextControl)source).Text;
1134 private void AttemptSendPassword() {
1135 if (Page != null && !Page.IsValid) {
1139 if (CurrentView == View.UserName) {
1140 AttemptSendPasswordUserNameView();
1142 else if (CurrentView == View.Question) {
1143 AttemptSendPasswordQuestionView();
1148 /// Called when the user presses submit in the question view.
1149 /// Verifies the answer to the security question. If correct, sends password in e-mail.
1150 /// If answer is incorrect or there is any other error, a failure message is shown.
1152 private void AttemptSendPasswordQuestionView() {
1153 MembershipProvider provider = LoginUtil.GetProvider(MembershipProvider);
1154 MembershipUser user = provider.GetUser(UserNameInternal, /*userIsOnline*/ false, /*throwOnError*/ false);
1156 if (user.IsLockedOut) {
1157 SetFailureTextLabel(_questionContainer, GeneralFailureText);
1161 Question = user.PasswordQuestion;
1162 if (String.IsNullOrEmpty(Question)) {
1163 SetFailureTextLabel(_questionContainer, GeneralFailureText);
1167 LoginCancelEventArgs cancelEventArgs = new LoginCancelEventArgs();
1168 OnVerifyingAnswer(cancelEventArgs);
1169 if (cancelEventArgs.Cancel) {
1173 string answer = AnswerInternal;
1174 string password = null;
1175 string email = user.Email;
1176 // If there is no email address, show the GeneralFailureText and return immediately.
1177 // We must be especially sure we do not reset the password if we do not have an
1178 // email address. (VSWhidbey 387663)
1179 if (String.IsNullOrEmpty(email)) {
1180 SetFailureTextLabel(_questionContainer, GeneralFailureText);
1184 if (provider.EnablePasswordRetrieval) {
1185 password = user.GetPassword(answer, /*throwOnError*/ false);
1187 else if (provider.EnablePasswordReset) {
1188 password = user.ResetPassword(answer, /*throwOnError*/ false);
1191 throw new HttpException(SR.GetString(SR.PasswordRecovery_RecoveryNotSupported));
1194 if (password != null) {
1195 LoginUtil.SendPasswordMail(email, user.UserName, password, MailDefinition,
1196 SR.GetString(SR.PasswordRecovery_DefaultSubject),
1197 SR.GetString(SR.PasswordRecovery_DefaultBody),
1198 OnSendingMail, OnSendMailError, this);
1199 PerformSuccessAction();
1202 OnAnswerLookupError(EventArgs.Empty);
1203 SetFailureTextLabel(_questionContainer, QuestionFailureText);
1207 // If the user lookup fails after it succeeded in the previous view,
1208 // it is considered a general failure
1209 SetFailureTextLabel(_questionContainer, GeneralFailureText);
1214 /// Called when the user presses submit in the user name view.
1215 /// If user name is valid, sends password in e-mail.
1216 /// If user name is invalid or there is any other error, a failure message is shown.
1218 private void AttemptSendPasswordUserNameView() {
1219 LoginCancelEventArgs cancelEventArgs = new LoginCancelEventArgs();
1220 OnVerifyingUser(cancelEventArgs);
1221 if (cancelEventArgs.Cancel) {
1225 MembershipProvider provider = LoginUtil.GetProvider(MembershipProvider);
1226 MembershipUser user = provider.GetUser(UserNameInternal, /*isUserOnline*/ false, /*throwOnError*/ false);
1228 if (user.IsLockedOut) {
1229 SetFailureTextLabel(_userNameContainer, UserNameFailureText);
1233 if (provider.RequiresQuestionAndAnswer) {
1234 Question = user.PasswordQuestion;
1235 if (String.IsNullOrEmpty(Question)) {
1236 SetFailureTextLabel(_userNameContainer, GeneralFailureText);
1239 CurrentView = View.Question;
1242 string password = null;
1243 string email = user.Email;
1244 // If there is no email address, show the GeneralFailureText and return immediately.
1245 // We must be especially sure we do not reset the password if we do not have an
1246 // email address. (VSWhidbey 387663)
1247 if (String.IsNullOrEmpty(email)) {
1248 SetFailureTextLabel(_userNameContainer, GeneralFailureText);
1252 if (provider.EnablePasswordRetrieval) {
1253 password = user.GetPassword(/*throwOnError*/ false);
1255 else if (provider.EnablePasswordReset) {
1256 password = user.ResetPassword(/*throwOnError*/ false);
1259 throw new HttpException(SR.GetString(SR.PasswordRecovery_RecoveryNotSupported));
1262 if (password != null) {
1263 LoginUtil.SendPasswordMail(email, user.UserName, password, MailDefinition,
1264 SR.GetString(SR.PasswordRecovery_DefaultSubject),
1265 SR.GetString(SR.PasswordRecovery_DefaultBody),
1266 OnSendingMail, OnSendMailError, this);
1267 PerformSuccessAction();
1270 SetFailureTextLabel(_userNameContainer, GeneralFailureText);
1275 OnUserLookupError(EventArgs.Empty);
1276 SetFailureTextLabel(_userNameContainer, UserNameFailureText);
1282 /// Instantiates the proper template in the template container, and wires up necessary events.
1284 protected internal override void CreateChildControls() {
1287 CreateQuestionView();
1288 CreateSuccessView();
1291 private void CreateQuestionView() {
1292 ITemplate template = null;
1293 _questionContainer = new QuestionContainer(this);
1294 _questionContainer.ID = _questionContainerID;
1295 _questionContainer.RenderDesignerRegion = _renderDesignerRegion;
1296 if (QuestionTemplate != null) {
1297 template = QuestionTemplate;
1301 template = new DefaultQuestionTemplate(this);
1302 _questionContainer.EnableViewState = false;
1304 // Disable theming if using default template (VSWhidbey 86010)
1305 _questionContainer.EnableTheming = false;
1308 template.InstantiateIn(_questionContainer);
1309 Controls.Add(_questionContainer);
1311 IEditableTextControl answerTextBox = _questionContainer.AnswerTextBox as IEditableTextControl;
1312 if (answerTextBox != null) {
1313 answerTextBox.TextChanged += new EventHandler(AnswerTextChanged);
1317 private void CreateSuccessView() {
1318 ITemplate template = null;
1319 _successContainer = new SuccessContainer(this);
1320 _successContainer.ID = _successContainerID;
1321 _successContainer.RenderDesignerRegion = _renderDesignerRegion;
1322 if (SuccessTemplate != null) {
1323 template = SuccessTemplate;
1327 template = new DefaultSuccessTemplate(this);
1328 _successContainer.EnableViewState = false;
1330 // Disable theming if using default template (VSWhidbey 86010)
1331 _successContainer.EnableTheming = false;
1333 template.InstantiateIn(_successContainer);
1334 Controls.Add(_successContainer);
1337 private void CreateUserView() {
1338 ITemplate template = null;
1339 _userNameContainer = new UserNameContainer(this);
1340 _userNameContainer.ID = _userNameContainerID;
1341 _userNameContainer.RenderDesignerRegion = _renderDesignerRegion;
1342 if (UserNameTemplate != null) {
1343 template = UserNameTemplate;
1347 template = new DefaultUserNameTemplate(this);
1348 _userNameContainer.EnableViewState = false;
1350 // Disable theming if using default template (VSWhidbey 86010)
1351 _userNameContainer.EnableTheming = false;
1354 template.InstantiateIn(_userNameContainer);
1355 Controls.Add(_userNameContainer);
1357 // Set the editable child control properties here for two reasons:
1358 // - So change events will be raised if viewstate is disabled on the child controls
1359 // - Viewstate is always disabled for default template, and might be for user template
1360 // - So the controls render correctly in the designer
1361 SetUserNameEditableChildProperties();
1363 IEditableTextControl userNameTextBox = _userNameContainer.UserNameTextBox as IEditableTextControl;
1364 if (userNameTextBox != null) {
1365 userNameTextBox.TextChanged += new EventHandler(UserNameTextChanged);
1370 /// Loads the control state for those properties that should persist across postbacks
1371 /// even when EnableViewState=false.
1373 protected internal override void LoadControlState(object savedState) {
1374 if (savedState != null) {
1375 Triplet state = (Triplet)savedState;
1376 if (state.First != null) {
1377 base.LoadControlState(state.First);
1379 if (state.Second != null) {
1380 CurrentView = (View)(int)state.Second;
1382 if (state.Third != null) {
1383 _userName = (string)state.Third;
1390 /// Loads a saved state of the <see cref='System.Web.UI.WebControls.Login'/>.
1392 protected override void LoadViewState(object savedState) {
1393 if (savedState == null) {
1394 base.LoadViewState(null);
1397 object[] myState = (object[])savedState;
1398 if (myState.Length != _viewStateArrayLength) {
1399 throw new ArgumentException(SR.GetString(SR.ViewState_InvalidViewState));
1402 base.LoadViewState(myState[0]);
1403 if (myState[1] != null) {
1404 ((IStateManager)SubmitButtonStyle).LoadViewState(myState[1]);
1406 if (myState[2] != null) {
1407 ((IStateManager)LabelStyle).LoadViewState(myState[2]);
1409 if (myState[3] != null) {
1410 ((IStateManager)TextBoxStyle).LoadViewState(myState[3]);
1412 if (myState[4] != null) {
1413 ((IStateManager)HyperLinkStyle).LoadViewState(myState[4]);
1415 if (myState[5] != null) {
1416 ((IStateManager)InstructionTextStyle).LoadViewState(myState[5]);
1418 if (myState[6] != null) {
1419 ((IStateManager)TitleTextStyle).LoadViewState(myState[6]);
1421 if (myState[7] != null) {
1422 ((IStateManager)FailureTextStyle).LoadViewState(myState[7]);
1424 if (myState[8] != null) {
1425 ((IStateManager)SuccessTextStyle).LoadViewState(myState[8]);
1427 if (myState[9] != null) {
1428 ((IStateManager)MailDefinition).LoadViewState(myState[9]);
1430 if (myState[10] != null) {
1431 ((IStateManager)ValidatorTextStyle).LoadViewState(myState[10]);
1438 /// Raises the AnswerLookup event.
1440 protected virtual void OnAnswerLookupError(EventArgs e) {
1441 EventHandler handler = (EventHandler)Events[EventAnswerLookupError];
1442 if (handler != null) {
1449 /// Raises the VerifyingAnswer event.
1451 protected virtual void OnVerifyingAnswer(LoginCancelEventArgs e) {
1452 LoginCancelEventHandler handler = (LoginCancelEventHandler)Events[EventVerifyingAnswer];
1453 if (handler != null) {
1460 /// Raises the SendingMail event.
1462 protected virtual void OnSendingMail(MailMessageEventArgs e) {
1463 MailMessageEventHandler handler = (MailMessageEventHandler)Events[EventSendingMail];
1464 if (handler != null) {
1469 protected virtual void OnSendMailError(SendMailErrorEventArgs e) {
1470 SendMailErrorEventHandler handler = (SendMailErrorEventHandler)Events[EventSendMailError];
1471 if (handler != null) {
1478 /// Raises the VerifyingUser event.
1480 protected virtual void OnVerifyingUser(LoginCancelEventArgs e) {
1481 LoginCancelEventHandler handler = (LoginCancelEventHandler)Events[EventVerifyingUser];
1482 if (handler != null) {
1489 /// Called when an event is raised by a control inside one of our templates. Attempts to send
1490 /// password if the event was raised by the submit button.
1492 protected override bool OnBubbleEvent(object source, EventArgs e) {
1493 bool handled = false;
1494 if (e is CommandEventArgs) {
1495 CommandEventArgs ce = (CommandEventArgs)e;
1496 if (ce.CommandName.Equals(SubmitButtonCommandName, StringComparison.CurrentCultureIgnoreCase)) {
1497 AttemptSendPassword();
1505 protected internal override void OnInit(EventArgs e) {
1507 Page.RegisterRequiresControlState(this);
1508 Page.LoadComplete += new EventHandler(OnPageLoadComplete);
1511 private void OnPageLoadComplete(object sender, EventArgs e) {
1512 if (CurrentView == View.Question) {
1513 // Question will be null if the page was posted back using a control outside the
1514 // PasswordRecovery (VSWhidbey 81302). Load the Question in Page.LoadComplete instead
1515 // of Control.OnPreRender(), so that the Question property is available to the page
1516 // developer earlier in the lifecycle.
1517 if (String.IsNullOrEmpty(Question)) {
1518 MembershipProvider provider = LoginUtil.GetProvider(MembershipProvider);
1519 MembershipUser user = provider.GetUser(UserNameInternal, /*isUserOnline*/ false, /*throwOnError*/ false);
1521 Question = user.PasswordQuestion;
1522 if (String.IsNullOrEmpty(Question)) {
1523 SetFailureTextLabel(_questionContainer, GeneralFailureText);
1527 SetFailureTextLabel(_questionContainer, GeneralFailureText);
1534 /// Overridden to set the editable child control properteries.
1536 protected internal override void OnPreRender(EventArgs e) {
1537 base.OnPreRender(e);
1539 _userNameContainer.Visible = false;
1540 _questionContainer.Visible = false;
1541 _successContainer.Visible = false;
1542 switch (CurrentView) {
1544 _userNameContainer.Visible = true;
1545 // Set the editable child control properties here instead of Render, so they get into viewstate
1546 // for the user template.
1547 SetUserNameEditableChildProperties();
1550 _questionContainer.Visible = true;
1553 _successContainer.Visible = true;
1560 /// Raises the UserLookupError event
1562 protected virtual void OnUserLookupError(EventArgs e) {
1563 EventHandler handler = (EventHandler)Events[EventUserLookupError];
1564 if (handler != null) {
1569 private void PerformSuccessAction() {
1570 string successPageUrl = SuccessPageUrl;
1571 if (!String.IsNullOrEmpty(successPageUrl)) {
1572 // Microsoft suggested that we should not terminate execution of current page, to give
1573 // page a chance to cleanup its resources. This may be less performant though.
1574 // Microsoft suggested that we need to call ResolveClientUrl before redirecting.
1575 // Example is this control inside user control, want redirect relative to user control dir.
1576 Page.Response.Redirect(ResolveClientUrl(successPageUrl), false);
1579 CurrentView = View.Success;
1585 /// Adds the ClientID and renders contents, because we don't want the outer <span>.
1587 protected internal override void Render(HtmlTextWriter writer) {
1589 Page.VerifyRenderingInServerForm(this);
1592 EnsureChildControls();
1595 // Need to redo this for the designer as there's no PreRender(sigh)
1596 _userNameContainer.Visible = false;
1597 _questionContainer.Visible = false;
1598 _successContainer.Visible = false;
1599 switch (CurrentView) {
1601 _userNameContainer.Visible = true;
1604 _questionContainer.Visible = true;
1607 _successContainer.Visible = true;
1612 switch (CurrentView) {
1614 SetUserNameChildProperties();
1617 SetQuestionChildProperties();
1620 SetSuccessChildProperties();
1624 RenderContents(writer);
1628 /// Saves the control state for those properties that should persist across postbacks
1629 /// even when EnableViewState=false.
1631 protected internal override object SaveControlState() {
1632 object baseState = base.SaveControlState();
1633 if (baseState != null || _currentView != 0 || _userName != null) {
1634 // Save the int value of the enum (instead of the enum value itself)
1635 // to save space in ControlState
1636 object currentViewState = null;
1637 object userNameState = null;
1639 if (_currentView != 0) {
1640 currentViewState = (int)_currentView;
1642 // Don't save _userName once we have reached the success view (VSWhidbey 81327)
1643 if (_userName != null && _currentView != View.Success) {
1644 userNameState = _userName;
1646 return new Triplet(baseState, currentViewState, userNameState);
1654 /// Saves the state of the <see cref='System.Web.UI.WebControls.Login'/>.
1656 protected override object SaveViewState() {
1657 object[] myState = new object[_viewStateArrayLength];
1659 myState[0] = base.SaveViewState();
1660 myState[1] = (_submitButtonStyle != null) ? ((IStateManager)_submitButtonStyle).SaveViewState() : null;
1661 myState[2] = (_labelStyle != null) ? ((IStateManager)_labelStyle).SaveViewState() : null;
1662 myState[3] = (_textBoxStyle != null) ? ((IStateManager)_textBoxStyle).SaveViewState() : null;
1663 myState[4] = (_hyperLinkStyle != null) ? ((IStateManager)_hyperLinkStyle).SaveViewState() : null;
1664 myState[5] = (_instructionTextStyle != null) ? ((IStateManager)_instructionTextStyle).SaveViewState() : null;
1665 myState[6] = (_titleTextStyle != null) ? ((IStateManager)_titleTextStyle).SaveViewState() : null;
1666 myState[7] = (_failureTextStyle != null) ? ((IStateManager)_failureTextStyle).SaveViewState() : null;
1667 myState[8] = (_successTextStyle != null) ? ((IStateManager)_successTextStyle).SaveViewState() : null;
1668 myState[9] = (_mailDefinition != null) ? ((IStateManager)_mailDefinition).SaveViewState() : null;
1669 myState[10] = (_validatorTextStyle != null) ? ((IStateManager)_validatorTextStyle).SaveViewState() : null;
1671 for (int i = 0; i < _viewStateArrayLength; i++) {
1672 if (myState[i] != null) {
1677 // More performant to return null than an array of null values
1683 /// Allows the designer to set the CurrentView, so the different templates can be shown in the designer.
1685 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
1686 protected override void SetDesignModeState(IDictionary data) {
1688 object o = data["CurrentView"];
1690 CurrentView = (View)o;
1692 o = data["ConvertToTemplate"];
1694 _convertingToTemplate = (bool)o;
1696 o = data["RegionEditing"];
1698 _renderDesignerRegion = (bool)o;
1704 /// Used frequently, so extracted into method.
1706 private void SetFailureTextLabel(QuestionContainer container, string failureText) {
1707 ITextControl failureTextLabel = (ITextControl)container.FailureTextLabel;
1708 if (failureTextLabel != null) {
1709 failureTextLabel.Text = failureText;
1714 /// Used frequently, so extracted into method.
1716 private void SetFailureTextLabel(UserNameContainer container, string failureText) {
1717 ITextControl failureTextLabel = (ITextControl)container.FailureTextLabel;
1718 if (failureTextLabel != null) {
1719 failureTextLabel.Text = failureText;
1724 /// Internal because called from PasswordRecoveryAdapter.
1726 internal void SetQuestionChildProperties() {
1727 SetQuestionCommonChildProperties();
1728 if (QuestionTemplate == null) {
1729 SetQuestionDefaultChildProperties();
1734 /// Properties that apply to both default and user templates.
1736 private void SetQuestionCommonChildProperties() {
1737 QuestionContainer container = _questionContainer;
1739 // Clear out the tab index so it doesn't get applied to the tables in the container
1740 Util.CopyBaseAttributesToInnerControl(this, container);
1742 container.ApplyStyle(ControlStyle);
1744 // We need to use UserNameInternal for the DropDownList case where it won't fire a TextChanged for the first item
1745 ITextControl userName = (ITextControl)container.UserName;
1746 if (userName != null) {
1747 // VSWhidbey 304890 - Encode the user name
1748 userName.Text = HttpUtility.HtmlEncode(UserNameInternal);
1751 ITextControl question = (ITextControl)container.Question;
1752 if (question != null) {
1753 // VSWhidbey 385802 - Encode the question
1754 question.Text = HttpUtility.HtmlEncode(Question);
1757 ITextControl answerTextBox = (ITextControl)container.AnswerTextBox;
1758 if (answerTextBox != null) {
1759 answerTextBox.Text = String.Empty;
1764 /// Properties that apply to only the default template.
1766 private void SetQuestionDefaultChildProperties() {
1767 QuestionContainer container = _questionContainer;
1769 // Need to set the BorderPadding on the BorderTable instead of the LayoutTable, since
1770 // setting it on the LayoutTable would cause all of the controls inside the Login to be
1771 // separated by the BorderPadding amount.
1772 container.BorderTable.CellPadding = BorderPadding;
1773 container.BorderTable.CellSpacing = 0;
1775 Literal title = container.Title;
1776 string titleText = QuestionTitleText;
1777 if (titleText.Length > 0) {
1778 title.Text = titleText;
1779 if (_titleTextStyle != null) {
1780 LoginUtil.SetTableCellStyle(title, TitleTextStyle);
1782 LoginUtil.SetTableCellVisible(title, true);
1785 LoginUtil.SetTableCellVisible(title, false);
1788 Literal instruction = container.Instruction;
1789 string instructionText = QuestionInstructionText;
1790 if (instructionText.Length > 0) {
1791 instruction.Text = instructionText;
1792 if (_instructionTextStyle != null) {
1793 LoginUtil.SetTableCellStyle(instruction, InstructionTextStyle);
1795 LoginUtil.SetTableCellVisible(instruction, true);
1798 LoginUtil.SetTableCellVisible(instruction, false);
1801 Literal userNameLabel = container.UserNameLabel;
1802 string userNameLabelText = UserNameLabelText;
1803 if (userNameLabelText.Length > 0) {
1804 userNameLabel.Text = userNameLabelText;
1805 if (_labelStyle != null) {
1806 LoginUtil.SetTableCellStyle(userNameLabel, LabelStyle);
1808 userNameLabel.Visible = true;
1811 // DO NOT make the whole table cell invisible, because in some layouts it must exist for things
1812 // to align correctly. Uncommon that this property will be empty anyway.
1813 userNameLabel.Visible = false;
1816 // Do not make this control invisible if its text is empty, because it must be present in the created
1817 // template in the designer. Uncommon that the text will be empty anyway.
1818 Control userName = container.UserName;
1819 if (UserNameInternal.Length > 0) {
1820 userName.Visible = true;
1823 userName.Visible = false;
1825 if (userName is WebControl) ((WebControl)userName).TabIndex = TabIndex;
1827 Literal questionLabel = container.QuestionLabel;
1828 string questionLabelText = QuestionLabelText;
1829 if (questionLabelText.Length > 0) {
1830 questionLabel.Text = questionLabelText;
1831 if (_labelStyle != null) {
1832 LoginUtil.SetTableCellStyle(questionLabel, LabelStyle);
1834 questionLabel.Visible = true;
1837 // DO NOT make the whole table cell invisible, because in some layouts it must exist for things
1838 // to align correctly. Uncommon that this property will be empty anyway.
1839 questionLabel.Visible = false;
1842 // Do not make this control invisible if its text is empty, because it must be present in the created
1843 // template in the designer. Uncommon that the text will be empty anyway.
1844 Control question = container.Question;
1845 if (Question.Length > 0) {
1846 question.Visible = true;
1849 question.Visible = false;
1852 Literal answerLabel = container.AnswerLabel;
1853 string answerLabelText = AnswerLabelText;
1854 if (answerLabelText.Length > 0) {
1855 answerLabel.Text = answerLabelText;
1856 if (_labelStyle != null) {
1857 LoginUtil.SetTableCellStyle(answerLabel, LabelStyle);
1859 answerLabel.Visible = true;
1862 // DO NOT make the whole table cell invisible, because in some layouts it must exist for things
1863 // to align correctly. Uncommon that this property will be empty anyway.
1864 answerLabel.Visible = false;
1867 WebControl answerTextBox = (WebControl)container.AnswerTextBox;
1868 Debug.Assert(answerTextBox != null, "AnswerTextBox cannot be null for the DefaultTemplate");
1869 if (_textBoxStyle != null) {
1870 answerTextBox.ApplyStyle(TextBoxStyle);
1872 answerTextBox.TabIndex = TabIndex;
1873 answerTextBox.AccessKey = AccessKey;
1875 bool enableValidation = (CurrentView == View.Question);
1876 RequiredFieldValidator answerRequired = container.AnswerRequired;
1877 answerRequired.ErrorMessage = AnswerRequiredErrorMessage;
1878 answerRequired.ToolTip = AnswerRequiredErrorMessage;
1879 answerRequired.Enabled = enableValidation;
1880 answerRequired.Visible = enableValidation;
1881 if (_validatorTextStyle != null) {
1882 answerRequired.ApplyStyle(_validatorTextStyle);
1885 LinkButton linkButton = container.LinkButton;
1886 ImageButton imageButton = container.ImageButton;
1887 Button pushButton = container.PushButton;
1889 WebControl button = null;
1890 switch (SubmitButtonType) {
1891 case ButtonType.Link:
1892 linkButton.Text = SubmitButtonText;
1893 button = linkButton;
1895 case ButtonType.Image:
1896 imageButton.ImageUrl = SubmitButtonImageUrl;
1897 imageButton.AlternateText = SubmitButtonText;
1898 button = imageButton;
1900 case ButtonType.Button:
1901 pushButton.Text = SubmitButtonText;
1902 button = pushButton;
1906 // Set all buttons to nonvisible, then set the selected button to visible
1907 linkButton.Visible = false;
1908 imageButton.Visible = false;
1909 pushButton.Visible = false;
1910 button.Visible = true;
1911 button.TabIndex = TabIndex;
1913 if (_submitButtonStyle != null) {
1914 button.ApplyStyle(SubmitButtonStyle);
1917 HyperLink helpPageLink = container.HelpPageLink;
1918 string helpPageText = HelpPageText;
1920 Image helpPageIcon = container.HelpPageIcon;
1921 if (helpPageText.Length > 0) {
1922 helpPageLink.Text = helpPageText;
1923 helpPageLink.NavigateUrl = HelpPageUrl;
1924 helpPageLink.TabIndex = TabIndex;
1925 helpPageLink.Visible = true;
1928 helpPageLink.Visible = false;
1931 string helpPageIconUrl = HelpPageIconUrl;
1932 bool helpPageIconVisible = (helpPageIconUrl.Length > 0);
1933 helpPageIcon.Visible = helpPageIconVisible;
1934 if (helpPageIconVisible) {
1935 helpPageIcon.ImageUrl = helpPageIconUrl;
1936 helpPageIcon.AlternateText = helpPageText;
1939 if (helpPageLink.Visible || helpPageIcon.Visible) {
1940 if (_hyperLinkStyle != null) {
1941 // Apply style except font to table cell, then apply font and forecolor to HyperLinks
1943 TableItemStyle hyperLinkStyleExceptFont = new TableItemStyle();
1944 hyperLinkStyleExceptFont.CopyFrom(HyperLinkStyle);
1945 hyperLinkStyleExceptFont.Font.Reset();
1946 LoginUtil.SetTableCellStyle(helpPageLink, hyperLinkStyleExceptFont);
1947 helpPageLink.Font.CopyFrom(HyperLinkStyle.Font);
1948 helpPageLink.ForeColor = HyperLinkStyle.ForeColor;
1950 LoginUtil.SetTableCellVisible(helpPageLink, true);
1953 LoginUtil.SetTableCellVisible(helpPageLink, false);
1956 Control failureTextLabel = container.FailureTextLabel;
1957 if (((ITextControl)failureTextLabel).Text.Length > 0) {
1958 LoginUtil.SetTableCellStyle(failureTextLabel, FailureTextStyle);
1959 LoginUtil.SetTableCellVisible(failureTextLabel, true);
1962 LoginUtil.SetTableCellVisible(failureTextLabel, false);
1967 /// Internal because called from PasswordRecoveryAdapter.
1969 internal void SetSuccessChildProperties() {
1970 SuccessContainer container = _successContainer;
1972 // Clear out the tab index so it doesn't get applied to the tables in the container
1973 Util.CopyBaseAttributesToInnerControl(this, container);
1975 container.ApplyStyle(ControlStyle);
1977 if (SuccessTemplate == null) {
1978 container.BorderTable.CellPadding = BorderPadding;
1979 container.BorderTable.CellSpacing = 0;
1981 Literal successTextLabel = container.SuccessTextLabel;
1982 string successText = SuccessText;
1983 if (successText.Length > 0) {
1984 successTextLabel.Text = successText;
1985 if (_successTextStyle != null) {
1986 LoginUtil.SetTableCellStyle(successTextLabel, _successTextStyle);
1988 LoginUtil.SetTableCellVisible(successTextLabel, true);
1991 LoginUtil.SetTableCellVisible(successTextLabel, false);
1997 /// Internal because called from PasswordRecoveryAdapter.
1999 internal void SetUserNameChildProperties() {
2000 SetUserNameCommonChildProperties();
2001 if (UserNameTemplate == null) {
2002 SetUserNameDefaultChildProperties();
2007 /// Properties that apply to both default and user templates.
2009 private void SetUserNameCommonChildProperties() {
2010 // Clear out the tab index so it doesn't get applied to the tables in the container
2011 Util.CopyBaseAttributesToInnerControl(this, _userNameContainer);
2013 _userNameContainer.ApplyStyle(ControlStyle);
2017 /// Properties that apply to only the default template.
2019 private void SetUserNameDefaultChildProperties() {
2020 UserNameContainer container = _userNameContainer;
2021 if (UserNameTemplate == null) {
2022 _userNameContainer.BorderTable.CellPadding = BorderPadding;
2023 _userNameContainer.BorderTable.CellSpacing = 0;
2025 Literal title = container.Title;
2026 string titleText = UserNameTitleText;
2027 if (titleText.Length > 0) {
2028 title.Text = titleText;
2029 if (_titleTextStyle != null) {
2030 LoginUtil.SetTableCellStyle(title, TitleTextStyle);
2032 LoginUtil.SetTableCellVisible(title, true);
2035 LoginUtil.SetTableCellVisible(title, false);
2038 Literal instruction = container.Instruction;
2039 string instructionText = UserNameInstructionText;
2040 if (instructionText.Length > 0) {
2041 instruction.Text = instructionText;
2042 if (_instructionTextStyle != null) {
2043 LoginUtil.SetTableCellStyle(instruction, InstructionTextStyle);
2045 LoginUtil.SetTableCellVisible(instruction, true);
2048 LoginUtil.SetTableCellVisible(instruction, false);
2051 Literal userNameLabel = container.UserNameLabel;
2052 string userNameLabelText = UserNameLabelText;
2053 if (userNameLabelText.Length > 0) {
2054 userNameLabel.Text = userNameLabelText;
2055 if (_labelStyle != null) {
2056 LoginUtil.SetTableCellStyle(userNameLabel, LabelStyle);
2058 userNameLabel.Visible = true;
2061 // DO NOT make the whole table cell invisible, because in some layouts it must exist for things
2062 // to align correctly. Uncommon that this property will be empty anyway.
2063 userNameLabel.Visible = false;
2066 WebControl userNameTextBox = (WebControl)container.UserNameTextBox;
2067 Debug.Assert(userNameTextBox != null, "UserNameTextBox cannot be null for the DefaultTemplate");
2068 if (_textBoxStyle != null) {
2069 userNameTextBox.ApplyStyle(TextBoxStyle);
2071 userNameTextBox.TabIndex = TabIndex;
2072 userNameTextBox.AccessKey = AccessKey;
2074 bool enableValidation = (CurrentView == View.UserName);
2075 RequiredFieldValidator userNameRequired = container.UserNameRequired;
2076 userNameRequired.ErrorMessage = UserNameRequiredErrorMessage;
2077 userNameRequired.ToolTip = UserNameRequiredErrorMessage;
2078 userNameRequired.Enabled = enableValidation;
2079 userNameRequired.Visible = enableValidation;
2080 if (_validatorTextStyle != null) {
2081 userNameRequired.ApplyStyle(_validatorTextStyle);
2084 LinkButton linkButton = container.LinkButton;
2085 ImageButton imageButton = container.ImageButton;
2086 Button pushButton = container.PushButton;
2088 WebControl button = null;
2089 switch (SubmitButtonType) {
2090 case ButtonType.Link:
2091 linkButton.Text = SubmitButtonText;
2092 button = linkButton;
2094 case ButtonType.Image:
2095 imageButton.ImageUrl = SubmitButtonImageUrl;
2096 imageButton.AlternateText = SubmitButtonText;
2097 button = imageButton;
2099 case ButtonType.Button:
2100 pushButton.Text = SubmitButtonText;
2101 button = pushButton;
2105 // Set all buttons to nonvisible, then set the selected button to visible
2106 linkButton.Visible = false;
2107 imageButton.Visible = false;
2108 pushButton.Visible = false;
2109 button.Visible = true;
2110 button.TabIndex = TabIndex;
2112 if (_submitButtonStyle != null) {
2113 button.ApplyStyle(SubmitButtonStyle);
2116 HyperLink helpPageLink = container.HelpPageLink;
2117 string helpPageText = HelpPageText;
2119 Image helpPageIcon = container.HelpPageIcon;
2120 if (helpPageText.Length > 0) {
2121 helpPageLink.Text = helpPageText;
2122 helpPageLink.NavigateUrl = HelpPageUrl;
2123 helpPageLink.Visible = true;
2124 helpPageLink.TabIndex = TabIndex;
2127 helpPageLink.Visible = false;
2129 string helpPageIconUrl = HelpPageIconUrl;
2130 bool helpPageIconVisible = (helpPageIconUrl.Length > 0);
2131 helpPageIcon.Visible = helpPageIconVisible;
2132 if (helpPageIconVisible) {
2133 helpPageIcon.ImageUrl = helpPageIconUrl;
2134 helpPageIcon.AlternateText = helpPageText;
2137 if (helpPageLink.Visible || helpPageIcon.Visible) {
2138 if (_hyperLinkStyle != null) {
2139 // Apply style except font to table cell, then apply font and forecolor to HyperLinks
2141 Style hyperLinkStyleExceptFont = new TableItemStyle();
2142 hyperLinkStyleExceptFont.CopyFrom(HyperLinkStyle);
2143 hyperLinkStyleExceptFont.Font.Reset();
2144 LoginUtil.SetTableCellStyle(helpPageLink, hyperLinkStyleExceptFont);
2145 helpPageLink.Font.CopyFrom(HyperLinkStyle.Font);
2146 helpPageLink.ForeColor = HyperLinkStyle.ForeColor;
2148 LoginUtil.SetTableCellVisible(helpPageLink, true);
2151 LoginUtil.SetTableCellVisible(helpPageLink, false);
2154 Control failureTextLabel = container.FailureTextLabel;
2155 if (((ITextControl)failureTextLabel).Text.Length > 0) {
2156 LoginUtil.SetTableCellStyle(failureTextLabel, FailureTextStyle);
2157 LoginUtil.SetTableCellVisible(failureTextLabel, true);
2160 LoginUtil.SetTableCellVisible(failureTextLabel, false);
2166 /// Called from CreateChildControls and PreRender
2167 // - So change events will be raised if viewstate is disabled on the child controls
2168 // - Viewstate is always disabled for default template, and might be for user template
2169 // - So the controls render correctly in the designer
2171 private void SetUserNameEditableChildProperties() {
2172 // We need to use UserNameInternal for the DropDownList case where it won't fire a TextChanged for the first item
2173 string userName = UserNameInternal;
2174 if (userName.Length > 0) {
2175 ITextControl userNameTextBox = (ITextControl)_userNameContainer.UserNameTextBox;
2176 // UserNameTextBox is a required control, but it may be null at design-time
2177 if (userNameTextBox != null) {
2178 userNameTextBox.Text = userName;
2185 /// Marks the starting point to begin tracking and saving changes to the
2186 /// control as part of the control viewstate.
2188 protected override void TrackViewState() {
2189 base.TrackViewState();
2191 if (_submitButtonStyle != null) {
2192 ((IStateManager)_submitButtonStyle).TrackViewState();
2194 if (_labelStyle != null) {
2195 ((IStateManager)_labelStyle).TrackViewState();
2197 if (_textBoxStyle != null) {
2198 ((IStateManager)_textBoxStyle).TrackViewState();
2200 if (_hyperLinkStyle != null) {
2201 ((IStateManager)_hyperLinkStyle).TrackViewState();
2203 if (_instructionTextStyle != null) {
2204 ((IStateManager)_instructionTextStyle).TrackViewState();
2206 if (_titleTextStyle != null) {
2207 ((IStateManager)_titleTextStyle).TrackViewState();
2209 if (_failureTextStyle != null) {
2210 ((IStateManager)_failureTextStyle).TrackViewState();
2212 if (_successTextStyle != null) {
2213 ((IStateManager)_successTextStyle).TrackViewState();
2215 if (_mailDefinition != null) {
2216 ((IStateManager)_mailDefinition).TrackViewState();
2218 if (_validatorTextStyle != null) {
2219 ((IStateManager)_validatorTextStyle).TrackViewState();
2223 private void UpdateValidators() {
2224 if (UserNameTemplate == null && _userNameContainer != null) {
2225 bool enabled = (CurrentView == View.UserName);
2226 _userNameContainer.UserNameRequired.Enabled = enabled;
2227 _userNameContainer.UserNameRequired.Visible = enabled;
2229 if (QuestionTemplate == null && _questionContainer != null) {
2230 bool enabled = (CurrentView == View.Question);
2231 _questionContainer.AnswerRequired.Enabled = enabled;
2232 _questionContainer.AnswerRequired.Visible = enabled;
2237 /// Called when the answer text box changes.
2239 private void UserNameTextChanged(object source, EventArgs e) {
2240 UserName = ((ITextControl)source).Text;
2244 /// The default question template for the control, used if QuestionTemplate is null.
2246 private sealed class DefaultQuestionTemplate : ITemplate {
2247 private PasswordRecovery _owner;
2249 public DefaultQuestionTemplate(PasswordRecovery owner) {
2254 /// Creates the child controls, sets certain properties (mostly static properties)
2256 private void CreateControls(QuestionContainer questionContainer) {
2257 string validationGroup = _owner.UniqueID;
2259 questionContainer.Title = new Literal();
2260 questionContainer.Instruction = new Literal();
2261 questionContainer.UserNameLabel = new Literal();
2262 questionContainer.UserName = new Literal();
2263 questionContainer.QuestionLabel = new Literal();
2264 questionContainer.Question = new Literal();
2266 // Needed for "convert to template" feature
2267 questionContainer.UserName.ID = _userNameID;
2268 questionContainer.Question.ID = _questionID;
2270 TextBox answerTextBox = new TextBox();
2271 answerTextBox.ID = _answerID;
2272 questionContainer.AnswerTextBox = answerTextBox;
2273 questionContainer.AnswerLabel = new LabelLiteral(answerTextBox);
2275 bool enableValidation = (_owner.CurrentView == View.Question);
2276 RequiredFieldValidator answerRequired = new RequiredFieldValidator();
2277 answerRequired.ID = _answerRequiredID;
2278 answerRequired.ValidationGroup = validationGroup;
2279 answerRequired.ControlToValidate = answerTextBox.ID;
2280 answerRequired.Display = _requiredFieldValidatorDisplay;
2281 answerRequired.Text = SR.GetString(SR.LoginControls_DefaultRequiredFieldValidatorText);
2282 answerRequired.Enabled = enableValidation;
2283 answerRequired.Visible = enableValidation;
2284 questionContainer.AnswerRequired = answerRequired;
2286 LinkButton linkButton = new LinkButton();
2287 linkButton.ID = _linkButtonID;
2288 linkButton.ValidationGroup = validationGroup;
2289 linkButton.CommandName = SubmitButtonCommandName;
2290 questionContainer.LinkButton = linkButton;
2292 ImageButton imageButton = new ImageButton();
2293 imageButton.ID = _imageButtonID;
2294 imageButton.ValidationGroup = validationGroup;
2295 imageButton.CommandName = SubmitButtonCommandName;
2296 questionContainer.ImageButton = imageButton;
2298 Button pushButton = new Button();
2299 pushButton.ID = _pushButtonID;
2300 pushButton.ValidationGroup = validationGroup;
2301 pushButton.CommandName = SubmitButtonCommandName;
2302 questionContainer.PushButton = pushButton;
2304 questionContainer.HelpPageLink = new HyperLink();
2305 questionContainer.HelpPageLink.ID = _helpLinkID;
2306 questionContainer.HelpPageIcon = new Image();
2308 Literal failureTextLabel = new Literal();
2309 failureTextLabel.ID = _failureTextID;
2310 questionContainer.FailureTextLabel = failureTextLabel;
2314 /// Adds the controls to a table for layout. Layout depends on TextLayout.
2316 private void LayoutControls(QuestionContainer questionContainer) {
2317 LoginTextLayout textLayout = _owner.TextLayout;
2318 if (textLayout == LoginTextLayout.TextOnLeft) {
2319 LayoutTextOnLeft(questionContainer);
2322 LayoutTextOnTop(questionContainer);
2326 private void LayoutTextOnLeft(QuestionContainer questionContainer) {
2327 Table table = new Table();
2328 table.CellPadding = 0;
2332 r = new LoginUtil.DisappearingTableRow();
2333 c = new TableCell();
2335 c.HorizontalAlign = HorizontalAlign.Center;
2336 c.Controls.Add(questionContainer.Title);
2340 r = new LoginUtil.DisappearingTableRow();
2341 c = new TableCell();
2343 c.HorizontalAlign = HorizontalAlign.Center;
2344 c.Controls.Add(questionContainer.Instruction);
2348 r = new LoginUtil.DisappearingTableRow();
2349 c = new TableCell();
2350 c.HorizontalAlign = HorizontalAlign.Right;
2351 c.Controls.Add(questionContainer.UserNameLabel);
2354 c = new TableCell();
2355 c.Controls.Add(questionContainer.UserName);
2359 r = new LoginUtil.DisappearingTableRow();
2360 c = new TableCell();
2361 c.HorizontalAlign = HorizontalAlign.Right;
2362 c.Controls.Add(questionContainer.QuestionLabel);
2365 c = new TableCell();
2366 c.Controls.Add(questionContainer.Question);
2370 r = new LoginUtil.DisappearingTableRow();
2371 c = new TableCell();
2372 c.HorizontalAlign = HorizontalAlign.Right;
2373 c.Controls.Add(questionContainer.AnswerLabel);
2374 if (_owner.ConvertingToTemplate) {
2375 questionContainer.AnswerLabel.RenderAsLabel = true;
2379 c = new TableCell();
2380 c.Controls.Add(questionContainer.AnswerTextBox);
2381 c.Controls.Add(questionContainer.AnswerRequired);
2385 r = new LoginUtil.DisappearingTableRow();
2386 c = new TableCell();
2388 c.HorizontalAlign = HorizontalAlign.Center;
2389 c.Controls.Add(questionContainer.FailureTextLabel);
2393 r = new LoginUtil.DisappearingTableRow();
2394 c = new TableCell();
2396 c.HorizontalAlign = HorizontalAlign.Right;
2397 c.Controls.Add(questionContainer.LinkButton);
2398 c.Controls.Add(questionContainer.ImageButton);
2399 c.Controls.Add(questionContainer.PushButton);
2403 r = new LoginUtil.DisappearingTableRow();
2404 c = new TableCell();
2406 c.Controls.Add(questionContainer.HelpPageIcon);
2407 c.Controls.Add(questionContainer.HelpPageLink);
2411 Table table2 = LoginUtil.CreateChildTable(_owner.ConvertingToTemplate);
2413 c = new TableCell();
2414 c.Controls.Add(table);
2418 questionContainer.LayoutTable = table;
2419 questionContainer.BorderTable = table2;
2420 questionContainer.Controls.Add(table2);
2423 private void LayoutTextOnTop(QuestionContainer questionContainer) {
2424 Table table = new Table();
2425 table.CellPadding = 0;
2429 r = new LoginUtil.DisappearingTableRow();
2430 c = new TableCell();
2431 c.HorizontalAlign = HorizontalAlign.Center;
2432 c.Controls.Add(questionContainer.Title);
2436 r = new LoginUtil.DisappearingTableRow();
2437 c = new TableCell();
2438 c.HorizontalAlign = HorizontalAlign.Center;
2439 c.Controls.Add(questionContainer.Instruction);
2443 r = new LoginUtil.DisappearingTableRow();
2444 c = new TableCell();
2445 c.Controls.Add(questionContainer.UserNameLabel);
2449 r = new LoginUtil.DisappearingTableRow();
2450 c = new TableCell();
2451 c.Controls.Add(questionContainer.UserName);
2455 r = new LoginUtil.DisappearingTableRow();
2456 c = new TableCell();
2457 c.Controls.Add(questionContainer.QuestionLabel);
2461 r = new LoginUtil.DisappearingTableRow();
2462 c = new TableCell();
2463 c.Controls.Add(questionContainer.Question);
2467 r = new LoginUtil.DisappearingTableRow();
2468 c = new TableCell();
2469 c.Controls.Add(questionContainer.AnswerLabel);
2470 if (_owner.ConvertingToTemplate) {
2471 questionContainer.AnswerLabel.RenderAsLabel = true;
2476 r = new LoginUtil.DisappearingTableRow();
2477 c = new TableCell();
2478 c.Controls.Add(questionContainer.AnswerTextBox);
2479 c.Controls.Add(questionContainer.AnswerRequired);
2483 r = new LoginUtil.DisappearingTableRow();
2484 c = new TableCell();
2485 c.HorizontalAlign = HorizontalAlign.Center;
2486 c.Controls.Add(questionContainer.FailureTextLabel);
2490 r = new LoginUtil.DisappearingTableRow();
2491 c = new TableCell();
2492 c.HorizontalAlign = HorizontalAlign.Right;
2493 c.Controls.Add(questionContainer.LinkButton);
2494 c.Controls.Add(questionContainer.ImageButton);
2495 c.Controls.Add(questionContainer.PushButton);
2499 r = new LoginUtil.DisappearingTableRow();
2500 c = new TableCell();
2501 c.Controls.Add(questionContainer.HelpPageIcon);
2502 c.Controls.Add(questionContainer.HelpPageLink);
2506 Table table2 = LoginUtil.CreateChildTable(_owner.ConvertingToTemplate);
2508 c = new TableCell();
2509 c.Controls.Add(table);
2513 questionContainer.LayoutTable = table;
2514 questionContainer.BorderTable = table2;
2515 questionContainer.Controls.Add(table2);
2518 void ITemplate.InstantiateIn(Control container) {
2519 QuestionContainer questionContainer = (QuestionContainer)container;
2520 CreateControls(questionContainer);
2521 LayoutControls(questionContainer);
2526 /// The default success template for the control, used if SuccessTemplate is null.
2528 private sealed class DefaultSuccessTemplate : ITemplate {
2529 private PasswordRecovery _owner;
2531 public DefaultSuccessTemplate(PasswordRecovery owner) {
2535 private void CreateControls(SuccessContainer successContainer) {
2536 successContainer.SuccessTextLabel = new Literal();
2539 private void LayoutControls(SuccessContainer successContainer) {
2540 Table table = new Table();
2541 table.CellPadding = 0;
2542 TableRow r = new LoginUtil.DisappearingTableRow();
2543 TableCell c = new TableCell();
2545 c.Controls.Add(successContainer.SuccessTextLabel);
2549 // Extra table for border padding
2550 Table table2 = LoginUtil.CreateChildTable(_owner.ConvertingToTemplate);
2552 c = new TableCell();
2553 c.Controls.Add(table);
2557 successContainer.LayoutTable = table;
2558 successContainer.BorderTable = table2;
2559 successContainer.Controls.Add(table2);
2562 void ITemplate.InstantiateIn(Control container) {
2563 SuccessContainer successContainer = (SuccessContainer)container;
2564 CreateControls(successContainer);
2565 LayoutControls(successContainer);
2570 /// The default user name template for the control, used if UserNameTemplate is null.
2572 private sealed class DefaultUserNameTemplate : ITemplate {
2573 private PasswordRecovery _owner;
2575 public DefaultUserNameTemplate(PasswordRecovery owner) {
2579 private void CreateControls(UserNameContainer userNameContainer) {
2580 string validationGroup = _owner.UniqueID;
2582 userNameContainer.Title = new Literal();
2583 userNameContainer.Instruction = new Literal();
2585 TextBox userNameTextBox = new TextBox();
2586 // Must explicitly set the ID of controls that raise postback events
2587 userNameTextBox.ID = _userNameID;
2588 userNameContainer.UserNameTextBox = userNameTextBox;
2589 userNameContainer.UserNameLabel = new LabelLiteral(userNameTextBox);
2591 bool enableValidation = (_owner.CurrentView == View.UserName);
2592 RequiredFieldValidator userNameRequired = new RequiredFieldValidator();
2593 userNameRequired.ID = _userNameRequiredID;
2594 userNameRequired.ValidationGroup = validationGroup;
2595 userNameRequired.ControlToValidate = userNameTextBox.ID;
2596 userNameRequired.Display = _requiredFieldValidatorDisplay;
2597 userNameRequired.Text = SR.GetString(SR.LoginControls_DefaultRequiredFieldValidatorText);
2598 userNameRequired.Enabled = enableValidation;
2599 userNameRequired.Visible = enableValidation;
2600 userNameContainer.UserNameRequired = userNameRequired;
2602 LinkButton linkButton = new LinkButton();
2603 linkButton.ID = _linkButtonID;
2604 linkButton.ValidationGroup = validationGroup;
2605 linkButton.CommandName = SubmitButtonCommandName;
2606 userNameContainer.LinkButton = linkButton;
2608 ImageButton imageButton = new ImageButton();
2609 imageButton.ID = _imageButtonID;
2610 imageButton.ValidationGroup = validationGroup;
2611 imageButton.CommandName = SubmitButtonCommandName;
2612 userNameContainer.ImageButton = imageButton;
2614 Button pushButton = new Button();
2615 pushButton.ID = _pushButtonID;
2616 pushButton.ValidationGroup = validationGroup;
2617 pushButton.CommandName = SubmitButtonCommandName;
2618 userNameContainer.PushButton = pushButton;
2620 userNameContainer.HelpPageLink = new HyperLink();
2621 userNameContainer.HelpPageLink.ID = _helpLinkID;
2622 userNameContainer.HelpPageIcon = new Image();
2624 Literal failureTextLabel = new Literal();
2625 failureTextLabel.ID = _failureTextID;
2626 userNameContainer.FailureTextLabel = failureTextLabel;
2629 private void LayoutControls(UserNameContainer userNameContainer) {
2630 LoginTextLayout textLayout = _owner.TextLayout;
2631 if (textLayout == LoginTextLayout.TextOnLeft) {
2632 LayoutTextOnLeft(userNameContainer);
2635 LayoutTextOnTop(userNameContainer);
2639 private void LayoutTextOnLeft(UserNameContainer userNameContainer) {
2640 Table table = new Table();
2641 table.CellPadding = 0;
2645 r = new LoginUtil.DisappearingTableRow();
2646 c = new TableCell();
2648 c.HorizontalAlign = HorizontalAlign.Center;
2649 c.Controls.Add(userNameContainer.Title);
2653 r = new LoginUtil.DisappearingTableRow();
2654 c = new TableCell();
2656 c.HorizontalAlign = HorizontalAlign.Center;
2657 c.Controls.Add(userNameContainer.Instruction);
2661 r = new LoginUtil.DisappearingTableRow();
2662 c = new TableCell();
2663 c.HorizontalAlign = HorizontalAlign.Right;
2664 c.Controls.Add(userNameContainer.UserNameLabel);
2665 if (_owner.ConvertingToTemplate) {
2666 userNameContainer.UserNameLabel.RenderAsLabel = true;
2670 c = new TableCell();
2671 c.Controls.Add(userNameContainer.UserNameTextBox);
2672 c.Controls.Add(userNameContainer.UserNameRequired);
2676 r = new LoginUtil.DisappearingTableRow();
2677 c = new TableCell();
2679 c.HorizontalAlign = HorizontalAlign.Center;
2680 c.Controls.Add(userNameContainer.FailureTextLabel);
2684 r = new LoginUtil.DisappearingTableRow();
2685 c = new TableCell();
2687 c.HorizontalAlign = HorizontalAlign.Right;
2688 c.Controls.Add(userNameContainer.LinkButton);
2689 c.Controls.Add(userNameContainer.ImageButton);
2690 c.Controls.Add(userNameContainer.PushButton);
2694 r = new LoginUtil.DisappearingTableRow();
2695 c = new TableCell();
2697 c.Controls.Add(userNameContainer.HelpPageIcon);
2698 c.Controls.Add(userNameContainer.HelpPageLink);
2702 Table table2 = LoginUtil.CreateChildTable(_owner.ConvertingToTemplate);
2704 c = new TableCell();
2705 c.Controls.Add(table);
2709 userNameContainer.LayoutTable = table;
2710 userNameContainer.BorderTable = table2;
2711 userNameContainer.Controls.Add(table2);
2714 private void LayoutTextOnTop(UserNameContainer userNameContainer) {
2715 Table table = new Table();
2716 table.CellPadding = 0;
2720 r = new LoginUtil.DisappearingTableRow();
2721 c = new TableCell();
2722 c.HorizontalAlign = HorizontalAlign.Center;
2723 c.Controls.Add(userNameContainer.Title);
2727 r = new LoginUtil.DisappearingTableRow();
2728 c = new TableCell();
2729 c.HorizontalAlign = HorizontalAlign.Center;
2730 c.Controls.Add(userNameContainer.Instruction);
2734 r = new LoginUtil.DisappearingTableRow();
2735 c = new TableCell();
2736 c.Controls.Add(userNameContainer.UserNameLabel);
2737 if (_owner.ConvertingToTemplate) {
2738 userNameContainer.UserNameLabel.RenderAsLabel = true;
2743 r = new LoginUtil.DisappearingTableRow();
2744 c = new TableCell();
2745 c.Controls.Add(userNameContainer.UserNameTextBox);
2746 c.Controls.Add(userNameContainer.UserNameRequired);
2750 r = new LoginUtil.DisappearingTableRow();
2751 c = new TableCell();
2752 c.HorizontalAlign = HorizontalAlign.Center;
2753 c.Controls.Add(userNameContainer.FailureTextLabel);
2757 r = new LoginUtil.DisappearingTableRow();
2758 c = new TableCell();
2759 c.HorizontalAlign = HorizontalAlign.Right;
2760 c.Controls.Add(userNameContainer.LinkButton);
2761 c.Controls.Add(userNameContainer.ImageButton);
2762 c.Controls.Add(userNameContainer.PushButton);
2766 r = new LoginUtil.DisappearingTableRow();
2767 c = new TableCell();
2768 c.Controls.Add(userNameContainer.HelpPageIcon);
2769 c.Controls.Add(userNameContainer.HelpPageLink);
2773 Table table2 = LoginUtil.CreateChildTable(_owner.ConvertingToTemplate);
2775 c = new TableCell();
2776 c.Controls.Add(table);
2780 userNameContainer.LayoutTable = table;
2781 userNameContainer.BorderTable = table2;
2782 userNameContainer.Controls.Add(table2);
2785 void ITemplate.InstantiateIn(Control container) {
2786 UserNameContainer userNameContainer = (UserNameContainer)container;
2787 CreateControls(userNameContainer);
2788 LayoutControls(userNameContainer);
2794 /// Container for the question template. Contains properties that reference each child control.
2795 /// For the default template, the properties are set when the child controls are created.
2796 /// For the user template, the controls are looked up dynamically by ID. Some controls are required,
2797 /// and an exception is thrown if they are missing. Other controls are optional, and an exception is
2798 /// thrown if they have the wrong type.
2799 /// Internal instead of private because it must be used by PasswordRecoveryAdapter.
2801 internal sealed class QuestionContainer : LoginUtil.GenericContainer<PasswordRecovery>, INonBindingContainer {
2802 private LabelLiteral _answerLabel;
2803 private RequiredFieldValidator _answerRequired;
2804 private Control _answerTextBox;
2805 private Control _failureTextLabel;
2806 private HyperLink _helpPageLink;
2807 private Image _helpPageIcon;
2808 private ImageButton _imageButton;
2809 private Literal _instruction;
2810 private LinkButton _linkButton;
2811 private Button _pushButton;
2812 private Control _question;
2813 private Literal _questionLabel;
2814 private Literal _title;
2815 private Literal _userNameLabel;
2816 private Control _userName;
2818 public QuestionContainer(PasswordRecovery owner) : base(owner) {
2821 public LabelLiteral AnswerLabel {
2823 return _answerLabel;
2826 _answerLabel = value;
2830 public RequiredFieldValidator AnswerRequired {
2832 return _answerRequired;
2836 _answerRequired = value;
2840 public Control AnswerTextBox {
2842 if (_answerTextBox != null) {
2843 return _answerTextBox;
2846 return FindRequiredControl<IEditableTextControl>(_answerID, SR.PasswordRecovery_NoAnswerTextBox);
2850 _answerTextBox = value;
2854 protected override bool ConvertingToTemplate {
2856 return Owner.ConvertingToTemplate;
2860 public Control FailureTextLabel {
2862 if (_failureTextLabel != null) {
2863 return _failureTextLabel;
2866 return FindOptionalControl<ITextControl>(_failureTextID);
2870 _failureTextLabel = value;
2874 public Image HelpPageIcon {
2876 return _helpPageIcon;
2879 _helpPageIcon = value;
2883 public HyperLink HelpPageLink {
2885 return _helpPageLink;
2888 _helpPageLink = value;
2892 public ImageButton ImageButton {
2894 return _imageButton;
2897 _imageButton = value;
2901 public Literal Instruction {
2903 return _instruction;
2906 _instruction = value;
2910 public LinkButton LinkButton {
2915 _linkButton = value;
2919 public Button PushButton {
2924 _pushButton = value;
2928 public Control Question {
2930 if (_question != null) {
2934 return FindOptionalControl<ITextControl>(_questionID);
2942 public Literal QuestionLabel {
2944 return _questionLabel;
2947 _questionLabel = value;
2951 public Literal Title {
2960 public Control UserName {
2962 if (_userName != null) {
2966 return FindOptionalControl<ITextControl>(_userNameID);
2974 public Literal UserNameLabel {
2976 return _userNameLabel;
2979 _userNameLabel = value;
2985 /// Container for the success template.
2986 /// Internal instead of private because it must be used by PasswordRecoveryAdapter.
2988 internal sealed class SuccessContainer : LoginUtil.GenericContainer<PasswordRecovery>, INonBindingContainer {
2989 private Literal _successTextLabel;
2991 public SuccessContainer(PasswordRecovery owner) : base(owner) {
2994 protected override bool ConvertingToTemplate {
2996 return Owner.ConvertingToTemplate;
3000 public Literal SuccessTextLabel {
3002 return _successTextLabel;
3005 _successTextLabel = value;
3011 /// Container for the user name template. Contains properties that reference each child control.
3012 /// For the default template, the properties are set when the child controls are created.
3013 /// For the user template, the controls are looked up dynamically by ID. Some controls are required,
3014 /// and an exception is thrown if they are missing. Other controls are optional, and an exception is
3015 /// thrown if they have the wrong type.
3016 /// Internal instead of private because it must be used by PasswordRecoveryAdapter.
3018 internal sealed class UserNameContainer : LoginUtil.GenericContainer<PasswordRecovery>, INonBindingContainer {
3019 private Control _failureTextLabel;
3020 private Image _helpPageIcon;
3021 private HyperLink _helpPageLink;
3022 private ImageButton _imageButton;
3023 private Literal _instruction;
3024 private LinkButton _linkButton;
3025 private Button _pushButton;
3026 private Literal _title;
3027 private LabelLiteral _userNameLabel;
3028 private RequiredFieldValidator _userNameRequired;
3029 private Control _userNameTextBox;
3031 public UserNameContainer(PasswordRecovery owner) : base(owner) {
3034 protected override bool ConvertingToTemplate {
3036 return Owner.ConvertingToTemplate;
3040 public Control FailureTextLabel {
3042 if (_failureTextLabel != null) {
3043 return _failureTextLabel;
3046 return FindOptionalControl<ITextControl>(_failureTextID);
3050 _failureTextLabel = value;
3054 public Image HelpPageIcon {
3056 return _helpPageIcon;
3059 _helpPageIcon = value;
3063 public HyperLink HelpPageLink {
3065 return _helpPageLink;
3068 _helpPageLink = value;
3072 public ImageButton ImageButton {
3074 return _imageButton;
3077 _imageButton = value;
3081 public Literal Instruction {
3083 return _instruction;
3086 _instruction = value;
3090 public LinkButton LinkButton {
3095 _linkButton = value;
3099 public Button PushButton {
3104 _pushButton = value;
3108 public Literal Title {
3117 public LabelLiteral UserNameLabel {
3119 return _userNameLabel;
3122 _userNameLabel = value;
3126 public RequiredFieldValidator UserNameRequired {
3128 return _userNameRequired;
3132 _userNameRequired = value;
3136 public Control UserNameTextBox {
3138 if (_userNameTextBox != null) {
3139 return _userNameTextBox;
3142 return FindRequiredControl<IEditableTextControl>(_userNameID, SR.PasswordRecovery_NoUserNameTextBox);
3146 _userNameTextBox = value;
3152 /// Internal because used from PasswordRecoveryAdapter
3154 internal enum View {