TechHui

Hawaiʻi's Technology and New Media Community

Last week we made the basic WCF service, based on the template from VS2010.  A set of defaults that can be built on.  To make your own service, the assumption would be to make another interface, implement it, and then copy the app.config.  For the most part, that is correct.  What is less obvious is where those values come from, and what do they mean.  This week we will create our own service, and modify the app.config to expose it.  Everything we will do this week builds on the project from last week.

We will start by creating the interface.  In the SimpleServiceLibrary project create the interface IDocumentStorageService.  It should look like this:

namespace SimpleServiceLibrary

{

    using System.ServiceModel;

 

    [ServiceContract]

    public interface IDocumentStorageService

    {

        [OperationContract]

        void StoreDocument(string documentType, string documentName, string document);

    }

}

 

Not much to it, but the attributes are important.  The ServiceContract attribute is telling WCF that this is an interface that declares what operations the service supports.  The OperationContract attribute indicates the specifics of the ServiceContract.  They are the operations available to the client.  Creating the implementation is just like implementing any interface:

namespace SimpleServiceLibrary

{

    using System;

    using System.Collections.Generic;

 

    public class DocumentStorageService : IDocumentStorageService

    {

        Dictionary<Guid, Tuple<string, string, string>> store = new Dictionary<Guid, Tuple<string, string, string>>();

 

        public void StoreDocument(string documentType, string documentName, string document)

        {

            Tuple<string, string, string> item = new Tuple<string, string, string>(documentType, documentName, document);

            this.store.Add(Guid.NewGuid(), item);

        }

    }

}

 

Now we have creating a interface that declares our service, and a class that defines it.  Now we get to the point of this post.  To make this new service work, remember your ABC’s.

A: The Address – Where is the service

B: Binding – How do you talk to the service

C: Contract – What does the service do?

 

We have taking care of the Contract now we will take care of the address and the bindings.  I have cut out all the comments, and highlighted your ABCs:

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

<configuration>

 

  <system.web>

    <compilation debug="true" />

  </system.web>

  <system.serviceModel>

   

    <services>

      <service name="SimpleServiceLibrary.Service1">

        <host>

          <baseAddresses>

            <add baseAddress = "http://localhost:8732/Design_Time_Addresses/SimpleServiceLibrary/Service1/" />

          </baseAddresses>

        </host>

        <endpoint address ="" binding="wsHttpBinding" contract="SimpleServiceLibrary.IService1">

          <identity>

            <dns value="localhost"/>

          </identity>

        </endpoint>

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

      </service>

    </services>

   

    <behaviors>

      <serviceBehaviors>

        <behavior>

          <serviceMetadata httpGetEnabled="True"/>

          <serviceDebug includeExceptionDetailInFaults="False" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

 

</configuration>

 

To make the new service work, you need to add the following to the services section.  I have highlighted the specific items I changed.

<service name="SimpleServiceLibrary.DocumentStorageService">

        <host>

          <baseAddresses>

            <add baseAddress = "http://localhost:8732/Design_Time_Addresses/SimpleServiceLibrary/DocumentStorageService/" />

          </baseAddresses>

        </host>

        <endpoint address ="" binding="wsHttpBinding" contract="SimpleServiceLibrary.IDocumentStorageService">

          <identity>

            <dns value="localhost"/>

          </identity>

        </endpoint>

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

      </service>

    </services>

 

Where did these values come from?  Let’s go through them.

<service name="SimpleServiceLibrary.DocumentStorageService">

This is the fully qualified name to your implementation of the interface.  This is important, because it is what allows you to quickly change from one implementation of the interface to another.

 

<add baseAddress = "http://localhost:8732/Design_Time_Addresses/SimpleServiceLibrary/DocumentStorageService/" />

Just as the attribute suggests this is the base address for the service.  It can be over-ridden later if you want.  There is an important piece of magic with the default address.  If you are running as a normal user, do not change the first part of that address.  Changing it will require you to run VS2010 with elevated permissions. 

 

<endpoint address="" binding="wsHttpBinding" contract="SimpleServiceLibrary.IDocumentStorageService">

Here are your ABC’s.  The address can be relative or absolute.  It is also possible to specify a URI that indicates a completely different protocol for the same implementation of the interface.  The binding indicates the protocol to use.  There are many different types of built in protocols.  I hope to get to them in future posts.  Finally, the contract is the fully qualified name to the interface that the class specified in the service name is implementing.

The other settings I will discuss in the future.  The next thing to do is to delete the old service.  It is a very simple process:

  1. Delete the contents of the Service element for the old service:

 <service name="SimpleServiceLibrary.Service1">

  1. Delete the old IService1 interface
  2. Delete the old Service1 class

Your app.config should look like this:

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

<configuration>

 

  <system.web>

    <compilation debug="true" />

  </system.web>

  <system.serviceModel>

   

    <services>

      <service name="SimpleServiceLibrary.DocumentStorageService">

        <host>

          <baseAddresses>

            <add baseAddress = "http://localhost:8732/Design_Time_Addresses/SimpleServiceLibrary/DocumentStorageService/" />

          </baseAddresses>

        </host>

        <endpoint address ="" binding="wsHttpBinding" contract="SimpleServiceLibrary.IDocumentStorageService">

          <identity>

            <dns value="localhost"/>

          </identity>

        </endpoint>

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

      </service>

    </services>

 

    <behaviors>

      <serviceBehaviors>

        <behavior>

          <serviceMetadata httpGetEnabled="True"/>

          <serviceDebug includeExceptionDetailInFaults="False" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

 

</configuration>

 

And your solution looks like this:

 

We also have the old test to clean up, Delete the reference to ServiceReference1, and create a reference to the new service, just as we did last week.  The result should look something like this:

When you finish, the test will fail to build.  Update the test case, providing the new webservice namespace, and call the new StoreDocument method:

namespace ServiceTesting

{

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using ServiceTesting.DocumentStorageService;

 

    [TestClass]

    public class Service1Test

    {

        [TestMethod]

        public void StoreDocumentTest()

        {

            IDocumentStorageService service = new DocumentStorageServiceClient();

            service.StoreDocument("txt", "sample", "This is a test");

        }

    }

}

 

This will give you a working test case, running your own service, with your own name.  This may seem like very basic information, but it is the heart of WCF and understanding this is key to future success.  Next week we will take what we know about WCF and discuss high level design considerations when starting to write real solutions that will be used with WCF.

 

 

 

 

Views: 97

Comment

You need to be a member of TechHui to add comments!

Join TechHui

Sponsors

web design, web development, localization

© 2014   Created by Daniel Leuck.

Badges  |  Report an Issue  |  Terms of Service