Solved

strange problme with IE and ajax call using JQUERY and JSON

Posted on 2009-03-31
17
1,656 Views
Last Modified: 2012-05-06
Hi i have a code that works absolutely fine in all browsers except IE7 (and may be IE6)

Here is my code architecture

- ASP page  containing Jquery code
- Handler.ashx  server file called by Jquery
- JSON return by the server file
- jTemplate on the client side

when AJAX is called by the IE7 client then it throws an error  
"$T.title is null or not an object"


so why this code is running ok in all browsers  fire, safari and chrome and not in IE7


ASPX page code

--------------------
 

        function GetSectionDetails()

        {

              var k;

              var handlerUrl = "http://localhost:1453/PaggingDotNet/Handler.ashx?op=op2&lid=123&oid=11234999";

              

           

              //$(detailsArea).load(FormatUrl(handlerUrl));

            

              //--------------------------------------------------------

              //ATTENTION THIS LINE OF CODE HAS SOME PROBLME IN FIREFOX 

              //$(detailsArea).html("Loading....");

              //--------------------------------------------------------

              

              //this statement will generate a new random number so that cacheing does not affect the reponse form server.

              handlerUrl = FormatUrl(handlerUrl);

              $.ajax({

                type: "GET",

                url: handlerUrl,

                data: "{}",

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

                dataType: "json",

                success: function(msg) 

                 {

                        ApplyTemplate(msg) 

                  },

                  error: function() 

                  {   

                        alert("Some error occured");

                  }
 

                  

              });

        }        

        

        

        function ApplyTemplate(msg) 

        {   

              $("#detailsArea").setTemplate($("#TemplateResultsTable").html());   

              $("#detailsArea").processTemplate(msg);                 

        }         
 

        function FormatUrl(url)

        {

            var newUrl = url;

            newUrl += '&ver=' + Math.random().toString();

            return newUrl;

        }
 
 

and jTemplate

-----------------

<script type="text/html" id="TemplateResultsTable">   

{#template MAIN}   

<table  cellpadding="10" cellspacing="0">   

  <tr>   

    <th>Title</th>   

    <th>Desc</th>   

  </tr>   

  {#foreach $T.Records as CD}   

    {#include ROW root=$T.CD}   

  {#/for}   

</table>   

{#/template MAIN}   
 
 

{#template ROW}   

<tr>   

  <td>{$T.title}</td>   

  <td>{$T.Desc333}</td>   

</tr>   

{#/template ROW}   

</script>  
 
 
 
 
 
 
 
 
 

and server side ASHX  file code

--------------------------------------

    public void ProcessRequest (HttpContext context) 

    {

        context.Response.ContentType = "application/json";

        

        string s = "";
 
 

            s = "{";

            s = s + "\"Result\":\"ok\",";

            s = s + "\"Param\":\"My Name 121 1989\",";

            s = s + "\"Records\":";

            s = s + "[";

            s = s + "{";

            s = s + "\"title\":\"Title 1\",";

            s = s + "\"Desc333\":\"" + context.Request.QueryString["ver"].ToLower() + "\"";

            s = s + "},";
 

            s = s + "{";

            s = s + "\"title\":\"Title 2 ewf wef wef we fwef we\",";

            s = s + "\"Desc333\":\"My Description 2\"";

            s = s + "},";
 

            s = s + "{";

            s = s + "\"title\":\"Title 3\",";

            s = s + "\"Desc333\":\"My Descewf wef wef ewf wef ription 1\"";

            s = s + "},";

            s = s + "]";

            s = s + "}";
 

        context.Response.Write(s);

    }
 
 
 
 

as you can see the server side code only generates the JSON and returns it to client side

Open in new window

0
Comment
Question by:shahzad73
  • 9
  • 5
  • 3
17 Comments
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 24036732
Please show the actual JSON produced
0
 
LVL 1

Author Comment

by:shahzad73
ID: 24037448
this was the result   Result is just a field to indicate that the processing is ok     param is some information retured.    actual records are withni Records


{"Result":"ok","Param":"Total Record : 3","Records":[{"title":"Title 1","Desc333":"My Description 1"},{"title":"Title 2","Desc333":"My Description 2"},{"title":"Title 3","Desc333":"My Description 3"},]}
0
 
LVL 1

Author Comment

by:shahzad73
ID: 24037745
got another code that works fine in all browsers first time but second call throws error in javascript.   error is on the line whichs call Jtemplate

$("#dvDetails").processTemplate(employees);

error is  

"constructor is null or not an object"


i did some debuggig  and instead of calling jtemplate i make an alert.   and looks like call to server is made successfully.     client javascript recreivs the data  and when alert     alert(myobj.Head[1].id);     i am shown a different GUID that is generated dynamically on the server side   BUT  in IE it ALWAYS shows the same GUID that was received first time       ALL other browsers shows a different GUID  
NOW I CANNOT understand why IE behaves differntly




this time my data returned by the server process is  

{ "Head":[ { "id":"59b8fc11-2434-41d4-b44a-99ba84c848a1","username":"user name","firstname":"name 2","lastname":"last name"}, { "id":"4bd08f94-5148-44bc-92c9-f738c430c621","username":"user name 1","firstname":"name 3","lastname":"last name"}, { "id":"160aca2d-6829-4730-9772-460c9d1bd612","username":"user name 2","firstname":"name 4","lastname":"last name"}, { "id":"cc630527-f5ba-478f-a102-42640841b813","username":"user name 3","firstname":"name 5","lastname":"last name"}, { "id":"164b40b0-5804-45fc-9430-32c0461b9f38","username":"user name 4","firstname":"name 6","lastname":"last name"} ]}
        $(document).ready(

        function() 

        {

             $("#ddlDept").change(

             function() 

             {

                var DeptID = $("#ddlDept > option[@selected]").attr("text");

                if (DeptID != 0) 

                {

                    $.getJSON('http://localhost:1453/PaggingDotNet/Ajax2/Handler.ashx', 

                    function(employees) 

                    {

                        

                        var myobj;

                        myobj = null;

                        myobj = employees;

                        

                        //alert(employees);

                        //$("#Div1").html(employees);

                        

                        $("#dvDetails").setTemplate($("#TemplateResultsTable").html());

                        $("#dvDetails").processTemplate(employees);

                        

                        

                        //comments above jtemplate calls and codes does not show an error. following alert shows GUID of first record.  BUT IN IE IT ALWAYS SHOWS THE GUID FIRST TIME RECEIVED

                        //alert(myobj.Head[0].id);

                    });               

                }                

              });

         });

Open in new window

0
 
LVL 1

Author Comment

by:shahzad73
ID: 24037806
second call always produces the error    "constructor is null or not an object"      and error is i think on the call to jTemplates in javascript when we want to process the template      what's going on
0
 
LVL 1

Author Comment

by:shahzad73
ID: 24038044
is there any caching problme in IE that it always shows the same results in every call altgough server is sending differnet data
0
 
LVL 1

Author Comment

by:shahzad73
ID: 24038054
i am increasing my points   please give me some solution     or any other code   using  html and javascript on the client side  with jtemplate showing records in table      and    .ashx  on the server side that returns different data.    and also code should work in every browser
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 24038066
I thought perhaps the JSON might be malformed
so I tried here
http://braincast.nl/samples/jsoneditor/

but it looks ok.

I hope some jQuery experts can find the issue
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 24038071
Yes IE caches ajax/JSON and it is a pain the neck. Try expiring the result using expiry headers or add &rnd="+Math.random()
to the query string
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 1

Author Comment

by:shahzad73
ID: 24038723
can u give me some working codes that works in all browsers or give me link online where i can dowload some smaple
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 24038863
I have zero experience with ASP.NET and jTemplate, so we will have to wait until someone with such knowledge shows up.
Alternatively delete and re-open the question with the more specific issues
0
 
LVL 1

Author Comment

by:shahzad73
ID: 24038971
ok i added a random value to the path and now IE is also showing different values code is given

now i have only problmes with jTemplates notice in the follownig code that i commented these lines

                        $("#dvDetails").setTemplate($("#TemplateResultsTable").html());
                        $("#dvDetails").processTemplate(employees);

if i uncomment the lines and then run then all browsers the code runs fine FIRST TIME ONLY, ajax call goes to server, data is fetched and then template is applied   BUT SECOND  call will gennerate folllowing error   as reported by IE (other browsers simply do not show any acivity
"constructor is null or not an object"

looks like template is already applied and DIV are loaded with template data and now they are causing problems second tmie.


my template is given below
<script type="text/html" id="TemplateResultsTable">  
<table>

  <thead>

    <tr style="background-color:Maroon;color:White;">
      <th>Employee ID</th>
      <th>User Name</th>
      <th>First Name</th>
      <th>last Name</th>
    </tr>

  </thead>

  <tbody>

   {#foreach $T.Head as record}

    <tr>

      <td>{$T.record.id}</td>

      <td>{$T.record.username}</td>

      <td>{$T.record.firstname}</td>

      <td>{$T.record.lastname}</td>

    </tr>

    {#/for}

  </tbody>

</table>
</script>
        $(document).ready(

        function() 

        {

             $("#ddlDept").change(

             function() 

             {

                var DeptID = $("#ddlDept > option[@selected]").attr("text");

                var path;

                

                

                

                if (DeptID != 0) 

                {

                    path = FormatUrl('http://localhost:1453/PaggingDotNet/Ajax2/Handler.ashx');

                    

                    $.getJSON(path, 

                    function(employees) 

                    {

                        

                        var myobj;

                        myobj = null;

                        myobj = employees;

                        

                        

                        

                        //$("#dvDetails").setTemplate($("#TemplateResultsTable").html());

                        //$("#dvDetails").processTemplate(employees);

                                                

                        

                        

                        

                        var sss;

                        sss = "ID " + myobj.Head[0].id + "<br>";

                        sss = sss + "Name " + myobj.Head[0].firstname + " " + myobj.Head[0].lastname +  "<br>";

                        

                        sss = sss + "ID " + myobj.Head[1].id + "<br>";

                        sss = sss + "Name " + myobj.Head[1].firstname + " " + myobj.Head[1].lastname +  "<br>";
 

                        sss = sss + "ID " + myobj.Head[2].id + "<br>";

                        sss = sss + "Name " + myobj.Head[2].firstname + " " + myobj.Head[2].lastname +  "<br>";

                        

                        document.getElementById( 'dvDetails' ).innerHTML = '';                        

                        $("#dvDetails").html(sss);

                    });               

                }                

              });

              

         });
 
 
 
 

        function FormatUrl(url)

        {

            var newUrl = url;

            newUrl += '?ver=' + Math.random().toString();

            return newUrl;

        }

Open in new window

0
 
LVL 16

Accepted Solution

by:
anoyes earned 200 total points
ID: 24040283
Just an FYI, you can prevent caching w/o the use of random query strings by setting cache: false on the JQ $.ajax function.  You can't do that with $.getJSON, but since that is just a convenience function for $.ajax you could do the same thing as you have shown above like this, w/o the need to keep generating a random URL.  I'm looking into the jTemplate thing now...

        $(document).ready(

        function() 

        {

             $("#ddlDept").change(

             function() 

             {

                var DeptID = $("#ddlDept > option[@selected]").attr("text");

                var path;

                

                

                

                if (DeptID != 0) 

                {

                    path = 'http://localhost:1453/PaggingDotNet/Ajax2/Handler.ashx';

                    

                    $.ajax({

                    url: path,

                    dataType: 'json',

                    cache: false,

                    type: 'get',

                    success: function(employees) 

                    {

                        

                        var myobj;

                        myobj = null;

                        myobj = employees;

                        

                        

                        

                        //$("#dvDetails").setTemplate($("#TemplateResultsTable").html());

                        //$("#dvDetails").processTemplate(employees);

                                                

                        

                        

                        

                        var sss;

                        sss = "ID " + myobj.Head[0].id + "<br>";

                        sss = sss + "Name " + myobj.Head[0].firstname + " " + myobj.Head[0].lastname +  "<br>";

                        

                        sss = sss + "ID " + myobj.Head[1].id + "<br>";

                        sss = sss + "Name " + myobj.Head[1].firstname + " " + myobj.Head[1].lastname +  "<br>";

 

                        sss = sss + "ID " + myobj.Head[2].id + "<br>";

                        sss = sss + "Name " + myobj.Head[2].firstname + " " + myobj.Head[2].lastname +  "<br>";

                        

                        document.getElementById( 'dvDetails' ).innerHTML = '';                        

                        $("#dvDetails").html(sss);

                    });               

                }                

              });

              

         });

Open in new window

0
 
LVL 16

Assisted Solution

by:anoyes
anoyes earned 200 total points
ID: 24040767
OK, got it.  First of all forget about my code above - I missed a closing curly brace in there i think.  Anywho, your ASHX page was generating a JSON string with a trailing comma at the end of your records list, which IE doesn't like (http://blog.qoqoa.com/2006/04/18/trailing-comma-within-jsons-array/).  So, make sure that the Records array doesn't have any trailing commas, and the script below should take care of your caching issue.

    <script type="text/javascript">

        $(document).ready(

        function()

        {

            $("#ddlDept").change(

             function()

             {

                 var DeptID = $("#ddlDept > option:selected").attr("text");

                 var path;
 

                 if (DeptID != 0)

                 {

                     path = 'Handler.ashx';

                     $.ajax({

                         url: path,

                         type: 'get',

                         dataType: 'json',

                         cache: false,

                         success: function(employees) {

                             $("#dvDetails").setTemplate($("#TemplateResultsTable").html());

                             $("#dvDetails").processTemplate(employees);

                         }

                     });

                 }

             });
 

        });

    </script>

Open in new window

0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 24041960
Drat, I saw it and ignored it since the JSON editor was happy
0
 
LVL 1

Author Comment

by:shahzad73
ID: 24046511
alright you are right it worked       you owe me these points now     but if can look into this code also  because this code is also generating an error.  it calls the ajax first tmie correctly in all browsers and template is rendered correctly. but the second call reveals the following error.

constructor is null or not an object


this time i got a code    http://www.codeproject.com/KB/aspnet/ASPNET_DataTable_to_JSON.aspx    and function name is   CreateJsonParameters  


whole code is given below   any way i will give away the point

Server side code ASHX 

---------------------
 

<%@ WebHandler Language="C#" Class="Handler" %>
 

using System;

using System.Web;

using System.Data;

using System.Data.SqlClient;

using System.Text;
 
 

public class Handler : IHttpHandler {

    

    public void ProcessRequest (HttpContext context) 

    {

        context.Response.ContentType = "text/plain";

        //context.Response.ContentType = "application/json";
 

        DataTable dt = CreateDataTable();
 

        AddDataToTable("user name", "name 2", "last name", dt);

        AddDataToTable("user name 1", "name 3", "last name", dt);

        AddDataToTable("user name 2", "name 4", "last name", dt);

        AddDataToTable("user name 3", "name 5", "last name", dt);

        AddDataToTable("user name 4", "name 6", "last name", dt);
 

        context.Response.Write( CreateJsonParameters(dt) );

    }

    

    

 

    public bool IsReusable {

        get {

            return false;

        }

    }
 
 
 
 
 
 
 
 
 
 

    private DataTable CreateDataTable()

    {

        DataTable myDataTable = new DataTable();
 

        DataColumn myDataColumn;
 

        myDataColumn = new DataColumn();

        myDataColumn.DataType = Type.GetType("System.String");

        myDataColumn.ColumnName = "id";

        myDataTable.Columns.Add(myDataColumn);
 

        myDataColumn = new DataColumn();

        myDataColumn.DataType = Type.GetType("System.String");

        myDataColumn.ColumnName = "username";

        myDataTable.Columns.Add(myDataColumn);
 

        myDataColumn = new DataColumn();

        myDataColumn.DataType = Type.GetType("System.String");

        myDataColumn.ColumnName = "firstname";

        myDataTable.Columns.Add(myDataColumn);
 

        myDataColumn = new DataColumn();

        myDataColumn.DataType = Type.GetType("System.String");

        myDataColumn.ColumnName = "lastname";

        myDataTable.Columns.Add(myDataColumn);
 

        return myDataTable;

    }
 
 
 
 

    private void AddDataToTable(string username, string firstname, string lastname, DataTable myTable)

    {

        DataRow row;
 

        row = myTable.NewRow();
 

        row["id"] = Guid.NewGuid().ToString();

        row["username"] = username;

        row["firstname"] = firstname;

        row["lastname"] = lastname;
 

        myTable.Rows.Add(row);

    }
 
 
 
 
 
 
 
 
 
 

    public string CreateJsonParameters(DataTable dt)

    {
 

        /* /****************************************************************************
 

         * Without goingin to the depth of the functioning of this Method, i will try to give an overview
 

         * As soon as this method gets a DataTable it starts to convert it into JSON String,
 

         * it takes each row and in each row it grabs the cell name and its data.
 

         * This kind of JSON is very usefull when developer have to have Column name of the .
 

         * Values Can be Access on clien in this way. OBJ.HEAD[0].<ColumnName>
 

         * NOTE: One negative point. by this method user will not be able to call any cell by its index.
 

         * *************************************************************************/
 

        StringBuilder JsonString = new StringBuilder();
 

        //Exception Handling        
 

        if (dt != null && dt.Rows.Count > 0)

        {
 

            JsonString.Append("{ ");
 

            JsonString.Append("\"Head\":[ ");
 

            for (int i = 0; i < dt.Rows.Count; i++)

            {
 

                JsonString.Append("{ ");
 

                for (int j = 0; j < dt.Columns.Count; j++)

                {
 

                    if (j < dt.Columns.Count - 1)

                    {
 

                        JsonString.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + "\"" + dt.Rows[i][j].ToString() + "\",");
 

                    }
 

                    else if (j == dt.Columns.Count - 1)

                    {
 

                        JsonString.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + "\"" + dt.Rows[i][j].ToString() + "\"");
 

                    }
 

                }
 

                /*end Of String*/
 

                if (i == dt.Rows.Count - 1)

                {
 

                    JsonString.Append("} ");
 

                }
 

                else

                {
 

                    JsonString.Append("}, ");
 

                }
 

            }
 

            JsonString.Append("]}");
 

            return JsonString.ToString();
 

        }
 

        else

        {
 
 
 

            return null;
 

        }
 

    }
 
 
 

}
 
 
 
 
 
 
 

Javascript code

---------------
 
 

    <script type="text/javascript">

        $(document).ready(

        function()

        {

            $("#ddlDept").change(

             function()

             {

                 var DeptID = $("#ddlDept > option:selected").attr("text");

                 var path;

 

                 path = FormatUrl('http://localhost:1453/PaggingDotNet/Ajax2/Handler.ashx');

                 

                 if (DeptID != 0)

                 {

                     path = 'Handler.ashx';

                     $.ajax({

                         url: path,

                         type: 'get',

                         dataType: 'json',

                         cache: false,

                         success: function(employees) {

                             $("#dvDetails").setTemplate($("#TemplateResultsTable").html());

                             $("#dvDetails").processTemplate(employees);

                         }

                     });

                 }

             });

 

        });

        

        

        
 

        function FormatUrl(url)

        {

            var newUrl = url;

            newUrl += '?ver=' + Math.random().toString();

            return newUrl;

        }        

    </script>
 
 
 
 
 
 

jTemplate

----------

<script type="text/html" id="TemplateResultsTable">   

<table>
 

  <thead>
 

    <tr style="background-color:Maroon;color:White;">

      <th>Employee ID</th>

      <th>User Name</th>

      <th>First Name</th>

      <th>last Name</th>

    </tr>
 

  </thead>
 

  <tbody>
 

   {#foreach $T.Head as record}
 

    <tr>
 

      <td>{$T.record.id}</td>
 

      <td>{$T.record.username}</td>
 

      <td>{$T.record.firstname}</td>
 

      <td>{$T.record.lastname}</td>
 

    </tr>
 

    {#/for}
 

  </tbody>
 

</table>

</script>

Open in new window

0
 
LVL 16

Expert Comment

by:anoyes
ID: 24046535
Hmmm weird I was pretty sure I had tried that and it was working...oh well.  I'll check it out and get back to you as soon as i have a chance.

-adam
0
 
LVL 1

Author Closing Comment

by:shahzad73
ID: 31564767
anoyes    i will try to resolve the last problme if you can provide me any input that will be great
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

PROBLEM: The other day I was working on adding an ajax request to a webpage that already had a dialog box on the page.  The dialog box was using relative positioning to be positioned next to a form field I had on the page.  Everything was working…
Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now