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
The Layout
class is defined 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 I can get the literal JSON that would be (de)serialized. I'm using that to test invoking this service via 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 by buildLayout()
is the exact JSON returned by the serialize()
call in the VB code. For some reason, when I invoke the web service, the input parameter layout
in SaveLayout()
is Nothing. Something must be failing on deserialization. Any idea why?
See Question&Answers more detail:
os