Bidirectional WCF Client-Server Communication

For several weeks I worked on creating a client / server for managing server-side music server applications, which are controlled by several client applications located on the local network. I managed to get the client side to interact with the server, send commands to work with the music server and use callbacks, respond to client requests so that the entire client user interface can be updated accordingly. My problem, however, is that I cannot figure out how to send other messages that need to be sent from the server application to clients. I was hoping to use a callback method; however, I was not able to access it from the server side. Do I need to modify or create another contract,which provides communication with the server with clients? Is a binding change required? As I mentioned earlier, I have really been working on this for several weeks (which is starting to feel like β€œyears”) and hope that this last part of the application will work. Anyone please direct me in the right direction?

Client side SERVICE SERVICE:

<?xml version="1.0" encoding="utf-8"?>
<ServiceReference>
<ProxyGenerationParameters
    ServiceReferenceUri="http://localhost:8001/APService/mex"
    Name="APGateway"
    NotifyPropertyChange="True"
    UseObservableCollection="False">
</ProxyGenerationParameters>
<EndPoints>
    <EndPoint
        Address="net.tcp://localhost:8000/APService/service"
        BindingConfiguration="TcpBinding"
        Contract="APClient.APGateway.APUserService"
        >
    </EndPoint>
    <EndPoint
        Address="http://localhost:8001/APService/service"
        BindingConfiguration="HttpBinding"
        Contract="APClient.APGateway.APUserService"
        >
    </EndPoint>
</EndPoints>
</ServiceReference>

Client side AP CONFIG

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="APClient.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
</configSections>
<system.serviceModel>
    <client>
        <endpoint
            address="net.tcp://localhost:8000/APService/service"
            binding="netTcpBinding"
            contract="APClient.APGateway.APUserService"
            name="TcpBinding" />
        <endpoint
            address="http://localhost:8001/APService/service"
            binding="wsDualHttpBinding"
            contract="APClient.APGateway.APUserService"
            name="HttpBinding" />
    </client>
</system.serviceModel>
<applicationSettings>
    <APClient.Properties.Settings>
        <setting name="pathToDatabase" serializeAs="String">
            <value>C:\Users\Bill\Documents\APData\</value>
        </setting>
    </APClient.Properties.Settings>
</applicationSettings>

Server side AP.CONFIG

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MetadataBehavior">
           <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8001/APService/mex" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="MetadataBehavior" name="APService.APService">
        <endpoint address="service" binding="netTcpBinding" name="TcpBinding"
          contract="APService.IAPServiceInventory" />
        <endpoint address="service" binding="wsDualHttpBinding" name="HttpBinding"
         contract="APService.IAPServiceInventory" />
        <endpoint address="mex" binding="mexHttpBinding" name="MexBinding"
          contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8000/APService/" />
            <add baseAddress="http://localhost:8001/APService/" />
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

Server side APSERVICE.CS

namespace APService
{
     [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single,InstanceContextMode=InstanceContextMode.PerCall)]
 public class APService : IAPServiceInventory
 {
      private static List<IClientCallback> _callbackList = new List<IClientCallback>();
      private static int _beerInventory = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["InitialBeerInventory"]);
      public APService() {}
      public int SubscribeToServer(string guestName)
      {
           IClientCallback guest = OperationContext.Current.GetCallbackChannel<IClientCallback>();
           if(!_callbackList.Contains(guest)) { _callbackList.Add(guest); }
           else { Console.WriteLine(guest + " is already logged onto the Server."); }
           _callbackList.ForEach(delegate(IClientCallback callback) { callback.NotifyGuestJoinedParty(guestName); });
      }
      public void UpdateClients(string guestName,string UpdateInfo)
      {
           _callbackList.ForEach(delegate(IClientCallback callback) { callback.NotifyUpdateClients(guestName,UpdateInfo); });
      }
      public void SendRequestToServer(string guestName, string request)
      {
           _callbackList.ForEach(delegate(IClientCallback callback) { callback.NotifyRequestMadeToServer(guestName,request); });
           if(request == "Play") { APControl.Play(); }
           else if(request == "Stop") { APControl.Stop(); }
           else if(request == "Pause") { APControl.PlayPause(); }
           else if(request == "Next Track") { APControl.NextTrack(); }
           else if(request == "Previous Track") { APControl.PreviousTrack(); }
           else if(request == "Mute") { APControl.Mute(); }
           else if(request == "Volume Up") { APControl.VolumeUp(5); }
           else if(request == "Volume Down") { APControl.VolumeDown(5); }
      }
      public void CancelServerSubscription(string guestName)   
      {
           IClientCallback guest = OperationContext.Current.GetCallbackChannel<IClientCallback>();
           if(_callbackList.Contains(guest)) { _callbackList.Remove(guest); }
           _callbackList.ForEach(delegate(IClientCallback callback) { callback.NotifyGuestLeftParty(guestName); });
      }
 }

Server side IAPSERVICE.CS

namespace APService
{
     [ServiceContract(Name="APUserService",Namespace="http://AP.com/WCFClientServer/",SessionMode=SessionMode.Required, CallbackContract=typeof(IClientCallback))]
 public interface IAPServiceInventory
 {
      [OperationContract()]
      int SubscribeToServer(string guestName);
      [OperationContract(IsOneWay=true)]
      void SendRequestToServer(string guestName,string request);
      [OperationContract(IsOneWay=true)]
      void UpdateClients(string guestName,string UpdateInfo);
      [OperationContract(IsOneWay=true)]
      void CancelServerSubscription(string guestName);
 }
 }

Server Side - IAPServiceCallback.cs

namespace APService
{
     public interface IClientCallback
     {
          [OperationContract(IsOneWay=true)]
          void NotifyGuestJoinedParty(string guestName);
          [OperationContract(IsOneWay=true)]
          void NotifyUpdateClients(string guestName,string UpdateInfo);
          [OperationContract(IsOneWay=true)]
          void NotifyRequestMadeToServer(string guestName,string request);
          [OperationContract(IsOneWay=true)]
          void NotifyGuestLeftParty(string guestName);
     }
+5
source share
1 answer

I think you can follow this link to understand the mechanism.

Nlv

+1
source

All Articles