Hi,
I work on a large, enterprise application built with many user controls. The user controls have NO ASCX, they are completely defined at runtime in CS files. Additionally, when developing user controls for the application and implementing new functionality, I don't have control over the framework or hierarchy of the parent controls which will consume my user controls. They might be nested 5 layers deep, user control on top of user control.
I've seen many posts about the perils of using RadAjaxManager with UpdatePanels, but I don't have a choice in the matter and I haven't encountered the same issues others have reported. So I apologize if this is redundant but I've not seen anything about my scenario or the strange behavior I'm seeing.
Basically, if a parent up the control hierarchy employs an UpdatePanel, when the AsyncUpload control posts pack (using RadAjaxManager), the ajax response is improperly formatted and the ajax path to the RadAjaxManager target control(s) actually appears in the html markup and that containers child controls are rendered twice. The html render is completely broken as you can see in the mock up I have included. I think this may be a bug in RadAjaxManager.
I'm including code for 3 files - 3 layers of hierarchy, which demonstrates the issue.
fileUpload.aspx
ParentControl.cs (created by fileUpload)
UploadControl.cs (created by ParentControl) <-- this is the only one I have control over.
Notes:
Keep in mind that if we equate this to my situation, UploadControl is the only one I can change, I don't have access to ParentControl or fileUpload.
In the demo app, the issue only happens if the UpdateMode of the panel in ParentControl.cs is set to Always. This has something to do with the fact that everything in UloadControl sits on a generic Panel. If I remove the Panel and just drop the objects in UploadControl directly in the Controls collection, then the ajax render will be messed up regardless of the UpdateMode setting in the ParentControl. Changing the UpdateMode in the ParentControl is not an option, there are often good reasons why it's set to Always - other children of the parent may rely on that setting.
As always, thanks in advance,
JD
fileUpload.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="fileUpload.aspx.cs" Inherits="TelerikApp.fileUpload" %><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title></head><body> <form id="form1" runat="server"> <div> </div> </form></body></html>fileUpload.aspx.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using Telerik.Web.UI;using TelerikApp.Controls;namespace TelerikApp{ public partial class fileUpload : System.Web.UI.Page { protected WebControl _DivPageContent = new WebControl(HtmlTextWriterTag.Div); protected void Page_Init(object sender, EventArgs e) { this._DivPageContent.Controls.Add((Control)(new ParentControl())); _DivPageContent.ID = "_DivPageContent"; this.form1.Controls.Add(_DivPageContent); RadAjaxManager manager = new RadAjaxManager(); manager.ID = "RadAjaxManager1"; this.form1.Controls.Add(manager); } }}ParentControl.cs
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using Telerik.Web.UI;namespace TelerikApp.Controls{ public class ParentControl : WebControl { private RadButton _someButton = new RadButton(); UpdatePanel _update = new UpdatePanel(); UploadControl _upLoad = null; protected override void OnInit(EventArgs e) { this._someButton.ID = "SomeButton"; this._someButton.Text = "Click Me"; this._someButton.AutoPostBack = true; this._someButton.Click += _someButton_Click; this._update.ID = "myUpdatePanel"; this._update.UpdateMode = UpdatePanelUpdateMode.Always; //.Conditional Fixes issue in some cases this._upLoad = new UploadControl(); this._upLoad.ID = "myUpLoadControl"; this._update.ContentTemplateContainer.Controls.Add(this._upLoad); this._update.ContentTemplateContainer.Controls.Add(new LiteralControl("<br/><br/>More Controls on the UpdatePanel<br/>")); this._update.ContentTemplateContainer.Controls.Add(this._someButton); this.Controls.Add(_update); base.OnInit(e); } void _someButton_Click(object sender, EventArgs e) { //any silly functionality if (this._someButton.ToolTip == "") this._someButton.ToolTip = "0"; int count = int.Parse(this._someButton.ToolTip) + 1; this._someButton.Text = "You've Clicked " + count.ToString() + " times"; this._someButton.ToolTip = (count).ToString(); } }}UploadControl.cs
using System;using System.Threading;using System.Web.UI;using System.Web.UI.WebControls;using Telerik.Web.UI;namespace TelerikApp.Controls{ public class UploadControl : WebControl { private RadButton _btUpload = new RadButton(); private RadAsyncUpload _fiInput = new RadAsyncUpload(); private DropDownList _DdDocumentTypes = null; private Label _lbl = new Label(); private RadAjaxManager _ajaxManager = new RadAjaxManager(); private Panel _DocUploadControlPanel = new Panel(); private RadAjaxLoadingPanel _ajaxLoadingPanel = null; protected override void OnInit(EventArgs e) { base.OnInit(e); ScriptManager scriptManager = new ScriptManager(); scriptManager.ID = "scriptManager"; this.Page.Form.Controls.Add(scriptManager); this._lbl.ID = "_lbl"; this._lbl.Text = ""; this._DocUploadControlPanel.ID = "_DocUploadControlPanel"; this._DocUploadControlPanel.CssClass += " docUploadControlPanel"; this._DocUploadControlPanel.Style.Add("display", "inline-block"); this._DocUploadControlPanel.BackColor = System.Drawing.Color.LightBlue; this._DdDocumentTypes = new DropDownList(); this._DdDocumentTypes.ID = "DDLDocumentTypes"; this._DdDocumentTypes.EnableViewState = false; this._DdDocumentTypes.AutoPostBack = false; this._DdDocumentTypes.Items.Add(new ListItem("type1")); this._DdDocumentTypes.Items.Add(new ListItem("type2")); this._ajaxLoadingPanel = new RadAjaxLoadingPanel(); this._ajaxLoadingPanel.ID = "_ajaxLoadingPanel"; this._ajaxLoadingPanel.Transparency = 50; this._ajaxLoadingPanel.BackColor = System.Drawing.Color.DarkGray; this._ajaxLoadingPanel.Skin = "Default"; this._fiInput.ID = "FileInput"; this._fiInput.MultipleFileSelection = Telerik.Web.UI.AsyncUpload.MultipleFileSelection.Disabled; this._fiInput.FileUploaded += FileUploaded; this._btUpload.ID = "UploadButton"; this._btUpload.CausesValidation = false; this._btUpload.Text = "Upload"; DataBind(); this._DocUploadControlPanel.Controls.Add(this._ajaxLoadingPanel); this._DocUploadControlPanel.Controls.Add(this._DdDocumentTypes); this._DocUploadControlPanel.Controls.Add(this._fiInput); this._DocUploadControlPanel.Controls.Add(this._btUpload); this._DocUploadControlPanel.Controls.Add(new LiteralControl("<br/>")); this._DocUploadControlPanel.Controls.Add(this._lbl); this.Controls.Add(_DocUploadControlPanel); } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); _ajaxManager = RadAjaxManager.GetCurrent(Page); _ajaxManager.AjaxSettings.AddAjaxSetting(this._btUpload, this._DocUploadControlPanel, this._ajaxLoadingPanel); //_ajaxManager.AjaxSettings.AddAjaxSetting(_btUpload, _lbl); } private void FileUploaded(object sender, FileUploadedEventArgs e) { Thread.Sleep(2000); _lbl.Text = "UPLOADED " + e.File.FileName + " TYPE: " + this._DdDocumentTypes.SelectedValue; _lbl.BackColor = System.Drawing.Color.LightGreen; } }}