Passing a JSON object as a Dictionary(Of String, Object) to WCF Web Service
I'm trying to setup a WCF web service to be consumed by JavaScript using JSON and jQuery. I've noticed that you can send JSON without a DataContract if the service method parameters match the naming structure of the JSON object:
<ServiceContract(Namespace:="http://foo.com/bar")>
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)>
Public Class WebServices
<OperationContract()>
Public Function Test(fullname As String)
Return CustomFunctions.SerializeJSON(New With {
.SSN = "999-99-9999",
.Birthday = "9/22/1983"})
End Function
End Class
...And JavaScript...
$.ajax({
url: "webservices.svc/Test",
data: JSON.stringify({
"fullname" : "John Smith"
}),
type: "POST",
processType: false,
contentType: "application/json; charset=utf-8",
dataType: "text",
success: function (result)
{
console.log(result);
},
error: function (xhr)
{
console.log(xhr.responseText);
}
});
This works great, but I can see an issue coming up if I want to send the web service a lot of data. Naturally the parameter list is going to get really long and ugly. The alternative is to create a DataContract. However I'm most likely going to be creating a lot of web services and I don't want to have to create a brand new DataContract every time I want to send data longer than 5 key-value pairs.
What I'm hoping is that there's a way to access the incoming JSON object as a Dictionary(Of String, Object) through the method parameter:
<OperationContract()>
Public Function Test(data As Dictionary(Of String, Object))
Dim firstName As String = data("FirstName")
Dim lastName as String = data("LastName")
'...logic goes here...
'....return JSON object
End Function
Does anyone know if this is possible? What do most people do in this sc开发者_如何学JAVAenario? I had this working great in ASMX so I know it's possible.
Ok I think I figured out how to do this (for those interested). I need to bypass the DataContracts (nothing against DataContracts, they're just a litte much when the only client is my AJAX code). In order to do this I changed the web service method to look like this:
<OperationContract()>
<WebInvoke(Method:="POST", BodyStyle:=WebMessageBodyStyle.Bare, ResponseFormat:=WebMessageFormat.Json)>
Public Function Test(request As Stream) As String
Using reader As New StreamReader(request)
Dim serializer As New JavaScriptSerializer()
Dim data As Dictionary(Of String, Object) = serializer.Deserialize(Of Dictionary(Of String, Object))(reader.ReadToEnd())
Dim firstName As String = data("FirstName")
Dim lastName As String = data("LastName")
Return serializer.Serialize(New With {.SSN = "999-99-9999",
.Birthday = "9/22/1983"})
End Using
End Function
This will take in the request as a raw stream and leave the deserialization up to me (which I actually prefer - the less magic the better).
The AJAX didn't change much except for the fact that I needed to remove the contentType (leave it as default) and change the dataType of the response to json (when it was "text" I needed to deserialize it twice for some reason):
$.ajax({
url: "webservices.svc/Test",
data: JSON.stringify({
"FirstName": "John",
"LastName": "Smith"
}),
type: "POST",
dataType: "json",
success: function (result)
{
var data = JSON.parse(result);
console.log(data.SSN);
},
error: function (xhr)
{
console.log(xhr.responseText);
}
});
I hope this helps anyone wanting to avoid DataContracts.
精彩评论