简体   繁体   中英

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. 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. 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.

Any suggestions in adding an Andriod client, using JSON, to a Duplex WCF Service is much appreciated.

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

For the WCF WebService implementing WebSockects, you could define a custom binding like this:

<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. 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.

To convert your stringified JSON objects on the service to something that you can actually work with, you can use a serializer:

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! 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.

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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