2 // System.Web.UI.WebControls.BaseValidator
5 // Chris Toshok (toshok@novell.com)
7 // (C) 2005-2010 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Web.Configuration;
30 using System.ComponentModel;
32 using System.Reflection;
33 using System.Collections;
34 using System.Security.Permissions;
36 namespace System.Web.UI.WebControls
39 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
40 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
42 [DefaultProperty("ErrorMessage")]
43 [Designer("System.Web.UI.Design.WebControls.BaseValidatorDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
44 public abstract class BaseValidator : Label, IValidator
49 bool pre_render_called = false;
51 protected BaseValidator ()
54 this.ForeColor = Color.Red;
59 [EditorBrowsable(EditorBrowsableState.Never)]
60 public override string AssociatedControlID {
61 get { return base.AssociatedControlID; }
62 set { base.AssociatedControlID = value; }
67 public virtual string ValidationGroup {
68 get { return ViewState.GetString ("ValidationGroup", String.Empty); }
69 set { ViewState["ValidationGroup"] = value; }
73 [DefaultValue (false)]
74 public bool SetFocusOnError {
75 get { return ViewState.GetBool ("SetFocusOnError", false); }
76 set { ViewState["SetFocusOnError"] = value; }
79 /* listed in corcompare */
80 [MonoTODO("Why override?")]
81 [PersistenceMode (PersistenceMode.InnerDefaultProperty)]
83 public override string Text
85 get { return base.Text; }
86 set { base.Text = value; }
89 [IDReferenceProperty (typeof (Control))]
91 [TypeConverter(typeof(System.Web.UI.WebControls.ValidatedControlConverter))]
93 [WebSysDescription ("")]
94 [WebCategory ("Behavior")]
95 public string ControlToValidate {
96 get { return ViewState.GetString ("ControlToValidate", String.Empty); }
97 set { ViewState ["ControlToValidate"] = value; }
101 [DefaultValue(ValidatorDisplay.Static)]
102 [WebSysDescription ("")]
103 [WebCategory ("Appearance")]
104 public ValidatorDisplay Display {
105 get { return (ValidatorDisplay)ViewState.GetInt ("Display", (int)ValidatorDisplay.Static); }
106 set { ViewState ["Display"] = (int)value; }
111 [WebSysDescription ("")]
112 [WebCategory ("Behavior")]
113 public bool EnableClientScript {
114 get { return ViewState.GetBool ("EnableClientScript", true); }
115 set { ViewState ["EnableClientScript"] = value; }
118 public override bool Enabled {
119 get { return ViewState.GetBool ("BaseValidatorEnabled", true); }
120 set { ViewState ["BaseValidatorEnabled"] = value; }
125 [WebSysDescription ("")]
126 [WebCategory ("Appearance")]
127 public string ErrorMessage {
128 get { return ViewState.GetString ("ErrorMessage", String.Empty); }
129 set { ViewState ["ErrorMessage"] = value; }
132 [DefaultValue(typeof (Color), "Red")]
133 public override Color ForeColor {
134 get { return forecolor; }
137 base.ForeColor = value;
144 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
145 [WebSysDescription ("")]
146 [WebCategory ("Misc")]
147 public bool IsValid {
148 get { return valid; }
149 set { valid = value; }
152 protected bool PropertiesValid {
154 Control control = NamingContainer.FindControl (ControlToValidate);
162 protected bool RenderUplevel {
163 get { return render_uplevel; }
166 internal bool GetRenderUplevel ()
168 return render_uplevel;
171 protected override void AddAttributesToRender (HtmlTextWriter writer)
173 /* if we're rendering uplevel, add our attributes */
174 if (render_uplevel) {
175 /* force an ID here if we weren't assigned one */
177 writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
179 if (ControlToValidate != String.Empty)
180 RegisterExpandoAttribute (ClientID, "controltovalidate", GetControlRenderID (ControlToValidate));
182 if (ErrorMessage != String.Empty)
183 RegisterExpandoAttribute (ClientID, "errormessage", ErrorMessage, true);
185 if (ValidationGroup != String.Empty)
186 RegisterExpandoAttribute (ClientID, "validationGroup", ValidationGroup, true);
189 RegisterExpandoAttribute (ClientID, "focusOnError", "t");
191 bool enabled = IsEnabled;
193 RegisterExpandoAttribute (ClientID, "enabled", "False");
195 if (enabled && !IsValid)
196 RegisterExpandoAttribute (ClientID, "isvalid", "False");
198 if (Display == ValidatorDisplay.Static)
199 writer.AddStyleAttribute ("visibility", "hidden");
201 writer.AddStyleAttribute ("display", "none");
204 if (Display != ValidatorDisplay.Static)
205 RegisterExpandoAttribute (ClientID, "display", Display.ToString ());
208 base.AddAttributesToRender (writer);
211 internal void RegisterExpandoAttribute (string controlId, string attributeName, string attributeValue)
213 RegisterExpandoAttribute (controlId, attributeName, attributeValue, false);
216 internal void RegisterExpandoAttribute (string controlId, string attributeName, string attributeValue, bool encode)
219 if (page.ScriptManager != null)
220 page.ScriptManager.RegisterExpandoAttributeExternal (this, controlId, attributeName, attributeValue, encode);
222 page.ClientScript.RegisterExpandoAttribute (controlId, attributeName, attributeValue, encode);
225 protected void CheckControlValidationProperty (string name, string propertyName)
227 Control control = NamingContainer.FindControl (name);
228 PropertyDescriptor prop = null;
231 throw new HttpException (String.Format ("Unable to find control id '{0}'.", name));
233 prop = BaseValidator.GetValidationProperty (control);
235 throw new HttpException (String.Format ("Unable to find ValidationProperty attribute '{0}' on control '{1}'", propertyName, name));
238 protected virtual bool ControlPropertiesValid ()
240 if (ControlToValidate.Length == 0) {
241 throw new HttpException (String.Format ("ControlToValidate property of '{0}' cannot be blank.", ID));
244 CheckControlValidationProperty (ControlToValidate, String.Empty);
249 protected virtual bool DetermineRenderUplevel ()
251 if (!EnableClientScript)
254 if (HttpContext.Current == null)
258 /* From someplace on the web: "JavaScript 1.2
259 * and later (also known as ECMAScript) has
260 * built-in support for regular
262 ((Page.Request.Browser.EcmaScriptVersion.Major == 1
263 && Page.Request.Browser.EcmaScriptVersion.Minor >= 2)
264 || (Page.Request.Browser.EcmaScriptVersion.Major > 1))
266 /* document.getElementById, .getAttribute,
267 * etc, are all DOM level 1. I don't think we
268 * use anything in level 2.. */
269 && Page.Request.Browser.W3CDomVersion.Major >= 1);
271 return UplevelHelper.IsUplevel (
272 System.Web.Configuration.HttpCapabilitiesBase.GetUserAgentForDetection (HttpContext.Current.Request));
276 protected abstract bool EvaluateIsValid ();
278 protected string GetControlRenderID (string name)
280 Control control = NamingContainer.FindControl (name);
284 return control.ClientID;
287 protected string GetControlValidationValue (string name)
289 Control control = NamingContainer.FindControl (name);
294 PropertyDescriptor prop = BaseValidator.GetValidationProperty (control);
298 object o = prop.GetValue (control);
304 return ((ListItem) o).Value;
306 return o.ToString ();
309 public static PropertyDescriptor GetValidationProperty (object o)
311 PropertyDescriptorCollection props;
312 System.ComponentModel.AttributeCollection col;
314 props = TypeDescriptor.GetProperties (o);
315 col = TypeDescriptor.GetAttributes (o);
317 foreach (Attribute at in col) {
318 ValidationPropertyAttribute vpa = at as ValidationPropertyAttribute;
319 if (vpa != null && vpa.Name != null)
320 return props[vpa.Name];
326 protected internal override void OnInit (EventArgs e)
329 /* according to an msdn article, this is done here */
331 page.Validators.Add (this);
332 page.GetValidators (ValidationGroup).Add (this);
337 protected internal override void OnPreRender (EventArgs e)
339 base.OnPreRender (e);
341 pre_render_called = true;
343 ControlPropertiesValid ();
345 render_uplevel = DetermineRenderUplevel ();
347 RegisterValidatorCommonScript ();
350 protected internal override void OnUnload (EventArgs e)
353 /* according to an msdn article, this is done here */
355 page.Validators.Remove (this);
356 string validationGroup = ValidationGroup;
357 if (!String.IsNullOrEmpty (validationGroup))
358 page.GetValidators (ValidationGroup).Remove (this);
363 protected void RegisterValidatorCommonScript ()
367 if (page.ScriptManager != null) {
368 page.ScriptManager.RegisterClientScriptResourceExternal (this, typeof (BaseValidator), "WebUIValidation_2.0.js");
369 page.ScriptManager.RegisterClientScriptBlockExternal (this, typeof (BaseValidator), "ValidationInitializeScript", page.ValidationInitializeScript, true);
370 page.ScriptManager.RegisterOnSubmitStatementExternal (this, typeof (BaseValidator), "ValidationOnSubmitStatement", page.ValidationOnSubmitStatement);
371 page.ScriptManager.RegisterStartupScriptExternal (this, typeof (BaseValidator), "ValidationStartupScript", page.ValidationStartupScript, true);
372 } else if (!page.ClientScript.IsClientScriptIncludeRegistered (typeof (BaseValidator), "Mono-System.Web-ValidationClientScriptBlock")) {
373 page.ClientScript.RegisterClientScriptInclude (typeof (BaseValidator), "Mono-System.Web-ValidationClientScriptBlock",
374 page.ClientScript.GetWebResourceUrl (typeof (BaseValidator), "WebUIValidation_2.0.js"));
375 page.ClientScript.RegisterClientScriptBlock (typeof (BaseValidator), "Mono-System.Web-ValidationClientScriptBlock.Initialize", page.ValidationInitializeScript, true);
376 page.ClientScript.RegisterOnSubmitStatement (typeof (BaseValidator), "Mono-System.Web-ValidationOnSubmitStatement", page.ValidationOnSubmitStatement);
377 page.ClientScript.RegisterStartupScript (typeof (BaseValidator), "Mono-System.Web-ValidationStartupScript", page.ValidationStartupScript, true);
382 protected virtual void RegisterValidatorDeclaration ()
386 if (page.ScriptManager != null) {
387 page.ScriptManager.RegisterArrayDeclarationExternal (this, "Page_Validators", String.Concat ("document.getElementById ('", ClientID, "')"));
388 page.ScriptManager.RegisterStartupScriptExternal (this, typeof (BaseValidator), ClientID + "DisposeScript",
390 document.getElementById('" + ClientID + @"').dispose = function() {
391 Array.remove(Page_Validators, document.getElementById('" + ClientID + @"'));
395 page.ClientScript.RegisterArrayDeclaration ("Page_Validators", String.Concat ("document.getElementById ('", ClientID, "')"));
399 protected internal override void Render (HtmlTextWriter writer)
401 if (!IsEnabled && !EnableClientScript)
404 if (render_uplevel) {
405 /* according to an msdn article, this is done here */
406 RegisterValidatorDeclaration ();
409 bool render_tags = false;
410 bool render_text = false;
411 bool render_nbsp = false;
414 if (!pre_render_called) {
417 } else if (render_uplevel) {
419 render_text = Display != ValidatorDisplay.None;
421 if (Display != ValidatorDisplay.None) {
424 render_nbsp = v && Display == ValidatorDisplay.Static;
429 AddAttributesToRender (writer);
430 writer.RenderBeginTag (HtmlTextWriterTag.Span);
433 if (render_text || render_nbsp) {
437 if (String.IsNullOrEmpty (text))
447 writer.RenderEndTag ();
450 /* the docs say "public sealed" here */
451 public void Validate ()
453 if (IsEnabled && Visible)
454 IsValid = ControlPropertiesValid () && EvaluateIsValid ();