Factoring Interfaces

I am embarking on my first WCF based service. This service will be evolved from an existing .asmx based set of web services that expose over 200 webmethods. My question is, what is the best way to (re)factor the .asmx interfaces in WCF I was considering a single IMyInterface containing the 200+ methods, and then perhaps partial classes for the implementation to maintain some modularity. Is this a bad idea Are there any best practices for factoring WCF interfaces


Answer this question

Factoring Interfaces

  • rpgoldberg

    If you implement multiple interfaces,and if you host this service in IIS

    svcutil will generate two different proxy classes for each interface(These two classes will be in same .cs file)

    My service code:

    // Copyright (c) Microsoft Corporation. All Rights Reserved.

    using System;

    using System.ServiceModel;

    namespace Microsoft.ServiceModel.Samples

    {

    // Define a service contract.

    [ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]

    public interface ICalculator

    {

    [OperationContract]

    double Add(double n1, double n2);

    [OperationContract]

    double Subtract(double n1, double n2);

    [OperationContract]

    double Multiply(double n1, double n2);

    [OperationContract]

    double Divide(double n1, double n2);

    }

    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]

    public interface iHello

    {

    [OperationContract]

    string SayHello();

    }

    // Service class which implements the service contract.

    public class CalculatorService : ICalculator, iHello

    {

    public double Add(double n1, double n2)

    {

    return n1 + n2;

    }

    public double Subtract(double n1, double n2)

    {

    return n1 - n2;

    }

    public double Multiply(double n1, double n2)

    {

    return n1 * n2;

    }

    public double Divide(double n1, double n2)

    {

    return n1 / n2;

    }

    #region iHello Members

    public string SayHello()

    {

    return "Hello";

    }

    #endregion

    }

    }

    web.config for above service:

    < xml version="1.0" encoding="utf-8" >

    <configuration>

    <system.serviceModel>

    <services>

    <service

    name="Microsoft.ServiceModel.Samples.CalculatorService"

    behaviorConfiguration="CalculatorServiceBehavior">

    <!-- use base address provided by host -->

    <endpoint address=""

    binding="wsHttpBinding"

    bindingConfiguration="Binding1"

    contract="Microsoft.ServiceModel.Samples.ICalculator" />

    <endpoint address=""

    binding="wsHttpBinding"

    bindingConfiguration="Binding1"

    contract="Microsoft.ServiceModel.Samples.iHello" />

    </service>

    </services>

    <bindings>

    <wsHttpBinding>

    <binding name="Binding1" />

    </wsHttpBinding>

    </bindings>

    <!--For debugging purposes set the returnUnknownExceptionsAsFaults attribute to true-->

    <behaviors>

    <behavior

    name="CalculatorServiceBehavior"

    returnUnknownExceptionsAsFaults="False" >

    </behavior>

    </behaviors>

    </system.serviceModel>

    </configuration>

    .SVC file code:

    %@ServiceHost language=c# Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %

    CONCLUSION:

    i implemented two classes,and i have endpoint address for two interfaces on server side

    client will generate proxy for both end point address(1 proxy class for each interface and they will be in same .cs file),if you want,you can delete un wanted code from client proxy code (in case if your client1 only needs ihello interface,you can delete icaluculator proxy code)



  • Colin M.

    self host case,base address and end point address can be same or different(IIS hosted cases,we always use base address as endpoint address),so you can use same kind of config for self hosted case also.

    EXAMPLE:

    CLIENT CODE:

    public class CalculatorService : ICalculator, iHello

    {

    public static void Main()

    {

    ServiceHost sh = new ServiceHost(typeof(CalculatorService), new Uri("http://locahost/mysvc"));

    sh.Open();

    Console.WriteLine("click some key to quit");

    Console.ReadKey();

    }

    APP.CONFIG FILE:

    < xml version="1.0" encoding="utf-8" >

    <configuration>

    <system.serviceModel>

    <services>

    <service

    name="Microsoft.ServiceModel.Samples.CalculatorService"

    behaviorConfiguration="CalculatorServiceBehavior">

    <!-- use base address provided by host -->

    <endpoint address="http://locahost/xyz"

    binding="basicHttpBinding"

    bindingConfiguration="Binding1"

    contract="Microsoft.ServiceModel.Samples.ICalculator" />

    <endpoint address="http://locahost/xyz"

    binding="basicHttpBinding"

    bindingConfiguration="Binding1"

    contract="Microsoft.ServiceModel.Samples.iHello" />

    </service>

    </services>

    <bindings>

    <basicHttpBinding>

    <binding name="Binding1">

    <security mode="None" >

    <transport clientCredentialType="None"/>

    </security>

    </binding>

    </basicHttpBinding>

    </bindings>

    <!--For debugging purposes set the returnUnknownExceptionsAsFaults attribute to true-->

    <behaviors>

    <behavior

    name="CalculatorServiceBehavior"

    returnUnknownExceptionsAsFaults="False" >

    </behavior>

    </behaviors>

    </system.serviceModel>

    </configuration>

    without config,This code should work:

    public class CalculatorService : ICalculator, iHello

    {

    public static void Main()

    {

    WSHttpBinding b=new WSHttpBinding();

    ServiceHost sh = new ServiceHost(typeof(CalculatorService), new Uri("http://locahost/mysvc"));

    sh.AddServiceEndpoint("Microsoft.ServiceModel.Samples.ICalculator", b, "");

    sh.AddServiceEndpoint("Microsoft.ServiceModel.Samples.iHello", b, "");

    sh.Open();

    Console.WriteLine("click some key to quit");

    Console.ReadKey();

    }

    -Thank you

    Madhu



  • ldcooke

    in wcf,each ABC(Address+Binding+contract(interface)) combination will define the client side proxy

    If all these methods logically don't fit into one service,dividing them into multiple services or divide them into multiple interfaces and implement multiple interfaces in one serviec is good idea.

    As i know,we don't have any best practise documents yet,most of documentation will be available for RCO(Next release)

    -Thank you

    Madhu



  • ieee488

    Thanks for the sample. How would I go about hosting this outside of IIS Say, for example, in a Windows Service or console app Can I still bind both interface endpoints to the same address What if I have interfaces IFoo and IBar, implemented in classes Foo and Bar Your sample has two interfaces implemented by one class.

  • alden

    There's several samples on how to host outside of IIS.

    The TechnologySamples\Basic\Service\Addressing sample is a good one to look at for a Console app hosted service.

    Thanks!

    Scott



  • dean183

    Dividing into multiple interfaces, and implementing them in one service may be what I want. My goal is to expose a single endpoint (i.e. http://server:8080/default.svc) for all my methods, while keeping the code maintainable (avoiding monolithic classes). Do you have some sample code that illustrates how to do this

  • burov

    If you have multiple classes, then you need to have multiple .svc files

    becuase service host can point to only one type.

    if you want to do the same in console app by writing your own service hosting code, you have to have two diffrent hosting environments (one for each class)

    hope this answers your question.

    Regards,

    Venkat



  • Factoring Interfaces