About
This project presents a simple, but fun WCF Halloween Name Service Application. The service provides either a single Halloween name (string), or an array of Halloween names. It is hosted using IIS Express to quickly demo and test the service with a client.
A client “tester” console application tests the service and provides output to the user.
Architecture
The demo project consists of these component topics:
- Halloween Name WCF Service Application
- Name (DataContract Model)
- NameHelper (Helper Class)
- IHalloweenService (Interface for Service)
- HalloweenService (Code that Implements the Service Interface)
- Client “Tester to Service” Console Application
- Connected Service “Proxy Reference” HalloweenNameServiceRef
- Main Program (Tests and Outputs to User Results)
Halloween Name WCF Service Application
A WCF Service Application project was added to my Visual Studio solution. The code is available on GitHub here.
Name (Data Model Contract)
The Name class is a simple DataContract with two DataMember representing a first name and a last name of a Halloween name implemented as automatic properties. The code is available on GitHub here.
1 2 3 4 5 6 7 8 9 10 |
[DataContract] public class Name { [DataMember] public string FirstName { get; set; } [DataMember] public string LastName { get; set; } } // end of class |
Name Helper (Helper Class)
The NameHelper is a static utility or helper class for the service application. The code is available on GitHub here.
It initializes and loads two static lists of first names and last names from two separate text files in the App_Data directory using reflection (See text files here). The class uses a random number generator to randomize picking of names from both lists. The random names are then built into a Name object with the first and last name, then returned to the caller.
There are two static methods in the NameHelper class:
LoadNames
This method will create two lists (List<string>) representing the first names and last names of a Halloween name. It retrieves the names from two separate text files in the App_Data directory using reflection. Note: The text files are Embedded Resources in the project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/// <summary> /// LoadNames /// This method will create two lists representing the /// first names and last names of a Halloween name. It /// retrieves the names from two separate text files in the /// App_Data directory using reflection. Make sure the text /// files are Embedded Resources in the project. /// </summary> private static void LoadNames() { List<string> firstNames = new List<string>(); List<string> lastNames = new List<string>(); Assembly asm = Assembly.GetExecutingAssembly(); // First Names using (StreamReader sr = new StreamReader(asm.GetManifestResourceStream("HalloweenName.App_Data.FirstNames.txt"))) { while (!sr.EndOfStream) { string name = sr.ReadLine().Trim().ToLower(); if (!string.IsNullOrEmpty(name)) { firstNames.Add(string.Format("{0}{1}", char.ToUpper(name[0]), name.Substring(1))); } } } // Last Names using (StreamReader sr = new StreamReader(asm.GetManifestResourceStream("HalloweenName.App_Data.LastNames.txt"))) { while (!sr.EndOfStream) { string name = sr.ReadLine().Trim().ToLower(); if (!string.IsNullOrEmpty(name)) { lastNames.Add(string.Format("{0}{1}", char.ToUpper(name[0]), name.Substring(1))); } } } m_FirstNames = firstNames; m_LastNames = lastNames; } // end of method |
GetRandomName
This method will build and return a random generated Name object from predetermined List<string> of first names and last names that have been loaded from files in the project. It first determines if the static lists have been loaded, and if not, it calls the LoadNames() method to load the lists.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/// <summary> /// GetRandomName() /// This method will return a random generated Name /// object from a pre-deterermined list of First Names /// and Last Names that have been loaded from files in /// the project. It first determines if the Lists have been /// loaded, if not, it calls the method to load the lists. /// </summary> /// <returns>Name object of a Halloween Name</returns> public static Name GetRandomName() { if (m_FirstNames.Count == 0) { LoadNames(); } Name p = new Name(); int index = m_Rnd.Next(0, m_FirstNames.Count); p.FirstName = m_FirstNames[index]; index = m_Rnd.Next(0, m_LastNames.Count); p.LastName = m_LastNames[index]; return p; } // end of method } // end of class |
IHalloweenService (Interface for Service)
The ServiceContract for the Halloween Name Service allows for two possible options: a single Name entity and a list of Name entities. The first OperationContract will return a Name object, representing a randomly generated Halloween Name. The second OperationContract will return a List<Name> (list of randomly generated Halloween names) but since WCF cannot return generics by default, it will actually return an array of Name objects that the client can use to enumerate or convert to a generic of List<Name>. The code is available on GitHub here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/// <summary> /// Interface for the HalloweenService /// </summary> [ServiceContract] public interface IHalloweenService { /// <summary> /// Get a Random Halloween Name! /// </summary> /// <returns>Name</returns> [OperationContract] Name GetRandomName(); /// <summary> /// Get a List of Random Halloween Names /// </summary> /// <param name="count">Number of Random Names Requested</param> /// <returns>List of Name objects</returns> [OperationContract] List<Name> GetRandomNames(int count); } // end of interface |
HalloweenService (Code that Implements the Service Interface)
The service implementation code relies on the NameHelper class to further simplify and abstract the implementation. The code is available on GitHub here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/// <summary> /// Implements the HalloweenService /// </summary> public class HalloweenService : IHalloweenService { /// <summary> /// Gets a Fun Random Halloween Name /// </summary> /// <returns>Name</returns> public Name GetRandomName() { return NameHelper.GetRandomName(); } // end of method /// <summary> /// Get a List of Fun Random Halloween Names /// </summary> /// <param name="count">Number of Names (int) requested</param> /// <returns>List of Name objects</returns> public List<Name> GetRandomNames(int count) { List<Name> names = new List<Name>(); for (int i = 0; i < count; i++) { names.Add(NameHelper.GetRandomName()); } // end of for loop return names; } // end of method } // end of class |
Client “Tester to Service” Console Application
The client “tester to service” is a simple console application project in the same solution that connects to the Halloween Name service by use of a proxy generated by SVCUTIL. The client program will use this proxy to test each OperationContract or method available in the ServiceContract and return the results to the user on the console window. The code is available on GitHub here.
Connected Service “Proxy Reference” HalloweenNameServiceRef
I used the simple “Add Service Reference” wizard to create a Service Reference to an existing service in my Visual Studio solution. After selecting the “Discover” button on the wizard, it was able to first load, instance, and then recognize the Halloween Name service and build the service reference using the exposed meta-exchange data “WSDL”. See the demo section for more information on how to use SVCUTIL without the wizard to generate client “tester” proxies to an existing service. The auto-generated code is available on GitHub here.
Main Program
The main program in the client “tester” console application first connects to the Halloween Service using a client proxy with classes built from the “Add Service Reference” wizard. Based on this proxy, it then can call upon and retrieves either a single Halloween name or an enumerable list of Halloween Names. Note: The Halloween Service actually returns the List<Name> as an array[Name] and my client program converts it to a List (WCF does not work with generics by default). The code is available on GitHub here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
/// <summary> /// Client "Tester" Application for Halloween Service /// </summary> class Program { /// <summary> /// Main Method for Program Entry /// </summary> /// <param name="args">No input arguments used</param> static void Main(string[] args) { // Create Client Proxy to the Service HalloweenServiceClient proxy = new HalloweenServiceClient(); #region Test Get One Halloween Name // Call the Service through the Proxy Name n = proxy.GetRandomName(); // Write the Result to the Console Window Console.WriteLine("Your Halloween Name is {0} {1}", n.FirstName, n.LastName); Console.WriteLine(); #endregion Test Get One Halloween Name #region Test Get List of Halloween Names // Call the Service through the Proxy // FYI WCF/WSDL Does not Support Generics in Services // It returns an Array of Items List<Name> names = proxy.GetRandomNames(5).ToList<Name>(); Console.WriteLine("List of Halloween Names"); Console.WriteLine("======================="); foreach (Name item in names) { Console.WriteLine("{0} {1}", item.FirstName, item.LastName); } #endregion Test Get List of Halloween Names // Wait for the User to See the Input Console.WriteLine("Press <Enter> to Quit..."); Console.ReadLine(); } // end of main method } // end of class |
Demo
Code
The entire project code repository is available on GitHub here.