Ajax.NET bugfixes and new features

I fixed several bugs in the last week. Because of internal complete redesign some objects like DataSet returned wrong to the client-side Javascript. Also some NullReferenceExceptions have been fixed. The proxy files are cached, now.

New features are supporting Bitmap as return value, new .getTable("name") on DataSets to get DataTables instead of the index usage, large data as request arguments (i.e. for contact form or forum), context for the client-side Javascript callback, full Unicode support, new IAjaxObjectConverters, arrays of integer and strings are supported as method arguments:

[Ajax.AjaxMethod]
public string Test18(string[] s)
{
  string r = "";
  foreach(string ss in s)
    r += "<p>" + ss + "</p>\r\n";

  return r;
}

To download version 5.5.13.1 click here. The online examples are updated and will replace the UsageGuide document later. You can download the online examples with full source code at http://ajax.schwarz-interactive.de

The source code of the IAjaxObjectConverters will be placed on my web site in the next days. Currently in the download of the examples you will find a IAjaxObjectConverter for System.DateTime.

Updated: DataSets throw a StackOverflowException when using GUIDs. A workaround will be available here: http://weblogs.asp.net/mschwarz/archive/2005/06/02/410061.aspx The bug is fixed in version 5.6.2.1.

26 Comments

  • G&#252;nther said

    Hi Michael, I got the following error when trying to unzip the new version: Warning: skipping &quot;Ajax.dll&quot;, The 32-bit CRC stored in the local header for this file is not the same as the 32-bit CRC stored in the central header.

    Therefore, I was not able to unzip ajax.dll.

  • G&#252;nther said

    Hmm, I was able to unzip with winrar. I got the (5.5.13.1) version, where did the new version end up?

    Have a nice weekend!

  • Michael Schwarz said

    I updated the Ajax.zip, it was still the old one, thanks.

    @Arno: Yes, I will go on, but you can do it also by building a IAjaxObjectConverter.
    @AndersH: Ok, I will make a change that it is easier to read.

  • walaqi said

    hi,your work is great.i think it is a good prototype for the implement of ajax model.
    but i am doubt about what will happen when i use it under asynchronous scenario.

  • walaqi said

    btw:I test your sample.
    i think it is not safe if you transform the data which user submiting by querystring when you call the method.i can even call the method by combine the whole url in addressbox of ie

  • Michael Schwarz said

    @walaqi: What should happen, the calls are asynchronous calls?!? The second question is no real question, or? Every form you can send is always something you can do directly, there is no more or less security than with typical web sites. Or do you mean something different?

    @Keith: See my last posts here. I'd like to start it but I've some problems where to do this.

  • Nick! said

    Michael, I'm not sure if my comment got through to you through the other form, but I'm having a problem with Ajax.NET returning objects with enums -- specifically, the whole application pool crashes. If I remove the enums its fine, doesn't matter what enum I use (my own, DayOfWeek, one from Ajax.net). Only thing I wonder is if it's because I'm using this on .NET Framework 2.0 Beta 2. Are there any known issues with enums at this point on 1.1?

    Ajax.NET is great otherwise :) If I can get past the enum problems it's ultra handy, cool stuff! And really, it's quite likely that what I would use this for in a live sense wouldn't use enums anyhow.

  • Ryan said

    I'm having particular problems returning a DataSet when filled with a DataAdapter...

    Imports System.Data
    Imports System.Data.SqlClient

    Namespace StoredProcedures
    Class GetMail
    Private Shared sqlAdapter As SqlDataAdapter
    Private Shared dsReturn As DataSet
    Private Shared sqlCommand As sqlCommand

    Shared Function Invoke(ByVal sqlConn As SqlConnection, ByVal UserId As Int64, ByVal Start As Int64, ByVal Amount As Int16, ByRef Count As Int32) As DataSet
    sqlCommand = New sqlCommand(&quot;sm_GetMail&quot;, sqlConn)
    With sqlCommand
    .CommandType = CommandType.StoredProcedure
    .Parameters.Add(New SqlParameter(&quot;@UserID&quot;, UserId))
    .Parameters.Add(New SqlParameter(&quot;@StartAt&quot;, Start))
    .Parameters.Add(New SqlParameter(&quot;@Amount&quot;, Amount))
    .Parameters.Add(New SqlParameter(&quot;@TotalMail&quot;, Count)).Direction = ParameterDirection.Output
    End With
    Return ExecuteAdapter(sqlCommand, Count)
    End Function
    Private Shared Function ExecuteAdapter(ByVal sqlCmd As sqlCommand, ByRef Count As Int32) As DataSet
    sqlAdapter = New SqlDataAdapter(sqlCmd)
    dsReturn = New DataSet
    sqlAdapter.Fill(dsReturn)
    sqlAdapter = Nothing
    If Object.ReferenceEquals(sqlCmd.Parameters(&quot;@Count&quot;).Value, System.DBNull.Value) = True Then
    Count = 0
    End If
    Return dsReturn
    End Function
    End Class
    End Namespace

    -------------
    When I execute the GetMail.Invoke everything seems to be fine the dataset gets populated correctly; however, when it returns via the exposed AjaxMethod I ALWAYS get a System.StackOverflowException in MSCORLIB.DLL.

    It errors on a call to System.Reflection.RuntimeFieldInfo.GetValue apparently from a call from PropsFieldsToJSON according to the call stack :\

    Is there any possible reason for this?

  • Ryan said

    The Ajax method is fairly simple and looks like..

    &lt;Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.Read)&gt; _
    Public Function GetMail() As DataSet
    Dim pCount As Int32
    Return StoredProcedures.GetMail.Invoke(New SqlClient.SqlConnection(&quot;serverinfohere&quot;), 1, 1, 50, pCount)
    End Function

  • KB said

    Is there anyway to access the HttpRequest object from an Ajax Method? If I try to access it inside an Ajax method, it is returning null.

  • AndersH said

    When typing in a expression like this 'javascript:alert(DemoMethods.Test18( [&quot;a\&quot;,\&quot;b&quot;] ).value);' at the test page, I would think that the correct response would be '&lt;p&gt;a&quot;,&quot;b&lt;/p&gt;' and not '&lt;p&gt;a\&lt;/p&gt;&lt;p&gt;&quot;b&lt;/p&gt;' as is return now. That is the quotes in the string should not break the string sinse they are escaped and the broken string should be unescaped.

    I tried to create a little function that would do the right thing, but maybe urlencoding would be simpler.

    private string[] FromJSArray(string s) {
    ArrayList list = new ArrayList();
    int StartPos = -1;
    if (s[0] != '[') throw new FormatException(&quot;Must start with a left square bracket&quot;);
    if (s[s.Length - 1] != ']') throw new FormatException(&quot;Must end with a right square bracket&quot;);
    for (int i = 1; i &lt; s.Length-1; i++) {
    Char ch = s[i];
    if (ch == '&quot;' &amp;&amp; StartPos == -1) {
    StartPos = i;
    } else if (ch == '\\' &amp;&amp; StartPos != -1) {
    i++;
    } else if (ch == '&quot;' &amp;&amp; StartPos != -1) {
    list.Add(System.Text.RegularExpressions.Regex.Unescape(s.Substring(StartPos+1, i - StartPos - 1)));
    StartPos = -1;
    i++;
    if (s[i] != ',' &amp;&amp; i != s.Length-2) new FormatException(&quot;Strings must be seperated by comma&quot;);
    } else if (StartPos == -1) {
    throw new FormatException(&quot;Invalid character outside string&quot;);
    }
    }
    if (StartPos != -1) throw new FormatException(&quot;String not ended&quot;);
    return (string[])list.ToArray(typeof(string));
    }

    (The forum doesn't seem to have a preview, so the code indentation will problably look broken)

  • How to access controls on partial Post Back? said

    Is it event possible to access a control from a server function when it is called from the client. All of my contorls are undefined when the server function is run. Do I need to call the OnInit() function or something?

  • scott e said

    Hi Michael,
    Sorry for no feedback for a bit... been quite busy. I have noticed with this new version, the support for the Decimal type has not been added -- remember you hooked me up with a version that supported it? Anyhow, could you put that back in the next version?

    Otherwise, it's looking great.

    Thanks,
    se

  • Michael Third said

    I must be doing something wrong, but when returning an ArrayList the following is the response stream:

    {'Capacity':4,'Count':4,'IsFixedSize':false,'IsReadOnly':false,'IsSynchronized':false,'SyncRoot':{},'Item':null}

    Thanks,

    Michael

  • Alan W. Cruz said

    Hi Michael,

    In my wrapper I'm using the following code to transform dataset, datatable and datarows into JSON objects, I would like to know if it is optimal or if it's better to find a way to transform the dataset.getxml into JSON format:

    Private Function ConvertDataSet(ByVal ds As DataSet) As String
    Dim sB As New StringBuilder(&quot;{&quot;)
    sB.Append(&quot;'Tables':&quot;)

    For Each dt As DataTable In ds.Tables
    sB.Append(ConvertDataTable(dt))
    sB.Append(&quot;,&quot;)
    Next

    sB.Remove(sB.ToString.Length - 1, 1)
    sB.Append(&quot;]}&quot;)

    Return sB.ToString
    End Function

    Private Function ConvertDataTable(ByVal dt As DataTable) As String
    Dim sB As New StringBuilder(&quot;{&quot;)
    sB.Append(&quot;'Name':'&quot;) : sB.Append(dt.TableName) : sB.Append(&quot;',&quot;)
    sB.Append(&quot;'Rows':[&quot;)

    For Each dr As DataRow In dt.Rows
    sB.Append(ConvertDataRow(dr))
    sB.Append(&quot;,&quot;)
    Next

    sB.Remove(sB.ToString.Length - 1, 1)
    sB.Append(&quot;]}&quot;)

    Return sB.ToString
    End Function

    Private Function ConvertDataRow(ByVal dr As DataRow) As String
    Dim sCol As String
    Dim sB As New StringBuilder(&quot;{&quot;)

    For Each col As DataColumn In dr.Table.Columns
    sCol = col.ColumnName
    sB.Append(&quot;'&quot;) : sB.Append(sCol) : sB.Append(&quot;':&quot;)

    Select Case dr(sCol).GetType.ToString()
    Case &quot;System.Int32&quot;
    sB.Append(dr(sCol)) : sB.Append(&quot;,&quot;)
    Case Else
    sB.Append(&quot;'&quot;) : sB.Append(dr(sCol)) : sB.Append(&quot;',&quot;)
    End Select
    Next

    sB.Remove(sB.ToString.Length - 1, 1)
    sB.Append(&quot;}&quot;)

    Return sB.ToString
    End Function

Comments have been disabled for this content.