Sanjeev Agarwal

Extending Web with ASP.NET

Dynamically create ASP.NET user control using JQuery and JSON enabled Ajax Web Service

Please read my previous post Dynamically create ASP.NET user control using ASP.NET Ajax and Web Service to understand this approach. In this article I am doing the same thing using JQuery. Other code I already explain in previous post, so I will explain only JQuery related code in this article. To subscribe my blog through mail, Please click here subscribe blog by email.

You can download the VB.NET solution code here and the C# solution code here

Dynamic control creation using JQuery is more fun and easy. Here is sample request to access JSON enabled web service using JQuery.

function getJsonAjaxObject(webServiceURL, jsonData) {

 $.ajax({

  type: "POST",

  contentType: "application/json; charset=utf-8",

  url: serviceURL,

  data: jsonData,

  success:

   function(msg){

   //execute code related to success of web service

   },

  error:

   function(XMLHttpRequest, textStatus, errorThrown){

      //execute code related to failier of web service

   }

 });

}


Few thing you need to consider when you are accesing ASP.NET webservice through JQuery.
  • Request verb Type
  • Content- length with IIS6+
  • Default contentType
  • JSON object formatting
  • Maximum length exceed exception

I am explaining these issues and workaround to make JQuery work fine with ASP.NET Ajax enabled web service.

Request action Type

ASP.NET Ajax enabled web service by default only allows the HTTP POST verb to be used when invoking web service methods using JSON, which means you can't inadvertently allow browsers to invoke methods via HTTP GET. Workaround for this issue is to use "POST" verb for request.

Content- length with IIS6+

Most installations of IIS6+ require a content-length be provided with all POST requests, even if there is no content (POST data). The content-length for a request with no data should be 0, but jQuery doesn’t set that header automatically unless there is a data parameter. The workaround for this issue to use an empty JSON object as a parameter on read-only requests.

for example data: "{}"

This will cause jQuery to correctly set a content-length, while your web service will ignore the empty parameter and treat the request as read-only. 

Default contentType 

ASP.NET AJAX enabled webservice requires a Content-Type header to be set to "application/json" for invocations to AJAX web services.  JSON requests that do not contain this header will be rejected by an ASP.NET server. For JQuery Ajax request you need to mention content type as application/json.

for example contentType: "application/json;charset=utf-8"

JSON object formatting

If you directly provide a JSON object as the data parameter for an JQuery Ajax call, jQuery will attempt to serialize the object instead of passing it on to your web service and you will get invalid JSON primitive exception.

Work around to this issue is to pass JSON data parameter as string, like this

data: "{'controlLocation':'~/Controls/GridView.ascx'}"

Maximum length exceed exception

When you are accessing large JSON object via script service you need to update maxJsonLength in web.config otherwise you will get "maximum length exceed" exception.

<system.web.extensions>

              <scripting>

                     <webServices>

        <jsonSerialization maxJsonLength="5000000" />

                     </webServices>

              </scripting>

       </system.web.extensions>

 


The C#/VB.NET code is same as my last post. The XHTML code is slightly changed to call JQuery function instead of ASP.NET AJAX. 

<%@ Page Language="C#" EnableViewState="false"  %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head id="head" runat="server">

    <title>With JQuery</title>

    <link type="text/css" href="StyleSheets/iGridView-classic.css" rel="stylesheet" />

    <link type="text/css" href="StyleSheets/iGridView-common.css" rel="stylesheet" />

    <script language="javascript" type="text/javascript"   src="Scripts/jquery-1.2.6.pack.js"></script>

    <style type="text/css">

        body

        {

            width:95%;

            padding-left:20px;

            font-family:Arial;

            font-size:10pt;

            padding-right:20px;

        }

    </style>

</head>

<body>

    <form id="form" runat="server">

        <input type="button" value="Load Customer Order" onclick="getData('ScriptService.asmx/GetControlHtml','~/Controls/GridView.ascx');" />

        <input type="button" value="Load Login" onclick="getData('ScriptService.asmx/GetControlHtml','~/Controls/LoginControl.ascx');" />

        <input type="button" value="Register New User" onclick="getData('ScriptService.asmx/GetControlHtml','~/Controls/NewUserControl.ascx');" />

 <div id="testDiv"></div>

    </form>

</body>

 

</html>

The JavaScript to call JSON enabled WebService is mentioned below

<script type="text/javascript">

function getData(serviceURL, controlLocation) {

 $.ajax({

  type: "POST",

  contentType: "application/json; charset=utf-8",

  url: serviceURL,

  data: "{'controlLocation':'" + controlLocation + "'}",

  success:

   function(msg){

     $('#testDiv').html(eval(msg));

     formatTable();

   },

  error:

   function(XMLHttpRequest, textStatus, errorThrown){

       alert( "Error Occured!" );

   }

 });

}

function formatTable(){

    //get all row in gridview table and set style/event/attribute on them

    $("div#testDiv tr")

    .addClass("data-row")

    .mouseover(function(){

    if(! isClickedStyleSet(this.className)){

    this.className = "row-over";}

    if(! jQuery.browser.mozilla){

    this.style.cursor ="hand";

    }})

    .mouseout(function(){

     if(! isClickedStyleSet(this.className)){

     this.className = "data-row" ;}

    })

    .click(

    function(){

      if(! isClickedStyleSet(this.className)){

    this.className = "row-select" ;}

    else{this.className = "data-row" ;}

    });

    //get all cell in gridview table and set style/event/attribute on them

    $("div#testDiv td")

    .addClass("data-row")

    .css("white-space", "nowrap")

    .css("vertical-align", "middle")

    .mouseover(function(){

    setTitle(this);

    });

}

       

function setTitle(object){

    //check browser type 

    if(jQuery.browser.mozilla){

        object.title = object.textContent;

    }

    else{

        object.title = object.innerText;

    }

}

function isClickedStyleSet(className){

    //if row is already clicked return true

    if(className == "row-select"){

    return true;

    }

    return false;

}       

 

</script>

Below is the screenshot of the initial page.

Gridview Effect 

When user clicks on "Load Customer Order", It will call the ScriptService.asmx/GetControlHtml Web Service method get the usercontrol html data, load in the 'testDIV' and format the table inside div to implement mouseover/mouseout, click and title functionality using JQuery.

Gridview Effect 

Same way user can clicks on "load login" button to load "User Login" form dynamically.

Gridview Effect 


To load any usercontrol you need to call "getdata" function with webservice url and control location.

for example getData('ScriptService.asmx/GetControlHtml', '~/Controls/GridView.ascx');.

Please post your valuable feedback for this article.

You can download the VB.NET solution code here and the C# solution code here

kick it on DotNetKicks.com

Comments

Michael Spivey said:

Maybe these type of web 2.0-style, AJAX controls would be a great front-end to call the Comments and Ratings web services offered at www.web2services.com.

# July 29, 2008 10:37 PM

khoa said:

If in my gridview have pager, i can't postback with your tip. In this case, what do you do ?

# August 1, 2008 11:38 PM

SanjeevAgarwal said:

Since paging is using postback so you can't use paging directly. Pass your page number to gridview using web service then you can get paged data. This concept is similar to ASP.NET MVC pattern  

# August 2, 2008 3:18 AM

jpg said:

I try your code and get an error message on

$('#testDiv').html(eval(msg));

saying

Microsoft JScript compilation error: Expected ';'

I change the value of msg for something else and then it work.

I test the function eval like

var test = eval(msg);

and I got the error.

I guest there is something in the return value of msg that the function eval() don't like.

I'm using vs2008 on window xp with IE 7.0 on targeting 3.5

msg value = {"d":"\r\n\u003cdiv\u003e\r\n\u003cinput type=\"hidden\" name=\"__VIEWSTATE\".........

Hope you can help,

thanks

# August 5, 2008 11:10 PM

Tony said:

Thanks for the example (have downloaded the c# solution), but I couldnt get the $('#testDiv').html(eval(msg)) bit working, had to change it to $('#testDiv').html(eval('(' + msg + ')'))

And after that,on the same line, I am getting an exception (stepping through the javascript in firebug):

"Node cannot be inserted at the specified point in the hierarchy" code: "3" nsresult: "0x80530003 (NS_ERROR_DOM_HIERARCHY_REQUEST_ERR)"

Am I doing something wrong?

Tony

# August 26, 2008 5:15 PM

SanjeevAgarwal said:

Tell me your browser version. I tested this code in firefox 2/3 and ie 6/7

# August 27, 2008 4:53 AM

Tony said:

firefox 2.

Had a bit of time to work on it and got it working for me as follows:

$('#testDiv').html(eval('(' + msg + ')').d)

or

ammended the $.ajax call and added

dataType: "json",

this way 'msg' gets evaled by jquery and the above line changes to:

$('#testDiv').html(msg.d)

Tony

# August 27, 2008 6:38 PM

k said:

When I run it I get the following error:

The state information is invalid for this page and might be corrupted.

Any Ideas?

# October 23, 2008 6:54 PM

Amin said:

Excellent Article Sanjeev... !!!

Cheers,

Amin Sayed

# November 3, 2008 1:56 AM

hung_asd321 said:

Help me error

The state information is invalid for this page and might be corrupted.

When using Ajax load content into a small page of a masterpage

Thanks for yours suggesstions

# November 17, 2008 10:48 PM

John said:

Hi,

If we put the AutoCompleteExtender control in the user control then it does not work...we get lots of javascript errors....

Any clue?

Thanks,

John

# March 27, 2009 8:09 AM

m7e7 said:

How do u handle events in User Controls with JQuery?

# August 18, 2009 10:53 AM

Sreekanth said:

Great Article Sanjeev,

I have been looking for the similar post long since I came to know about Ajax and jQuery. All the web services return simple "datetime" as a string to the client instead of complex html (user control).

Most of the time I used to get JSON parser error while trying to return dataset or table.

# October 13, 2009 9:33 AM

rizzy said:

this is kind of half-done.  There is no clue on how to handle post back from these controls.  They're simply rendered as html controls on the page, so I'm thinking they'll disappear on post back.  So this doesn't technically load user controls on to a page dynamically using ajax, this just takes the html stuff inside a user control and just puts it on to a page.  You can't really do anything on the server side with this on post back.

# October 28, 2009 2:20 PM

Kristof said:

I dont know why, but the option to disable the ViewState by EnableViewState=False is not working..?

The only solution I have, is to cut out the html portion by

RegEx.Replace("<div>(\n)?(<input.*?__VIEWSTATE.*?/>)(\n)?</div>")

Any ideas?

# October 29, 2009 5:00 PM

prashanthganathe said:

Hello Sanjeev, this is a great article.

I am using Jquery since more than 6 months i is really a great tool. I implemented this usercontrol before but missed out Regular expression.

I enchanced the code even furture and made a generic javascript where on success we can call another javascipt function too. Here is the code.

function getData(serviceURL, UCLocationPath, data, OnSuccessFunction) {

   $.ajax({

       type: "POST",

       contentType: "application/json; charset=utf-8",

       url: serviceURL,

       dataType: "json",

       data: "{'controlLocation':'" + UCLocationPath + "'}",

       success:

                      function(msg) {

                          debugger;

                          var strFun = OnSuccessFunction;

                          var strParam = msg;

                          //  strParam = "this is the parameter";

                          //var funcCall = strFun + "('" + strParam + "');";

                          if (msg.d != null)

                              strParam = msg.d;

                          //  var funcCall = strFun + "('" + strParam + "');";

                          var funcCall = strFun + "('perfect');";

                         // funcCall = funcCall.repace("'", "\'");

                          var ret = eval(funcCall);

                      },

       error:

                      function(XMLHttpRequest, textStatus, errorThrown) {

                          alert("Please try agian.!");

                      }

   });

}

if usercontrol has a jquery functions in it then it is creating a problem. I am still working on this, hope in a day i will find a solution.

# November 6, 2009 6:51 AM

alok.arora said:

Hi Sanjeev,

1. Do you have tried creating any server side control inside these controls?

2. Do you have seen the development effort in case where you need to develop all functions in JavaScript using JQuery/JSON?

3. Do you heard about IHttpHandlers over Web Services?

4. Do you tried updating these controls back from server in case of some event being fired and effect is to be shown on these UserControls?

5. Do you thought of the overhead on features like skinning using XHTML/CSS2.0?

6. Do you tried to compare this with some other Ajax Techniques such as JQuery/IHttpHandler.

let me know your thoughts on all these aspects...

I'm really interested to implement this, but a bit worried about these stuffs, I hope you may spare your time to help me out with this.

I'll surely compensate for this to you.

Thanks in advance!

# March 5, 2010 2:24 AM

xvladus1 said:

Thank you for a good explanation.

# April 30, 2010 11:39 AM

Muhammad said:

I have some code and when i want to click on button change some other control like change color of paragraph

it doesnot work when i use click event with paragraph selector and change the color of paragraph it works. i dont know what is the problem.

# May 28, 2010 3:17 AM

zulfiqar.langah said:

Good Effort dude

# June 3, 2010 3:38 AM

Joel Dow said:

I like this solution for purely static controls but what if the control has public properties.  I suppose your service would have to expose a NameValueCollection parameter and then you would have to go through and try to match up keys to control properties if they exist.

# June 15, 2010 10:16 AM

hamid reza mansouri said:

very tnx

# April 2, 2011 10:09 AM

buy flagyl 200mg said:

If in my gridview have pager, i can't postback with your tip. In this case, what do you do ?

# July 19, 2011 3:26 AM

Srini said:

Great article. It saved bunch of time for me....

# July 28, 2011 10:10 AM

Mandar said:

Thanks Tony

for ur below given info

dataType: "json",

this way 'msg' gets evaled by jquery and the above line changes to:

$('#testDiv').html(msg.d)

thanks a lot

# September 13, 2011 4:54 AM

Jaime García said:

I think this is not a good way to load ASCX. If you have  js includes on your ascx yo can se how its are never cached by the browser.

I think thereis a better way to load ASCX (or not using ASCX) with jquery.

Anyway, good article!

# January 18, 2012 2:58 AM

Arjun said:

How to we perform server button click.

# September 21, 2012 3:49 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)