SitePoint Sponsor

User Tag List

Results 1 to 12 of 12
  1. #1
    SitePoint Member
    Join Date
    Oct 2011
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Serialize/Deserialize JSON object in .NET 3.5 Using JavaScriptSerializer

    Hello Sitepoint,

    I am trying to implement some AJAX(using jQuery) in my company's CMS system and am running into a couple problems. I have read all over online and looked at quite a few examples but just can't seem to get this to work or understand the best practice when communicating with methods on the server through AJAX.

    I would like to just pass a JSON object into .NET method, deserialize into an object, insert into db, and serialize the object back to the caller without using WCF, etc. The problem is I keep receiving this error message: No parameterless constructor defined for type of \u0027System.String\u0027. If anyone could give me some insight or comprehensive examples to read through I would very much like you forever:)

    My JSON as I build it from the form:
    Code:
     var data = '{"replacementPartsDiagram":{"diagramTitle": "' + DiagramTitle + '","diagramImagePath": "' + DiagramImagePath + '","diagramSortOrder": ' + DiagramSortOrder + ',"flattenedDiagramRefNumbers": "' + FlattenedDiagramRefNumbers + '"}}';
    The actual post request going through(according to firebug):
    Code:
    {"replacementPartsDiagram":{"diagramTitle": "Foo Bar","diagramImagePath": "Koala.jpg","diagramSortOrder": 3,"flattenedDiagramRefNumbers": "1,44394,2,45194,--,47092,3,45202,4,44403,5,45200,6,44405,7,44407,8,44409,9,44411"}}
    Calling jQuery Ajax method(being called through a jQuery UI dialog add button):
    Code:
    $.ajax({
                                type: 'POST',
                                url: 'categories.aspx/addRPDiagram',
                                data: data,
                                contentType: "application/json; charset=utf-8",
                                dataType: "json",
                                context: this,
                                timeout: 5000,
                                success: function (msg) {
                                    alert(msg.d);
                                    /*if (msg.d) {
                                    alert("Successfully entered the new diagram");
                                    }
                                    else {
                                    alert("Error! The diagram was not entered into the database!");
                                    }*/
                                    $(this).dialog("close");
                                },
                                error: function (xhr, status, errorThrown) {
                                    alert("Error!" + xhr.responseText + '  ' + errorThrown);
                                }
                            });
    The webmethod in .NET. I just wanted to see if I could get anything returned at this point:
    Code:
     <WebMethod()> _
        Public Shared Function addRPDiagram(replacementPartsDiagram As String) As String
            Dim serializer = New JavaScriptSerializer()
            Dim rep As ReplacementPartsDiagram = serializer.Deserialize(Of ReplacementPartsDiagram)(replacementPartsDiagram)
            Return rep.DiagramTitle
        End Function
    The ReplacementPartsDiagram Class:
    Code:
    Public Class ReplacementPartsDiagram
        Private _diagramTitle As String
        Private _diagramImagePath As String
        Private _diagramSortOrder As Integer
        Private _flattenedDiagramRefNumbers As String
    
        Public Sub ReplacementPartsDiagram()
    
        End Sub
    
        Public Property DiagramTitle As String
            Get
                Return _diagramTitle
            End Get
            Set(value As String)
                If _diagramTitle = value Then
                    Return
                End If
                _diagramTitle = value
            End Set
        End Property
    
        Public Property DiagramImagePath As String
            Get
                Return _diagramImagePath
            End Get
            Set(value As String)
                If _diagramImagePath = value Then
                    Return
                End If
                _diagramImagePath = value
            End Set
        End Property
    
        Public Property DiagramSortOrder As Integer
            Get
                Return _diagramSortOrder
            End Get
            Set(value As Integer)
                If _diagramSortOrder = value Then
                    Return
                End If
                _diagramSortOrder = value
            End Set
        End Property
        Public Property FlattenedDiagramRefNumbers As String
            Get
                Return _flattenedDiagramRefNumbers
            End Get
            Set(value As String)
                If _flattenedDiagramRefNumbers = value Then
                    Return
                End If
                _flattenedDiagramRefNumbers = value
            End Set
        End Property
    
        
    End Class
    I just can't seem to wrap my head around the best way to do this as there is so many examples everywhere. Any direction would be awesome.

    Thanks guys!

  2. #2
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    What you really want to be using is the WebAPI -- that does this automagically.

    The error message is accurate -- it can't construct an instance of the string class. It will, however, automagically deserialize your json if you just let it take the ReplacementPartsDiagram as the parameter.

  3. #3
    SitePoint Member
    Join Date
    Oct 2011
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have read a bit on webAPI, but is it supported in 3.5? If so I will read on that.

    So your saying my web method signature should look like this?:
    Code:
    Public Shared Function addRPDiagram(replacementPartsDiagram As ReplacementPartsDiagram) As String
            Dim serializer = New JavaScriptSerializer()
            Dim rep As ReplacementPartsDiagram = serializer.Deserialize(Of ReplacementPartsDiagram)(replacementPartsDiagram)
    End Function
    Thanks WWB!

  4. #4
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Web API on 3.5? No, it is 4.0 / 4.5 only.

    My VB is a bit rusty, but yes, that looks largely right. What are you returning there? It doesn't seem to be passing a string back.

  5. #5
    SitePoint Member
    Join Date
    Oct 2011
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sorry I forgot that portion...Right now I am just trying to return rep.DiagramTitle. The problem I found with setting the parameter to be strongly typed is I don't see an overloaded version of deserialize.

    It only takes the type - (Of T) and the input JSON string - (replacementPartsDiagram). That's why I initially had the parameter as a string.

    I decided to bypass this deserialization part just to see if I could populate an object with the individual properties in the JSON and then serialize the object back again.

    Code:
    Public Shared Function addRPDiagram(diagramTitle As String, diagramImagePath As String, diagramSortOrder As String, flattenedDiagramRefNumbers As String) As String
            Dim serializer = New JavaScriptSerializer()
           
            Dim rp As New ReplacementPartsDiagram
            rp.DiagramTitle = diagramTitle
            rp.DiagramImagePath = diagramImagePath
            rp.DiagramSortOrder = CInt(diagramSortOrder)
            rp.FlattenedDiagramRefNumbers = flattenedDiagramRefNumbers
            Return serializer.Serialize(rp)
    
          
        End Function
    The problem I am running into now is accessing the properties on the callback. When I try to alert the values of each property, I see undefined.
    Code:
     var data = "{'diagramTitle': '" + DiagramTitle + "','diagramImagePath': '" + DiagramImagePath + "','diagramSortOrder': " + DiagramSortOrder + ",'flattenedDiagramRefNumbers': '" + FlattenedDiagramRefNumbers + "'}";
                            $.ajax({
                                type: 'POST',
                                url: 'categories.aspx/addRPDiagram',
                                data: data,
                                contentType: "application/json; charset=utf-8",
                                dataType: "json",
                                context: this,
                                timeout: 5000,
                                success: function (msg) {
                                    var repDiag = msg.d;
                                    alert(repDiag.diagramTitle);
                                    alert(repDiag.diagramImagePath);
                                    alert(repDiag.diagramSortOrder);
                                    alert(repDiag.flattenedDiagramRefNumbers);
                                    /*if (msg.d) {
                                    alert("Successfully entered the new diagram");
                                    }
                                    else {
                                    alert("Error! The diagram was not entered into the database!");
                                    }*/
                                    $(this).dialog("close");
                                }
    Any hints to what I am missing?

  6. #6
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    The trick is you don't -- the web service deserializes the object for ya. Or at least it should.

  7. #7
    SitePoint Member
    Join Date
    Oct 2011
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I figured out why I couldn't access the values. I am not really understanding why for sure, but parsing the "d" object into a variable let me access them normally.
    Code:
    var data = "{'diagramTitle': '" + DiagramTitle + "','diagramImagePath': '" + DiagramImagePath + "','diagramSortOrder': " + DiagramSortOrder + ",'flattenedDiagramRefNumbers': '" + FlattenedDiagramRefNumbers + "'}";
                            $.ajax({
                                type: 'POST',
                                url: 'categories.aspx/addRPDiagram',
                                data: data,
                                contentType: "application/json; charset=utf-8",
                                dataType: "json",
                                context: this,
                                timeout: 5000,
                                success: function (msg) {
    
                                    result = $.parseJSON(msg.d);
                                    alert(result.DiagramTitle);
                                    alert(result.DiagramImagePath);
                                    alert(result.DiagramSortOrder);
                                    alert(result.FlattenedDiagramRefNumbers);
                                    /*if (msg.d) {
                                    alert("Successfully entered the new diagram");
                                    }
                                    else {
                                    alert("Error! The diagram was not entered into the database!");
                                    }*/
                                    $(this).dialog("close");
                                }
    The actual return from the web method after using the JavaScriptSerializer as this:
    Code:
    {"d":"{\"DiagramTitle\":\"Foo Bar\",\"DiagramImagePath\":\"Tulips.jpg\",\"DiagramSortOrder\":3,\"FlattenedDiagramRefNumbers\":\"1,44394,2,45194,--,47092,3,45202,4,44403,5,45200,6,44405,7,44407,8,44409,9,44411\"}"}
    Still can't get the deserialization of the JSON string to work in the webmethod though. Not quite sure what that's about or what I am missing there. Would DataContracts/Members be a better option?

  8. #8
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Just noticed one thing -- you should be feeding the javascript side of things a hash, not a string. It is probably jsoning your json now.

    DataContracts on your DTO would help.

    Finally, if you just want to POST a json string, you might want to look at writing a IHttpHandler and posting to that. Not the most ".NET" thing to do bit it does work pretty well.

  9. #9
    SitePoint Member
    Join Date
    Oct 2011
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am just using the JavaScriptSerializer on my object for the return to javascript. It wraps it in a "d" object I suppose for security? Anyways, how would I return this as a hash and be able to get the values returned? I am unfamiliar with that.

    I wonder if my deserializing the json into a .NET object problem I was having before was because I was because of how my json is formatted.....I have seen a lot of examples online where theirs supposedly works without a hitch. I was thinking of trying newton's JSON.NET instead of the .NET serializer to see if that made a difference.

    Do you know of any good sources(books or online tutts) for making a RESTful API in .NET 3.5 and above? Eventually I will refresh this project into MVC and I could see the need coming, but still have to support some of the 3.5 webforms portals we have internally.

    Thanks!

  10. #10
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Why are you stuck on 3.5? Very little reason not to upgrade to 4.0 which gets you the WebAPI which is quite sweet. Or other nifty toys like nancy. And a slew of awesome language features that you really can't understand you are missing until you are missing them.

    If you really can't get off 3.5, you might want to check out open rasta.

    If your definition of RESTful is really "I need to do a little bit of HTTP GET / POSTing of JSON at low scale" then IHttpHandlers work quite well in my experience.

    Json.NET is great. So great they actually folded it into the WebAPI. But serialization-wise it works lots like the JavaScript serializer so problems are likely to transfer. Might help if you post the DTO you are trying to deserialize from / to.

  11. #11
    SitePoint Member
    Join Date
    Oct 2011
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Right now I think I just need a little POSTing of JSON at low scale to get by until the upgrade to MVC and 4.0+'s goodness. I'll look into just the handlers for these cases right now but is there any difference's security wise between using the page methods decorated with webmethod and a handler?

    I finally did figure out my entire problem from the start using javascriptserializer......I feel like an idiot too.

    My client code after creating js object. I did go and get json2.js for JSON.stringify method on the DTO.
    Code:
    var ReplacementPartsDiagram = {};
    //assign members
    var DTO = { 'ReplacementPartsDiagram': ReplacementPartsDiagram };
    Webmethod:
    Code:
    Public Shared Function addRPDiagram(replacementPartsDiagram As ReplacementPartsDiagram) As String
    
    End Function
    No capital R......pfffttt. I guess the moral of the story is the names have to match exactly and like you said, Webmethod does automagically deserialize the object and everything works fine using it to serialize it back. I can't wait to dig into WEBAPI in the future.

    Thanks again WWB!

  12. #12
    SitePoint Author silver trophybronze trophy
    wwb_99's Avatar
    Join Date
    May 2003
    Location
    Washington, DC
    Posts
    10,649
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Yup, that is why I asked about the DTO. I think Json.NET handles this a bit better by default, and you could always use attributes to get around this if you wanted to be explicit.

    Security-wise there isn't a difference presuming you are using typical ASP.NET security -- anything served by aspnet_isapi can stand behind the same authentication.

    Also note that you can use ASP.NET web forms 4.0 (probably with zero code modification) with the web API, you don't have to use MVC.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •