将JSON对象作为字典(字符串,对象)传递给WCF Web服务

时间:2011-09-08 19:00:28

标签: vb.net wcf web-services json

我正在尝试使用JSON和jQuery设置一个WCF Web服务供JavaScript使用。我注意到,如果服务方法参数与JSON对象的命名结构匹配,则可以在没有DataContract的情况下发送JSON:

<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

......还有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);
    }
});

这很好用,但如果我想向Web服务发送大量数据,我可以看到一个问题。当然,参数列表会变得非常冗长和丑陋。另一种方法是创建DataContract。但是,我很可能会创建大量的Web服务,而且每次我想发送超过5个键值对的数据时,我都不想创建全新的DataContract。

我希望有一种方法可以通过方法参数以字典(Of String,Object)的形式访问传入的JSON对象:

<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

有人知道这是否可行?大多数人在这种情况下做了什么?我在ASMX工作得很好,所以我知道这是可能的。

1 个答案:

答案 0 :(得分:0)

好的,我想我想出了如何做到这一点(对于那些感兴趣的人)。我需要绕过DataContracts(没有任何反对DataContracts,当唯一的客户端是我的AJAX代码时,它们只是一个小问题)。为此,我将Web服务方法更改为:

<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

这会将请求作为原始流接收并将反序列化留给我(我实际上更喜欢 - 魔法越少越好)。

AJAX没有太大变化,除了我需要删除contentType(保留默认值)并将响应的dataType更改为json(当它是“text”时我需要将其反序列化两次某种原因):

$.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);
    }
});

我希望这有助于任何想要避免DataContracts的人。