0

Guys, I can't seem to get the object serialization working correctly clientside for my app? When I used the getJSON() method inside jQuery with a response mime type of text/json (serialized using JSON.Net library), it was working fine, but as soon as I moved it across to an ajax() request (so I could post my code in webmethods on my page) its fallen apart. Any ideas would be greatly appreciated.

Edit: I'm using framework 2.0, not 3.5

My javascript looks like this:

    function companySearch(txt) 
    {
        $("#<%= divCompanyResult.ClientID %>").hide();
        $("#<%= divCompanyResult.ClientID %>").html("");

        var strCompanySearch = $("#<%= tbCompanySearch.ClientID %>").val();

        $.ajax
        ({
            type: "POST",
            url: "Home.aspx/GetCompanies", 
            contentType: "application/json; charset=utf-8", 
            datatype: "json",
            data: "{name: '" + strCompanySearch + "'} ", 
            success: companySearchSuccess,
            error: onError
        });

        return (true);
    }

    function companySearchSuccess(response)
    {
        $.each(response, 
            function(i, company) 
            {
                $("#<%= divCompanyResult.ClientID %>").prepend(company.Name + "<br />");
            });

        $("#<%= divCompanyResult.ClientID %>").slideDown(1000);
    }

And my .ASPX page (nb. its a page, not a webservice), looks like this:

    [WebMethod]
    public static Company[] GetCompanies(string name)
    {
        Company[] companies = Company.FindCompanies(name);

        return companies;
    }

And the object its returning:

[ActiveRecord]
public class Company : ActiveRecordBase<Company>
{
    private int iD;
    private string name;
    private string accountNo;
    private string streetAddr1;
    private string streetAddr2;
    private string streetSuburb;
    private string streetCity;
    private string postAddr1;
    private string postAddr2;
    private string postSuburb;
    private string postState;
    private string postPC;
    private string accountType;
    private string accountSubType;
    private string areaRep;
    private string status;
    private string overview;
    private string bpcsId;
    private string modifiedBy;
    private DateTime modifiedDate;
    private IList<Contact> contacts;

    [PrimaryKey]
    public int ID { get { return this.iD; } set { this.iD = value; } }
    [Property]
    public string Name { get { return this.name; } set { this.name = value; } }
    [Property]
    public string AccountNo { get { return this.accountNo; } set { this.accountNo = value; } }
    [Property]
    public string StreetAddr1 { get { return this.streetAddr1; } set { this.streetAddr1 = value; } }
    [Property]
    public string StreetAddr2 { get { return this.streetAddr2; } set { this.streetAddr2 = value; } }
    [Property]
    public string StreetSuburb { get { return this.streetSuburb; } set { this.streetSuburb = value; } }
    [Property]
    public string StreetState { get { return this.streetCity; } set { this.streetCity = value; } }
    [Property]
    public string StreetPC { get { return this.streetCity; } set { this.streetCity = value; } }
    [Property]
    public string PostAddr1 { get { return this.postAddr1; } set { this.postAddr1 = value; } }
    [Property]
    public string PostAddr2 { get { return this.postAddr2; } set { this.postAddr2 = value; } }
    [Property]
    public string PostSuburb { get { return this.postSuburb; } set { this.postSuburb = value; } }
    [Property]
    public string PostState { get { return this.postState; } set { this.postState = value; } }
    [Property]
    public string PostPC { get { return this.postPC; } set { this.postPC = value; } }
    [Property]
    public string AccountType { get { return this.accountType; } set { this.accountType = value; } }
    [Property]
    public string AccountSubType { get { return this.accountSubType; } set { this.accountSubType = value; } }
    [Property]
    public string AreaRep { get { return this.areaRep; } set { this.areaRep = value; } }
    [Property]
    public string Status { get { return this.status; } set { this.status = value; } }
    [Property]
    public string Overview { get { return this.overview; } set { this.overview = value; } }
    [Property]
    public string BPCSId { get { return this.bpcsId; } set { this.bpcsId = value; } }
    [Property]
    public string ModifiedBy { get { return this.modifiedBy; } set { this.modifiedBy = value; } }
    [Property]
    public DateTime ModifiedDate { get { return this.modifiedDate; } set { this.modifiedDate = value; } }

    // Inverse ensures is read-only ie. Contact controls the relationship
    // Castle will usually infer relationship, but we explicitly set just to be on the safe side
    [HasMany(Inverse=true, Table="Contact", ColumnKey="CompanyId")] 
    [ScriptIgnore]
    public IList<Contact> Contacts { get { return this.contacts; } set { this.contacts = value; } }

    protected Company() { }

    public Company(string Name, string StreetAddr1)
    {
        this.Name = Name;
        this.StreetAddr1 = StreetAddr1;

        ModifiedBy = "Test";
        ModifiedDate = DateTime.Now;
    }

    public static Company[] FindCompanies(string name)
    {
        return FindAll(Expression.InsensitiveLike("Name", "%" + name + "%"));
    } 
}

2 Answers 2

3

Turns out I had overlooked the camel casing for the dataType property on my ajax request

Old:

    $.ajax
    ({
        type: "POST",
        url: "Home.aspx/GetCompanies", 
        contentType: "application/json; charset=utf-8", 
        datatype: "json",
        data: "{name: '" + strCompanySearch + "'} ", 
        success: companySearchSuccess,
        error: onError
    });

Solution

    $.ajax
    ({
        type: "POST",
        url: "Home.aspx/GetCompanies", 
        contentType: "application/json; charset=utf-8", 
        dataType: "json",
        data: "{name: '" + strCompanySearch + "'} ", 
        success: companySearchSuccess,
        error: onError
    });

Hope this helps others avoid the hours of searching google, tutorials and blogs that I suffered... Doh!

Sign up to request clarification or add additional context in comments.

1 Comment

Heh, I just spent 30 mins tearing my hair out trying to work out why my script couldn't read my object.....and it was exactly this mistake! :( Bloomin' case sensitive languages.
1

Microsoft's WebMethods encode the return data inside of an object named 'd'. So, you need to change your code to look like this:

function companySearchSuccess(response)
{
  // Get encoded data
  response = response.d; // you could rename this, or just change the variable reference

}

This is done to prevent a special kind of javascript exploit. You can see more details here and here.

3 Comments

Ah, the dreaded "d". Very questionable security "feature" if you ask me... anyway, "response = response.d || response;" would be more appropriate, as earlier versions of ASP.NET don't use the "d" wrapper.
Unfortunately I'm using framework 2.0, so this isn't the solution. I have checked the response with Firebug and the string isn't wrapped into a "d" object...
@Tsvetomir: good addition. But yeah, that 'feature' makes webmethods pretty incompatible with other frameworks, which can be a real pain.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.