Reputation: 201
I have created a page to display multiple user controls inside update panels. Some user controls will get loaded faster and some may take a longer time to load. Now when the page loads, it waits for all the user controls to get loaded and display the page only after that. But I want to load the user controls asynchronously with a loader image for each of them so that the light weight user controls will get loaded easily without waiting for the heavier ones.
Please help me to find a solution.
I have successfully loaded the user control into my page using the above method. However now i am facing difficulty in loading usercontrols containing ajax controls such as tab container, calender extender etc..
Is there any work around for this problem
Upvotes: 6
Views: 5886
Reputation: 21117
You will run into a bunch of issues: ViewState, controls needing form tags, postbacks will not work but if you are doing this with a control that is purely a View
it will work fine.
Script:
//use .ready() or pageLoad() and pass params etc if you need to
$.ajax({
type: 'POST',
url: 'Default.aspx/GetControlViaAjax',
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
$('#yourdiv').html(data.d);
}
});
WebMethod:
[WebMethod]
public static string GetControlViaAjax()
{
//example public properties, send null if you don't have any
Dictionary<string, object> d = new Dictionary<string, object>();
d.Add("CssClass", "YourCSSClass");
d.Add("Title", "Your title");
return RenderUserControl("/yourcontrol.ascx", true, d, null, null);
//use this one if your controls are compiled into a .dll
//return RenderUserControl(null, true, d, "Com.YourNameSpace.UI", "AwesomeControl");
}
Render method:
private static string RenderUserControl(string path, bool useFormLess,
Dictionary<string, object> controlParams, string assemblyName, string controlName )
{
Page pageHolder = null;
if (useFormLess)
{
pageHolder = new FormlessPage() { AppRelativeTemplateSourceDirectory = HttpRuntime.AppDomainAppVirtualPath }; //needed to resolve "~/"
}
else
{
pageHolder = new Page() { AppRelativeTemplateSourceDirectory = HttpRuntime.AppDomainAppVirtualPath };
}
UserControl viewControl = null;
//use path by default
if(String.IsNullOrEmpty(path))
{
//load assembly and usercontrol when .ascx is compiled into a .dll
string controlAssemblyName = string.Format("{0}.{1},{0}", assemblyName, controlName );
Type type = Type.GetType(controlAssemblyName);
viewControl = (UserControl)pageHolder.LoadControl(type, null);
}
else
{
viewControl = (UserControl)pageHolder.LoadControl(path);
}
viewControl.EnableViewState = false;
if (controlParams != null && controlParams.Count > 0)
{
foreach (var pair in controlParams)
{
Type viewControlType = viewControl.GetType();
PropertyInfo property =
viewControlType.GetProperty(pair.Key);
if (property != null)
{
property.SetValue(viewControl, pair.Value, null);
}
else
{
throw new Exception(string.Format(
"UserControl: {0} does not have a public {1} property.",
path, pair.Key));
}
}
}
if (useFormLess)
{
pageHolder.Controls.Add(viewControl);
}
else
{
HtmlForm form = new HtmlForm();
form.Controls.Add(viewControl);
pageHolder.Controls.Add(form);
}
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
FormlessPage class:
public class FormlessPage : Page
{
public override void VerifyRenderingInServerForm(Control control)
{
}
}
Upvotes: 8
Reputation: 1759
user controls are probably not the right answer, as they are meant for server side composition. you probably need some standalone (in the sense of being served up independently) components on the server that serve the html fragments you need so that you can request them with javascript and shove the result into the larger page.
Upvotes: 0