Tuesday, December 8, 2009

Lab #17: Creating a Syndication Feed with WCF 3.5

Members:

Rafael Zuniga, Stephen Cave

Summary:

The purpose of this lab is to create a syndication feed using WCF.

Procedure:

We begin by creating a new WCF syndication project:



Generated for us are Feed1.cs and IFeed1.cs. The first file implements the interface defined in the second. We proceed by renaming Feed1.cs to ArticleService.cs, which renames the Feed1 class to ArticleService, and IFeed1.cs to IArticleService.cs, which renames the IFeed1 interface to IArticleService.cs. The implementation has a default CreateFeed() function which contains the code for returning the formatted feed. Instead of using the default syndication creation code we gut it, keeping only the section determining which format to use and the feed to return. We then modify the sections which actually return the format by putting in the code from this article and we get:

if (query == "atom")
{
formatter = GetArticleInfoAtom();
}
else
{
formatter = GetArticleInfoRss();
}


No contract modifications are needed, instead we only need to put in the actual GetArticleAtom and GetArticleInfoRss methods. We can then run the project and access the feed, in RSS and Atom format, through HTTP:





Observations:
  1. Creating an RSS/Atom feed is ridiculously easy
  2. I probably did this wrong

Tuesday, November 10, 2009

Lab #16: Working with Reliable Sessions

Members:

Rafael Zuniga, Stephen Cave

Summary:

The purpose of this lab is to test how reliable sessions allow for clients to survive interruptions in the network.

Procedure:

We begin by opening the solution in Chapter6/ReliableSessions/ under the labs folder. We compile and run it to make sure it is working:



Which it is, so next we check out the configuration files and notice that we have WSHttpBinding with session support set to true. After we've noticed that we modify the configuration for the client to support diagnostics by adding a diagnostics section to the system.ServiceModel section. We also add a system.diagnostics section which will allow us to create a service log. We run the host and client again and this time after clicking the button several times we end up with a clienttrace.svclog in the c:\logs directory. Opening up the log reveals:



Next we download TcpTrace from this cool looking site, modify the client configuration to use port 8080 instead of 8000, and the host to use 8000. Running the project again with TcpTrace recording we send the first message from the client, stop the trace when we're about to send the second message, allow the second message to attempt to go through, start TcpTrace quickly, and finally let the client close the proxy. This time viewing the log we can see that there was an error when the client was attempting to send:



We can see that the message was successfully sent after TcpTrace was enabled again since the activity in the left pane shows that subsequent messages were processed successfully.

Observations:

  1. Reliable sessions are easy to implement and are very useful if your application requires state retention
  2. I thought TcpTrace would be similar to Wireshark but instead it's a simple re-director, kinda cool
  3. Apparently there's a file association with svclog so you don't have to dig around looking for svctraceviewer.exe

Tuesday, November 3, 2009

Lab #15: Protecting Shared Resources from Concurrent Access

Members:

Rafael Zuniga, Stephen Cave

Summary:

The purpose of this lab is to create an asynchronous client proxy that will issue concurrent requests to a singleton service.

Procedure:

We begin by opening the solution in the Chapter5/Concurrency found in the labs directory. A service has already been made which allows clients to add words to a dictionary. The service runs as a single instance using ConcurrencyMode set to Single as well. In order for our client to be able to use the service we must generate a proxy by running:

svcutil /a /o:proxy.cs /config:app.config http://localhost:8000

This will generate a client proxy to be used by our client application. Next we must edit the client to actually use the service. The client already includes the three buttons to call the service but we must implement the actual event handlers by adding the following:

MessagingServiceClient proxy = new MessagingServiceClient();

And filling in the event handlers for each of the three buttons. We also modify the close event to close the client proxy. Building the solution and running it we see the following when the client buttons are used:



Next we modify the concurrency mode to multiple and test again. This time instead of seeing the ordered service call we see multiple exceptions:



In order to prevent multiple service calls from attempting to access the same variable at once we must synchronize access. The MessagingService.cs is modified to include locking mechanisms. First we modify SendMessage1 by adding a try/finally statement in which a Monitor is used to lock the current service object. The SendMessage2 function is synchronized in a different way; instead of using a monitor we use the lock statement to gain a lock on the service object. The final function, SendMessage3, is synchronized using an attribute:

[MethodImpl(MethodImplOptions.Synchronized)]

The project is then recompiled and tested again. This time the results are the same as the first screen shot, that is, no exceptions are thrown and we see each of the calls. Since the currently example locks the whole service object it isn't very efficient if there are multiple resources that require access. Instead of locking the whole object, this time we modify the existing code to use a mutex. A new dictionary variable is added along with a mutex for each of the variables. The first two SendMessage funtions are modified to the first mutex in order to access the first dictionary and the third SendMessage function is modified to lock the second mutex when accessing the second dictionary. Rebuilding and running it gives us the same effect as in the first screen shot, that is, there are no exceptions thrown.

Observations:
  1. There are many ways to lock a resource: mutexes, monitors, the lock keyword, etc
  2. If there's more than one resource it's more efficient to lock it singly instead of locking the whole service object which prevents other clients from accessing other services
  3. If I remember correctly another way to lock a section of code is to use the lock keyword but on a lock dummy object which should only block access to that object and not the whole service
  4. Blogger has problems with some C# code so a lot of it has been omitted
  5. I bet it's those angle bracket things

Lab #14: Controlling Service Instancing

Members:

Rafael Zuniga, Stephen Cave

Summary:

The purpose of this lab is to show how service calls work with PerCall, PerSession, and Single instancing modes.

Procedure:

We begin by opening the solution in Chapter5/Instancing under the labs directory. After successfully building the solution we run the host and client testing out each of the services using no exception. Currently the host is set to serve PerCall so the variable value is not kept between each call by the client:


Services that support sessions display the following:



Next we test the exception handling for each of the types of bindings. The BasicHttpBinding and WSHttpBinding without session behave the same, that is after the exception the client is still able to call the host server. The same is not so with bindings supporting sessions, after the exception is thrown and displayed another error is displayed stating that the communication object has been faulted:



When calling the service using the client's fault button all of the services are able to recover and call again. Modifying the service by setting the InstanceContextMode to PerSession and running the tests again results in bindings without session support not retaining their variable value while those that do support sessions successfully increment the variable to 2. Next we modify the ServiceContract to disallow sessions by setting SessionMode to NotAllowed. This time if we attempt to run the project we are hit with an exception due to certain bindings requiring a session.



Since we can't run the project with the named pipe and TCP bindings we comment them out in the configuration file. Running the tests again we find that disallowing sessions is similar to setting PerCall since for each call, even if the binding supports sessions, the variable is initialized again to 1. Next we modify the service to require sessions. Again an exception is thrown since certain endpoints do not support sessions, such as BasicHttpBinding, so we must comment them out in the application configuration file. Running the tests again we find that the variable value is kept in between calls to the service. Next we modify the service to use a single instance and run the tests again. This time we find that the variable value is kept across all calls, including for bindings without sessions:



Observations:

  1. The usual access denied error for TCP connections, have to run Visual Studio with administrator permissions
  2. Bindings which use sessions fault when an exception is thrown unless you actually throw a fault exception
  3. This lab was one of the few that was actually problem free

Tuesday, October 27, 2009

Lab #13: Creating a Windows Service Host

Members:

Rafael Zuniga, Stephen Cave

Summary:

This lab will focus on creating and installing a Windows Service Host. A client will also be made which will be able to use the host.

Procedure:

We being by opening the existing solution which can be found in Chapter4/WindowsServiceHost in the labs directory. Next we add a new Windows Service project and rename the default service to MessagingServiceHost. The default constructor is modified as follows:

public MessagingServiceHost()
{
InitializeComponent();
this.ServiceName = "MessagingServiceHost";
}


Next we add a new application configuration and add a service model section which will expose an endpoint for our client to use. A reference to the Messaging project and the ServiceModel assembly is added. The OnStart and OnStop events are modified so the service begins and closes when the service is started and stopped:

protected override void OnStart(string[] args)
{
m_serviceHost = new ServiceHost(typeof(Messaging.MessagingService)); m_serviceHost.Open();
}

protected override void OnStop()
{
if (m_serviceHost != null) m_serviceHost.Close(); m_serviceHost = null;
}


A reference to Configuration.Install is added in order to create an installer for the service. The project is then compiled and the service is installed successfully:


And we can see the that the service can be found in the service management console:

A proxy for the client is then generated using svcutil.exe and the generated App.config and serviceproxy.cs are added to the project. A new click event is added to the client's call service button:

private void button1_Click(object sender, EventArgs e)
{
MessagingServiceClient proxy = new MessagingServiceClient();
MessageBox.Show(proxy.SendMessage(string.Format("Hello from {0}",
this.Text)));
}


The project is then compiled. And that's about it. There's problems running the service and when it does run it hates the client with a fiery passion. See below.

Observations:

  1. Windows Vista/7 are really harsh on what can and can't run
  2. The service installs fine but is unable to run due to the Network Service account not having enough privileges
  3. Changing the account to run the service under to system account allows it to run fine
  4. The problem is then on the client's end because it will not connect to the host giving the error "Credentials Rejected"
  5. To get around this the client must impersonate the credentials of a user with administrative access
  6. Even then it doesn't work due to the alignment of the moon and stars

Lab #12: Working with a Windows Forms Host

Members:

Rafael Zuniga, Stephen Cave

Summary:

The purpose of this lab is to add an existing service to a Windows Forms application and to experiment with starting the service from different locations.

Procedure:

We start by opening the solution found in Chapter4/WindowsApplicationHost which can be found under the labs directory. Right from the start the solution only builds two of the projects with the actual Windows Forms project failing since it lacks a reference to System.ServiceModel. We add the missing reference and also add a reference to the Message service project which is contained within the same solution. This time the project builds succesfully:

We must now modify the App.config for the host since it will require endpoint definitions for the service to be used:



behaviorConfiguration="serviceBehavior">



Next we modify the Windows Forms host code itself which is found in Program.cs:

static class Program
{
public static ServiceHost MessageServiceHost;

[STAThread]
static void Main()
{
Application.ApplicationExit += new EventHandler(Application_ApplicationExit); Program.MessageServiceHost = new ServiceHost(typeof(Messaging.MessagingService)); Program.MessageServiceHost.Open();

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}

static void Application_ApplicationExit(object sender, EventArgs e) { Program.MessageServiceHost.Close(); Program.MessageServiceHost = null; }
}


This code will allow the service to begin at application start up and shut down when the application exits. Next we must modify the client to use the service. We start by adding a service reference to our client which references the host project. Next we add a new button to Form1 and add an event handler to send a message to our host:

private void button1_Click(object sender, EventArgs e)
{
localhost.MessagingServiceClient proxy = new
Client.localhost.MessagingServiceClient();
proxy.SendMessage(
string.Format("Hello from {0}", this.Text));
}


Compiling and running the solution give us two windows. One is running the service while the other is the client which can call the service. Calling the service on the client results in the following:

In the image above the host is running in its own thread. Next we will modify the service to run within the UI thread. We begin by removing all of the previous start up code from the host and adding two buttons to Form1. Then we modify the start up code:

ServiceHost m_serviceHost;

public Form1()
{
InitializeComponent();
this.button2.Enabled = false; m_serviceHost = new ServiceHost( typeof(Messaging.MessagingService));
}


Two event handlers are added for each button; one to start the service and one to stop it:

private void button1_Click(object sender, EventArgs e)
{
this.button1.Enabled = false;
this.button2.Enabled = true;
m_serviceHost.Open();
}

private void button2_Click(object sender, EventArgs e)
{
this.button1.Enabled = true;
this.button2.Enabled = false;
m_serviceHost.Close();
}


The close event is also modified to close the service when the form is closed:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult result = MessageBox.Show(
"Are you sure you want to close the service?",
"Service Controller", MessageBoxButtons.YesNo,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);

if (result == DialogResult.Yes) { if (m_serviceHost != null) { m_serviceHost.Close(); m_serviceHost = null; } } else
e.Cancel = true;
}


We recompile and run the solution resulting in:


Here the service is running within the UI's message loop. Modifying the implementation of IMessagingService by adding the ServiceBehavior attribute with UseSynchronizationContext set to false forces the service to operate outside of the message loop and within its own thread. Next we will modify the service to allow for callbacks to the client. We modify MessagingService.cs by adding a callback attribute to the previous IMessagingService interface and creating a new interface called IMessagingServiceCallback:

public interface IMessagingServiceCallback
{
[OperationContract(IsOneWay = true)]
void MessageNotification(string message);
}


We next modify the client by updating the service reference, creating a new class named MessagingServiceCallback which implements the IMessagingServiceCallback interface, and adding code to provide a context to the client proxy. The end result is show below:


Observations:

  1. You can host a service through a GUI application and have it start in it's own thread by either starting it before the GUI is created or adding an attribute to force it into it's own thread.
  2. Running a service in the GUI thread is probably a bad idea since the message pump has a whole lot of things to handle already.
  3. Gotta freakin' run with administrator privileges
  4. Blogger butchered some of the XML configuration file stuff up there
  5. Is there a Blogger equivalent to [code][/code] tags most forums have?

Tuesday, October 20, 2009

Lab #11: Throwing Faults and Declaring Fault Contracts

Members:

Stephen Cave, Rafael Zuniga

Summary
:

The purpose of this lab is to demonstrate how you can declare fault contracts, throw faults, and trap faults.

Procedure

We start by opening up the provided Visual Studio solution found in the Chapter8/FaultContract/ of our labs directory. It opens up and compiles fine as you can see below:

Attempting to run the server we find the following error:


Following the link gives a solution involving registering our URL as a privileged since we're using Windows 7 which, like Vista, does not run everything with administrator privileges. Instead of registering the host we instead run it with administrator privileges. This time we have the host running successfully and can attempt to upload an image which results in:


An exception message that doesn't really tell us much. Next we modify the code in PhotoManagerService.cs to throw a fault exception instead by adding the following to the UploadPhoto method:

try {
PhotoUploadUtil photoUploadUtil = new PhotoUploadUtil();
photoUploadUtil.SavePhoto(fileInfo, fileData);
} catch (ConfigurationErrorsException exConfig) { throw new FaultException(exConfig.Message); }

We compile again, run it, and this time we see the following e:


Which is much more descriptive and helps us in figuring out what's gone wrong. Next we add an attribute to the UploadPhoto method declaration within the IPhotoUpload interface. This will allow us to throw a strongly typed exception when a fault occurs which is useful if you'd like to use custom exception classes. To continue we need to modify our previous exception catching code:

catch (ConfigurationErrorsException exConfig)
{
throw new FaultException(new ConfigurationErrorsException(exConfig.Message), new FaultReason(exConfig.Message), FaultCode.CreateReceiverFaultCode(new FaultCode("ConfigurationErrorsException")));
}


We also modify the client side proxy to support the new exception contract by adding an identical fault contract attribute to the existing code which can be found in localhost.cs and adding an assembly reference to the client project. Now the client must be modified to actually catch the exception:

catch(FaultException exConfig)
{
string s = String.Format("{0}\r\nERROR:(1)",
exConfig.GetType(), exConfig.Detail.Message);
MessageBox.Show(s);
}


We recompile and now see our strongly typed fault exception:


Observations:

  1. Windows 7 is pretty neat but the UAC options can really throw you for a loop if you're used to everything running as an administrator
  2. The default settings in for the TCP transport cause it to choke on larger images
  3. Being able to give a user a better error than the cryptic "ERROR: -14" is always a good thing
  4. I'm surprised that the error in the first screen shot also gave me a link on how to resolve it

Lab #10: Working with Uncaught Exceptions

Members:

Rafael Zuniga, Stephen Cave

Summary:

The purpose of this lab is to show how exceptions are reported in WCF.

Procedure:

We begin by opening the solution found in Chapter8/Exceptions in the lab directory. The project is compiled successfully and the host and client are run:



Next we try to upload theband.jpg which results in a fault:



The current exception message does not help in solving what the problem is so we modify the service application configuration to include debugging by adding a new element to the behavior section. We add a serviceDebug element with the includeExceptionDetailsInFailts attribute set to true. Now when we run the project again we get error information which helps us identify the problem:



Observations:

  1. If you're debugging you should probably turn this on
  2. This lab was really short

Tuesday, October 13, 2009

Lab #9: Using MTOM to Handle Large Messages with Binary Data

Members:

Rafael Zuniga, Stephen Cave

Summary:

The purpose of this lab is to how MTOM can be used to upload large files over HTTP.

Procedure:

We begin by opening the solution in Chapter3/LargeMessages/ which is in the labs directory. Next we attempt to run it and:



It seems the SQL database is not set up so we need to install SQL Server Manager Express edition to install the SQL database included with the lab. Running the setup gives us:



Ok, let's find out if there's a solution:



Well that would help except we just want SQL Server Manager Express but apparently Microsoft hates us and has us download the whole SQL server instead of offering it stand alone.

Observations:
  1. Early adopters beware

Tuesday, October 6, 2009

Lab 8: Distributing Calls with NetNamedPipeBinding and NetTcpBinding

Members:
Rafael Zuniga, Stephen Cave

Summary:
Unable to initiate database for query access and submittal. Trying to run without the DB produces the following.

Attempting to add database to the solution as a project yeilds failure.


Notes on Usefulness:
There is nothing useful about failure save motivation to try again later.

Problems/Mistakes/Differences -> troubleshooting encountered:
-Unable to run querry string on database, or attach database to solution. Cannot continue. Potentially missing installation features.

Tuesday, September 29, 2009

Lab #7: Controlling Message Serialization with Message Contracts

Members:
Rafael Zuniga, Stephen Cave

Summary:
First we implement save and get gig requests and responses in a new class messages for the gigManager project.

Updated functions savegig and getgig.

Next we create a proxy for the client, running host and adding a service reference. Code is added to GigInfoForm.cs and the buttons are completed, compiling and running without error.

Changing the header value passed results in an exception as intended by the book.

Notes on Usefulness:
It's neat to see services really come together, and auto generation of the proxy is still cool.

Differences/problems/mistakes -> troubleshooting:
-Minor issue deriving context of the book regarding which functions are to be adjusted where.

Lab #6: Designing a Service Contract

Members:
Rafael Zuniga, Stephen Cave

Summary:
Adding a name and namespace to the service contract results in an exception as expected.

Unfortunately, adding the next lines of code, actions and reply actions for operation1 and 2 causes an unintended exception, and I'm not sure what to do beyond check for syntax errors. The only thing notable is the book mentions to "Drill down from localhost.cs to Reference.cs" to put the new code, but no Reference.cs exists, and I'm not sure what "Drill down" means.

Notes on Usefulness:
Frustratingly enough, I apparently cannot design a service contract.

Differences/problems/mistakes -> troubleshooting:
-book mentions to "Drill down from localhost.cs to Reference.cs" to put the new code, but no Reference.cs exists, and I'm not sure what "Drill down" means. Inserted code nets an exception.

Tuesday, September 22, 2009

Lab #5: Hosting Multiple Services and Sharing Types

Members:
Rafael Zuniga, Stephen Cave

Summary:
Loading a pre-existing solution with multiple projects, we extend ServiceA and ServiceB by their corresponding implementations in MultiContractService, as well as with IAdmin. Also add return strings for each, simply detailing which function was called.


Next we add some references for the Host, add a good portion of book code to the app.config file to manage the multiple endpoints, and finally add code to main in program.cs to run our program.

Next we move to the InternalClient project, adding functionality to all the buttons so they can call our services.


Lastly we use the external client to get the wsdl and generate a proxy and finally we implement the external service calls through the buttons.

Notes on Usefulness:
Exploring usage of multiple endpoints and working both sides of development seems pretty important for real usage.

Differences/problems/mistakes -> troubleshooting:
-not much besides a few minor book code transfer errors. Not sure why copy is bugged like that.

Lab #4: Creating an IIS Host and Browsing Metadata

Members:
Rafael Zuniga, Stephen Cave

Summary:
In an effort to expose an endpoint via website, we first make some modifications to the supplied solution, adding a new website "IISHostedService", clearing the service implementation, modifying the @ServiceHost directive to associate with our service type, and making small changes to the web.config file regarding endpoint and service tags.
The next portion had us try to browse the metadata on the website. Unfortunately, due to some unknown issue, we could not get the website to display after about an hours worth of troubleshooting(notes are listed in the problems section). This may be an issue with windows 7 or my version of visual studio, which has worked alright up till now.
If I can figure out what the issue is, I will return and finish the last portion of the lab.
...
After enabling every IIS function under the sun, then going back to the FAQ on our class website and running ServiceModelReg -i on the 64bit v3.0 WCF framework, I think we finally have what we were looking for... Or maybe not.
Finally nailing down the issue, the book has another inconsistency in that at the behavior name flip flops in 2 example points between "ServiceBehavior" on page 54 and "returnFaults" on page 56, neither is really mentioned as a change in bold or anything to be aware of, but having swapped it, a mismatch is created. Lovely. Finally getting the correct output, though weirdly enough I must still have the svc file focused in VS for it to load the correct web address.
While as in the book there is now a link to the wsdl, clicking on it unfortunately brings us to another empty page. I shudder to think what may be behind this problem, or how to find it, as there is nothing left to enable, nor clues in the class FAQ.
Attempting to run svcutil for the last portion of this lab yields what appears to be results in cmd, but nothing is generated in visual studio, and I am unable to complete the lab.

Notes on Usefulness:
The intended effect of the lab seems very beneficial, but more and more it becomes frustrating working through errors in the book, and contradictions between my system and the books system, as well as the limited vision the book provides of what is supposed to be in the solution. Unfortunately no errors were generated in this lab, so the best we could muster was to poke around making changes here and there, hoping to stumble upon the issue.

Differences/problems/mistakes -> troubleshooting:
-when attempting to add a website to the solution, we get "Unable to create the website 'http://localhost/IISHostedService'. To access local IIS Web sites, you must install the following IIS components: IIS 6 Metabase and IIS 6 Configuration Compatibility Windows Authentication. In addition you must run Visual Studio in the context of an administrator account." Trying again brings another error, demanding Windows Authentication for IIS. After another enabling spree, the web site was added
-The book wants you to run the new website in debug mode (f5) but debugging is not enabled in Web.config and a prompt is supplied as a result. We enable debugging.
-When launched in either debugging or non-debugging, only a blank browser window is displayed, not the supposed metadata publishing. Weirder still, found debugging normally opens page http://localhost/IISHostedService/ but if we hit debug while looking at Service.svc, it fails to debug, and if we run without debugging, it loads the intended http://localhost/IISHostedService/Service.svc but there is no page to be displayed.
-apparently not all components of IIS were installed, and once installed they needed to be configured with the frustratingly obscure method described on the school website.
-Finally, a book inconsistency was found, that when fixed seems to let the website function properly as long as one debugs while the svc file is currently being focused. Still weird.
-once the website functioned, it still failed to properly generate wsdl for some unknown reason. The link is there, but it returns a blank page.

Tuesday, September 15, 2009

Lab #3: Using Tools to Generate Clients and Services

Members:
Rafael Zuniga, Stephen Cave

Summary:
Loading a premade solution, we are given a client and host project. Adding a WCF template we start our hello indigo service, adding code and references for both, and compiling with no errors.
Next we create a configuration file (after deleting the pre-supplied one) using WCF Service Configuration Editor, and enable service metadata with a metadata exchange endpoint.
Next we get to generate a client proxy with the Add Service Reference, which uses SvcUtil. A bunch of files are generated properly setting up the client, and after compiling the client is run and returns the intended output from the service.
Next we create another project with the WCF Service Library template - HelloIndigo. Small modifications to the service contract and implementation, and a compile results in no errors. Then we delete the app.config file and compile again - no errors. Next we hide the previous service files in Host, and reference to the new class library. With some more modifications to the program.cs and app.config files, we have the service referenced and can compile and run with no errors.
Next we move on to generating a proxy directly with SvcUtil, starting by allowing the host to continue running. We use visual studio's command line to access svcutil with the appropriate arguments and generate the proxy!
With another exclusion and some modifies to the client program.cs, we compile and run the client after no errors, and see the appropriate output.

Notes on Usefulness:
Learning how to construct proxies automatically is a very useful tool, where remembering all the specifications takes the place of constructing the code. Using SvcUtil directly also makes you look like a cool hacker in cmd mode, though typing anything in console is a pain and a half.

Differences/problems/mistakes -> troubleshooting:
-Supplied code in book for program.cs in Main() has some syntax errors with all the curly braces
-System.ServiceModel.AddressAccessDeniedException is thrown, got to remember to start visual studio with administrator privilages from now on (using windows 7 or vista I believe causes this)
-once again copy/paste from the book to load the command line string proved annoying to correct
-There's a grammar error in the book for the portion on renaming the service library .cs files
-localhostreference.svcmap is named reference.svcmap under local host in my version
-when modifying the final program.cs, the book states a "using()" when there shouldn't be one