views:

77

answers:

4

I realize there are tonnes of similar questions already up here but I cannot figure this one out.

I have a Web Service (C#, .net 3.5). The essential Code you need to know of is as follows:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WSMember : System.Web.Services.WebService {

    public WSMember () {   
    }


    [WebMethod]
    [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
    public string GetMember(string IdMember)
    {
        //Ignore the parameter for now... I will be looking up a database with it... 
        //For now just return a minimal object:
        Member m = new Member();
        m.Surname = "Smith";
        m.FirstName = "John";
        return new JavaScriptSerializer().Serialize(m);
    }

Also, in web.config, I made the following addition (which I just saw on some other post... is this normal/safe?)

  <webServices>
      <protocols>
        <add name="HttpGet" />
        <add name="HttpPost" />
      </protocols>
    </webServices>

Then in Default.aspx, I the two key references...

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt; 
<script type="text/javascript" src="jquery.json-2.2.min.js"  ></script>

jquery.json-2.2.min.js was downloaded from google code

And Here is the Javascript:

<script type="text/javascript">
         $(document).ready(function() {
             $("#button1").click(function(event) {
                 var myData = { IdMember: "2" };
                 var encoded = $.toJSON(myData);

                 alert(encoded);

                 $.ajax({
                     type: "POST",
                     url: "WSMember.asmx/GetMember",
                     data: encoded,
                     contentType: "application/json; charset=utf-8",
                     dataType: "json",
                     success: function(msg) {
                         alert("worked" + msg.d);
                         //$("#sidebar").append(msg);
                     },
                     error: function(msg) {
                         alert(msg.d);
                         //$("#sidebar").append(msg);
                     }
                 });
             });
         });

    </script>

When I execute it, the encoded json appears in the message box as expected... i.e. with double quotes:

{ "IdMember":"2" }

However, it always fails. Even for the most basic Hello World with no data being passed in, it fails. I keep getting "undefined" for the message data.

If I just use alert(msg), it displays [object XMLHttpRequest]

Does anyone know where my data is getting lost??

And another question... is there anything fundamentally wrong with what I'm doing?

Thanks a lot.

UPDATE: Problem is fixed. The key mistakes in the above code are:

[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]

should be

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

Also, on the form, when using a button to call the javascript, I was incorrectly setting the input type...

<input id="button1" type="submit" value="Just a test" />

when it should say:

<input id="button1" type="button" value="Just a test" />

Many thanks to all who helped.

+2  A: 

It seems to me that your main problem that you try to manually use JavaScriptSerializer().Serialize instead of returning an object. The response from the web service will be double JSON encoded.

You are right! There are a lot of a close questions. Look at here http://stackoverflow.com/questions/2670147/can-i-return-json-from-an-asmx-web-service-if-the-contenttype-is-not-json/2671583#2671583 and http://stackoverflow.com/questions/3189653/cant-get-jquery-ajax-to-parse-json-webservice-result/3190823#3190823 and you will (I hope) find the answer.

UPDATED: Sorry, but you have a small error somewhere what you didn't posted. To close the problem I created a small project with an old version of Visual Studio (VS2008) which has practically exactly your code and which work. I placed it on http://www.ok-soft-gmbh.com/jQuery/WSMember.zip. You can download it, compile and verify that it works. Then you can compare your code with my and find your error.

Best regards

Oleg
Oleg, On a slightly different topic, is changing these services to WCF REST strongly advised?? You seem to be all for it here...! http://stackoverflow.com/questions/3189653/cant-get-jquery-ajax-to-parse-json-webservice-result/3190823#3190823
beer-drinker
People downvote me for saying it, but I don't recommend using WCF for simple AJAX callbacks. WCF is far more powerful, but doesn't really bring much to the table if you aren't using that power. In fact, ASMX's JavaScriptSerializer is actually more flexible than WCF's DataContractJsonSerializer when it comes to dates and enums. WCF's added complexity is hard to justify in this scenario (they're working on it though).
Dave Ward
Oleg, your example drew my attention to one single line of code which fixed it. Thank you very much. The code was actually OK. for the button you have type="button". I had type="submit".I had just taken an old form and edited it... without noticing the type for the button. Also, I updated my jquery reference to 1.4.2 (I was still referring to 1.3.2) just for the sake of upating. I also use your "stringify" suggestion, although $.toJSON(myData) works too.Dave -- many thanks for your comments too. Very helpful.
beer-drinker
@Dave: I agree with you, that different technique are introduced for the special case where they do exactly what needed. I used mostly WCF, but agree that `JavaScriptSerializer` has some nice features which I also miss in `DataContractJsonSerializer`. In all cases if somebody ask something about ASMX in his question and his problem is easy enough, than I didn't recommend him to switch to WCF. Both technique are good enough in the most cases.
Oleg
+1  A: 

Hey,

If you are doing a post to your data, why are you defining UseHttpGet = true? Shouldn't that be false to match the response type from your request? Also, putting a breakpoint in the ws call to see exactly what the serializer returns would help too... I don't think it should return a JSON object if the return value is a string.

HTH.

Brian
Correct! It is one more bug in the program.
Oleg
A: 

thanks for the reply guys. I have tried the following so...

UseHttpGet = true is now changed to false. (Again - I saw it somewhere so I tried it... but I knew it couldn't be right :-/ )

Let's say the web service now returns a string. I build the string as follows (seems a bit crazy... serializing it did the exact same thing... )

    StringBuilder sb = new StringBuilder();
    sb.Append("{");
    sb.Append("\"Surname\":");
    sb.Append("\"");
    sb.Append(m.Surname);
    sb.Append("\"");

    sb.Append(",\"FirstName\":");
    sb.Append("\"");
    sb.Append(m.FirstName);
    sb.Append("\"");

    sb.Append("}");

    return sb.ToString();

This code returns something like:

{"Surname":"Smith","FirstName":"John"}

I still get the exact same error...

I have also tried something like returning the object "Member",so the code becomes:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public Member GetMember(string IdMember)
{
    Member m = new Member();
    m.Surname = "Smith";
    m.FirstName = "John";

    return m;
}

This too throws the same error.

Sorry to be a pain... I've read both of those links, and others. Just can't see why this any different.

Is there any extra config setting I need to be aware of possibly??

Thanks a lot for replies.

beer-drinker
you will typically want to update your original question if you have more information instead of posting an answer to your own question.
dave thieben
A: 

Yes, definitely do not manually serialize the object. If you return a Member type, the framework will handle the JSON serialization for you.

When you're seeing the [object XMLHttpRequest] alert, that sounds like it's getting into the error handler in your $.ajax() call, where the response passes in its XHR object as the first parameter. You're probably getting a 500 error on the server.

Here's an example of decoding the ASP.NET AJAX error response in jQuery. Most simply, change your error handler to this:

error: function(xhr, status, error) {
  var err = eval("(" + xhr.responseText + ")");

  alert(err.Message);
}

That will give you some insight into what the specific error is.

Dave Ward