Reputation: 12843
I am using this WebService and Class to Render UserControl and loading dynamically it with jQuery :
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.UI;
using System.Web.UI.HtmlControls;
namespace TestJQueryAjax
{
public class KeyVal
{
public string Key { set; get; }
public object Value { set; get; }
}
/// <summary>
/// Summary description for Ajax
/// </summary>
[ScriptService]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Ajax : WebService
{
/// <summary>
/// Removes Form tags using Regular Expression
/// </summary>
private static string cleanHtml(string html)
{
return Regex.Replace(html, @"<[/]?(form)[^>]*?>", string.Empty, RegexOptions.IgnoreCase);
}
[WebMethod(EnableSession = true)]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string RenderUserControl(string path,
List<KeyVal> properties)
{
Page pageHolder = new Page();
UserControl viewControl =
(UserControl)pageHolder.LoadControl(path);
viewControl.EnableViewState = false;
Type viewControlType = viewControl.GetType();
if (properties != null)
foreach (var pair in properties)
{
if (pair.Key != null)
{
PropertyInfo property =
viewControlType.GetProperty(pair.Key);
if (property != null)
{
if (pair.Value != null) property.SetValue(viewControl, pair.Value, null);
}
else
{
throw new NotImplementedException(string.Format(
"UserControl: {0} does not have a public {1} property.",
path, pair.Key));
}
}
}
//Form control is mandatory on page control to process User Controls
HtmlForm form = new HtmlForm();
//Add user control to the form
form.Controls.Add(viewControl);
//Add form to the page
pageHolder.Controls.Add(form);
//Write the control Html to text writer
StringWriter textWriter = new StringWriter();
//execute page on server
HttpContext.Current.Server.Execute(pageHolder, textWriter, false);
// Clean up code and return html
return cleanHtml(textWriter.ToString());
}
}
}
and here is the plugin that provided for loading usercontrol ;
$.fn.advloaduc = function(options) {
var defaults = {
webServiceName: 'Ajax.asmx', //Web Service name
renderUCMethod: 'RenderUserControl', //web service method
ucMethodJsonParams: '{path:\'\'}', //parameters
completeHandler: null //complete handler
};
var options = $.extend(defaults, options);
return this.each(function() {
var obj = $(this);
obj.prepend("<div align='center'> loading... <img src=\"images/loading.gif\"/></div>");
$.ajax({
type: "POST",
url: options.webServiceName + "/" + options.renderUCMethod,
data: options.ucMethodJsonParams,
contentType: "application/json; charset=utf-8",
dataType: "json",
success:
function(msg) {
obj.html(msg.d);
// if specified make callback and pass element
if (options.completeHandler)
options.completeHandler(this);
},
error:
function(XMLHttpRequest, textStatus, errorThrown) {
obj.html("error");
}
});
});
};
so both codes works well with this sample :
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/jquery.advloaduc.js" type="text/javascript"></script>
<script src="js/json2.js" type="text/javascript"></script>
<script type="text/javascript">
function showAlert() {
alert('finished!');
}
var fileName = 'part1.ascx';
var props = [{ 'Key': 'Text1', 'Value': 'test1' }, { 'Key': 'Text2', 'Value': 'test2'}];
var jsonText = JSON.stringify({ path: fileName, properties: props });
$(document).ready(function() {
$("#loadMyUc").advloaduc({
webServiceName: 'Ajax.asmx',
renderUCMethod: 'RenderUserControl',
ucMethodJsonParams: jsonText,
completeHandler: showAlert
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="loadMyUc" align="center">
</div>
</form>
</body>
</html>
But i want to make Postback and serverside actions in Loaded UserControl. Is it possible ? when i make postback in loaded usercontrol the error happens : Viewstate is corrupted is there any way exist ? is it need to upload sample with this code for better reviewing ?
Upvotes: 1
Views: 2002
Reputation: 11293
Without initially rendering the UserControl within the standard page lifecycle, postback events cannot be properly processed - your WebService won't keep track of ViewState in a way that's available to the rest of the AppDomain context.
It's quite an elaborate solution you have here, but it may be simpler to either 1. manually handle AJAX from the WebService or 2. include (dynamically or otherwise) an instance of the UserControl on the page and use jQuery to place it in the page.
And as much as I dislike recommending UpdatePanels, this may be an option to avoid having to re-write your UserControl to use AJAX rather than the traditional post-back model, but still give you the versatility of dynamically loading the UserControl.
Upvotes: 2