none
WCF service with multiple interfaces and multiple endpoints

    Question

  • Hi Techies

    I am new to wcf and blah... blah.. etc etc, you all know that :),

    I have a wcf service hosted inside my mvc application.

    task was to split service functionality into multiple interfaces and create endpoints for each of interface.

    the reference service is using webHttpBinding same I am following in newly developed service. here is snipt from web.config

     

    <system.serviceModel>
      <behaviors>
       <serviceBehaviors>
        <behavior name="MediaServiceBehaviors">
         <serviceMetadata httpGetEnabled="true" />
         <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
       </serviceBehaviors>
       <endpointBehaviors>
        <behavior name="MediaServiceAspNetAjaxBehavior">
         <enableWebScript />
        </behavior>
       </endpointBehaviors>
      </behaviors>
    
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    
      <services>
       <service behaviorConfiguration="MediaServiceBehaviors" name="ReaStyle.WCF.Service.MediaService">
        <endpoint
         address=""
         binding="webHttpBinding"
         contract="ReaStyle.WCF.Service.IMediaService">
        </endpoint>
        <endpoint address="mex"
             binding="mexHttpBinding"
             contract="IMetadataExchange" />
        <endpoint
         address="/js"
         behaviorConfiguration="MediaServiceAspNetAjaxBehavior"
         binding="webHttpBinding"
         contract="ReaStyle.WCF.Service.IJSMediaService">
        </endpoint>
       </service>
      </services>
      <bindings>
    
       <webHttpBinding>
        <binding name="DesktopBindingConfiguration" transferMode="Buffered" maxReceivedMessageSize="104857600" maxBufferSize="104857600">
         <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/>
        </binding>
       </webHttpBinding>
       </system.serviceModel>
    

     

    and this is code showing data contracts and interfaces which I have implemented in Media Service.

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using ReaStyle.MML.Services;
    
    namespace ReaStyle.WCF.Service
    {
      [DataContract]
      public class AddressRequest
      {
        [DataMember]
        public int PersonID{get;set;}
      }
    
      [DataContract]
      public class AddressResponse
      {
        [DataMember]
        public string City{get;set;}
        [DataMember]
        public string State{get;set;}
        [DataMember]
        public string Country{get;set;}
      }
      // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
      [ServiceContract]
      public interface IMediaService 
      {
        [OperationContract]
        Guid GetPersonID();
    
        [OperationContract]
        AddressResponse GetPersonAddress(AddressRequest request);
    
      }
    
      [ServiceContract]
      public interface IJSMediaService
      {
        [OperationContractAttribute(Name = "GetJsPersonID")]
        Guid GetPersonID();
    
        [OperationContract]
        AddressResponse GetJSPersonAddress(AddressRequest request);
      }
    
    }
    
    

     

    Following is my service code.

     

    <%@ ServiceHost Language="C#" Debug="true" Service="ReaStyle.WCF.Service.MediaService" CodeBehind="MediaService.svc.cs" %>
    
    
    using System;
    using System.ServiceModel.Activation;
    using System.ServiceModel;
    
    namespace ReaStyle.WCF.Service
    {
      [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
      public class MediaService : IMediaService,IJSMediaService
      {
        string id ;
        public MediaService()
        {
          id = "courage";
        }
    
        Guid IJSMediaService.GetPersonID()
        {
          return Guid.NewGuid();
        }
    
        AddressResponse IJSMediaService.GetJSPersonAddress(AddressRequest request)
        {
          return new AddressResponse() { City = "jsIslamabad", State = "Capital", Country = "Pakistan" };
        }
    
        
        Guid IMediaService.GetPersonID()
        {
          return Guid.NewGuid();
        }
    
        AddressResponse IMediaService.GetPersonAddress(AddressRequest request)
        {
          return new AddressResponse() { City = "Islamabad", State = "Capital", Country = "Pakistan" };
        }
      }
    }
    
    
    When I test the service using endpoint "http://localhost:61034/MediaService.svc" it does show no error neither did it show any methods exposed on
    ReaStyle.WCF.Service.IMediaService
    

    contract.

    I tried using second endpoint "http://localhost:61034/MediaService.svc/js" but wcftestclient threw error.

    Error: Cannot obtain Metadata from http://localhost:61034/MediaService.svc/js If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address.  For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error    URI: http://localhost:61034/MediaService.svc/js    Metadata contains a reference that cannot be resolved: 'http://localhost:61034/MediaService.svc/js'.    There was no endpoint listening at http://localhost:61034/MediaService.svc/js that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.    The remote server returned an error: (404) Not Found.HTTP GET Error    URI: http://localhost:61034/MediaService.svc/js    There was an error downloading 'http://localhost:61034/MediaService.svc/js'.    The request failed with HTTP status 404: Not Found.

     

    you can see in web.config section above I have added

    <serviceMetadata httpGetEnabled="true" /><br/>
    

    then why WCFTestClient is not finding/accepting it. I am sure I must have missed something, I have read different marked answers but none of them helping or may be I can not make use of them properly. Please suggest how can I solve this problem. I am stuck on it for last five days and now I am feeling I have IQ lower than a blond.  :(

    Your help is greatly appreciated.

    please help.

     

    Thanks

     


    m.imran.afzal
    Wednesday, March 23, 2011 8:16 AM

Answers

  • Hi Imran,

    Ok i understand :). When you want to split functionality into 2 service contracts (interfaces), i would introduce a second service service. Each service implements one service contract.

    When you only want to split the service contract but want to expose it via one service. You could do contract inheritance like this:

     [ServiceContract]
      public interface IMediaService : IJSMediaService 
      {
        [OperationContract]
        Guid GetPersonID();

        [OperationContract]
        AddressResponse GetPersonAddress(AddressRequest request);

      }

      [ServiceContract]
      public interface IJSMediaService
      {
        [OperationContractAttribute(Name = "GetJsPersonID")]
        Guid GetPersonID();

        [OperationContract]
        AddressResponse GetJSPersonAddress(AddressRequest request);
      }

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
      public class MediaService : IMediaService
      {
        string id ;
        public MediaService()
        {
          id = "courage";
        }
    .....

    }

    This way you split the functionality into 2 service contracts but the service exposes both, because it implements IMediaService. The endpoints you define should only have a contract for the IMediaService.

    Hope this helps!

    Regards,

    Dennis

    • Marked as answer by Yi-Lun Luo Tuesday, March 29, 2011 9:12 AM
    Thursday, March 24, 2011 7:54 AM

All replies

  • Hi,

    Why are you splitting the service contracts? I see that they have the same functionality? Thanks.

    Regards,

    Dennis

    Wednesday, March 23, 2011 11:49 AM
  • hi Dennis

     

    thanks for your reply, Infact this is not the original service , I just simulated the scenario, original service has different functionality in interfaces.

    this was just to give an ideas how am I doing. yah, I those interfaces too, there are few methods which are common and splited them as I need to return

    a response type of json when user calls that methods from jquery/javascript  and it should return a data contract  in different format when called from web/desktop server side code. that's why I put two methods in two different interfaces.

    I hope that make sense .

     

    Imran


    m.imran.afzal
    Thursday, March 24, 2011 4:35 AM
  • Hi Imran,

    Ok i understand :). When you want to split functionality into 2 service contracts (interfaces), i would introduce a second service service. Each service implements one service contract.

    When you only want to split the service contract but want to expose it via one service. You could do contract inheritance like this:

     [ServiceContract]
      public interface IMediaService : IJSMediaService 
      {
        [OperationContract]
        Guid GetPersonID();

        [OperationContract]
        AddressResponse GetPersonAddress(AddressRequest request);

      }

      [ServiceContract]
      public interface IJSMediaService
      {
        [OperationContractAttribute(Name = "GetJsPersonID")]
        Guid GetPersonID();

        [OperationContract]
        AddressResponse GetJSPersonAddress(AddressRequest request);
      }

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
      public class MediaService : IMediaService
      {
        string id ;
        public MediaService()
        {
          id = "courage";
        }
    .....

    }

    This way you split the functionality into 2 service contracts but the service exposes both, because it implements IMediaService. The endpoints you define should only have a contract for the IMediaService.

    Hope this helps!

    Regards,

    Dennis

    • Marked as answer by Yi-Lun Luo Tuesday, March 29, 2011 9:12 AM
    Thursday, March 24, 2011 7:54 AM