Shahin
Shahin

Reputation: 12843

Postback in loaded ASP.NET UserControl With jQuery

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

Answers (1)

lukiffer
lukiffer

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

Related Questions