WCF does not deserialize JSON input

I have a WCF service defined as follows:

Imports System.ServiceModel
Imports System.ServiceModel.Web

<ServiceContract()>
Public Interface ILayoutService

  <OperationContract()>
  <WebInvoke(Method:="POST",
             BodyStyle:=WebMessageBodyStyle.WrappedRequest,
             RequestFormat:=WebMessageFormat.Json,
             ResponseFormat:=WebMessageFormat.Json)>
  Sub SaveLayout(ByVal layout As Layout)

  <OperationContract()>
  Function GetLayout() As Layout

End Interface

A class is Layoutdefined as:

Imports System.Runtime.Serialization

<DataContract()>
Public Class Layout

  <DataMember()>
  Public Property Columns As New List(Of ContentColumn)

End Class

<DataContract()>
Public Class ContentColumn
  <DataMember()>
  Public Property Name As String = "Column Name"

  <DataMember()>
  Public Property Position As Integer

  <DataMember()>
  Public Property Modules As New List(Of ContentModule)

End Class

<DataContract()>
Public Class ContentModule

  <DataMember()>
  Public Property Name As String = "Module Name"

  <DataMember()>
  Public Property Position As Integer

End Class

The implementation of ILayoutService is as follows:

Imports System.ServiceModel.Activation
Imports System.Web.Script.Serialization

<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Required)>
Public Class LayoutService
  Implements ILayoutService

  Public Sub SaveLayout(ByVal layout As Layout) Implements ILayoutService.SaveLayout
    Dim l As New Layout
    Dim left, center, right As New ContentColumn

    left.Name = "Left Column"
    left.Position = 0
    center.Name = "Center Column"
    center.Position = 1
    right.Name = "Right Column"
    right.Position = 2

    Dim topLeft, centerLeft, bottomLeft, topCenter, centerCenter, bottomCenter, topRight, centerRight, bottomRight As New ContentModule

    topLeft.Name = "Top Left"
    topLeft.Position = 0
    centerLeft.Name = "Center Left"
    centerLeft.Position = 1
    bottomLeft.Name = "Bottom Left"
    bottomLeft.Position = 2

    topCenter.Name = "Top Center"
    topLeft.Position = 0
    centerCenter.Name = "Center Center"
    centerCenter.Position = 1
    bottomCenter.Name = "Bottom Center"
    bottomCenter.Position = 2

    topRight.Name = "Top Right"
    topRight.Position = 0
    centerRight.Name = "Center Right"
    centerRight.Position = 1
    bottomRight.Name = "Bottom Right"
    bottomRight.Position = 2

    left.Modules.Add(topLeft)
    left.Modules.Add(centerLeft)
    left.Modules.Add(bottomLeft)

    center.Modules.Add(topCenter)
    center.Modules.Add(centerCenter)
    center.Modules.Add(bottomCenter)

    right.Modules.Add(topRight)
    right.Modules.Add(centerRight)
    right.Modules.Add(bottomRight)

    l.Columns.Add(left)
    l.Columns.Add(center)
    l.Columns.Add(right)

    Dim json As New JsonResult
    json.Data = l
    Dim serializer As New JavaScriptSerializer
    Dim output = serializer.Serialize(json.Data)
  End Sub

  Public Function GetLayout() As Layout Implements ILayoutService.GetLayout
    Dim l As New Layout
    Dim c As New ContentColumn
    Dim m As New ContentModule
    c.Modules.Add(m)
    l.Columns.Add(c)
    Return l
  End Function
End Class

I implemented SaveLayout()so that I can get a literal JSON that will be (de) serialized. I use this to test the call to this service through jQuery:

$(document).ready(function () {

  $("#saveLayout").click(function () {

    var layout = buildLayout();
    var jsonLayout = $.toJSON(layout);

    $.ajax({
      type: "POST",
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      url: "/Services/LayoutService.svc/SaveLayout",
      data: jsonLayout,
      dataType: "json",
      success: function (result) {
        alert(result.d.Columns[0].Name);
      },
      error: function (xhr, ajaxOptions, thrownError) {
        var jsonFault = JSON.parse(xhr.responseText);
        alert(jsonFault.Message);
      }
    });
    return false;
  });

});

function buildLayout() {
  var layout = { "Columns": [
    { "Name": "Left Column", "Position": 0, "Modules": [
      { "Name": "Top Left", "Position": 0 },
      { "Name": "Center Left", "Position": 1 },
      { "Name": "Bottom Left", "Position": 2}]
    },
    { "Name": "Center Column", "Position": 1, "Modules": [
      { "Name": "Top Center", "Position": 0 },
      { "Name": "Center Center", "Position": 1 },
      { "Name": "Bottom Center", "Position": 2}]
    },
    { "Name": "Right Column", "Position": 2, "Modules": [
      { "Name": "Top Right", "Position": 0 },
      { "Name": "Center Right", "Position": 1 },
      { "Name": "Bottom Right", "Position": 2}]
    }]
  };

  return layout;
}

The layout returned buildLayout()is the exact JSON returned by the call serialize()in VB code. For some reason, when I call the web service, the input parameter Layoutin SaveLayout()is Nothing. Something must fail with deserialization. Any idea why?

+1
source share
1 answer

it is difficult to describe only the details that you have provided.

:

  • , SvcTraceViewer. MSDN .

  • . includeExceptionDetailInFaults, , .

  • Fiddler , .

, , , , . , , !:)

+1

All Articles