Saturday, April 16, 2011

Test WCF Services using the WCF Test Client Application

The WCF Test tool (WcfTestClient.ext) is great for testing Services locally before you deploy them or even get too far in the development process. You can test individual Methods in the Service. You have the ability to pass in arguments and review results in XML or as an object. The WCF Test Client should be located at C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\.

I’ll create a small WCF project named NorthwindServiceLibrary. It will use the Northwind Database and will expose one ServiceContract and two OperationContracts. The first Method will be GetCustomerOrder and will accept an integer argument that will be the OrderID. The second method will be GetCustomerOrders and this will accept a string argument of CustomerID and return a list of Order Objects for a given Customer.

So in Visual Studio (I’m using 2008 for this) we can create a new WCF Service Application and name it NorthwindServiceLibrary…. or whatever name you would like. I will keep the IService1.cs interface and Service1.cs default class. I’m removing the default contract and methods and replacing them with my own for the sake of cleanness, but for your first service, those defaults can come in handy as they are affective place-holders. Your IService.cs interface contract should look like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using NorthwindServiceLibrary.Data;

namespace NorthwindServiceLibrary{

[ServiceContract]
public interface IService1
{
[OperationContract]
Order GetCustomerOrder(int orderID);

[OperationContract]
List<Order> GetCustomerOrders(string customerID);
}
}

Notice I have a namespace called NorthwindServiceLibrary.Data. You can create this folder in your project and add the following DTO for a Order:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

namespace NorthwindServiceLibrary.Data
{
[DataContract]
public class
Order
{
[DataMember]
public int OrderID { get; set; }

[DataMember]
public string CustomerID { get; set; }

[DataMember]
public DateTime OrderDate { get; set; }

[DataMember]
public string ShipName { get; set; }

[DataMember]
public string ShipAddress { get; set; }

[DataMember]
public string ShipCity { get; set; }

[DataMember]
public string ShipState { get; set; }

[DataMember]
public string ShipZip { get; set; }

}
}

So now we can start adding code to our Service1.cs class. This class will have the two methods to implement the ServiceContract’s interface methods.

public class Service1 : IService1
{
public Order GetCustomerOrder(int orderID)
{
return BuildOrder(orderID);
}

public List<Order> GetCustomerOrders(string customerID)
{
return BuildOrders(customerID);
}



Below are the two methods that will read the Northwind Database and return either a single order or a List<Order> of orders for a Customer. 


private Order BuildOrder(int _id)
{
using (SqlConnection conn = new
SqlConnection
("Data Source=SAM-PC\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI"))
{
conn.Open();
SqlCommand command = new SqlCommand("Select * from Orders where OrderID = '" + _id + "'", conn);
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while(reader.Read())
{
Order order = new Order()
{
OrderID = reader.GetInt32(0),
CustomerID = reader.GetString(1),
OrderDate = (DateTime)reader["ShippedDate"],
ShipName = (string)reader["ShipName"],
ShipAddress = (string)reader["ShipAddress"].ToString(),
ShipCity = (string)reader["ShipCity"],
ShipState = (string)reader["ShipRegion"],
ShipZip = (string)reader["ShipPostalCode"]
};
return order;
}

}
return new Order();
}
}

/// <summary>
///
/// </summary>
/// <param name="_id"></param>
/// <returns></returns>
public List<Order> BuildOrders(string _id)
{
List<Order> orders = new List<Order>();
using (SqlConnection conn = new
SqlConnection
("Data Source=SAM-PC\\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI"))
{
conn.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "GetOrders";
command.Parameters.Add(new SqlParameter("@CustomerID", SqlDbType.VarChar)).Value = _id;

SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
orders.Add
(
new
Order
{
OrderID = (int)reader["OrderID"],
CustomerID = (string)reader["CustomerID"],
OrderDate = (DateTime)reader["ShippedDate"],
ShipName = (string)reader["ShipName"],
ShipAddress = (string)reader["ShipAddress"],
ShipCity = (string)reader["ShipCity"],
ShipState = (string)reader["ShipRegion"]
}
);
}
reader.Close();
return orders;
}
reader.Close();
return orders;
}
}
}


So that is pretty much all there is to the Service. Two methods in our interface one accepts an integer for OrderID and the other accepts a string CustomerID for a List<Order>() of orders for a given customer. Now as is this service is ready to run. When you run it, you should see a instance of the site/service running in your task manager. My url is: http://localhost:50304/. When I open it up in a browser window and click on Service1.svc, I get the following url in my browser: http://localhost:50304/Service1.svc. Now at this point I can just launch the WCFTextClient.exe application from C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE.

svchostaddress



Once you launch the application you select File/AddService and past in the http://localhost:50304/Service1.svc url. You will notice that the Service1 methods will be available in the left-pane. double-clicking the method will open up the right panel where you can enter arguments, click the Invoke button and view the output results.




svcResults

And that is how we can build and test a WCF service.

1 comment:

Muhammad Azeem said...

This is a nice article..
Its easy to understand ..
And this article is using to learn something about it..

c#, dot.net, php tutorial, Ms sql server

Thanks a lot..!
ri80