简体   繁体   English

WCF - 使用NetHttpBinding(WebSockets)或备用双工绑定发送JSON

[英]WCF - Sending JSON with NetHttpBinding(WebSockets) or alternative Duplex Binding

I am trying to hookup an Android client to a WCF service that currently is running with NetTcpBinding. 我正在尝试将Android客户端连接到当前使用NetTcpBinding运行的WCF服务。 The project requires that all the clients have a Duplex (Bi-Directional) Connection. 该项目要求所有客户端都具有双工(双向)连接。

Since the NetTcpBinding is not supported outside of .NET, I began researching alternative Duplex bindings. 由于.NET之外不支持NetTcpBinding,我开始研究替代双工绑定。 Websockets(NetHttpBinding) seems to be the answer, but it does not seem to have built in support for JSON and applying the same binding configuration of WebHttpBinding throws errors. Websockets(NetHttpBinding)似乎是答案,但它似乎没有内置对JSON的支持,并且应用WebHttpBinding的相同绑定配置会引发错误。

Any suggestions in adding an Andriod client, using JSON, to a Duplex WCF Service is much appreciated. 任何使用JSON将Andriod客户端添加到Duplex WCF服务的建议都非常感谢。

一个简单的解决方案是使用Newtonsoft将WCF返回对象转换为JSON字符串,并使用JSON.stringyfy或android中的类似函数在客户端解析此字符串。

For the WCF WebService implementing WebSockects, you could define a custom binding like this: 对于实现WebSockects的WCF WebService,您可以定义这样的自定义绑定:

<customBinding>
  <binding name="WebSocketBinding">
    <byteStreamMessageEncoding />
    <httpTransport>
      <webSocketSettings transportUsage="Always" />
    </httpTransport>
  </binding>
</customBinding>

Your service interface will have to look something like this: 您的服务界面必须如下所示:

[ServiceContract(CallbackContract = typeof(IMyCallBack))]
public interface IMyService
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void OnMessage(System.ServiceModel.Channels.Message msg);
}
[ServiceContract]
interface IMyCallBack
{
    [OperationContract(IsOneWay = true, Action="*")]
    void Reply(System.ServiceModel.Channels.Message msg);
}

The service implementation: 服务实施:

public class MyService: IMyService
{
    public void OnMessage(Message msg)
    {
        var callback = OperationContext.Current.GetCallbackChannel<IMyCallback>();
        if (msg.IsEmpty || ((IChannel)callback).State != CommunicationState.Opened)
        {
            return;
        }
        byte[] messageBody = msg.GetBody<byte[]>();
        string messageString = Encoding.UTF8.GetString(messageBody);

        ...

        callback.Reply(CreateMessage(responseString));
    }

    private Message CreateMessage(string messageString)
    {
        var messageBody = new ArraySegment<byte>(Encoding.UTF8.GetBytes(messageString));
        Message msg = ByteStreamMessage.CreateMessage(messageBody);
        msg.Properties["WebSocketMessageProperty"] = new WebSocketMessageProperty 
        { 
            MessageType = WebSocketMessageType.Text 
        };
        return msg;
    }
} 

This way, your service can receive stringified JSON objects from your client. 这样,您的服务就可以从您的客户端接收字符串化的JSON对象。 The service will receive them in the form of System.ServiceModel.Channels.ByteStreamMessage objects that esentially contain plain strings, making the conversion pretty simple, as seen above. 该服务将以System.ServiceModel.Channels.ByteStreamMessage对象的形式接收它们,这些对象实际上包含纯字符串,使转换非常简单,如上所示。

To convert your stringified JSON objects on the service to something that you can actually work with, you can use a serializer: 要将服务上的字符串化JSON对象转换为可以实际使用的对象,可以使用序列化程序:

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
dynamic messageObject = serializer.Deserialize<object>(stringMessage);

A better alternative would be to use static typing: I assume you know the types of the JSON objects you wish to transmit - create a corrseponding C# class for each one! 更好的选择是使用静态类型:我假设您知道要传输的JSON对象的类型 - 为每个对象创建一个corrseponding C#类! That way, you can use the class as the template parameter for the Deserialize<>() function and get a statically typed object as a return value. 这样,您可以使用该类作为Deserialize<>()函数的模板参数,并获取静态类型对象作为返回值。

If you have multiple different types of JSON objects, you can add a type property to them and then you can sort them on the service side: 如果您有多种不同类型的JSON对象,可以向它们添加type属性,然后您可以在服务端对它们进行排序:

dynamic messageObject = serializer.Deserialize<object>(stringMessage);

if (messageObject["type"] == "MyObject1") {
    MyObject1 myObject = serializer.Deserialize<MyObject1>(stringMessage);
    MyFunction1(myObject);
} else if (messageObject["type"] == "MyObject2") {
    MyObject2 myObject = serializer.Deserialize<MyObject2>(stringMessage);
    MyFunction2(myObject);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM