internal AjaxBase(System.Web.UI.Control control, HttpContext context) { if (!(control is IAjaxControl)) { throw new System.InvalidOperationException(); } _control = control; _properties = WebBindable.Properties(_control.GetType()); _context = context; _bindings = new PropertyBindings((IAjaxControl)_control); }
/// <summary> /// String of name=value pairs representing server-side parameters /// </summary> /// <param name="properties">array of bindable control properties</param> /// <param name="bindings">list of DOM property bindings</param> static internal string[] PropertyLists(PropertyInfo[] properties, PropertyBindings bindings, IAjaxControl control) { // bound dynamic parameters StringBuilder boundList = new StringBuilder(); // static parameters StringBuilder staticList = new StringBuilder(); string pair; Regex empty = new Regex("^0|null|\\[\\]$"); Type attributeType = typeof(WebBindable); foreach (PropertyInfo p in properties) { if (p.CanRead) { pair = string.Format("\"{0}={{0}}\",", p.Name); if (bindings.Contains(p)) { boundList.AppendFormat(pair, bindings[p]); } else { string value = p.GetValue(control, null).ToJSON(); if (!string.IsNullOrEmpty(value) && !empty.IsMatch(value)) { value = value.Trim('"'); } else if (WebBindable.AlwaysBind(p)) { // always bindable properties are scripted even if null value = EcmaScript.Null; } else { // ignore this property continue; } staticList.AppendFormat(pair, value); } } } if (boundList.Length > 2) { boundList.Length -= 1; } // remove trailing comma staticList.AppendFormat("\"id={0}\"", control.ID); return(new string[] { staticList.ToString(), boundList.ToString() }); }
/// <summary> /// Use reflection to render requested control /// </summary> internal override void Process() { if (!this.Response.WriteCache(this.Key)) { string typeName = base["type"]; StringBuilder sb = new StringBuilder(); HtmlTextWriter writer = new HtmlTextWriter(new StringWriter(sb)); IAjaxControl control; PropertyInfo[] properties; System.Type controlType; if (string.IsNullOrEmpty(typeName)) { this.Response.AddError("No control specified"); return; } // expand abbreviated type names typeName = AjaxBase.Expand(typeName); // get control type and validate if (Handlers.AjaxHandler.KnownType.ContainsKey(typeName)) { controlType = Handlers.AjaxHandler.KnownType[typeName]; } else { controlType = System.Type.GetType(typeName); } if (controlType == null) { this.Response.AddError("Control \"{0}\" could not found", typeName); return; } if (!this.ValidType(controlType)) { this.Response.AddError("Control \"{0}\" cannot be called asynchronously", typeName); return; } // now that validated, create instance and set properties using (Page page = new Page(this.Context)) { control = (IAjaxControl)page.LoadControl(controlType, null); } properties = WebBindable.Properties(controlType); try { foreach (PropertyInfo p in properties) { // only set properties for which a value has been passed if (!string.IsNullOrEmpty(this.Parameters[p.Name])) { p.SetValue(control, EcmaScript.ToType( this.Parameters[p.Name], p.PropertyType, this.Context), null); } } // set ID so generated JavaScript references are equivalent if (!string.IsNullOrEmpty(this.Parameters["id"])) { control.ID = this.Parameters["id"]; } if (!string.IsNullOrEmpty(this.Parameters["style"])) { control.CssStyle = this.Parameters["style"]; } if (!string.IsNullOrEmpty(this.Parameters["cssClass"])) { control.CssClass = this.Parameters["cssClass"]; } control.Ajax.Context = this.Context; // any control rendered by this method is isolated from // the normal page life cycle control.Ajax.RenderState = AjaxBase.RenderStates.Isolation; control.Ajax.RenderMode = AjaxBase.RenderModes.Asynchronous; control.RenderControl(writer); } catch (System.Exception ex) { Idaho.Exception.Log(ex); control.Ajax.Cacheable = false; this.Response.Error(ex); } finally { this.Response.Cacheable = control.Ajax.Cacheable; this.Response.CacheDependencies = control.Ajax.DependsOnType; this.Response.CacheKey = this.Key; this.Response.Complete(sb.ToString(), true); } } }