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;
}
}
}