Recent Posts

Categories

Archives

Calendar

March 2010
M T W T F S S
« Jan    
1234567
891011121314
15161718192021
22232425262728
293031  

Search


Meta

Simple WCF Service Host

app.config

The configuration for a simple http WCF host is:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
  </appSettings>

  <system.serviceModel>
    <services>
      <service name="AssemblyNamespace.ServiceImplementation"
               behaviorConfiguration="ServiceBehavior">
        <endpoint address="ServiceName"
                  binding="basicHttpBinding"
                  contract="AssemblyNamespace.ServiceContractInterface" />

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />

        <host>
          <baseAddresses>
            <add baseAddress="http://HostName:Port/"/>
          </baseAddresses>
        </host>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

An example:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
  </appSettings>

  <system.serviceModel>
    <services>
      <service name="TestService.CalculatorService"
               behaviorConfiguration="CalculatorServiceBehavior">
        <endpoint address="CalculatorService"
                  binding="basicHttpBinding"
                  contract="TestService.ICalculator" />

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />

        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/"/>
          </baseAddresses>
        </host>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

The Service

Define the service in an interface

using System.ServiceModel;

namespace TestService
{
    [ServiceContract]
    public interface ICalculator
    {
        #region Instance Methods

        [OperationContract]
        double Add(double n1, double n2);

        [OperationContract]
        double Divide(double n1, double n2);

        [OperationContract]
        double Multiply(double n1, double n2);

        [OperationContract]
        double Subtract(double n1, double n2);

        #endregion
    }
}

Then implement the interface

using System;

namespace TestService
{
    public class CalculatorService : ICalculator
    {
        #region ICalculator Members

        public double Add(double n1, double n2) {
            double result = n1 + n2;
            Console.WriteLine("Received Add({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Divide(double n1, double n2) {
            double result = n1/n2;
            Console.WriteLine("Received Divide({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Multiply(double n1, double n2) {
            double result = n1*n2;
            Console.WriteLine("Received Multiply({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Subtract(double n1, double n2) {
            double result = n1 - n2;
            Console.WriteLine("Received Subtract({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        #endregion
    }
}

The Host

Lastly create a host for the service

using System;
using System.ServiceModel;

namespace TestService
{
    internal class Program
    {
        #region Class Methods

        private static void Main() {
            using (ServiceHost serviceHost = new ServiceHost(typeof (CalculatorService))) {
                serviceHost.Open();

                Console.WriteLine("The calculator service is ready.");
                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();
            }
        }

        #endregion
    }
}

Simple Thread Safe Singleton

This is simple but should work:

public sealed class Singleton
{
   private static Singleton _instance = new Singleton();

   private Singleton() { }

   public static Singleton Instance
   {
      get
      {
         return _instance;
      }
   }
}

As the CLR synchronises static constructors it is thread safe. Also static constructors are not called until the types is accessed to you have lazy instantiation (use nesting if there are other static methods).

How to Use InternalsVisibleTo

VS2005 defaults new classes to internal rather than public (although it appears that Orcas defaults to public). This is good as it reduces the public interface of your assembly and it encourages you to actually think about whether a class needs to be public.

You can allow other assemblies access to your internal types and members though, by using the InternalsVisibleTo attribute. This is especially useful for allowing your test assembly to access your internal classes.

This attribute can only be applied to strongly named assemblies.

[assembly:InternalsVisibleTo("TestAssembly, PublicKey=TestAssembly’s public key")]

The attribute requires the assembly name and the public key. To retrieve the public key use sn.exe. Open a visual studio command prompt and enter:

sn.exe -Tp AssemblyPath

Alternatively if you use an alternate file explorer you could set up a macro.

How to Give an Assembly a Strong Name

To Strongly name an assembly you need to associate it with a public and private key. This can be either done by the developer when they compile the assembly (signing) or by at a later stage for instance by the QA department (delayed signing).

Public and private keys can be associated with code signing certificates, generated using sn.exe, or they can be generated from within Visual Studio.

Open the project properties for the assembly you want to sign and check ‘sign the assembly’ on the signing tab. To create a key file, select New from the drop down and follow the directions or Browse for an existing key file. If you create a key file it is worth moving it from the bin directory as you should be using it across multiple projects.

Once compiled you will have a signed assembly with a strong name.