Whew, well finally (no really) some code!
I created an empty solution called CheeseList_3_0_0_x and created all of my projects inside of it. Call it whatever you want. In my solution I created a project for my services called CheeseListServices and then created three services, one each for Brands, CheeseTypes and Links.
I structured my project so that each service was in its own folder. I did this so that nothing happens by default. What I mean by that is that all the examples presented by books and blogs just show one service, but, most projects will have more than one service and it took me a long time (blush) to figure out how to do this in an industrial strength way, so I am starting you out that way in the beginning.
The steps to do this after creating your blank solution is to highlight the solution and then add and then new project. Since we are coding in C# here, under the Visual C# header in the Project types list click on WCF and then click on WCF Service Library. I named mine CheeseListServices.
After creating your Service project, please delete the Service1.cs and IService1.cs files in the root of the project that were created by default. Leave App.config alone for now. Then, create a few folders for your services. We are mostly going to only use one, but the other services will have one or two methods in them so you can tell for sure that everything is setup correctly and what you are calling is actually answering. After you have created your folders, create the services you’ll be using, one service to a folder so that everything that relates to that service is in one place.
To create your services, click on the folder in your services project and then goto add and then new item. In the Templates window click on WCF Service. Give it a name that makes sense to you.
You’ll notice that only two files were created, one will house service interfaces and the other will house the actual services. We are going to need to add a third for data contracts.
In your references section add a reference to System.ServiceModel and make sure that you have a using statement for it in all of your services files. In addition, since I am wrapping an existing website I also added references to my datalayer, businesslayer and common dll’s from that project. The next step is to create the data contract to support your first example.
I chose the most simple, non-transactional, routine with no parameters I could think of to start small and that was to return a list of all brands. The business layer of the site has a brand object with a ListAll() method with no parameters, so this is my starting point. I would pick something very simple with no parameters or transactions and that returns something simple, like a list.
My data contracts for BrandServices is in a file called BrandDataContracts.cs. At this point please create a data contract that will contain the types in your service. Lets take a look at a snippet of code from my data contracts file for the Brand service, and walk through what is there and why. Basically I am going to want to return a list of brands that will contain an numeric ID of a brand and a label. There is much more to this file that we will go through later.
Let’s take a look at what we did.
We created an object called BrandList and decorated it with the DataContract attribute. And as a parameter to that attribute, we are providing a string that is formatted with the URL of the service, the service type and then a year and a month. This string will uniquely identify the service in metadata so think this through carefully as it will be very helpful to have something structured that will allow you to uniquely identify your data contracts as well as something that can indicate when they were created.
Next we have our private properties just like any object. Here we created properties for a brand id, a label and an error level.
For constructors, we are allowing the creation of an a BrandList object with or without parameters. Each constructor is also calling an init method we will use to set default and other values. In this case we are setting the default value of the error level to an init status – that is neither success or fail.
In the public properties section, we are exposing our private properties through get/set variables and then are decorating each with a Name, Order and IsRequired. This decoration is important because it is used in meta data when the objects properties are exposed. If you do not list an order, properties will be displayed in alpha order which may not be the best way. IsRequired is important because if something is set as IsRequired equals true and it is not present, an exception will be thrown. When IsRequired equals false, the variable is optional.
That’s it – we have created our first data contract. Now lets go and write the service.
Open the interface file for your service. In my case its IBrandServices.cs. We are going to create an interface for our Brand service and will expose a method to list all brands, or ListAll(). Please refer to the image below.
Lets look at what we did and why.
In our namespace, it’s just like before with our data contract with one difference. In this case we are creating a Service Contract.
The one method we want to expose at this point in our service will be that list of all brands, so here we create an interface for a ListAll() method that returns a List<BrandList>. The BrandList type in our List<> is the object we created in our data contract.
Next, lets create the actual service. In my case I created a BrandServices.cs file. Let’s take a look and see what was done.
We created a public object called BrandServices and derived it from our interface IBrandServices. We have one public method called ListAll() that returns a List<BrandList>. The first thing we do is to create a new brand object of type List<BrandList> and then call the ListAll() method in the business layer of the existing web site.
Since that application has been a self contained web site, we used DataTables for passing our data around. This is not a problem because all of the .NET controls can data bind to them. However DataTables will not work for services. We need strongly typed data.
Let’s take a step back for a minute to understand why we need strongly typed data. One of the crown jewels of using WCF to implement services is in the mechanism for a standard in the creation of metadata files that can be consumed by any application using our service, or in a word, interoperability. That is, you could write services in .NET and they can be consumed by a Java app or vice versa. But the calling application must have a way to find your service and then to understand the details of your service, operation, data and fault contracts.
I don’t want to get too deep here as the references linked to the first post in this series cover this in detail, but when we look at the metadata for the return value for the List<BrandList> it is seen as a BrandList. One side of the service can use all of its types but as long as they are translated and handled by metadata the calling application can consume them.
One more aspect of types. There is a generic type of collection available in the ServiceModel namespace that you can use instead of List<>. This is valuable because the program using the service may not know what a List<> is but needs a collection it can insert objects into to pass them back to you. We’ll get into this a little later, but if you create a data type based on an ObservableCollection<>, the client can create that type, fill it and send it back.
Ok, back to our code. After checking the error level and row count from the call to the ListAll() method exposed by the original business layer, for each data row in the returned data table, we are creating a new BrandList object and adding it to the brands list. If we do not throw an exception, we return the brands list.
For now I am going to skip exception handling, but will get back to it later after we get this service working. So you can copy and paste my catch block.
Ok, so to review, we created our solution and then created a project to house our services. We created one service that is consuming a method from an existing application and are supporting it with a data contract and an operation contract.
The next step will be to host the service so we can work with it, and we’ll do that in the next article. In that post we will learn how to set up IIS7 to host a service using the net.tcp protocol which is much faster than http and can feed either a website or a windows form application equally well.
This is the first in a series of articles designed to provide an example of a practical architecture for WCF in its support of a services oriented architecture.
We are going to look at how you could take an existing web site and wrap its functionality in services to be consumed by either a web site or a windows forms application. We will show you how to configure your network and servers to offer these services across domains and machine boundaries. We’ll also take a look at how to structure data contracts to provide robust objects and lists of objects across the wire with exception reporting. Finally we’ll look at how to configure support for distributed transactions and some suggestions for structuring projects to make testing and deployment easier.
There are a few references that I recommend using as you are learning WCF and they are posted here on the Computer Mutt. Those resources will address a wider range of WCF concepts much more in-depth than I will here as this article is focused on providing an approach to a particular problem, and not structured to review all options that are available. Michelle Leroux’s introduction in the chapter on working with WCF in Visual Studio 2008 which covers SOA and WCF is total gold, and every time I re-read it I get something out of it.
Ok, let’s take the first step look at what we have and what we want to wind up with. We are starting out with a current web site that site is a very simple ASP.NET 3.5 public web application in production that provides a list of cheese brands and cheese types that are made without animal rennet. It has discreet layers consisting of a data layer, business layer and presentation layer in the form of web pages. The data layer talks to Microsoft SQL Server 2008 and runs on IIS7 on Windows Server 2008. Everything is 64 bit and everything is on a single box. Basically it is simple running website and thus a good candidate for a first step.
Here is a network diagram showing the current architecture of the website we are going to transform:
The diagram below is what the architecture will look like after we transform it. The differences are that major components are separated by machine boundaries. The database has its own box, services has its own box, and the web site has its own box. On the services box we also have the original business and data layers along with IIS.
Once we transform our original website and began offering services, we are simply serving content to presentation layers both inside and outside of your network allowing you to use either browsers or Windows Forms applications. In the case of a browser, the user points to a URL to get content, in your Windows Forms application, you can configure an endpoint to point to, either way, desktop configuration and support can be much simpler as a result.
Configuring the environment for services behind the firewall is simpler than offering them over the network, and the scope of this series is for services on the inside of the firewall. In a subsequent article, I’ll walk you through the steps necessary to offer secure services over the internet.
We are going to use Visual Studio 2008 with .NET 3.5 along with WCF Services Templates to code services. Development is on a Vista machine. An aside on Vista first. I’ve heard how Vista sucked and to avoid it, however when I switched to developing and supporting ASP.NET apps on Windows Server 2008 & IIS7, I found that using Vista simplified development.
First, Vista uses IIS7 (which is the version on Server 2008) and it understands the web.config files generated by Visual Studio 2008. I can also configure those web.config files once in one place in the file, unlike developing on XP where you have to configure the same thing in several places in the file. Yes, UAC blows, but you can turn it off and I have had no problems using it. I’m not advocating that you switch from XP if you want to develop services to run on Windows Server 2008, I’m just passing along that I found with Vista I created a less error prone development environment.
One last word on environment. While you will be able to do everything in this series of articles on one machine, it will work out better for you in the long run if you have an Active Directory environment with at least three dedicated boxes; Web, Services, Database. If you have limited equipment, consider creating seperate environments using Hyper-V. Go to my recent post for help on creating and cloning Hyper-V environments.
I really want to emphasize that it is in your interest to invest the sweat in creating seperate environments to run the examples in this series. The reason is that a lot happens by default when you run everything on a single box and you’ll never realize it until you begin to move things around, and by then you’ll have to spend an undetermined amount of time to backtrack to uncover your mistakes. Also, nobody is really going to be running this stuff on a single machine in a production environment anyway, so you might as well get used to it right off of the bat. If you understand what the network requires to support WCF you’ll be more valuable to your company and customers.
Before finishing this introduction, some thoughts on the Web Client Software Factory (WCSF). This tool will allow you to code WCF services using a visual designer in Visual Studio. One of its strengths is that it forces a particular format on project directory structure which can be advantagous since everyone on the team will be forced to structure their work the same way. I began working in WCF using this tool, and I have to say it was a very confusing time for me as took a lot of effort to understand where the tool left off and WCF began; it was unnecessairly complex.
Furtheremore, once you start a project in the tool and need to make changes, you must go back and make them through the designer. There are some other very severe side effects to. One is that the tool will create directory and filenames that will break Visual Studio and this goes double if you are using Team Foundation Server. Having outlined some of my concerns, you have to that creating such a tool is a huge accomplishment, and although this tool is just in its beginning stages, over time I am certian refinements will be introduced smoothing out some of its early difficulties.
In my mind it is best to start out simply and do everything manually so you get a clear understanding of what you need to do to support WCF services.
Next up – A Practical Architecture for WCF – Part 2 which will demonstrate the creation of services.
One of the most valuable resources from my point of view is the author and lecturer Michele Leroux Bustamante. She has written a book published by O’Reilly called Learning WCF that is really a great step by step and practical approach to understanding the details and implications of WCF.
She will start with a high level concept and drill down through to source code to illustrate her point. And, because it is a learning experience, the code is in context with enough to help you implement it. I am mentioning this because a lot of the books I have read on WCF are basically concepts mapped to islands of code, but nothing at a practical level to help me to tie them together.
One note about the book. There is a new chapter out that covers Visual Studio 2008 and .NET 3.5, but unfortunately, there is a chance when you order online, you are not always garuanteed to get the second release. I bought the first release last year and wanted the second release and ordered from Amazon and they still sent me the first release. However, Michele says that really the only difference is chapter one and she did a deal with her publisher to provide that chapter in PDF form on her blog. The link is: http://www.thatindigogirl.com/downloads/LearningWCFChapter01VS2008.pdf.
Additionally she has done a 15 part lecture series on WCF published through Microsoft’s Webcast series. These lectures are downloadable and really very well worth the time. The link for the WCF Webcast series is: http://agarwalmk.spaces.live.com/blog/cns!780CD8FB86EF8F7C!14966.entry?wa=wsignin1.0&sa=16708577.
I am revising this post to include several other books I found really helpful along the way:
- Programming WCF by Juval Lowy – publisher O’Reilly
- Pro WCF by Chris Peiris and Dennis Mulder – publisher APress
- Essential Windows Communication Foundation for .NET 3.5 by Steve Maine – publisher Addison Wesley
Maine’s Essential Windows Communication Foundation was the hardest book for me to understand at the beginning because he does not take a cookbook but a conceptual approach. However the more I learned, the more I began gravitating to his book. I really like it, however I have gotten a lot out of all of the books.
Just as an FYI, in a related post, I am writing a series of articles on a practical WCF architecture. The first post is here.