Introduction
Well, this very article is in continuance with my previous article on WCF. Folks can view the earlier article by browsing over
to the URL: http://www.codeproject.com/Articles/566691/WCF-From-a-Beginners-perspective-a-Tutorial.
In this article I would want to explain and show how to consume a WCF service in an ASP.NET web application, and how to code a ASP.NET AJAX WCF service via codes
and lots of illustrations.
Viewers and readers who don't have much idea as to what is WCF, what it does and else, kindly visit the above listed URL, it gives an initial understanding of the subject,
as to how to start, how to proceed with coding WCF services and stuffs. Let's get started without further delay. Stay tuned.
Background
There ain't specific background as such, but since this is a sequel to the above mentioned article (visit URL), I suggest a glance at that wouldn't do any harm.
And yes, presence of Visual Studio 2008 is a pre-requisite.
Using the code
Let's start with the code part.
- Open your Visual Studio 2008 client, and click on New>Web Site.
- It will open a dialog box as shown below. Select WCF service from the template, give the location where you want to store the WCF service and then click OK.
- Visual Studio will open up a new solution. The solution will have one project WCF service project. Under App_Code folder, you can find two
class files namely Service.cs and IService.cs. Also, Service.svc file would be evident. There will be some default implementation in the class files.
Please delete them as per now, we will code our own functionalities.
- Let me give an idea as to what are we gonna do in this service. I am pretty fond of TV Series, hence this WCF service will help us to enter the details of our favorite
TV series and will also assist us in viewing the details of them, once entered. I have two operations in my ServiceContract under IService.cs,
namely InsertSeriesDetails() and GetSeriesDetails(). In my DataContract, I have three properties as DataMembers,
since these will be serialized, when WCF service is consumed. Insertion of TV series details and then retrieval of those details will take place via a database.
So let's create a table in a DB in SQL Server 2008.
- Open your SQL Management Studio, connect to your server, then create a table called as dbo.TVSeries in your desired database.
For the time being I have 3 columns in the table, namely TVSeriesName, FavMaleCharacter, FavFemaleCharacter. You can have more columns as you desire.
Copy the below SQL script and execute it in your SQL Management Studio.
CREATE TABLE dbo.TVSeries(
[TVSeriesName] VARCHAR(max) NOT NULL,
[FavMaleChar] VARCHAR(max) NOT NULL,
[FavFemaleChar] VARCHAR(max) NOT NULL)
Execute the script and you will find it evident under Tables category in your desired database as below:
We will not insert rows into the table now, we will do it via an ASP.NET web site.
- Let's head back on creation of the WCF service. Start coding in your IService.cs file as shown below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Data;
[ServiceContract]
public interface IService
{
[OperationContract]
string InsertSeriesDetails(TVSeries tvSeriesObj);
[OperationContract]
List<TVSeries> GetSeriesDetails();
}
[DataContract]
public class TVSeries
{
string seriesName = "";
string favMaleChar = "";
string favFemaleChar = "";
[DataMember]
public string TVSeriesName
{
get {return seriesName ;}
set { seriesName=value;}
}
[DataMember]
public string FavMaleCharacter
{
get {return favMaleChar ;}
set {favMaleChar=value ;}
}
[DataMember]
public string FavFemaleCharacter
{
get {return favFemaleChar ;}
set { favFemaleChar=value;}
}
}
I would like to explain as to what I have coded in the IService.cs file. Here I have an interface as a Service Contract, which encompasses 2 Operation Contracts within itself,
i.e., in plain words we can say that it has 2 methods defined under itself. Next, we have a user-defined class called as
TVSeries
having three DataMembers, which explains to the client that what kind of data it contains. After coding the
IService.cs file, we will have to write the functionalities of the methods in Service.cs file. Let's get ahead with that.
- Copy the below shown code into your Service.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
public class Service : IService
{
SqlConnection xconn = new SqlConnection(
ConfigurationManager.ConnectionStrings["connectionStrings"].ToString());
public string InsertSeriesDetails(TVSeries tvSeriesObj)
{
string msg = string.Empty;
SqlCommand xcmd = new SqlCommand("Insert into Development.dbo.TVSeries(
TVSeriesName,FavMaleChar,FavFemaleChar) values(@seriesName,@favMale,@favFemale)", xconn);
xcmd.Parameters.AddWithValue("@seriesName", tvSeriesObj.TVSeriesName);
xcmd.Parameters.AddWithValue("@favMale", tvSeriesObj.FavMaleCharacter);
xcmd.Parameters.AddWithValue("@favFemale", tvSeriesObj.FavFemaleCharacter);
try
{
xconn.Open();
int ret = xcmd.ExecuteNonQuery();
if (ret == 1)
{
msg = "Hurray...You have now entered your favorite TV Series Details..";
}
else
{
msg = "Some error occurred..Please try again";
}
}
finally
{
xconn.Close();
}
return msg;
}
public List<TVSeries> GetSeriesDetails()
{
List<TVSeries> TVlist = new List<TVSeries>();
SqlDataAdapter da = new SqlDataAdapter("select * from Development.dbo.TVSeries", xconn);
DataTable dt = new DataTable();
try
{
xconn.Open();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
TVSeries obj = new TVSeries();
obj.TVSeriesName = dt.Rows[i][0].ToString();
obj.FavMaleCharacter = dt.Rows[i][1].ToString();
obj.FavFemaleCharacter = dt.Rows[i][2].ToString();
TVlist.Add(obj);
}
}
}
finally
{
xconn.Close();
}
return TVlist;
}
}
In the above code, we are trying to establish a connection with the SQL database under which our table resides, then we have the implementation of the two operation contracts,
namely InsertSeriesDetails()
and GetSeriesDetails()
. InsertSeriesDetails()
takes the class TVSeries
as its argument,
then we define a SQLCommand
object,giving an appropriate Insert Query and then call the ExecuteNonQuery()
method, to insert a row into the DB.
GetSeriesDetails()
involves a SQLDataAdapter
, which fills a DataTable
with the records from the SQL table,
and then later we bind the results to a List.
I would like to point out at this point of time that, we can't use a DataTable directly
to bind the data when we use a WCF service. This very point will be discussed later in the article. Do watch for that.
I personally like to segregate the connection strings in the configuration file, rather than using the big connection string in the code-behind file itself.
You can define the connection string as below:
<connectionStrings>
<add name="connectionStrings" connectionString="Data Source=DEVELOPER-PC;Initial Catalog=Development;
Integrated Security=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
Also, an important part of the Config file would be the end-point configuration, for the time being I haven't messed up with the end points here, have left them to be default.
I have wsHttpBinding in the config file, you can alter if you want to.
<endpoint address="" binding="wsHttpBinding" contract="IService">
Now, the WCF service is ready, right click the Service.svc file and select and click 'View in Browser', the ASP.NET Development server will open your browser
and you can see your WCF service over there, something like below:
Here you go, your service is up and running. Now let's create an ASP.NET website which will act as a client to consume this WCF service.
- You can create a new solution or add another project in the above solution. as you desire. Next. click on New>WebSite.
- A dialog box will open suggesting a lot of templates, click on ASP.NET Web Site, give the storage location and hit OK.
- An empty website will be added to your solution. Refer to the attached zipped code on designing the page. Basically I have
3 textboxes, in which the user will enter the tv series name, his fav male and female character names,
2 buttons namely 'Insert' and 'Click to see the details' and 1 grid view. It looks something like below:
I have just given a lil bit design to the page using some CSS tricks and tips. You can find those stuffs in the StyleSheet.css page.
Nevamind, let's move ahead..
- Now comes the important part, adding the service reference to the web site. Right-click the web site project and click on
'Add Service Reference'. It will open a dialog box, where you will have to enter the URL of the service which you have just created,
and hit Go. The ASP.NET engine lists all the operations which are exposed by the WCF service, you need to provide a namespace and hit OK. See the image below for further reference.
- Now, open the Default.aspx.cs file and type in the code as below:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using TV;
using System.Collections.Generic;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
lblResult.Visible = false;
}
protected void Button1_Click(object sender, EventArgs e)
{
if (!(string.IsNullOrEmpty(txtSeriesName.Text) &&
string.IsNullOrEmpty(txtMale.Text) && string.IsNullOrEmpty(txtFemale.Text)))
{
ServiceClient obj = new ServiceClient();
TVSeries obj2 = new TVSeries();
obj2.TVSeriesName = txtSeriesName.Text;
obj2.FavMaleCharacter = txtMale.Text;
obj2.FavFemaleCharacter = txtFemale.Text;
string message = obj.InsertSeriesDetails(obj2);
lblResult.Visible = true;
lblResult.Text = message;
}
else
{
lblResult.Visible = true;
lblResult.Text = "Please enter the TV series details..Then hit Insert button...";
txtSeriesName.Focus();
}
}
protected void Button2_Click(object sender, EventArgs e)
{
lblResult.Visible = false;
ServiceClient obj3 = new ServiceClient();
IList<TVSeries> listTV = obj3.GetSeriesDetails();
grdView.DataSource = listTV;
grdView.DataBind();
}
}
Nothing special in the above code, we have just made an object of the proxy class created, ServiceClient
and using that object we are calling the two exposed operations
by the WCF service, on the 2 button clicks. Build the code, it should build without errors.
Also, check the config file of the website for the client endpoint details, should be similar to something like below:
<client>
<endpoint address="http://localhost:51861/NewService/Service.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService"
contract="TV.IService" name="WSHttpBinding_IService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
- Debug the solution, it shouldn't throw any errors as such and the functionalities should work as desired. Have a look below:
- I would like to stress on an important aspect over here, while consuming the WCF service, you might encounter an exception such as:
{"The server was unable to process the request due to an internal error.
For more information about the error, either turn on IncludeExceptionDetailInFaults
(either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior)
on the server in order to send the exception information back to the client, or turn on tracing
as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs."}
It suggests that something is wrong in your WCF service, an exception is unhandled. We need to get to the root cause as to what's wrong in the code or else.
For this we include the attribute includeExceptionDetailInFaults=true in the config file of the WCF service,
in order to get ample information on the unhandled exception or error, which is sent back to the client. Have a look below:
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
In my case, column names were not matching in the WCF service code and my DB, hence I too was getting the above enormous exception.
I included the above said attribute and I was able to get hold of my error and ultimately resolve it. See the below image for further reference.
Hope the readers have got an idea as to how to consume a WCF service in an ASP.NET web application. Next, let's focus on how to code an AJAX enabled WCF service.
Stay tuned.
An excerpt from MSDN is below:
ASP.NET AJAX consists of client-script libraries and of server components that are integrated to provide a robust development framework.
To access a service from an ASP.NET page: once the service URL is added to the ASP.NET Script Manager control on the page, service operations may be invoked
using JavaScript code that looks exactly like a regular JavaScript function call.
Most Windows Communication Foundation (WCF) services may be exposed as a service compatible with ASP.NET AJAX by adding an appropriate ASP.NET AJAX endpoint.
So what do we understand from the above texts? Let me try to explain this via a simple example.
You have a mathematical website, you need to display a little Pascal series in few labels in your website and give some effects on that to make the website look cool.
So what do you do now?
Have a AJAX enabled WCF service having an operation contract to do the coding part for your Pascal series, and call that service using Javascript code on to your labels,
no need to perform any server-side coding here,save your website from performance glitches and lags.
Summary is you can directly communicate your WCF service from client side Javascript code.
Let's go ahead to some codes.
- Open your VS 2008 and click on New>WebSite.
- Select ASP.NET WebSite template and give the location as you would like.
- Right click on the AJAX project and click on 'Add New Item'. Select AJAX enabled WCF service from the list and give a name.
- Once you add the AJAX enabled WCF service, a class file will be opened which will have some default code. Here we have a
[ServiceContract(Namespace="")]
attribute. Specify the namespace as the project name you have given in this case AJAX.
Write some operation contracts (methods) in the .cs file, which will be exposed ultimately.
Have a look at the below code for further reference.
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
[ServiceContract(Namespace = "AJAX")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MathService
{
[OperationContract]
public int Multiplication(int a, int b)
{
return a * b;
}
}
We have one operation contract which just multiplies 2 integers and returns back the result.Now let's configure the client to access the Service.
- Open the Default.aspx page and drop a ScriptManager from the AJAX portion of the ToolBox. Then we need to configure the ScriptManager to accept the WCF service,
something like below:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="MathService.svc" />
</Services>
</asp:ScriptManager>
You can also do this via Properties>Services (Add Collection). Now the script manager is configured, we need to do some designing in our page.
- Drop two labels and two HTML type textboxes (basically Input (text)), 1 HTML type button on your
Default.aspx page, something like below:
<asp:Label ID="Label1" runat="server" Text="Enter one number:"></asp:Label>
<input id="txtOne" type="text" />
<br />
<br />
<asp:Label ID="Label2" runat="server"
Text="Enter another number:"></asp:Label>
<input id="txtTwo" type="text" /><br />
<br />
<input id="btnClick" type="button" value="Click Me" onclick="return Multiply()" /><br />
<div id="new"></div>
We also have a div named as 'new' where we will display the result. The Default.aspx page will look something like below:
- Now comes the important part, to write the JavaScript code, be a little cautious over here. We have defined a function named as "
Multiply()
"
in the onclick
event of the button "Click Me", in this function itself we will configure as to how to call the WCF service's operation contract.
Start coding as below in the Default.aspx page itself:
<script type="text/javascript" language="javascript">
function Multiply() {
var service = new AJAX.MathService();
service.Multiplication($get("txtOne").value,
$get("txtTwo").value, onSuccess, onFailure);
}
function onSuccess(result) {
$get("new").innerHTML = "The multiplication is:"+result;
}
function onFailure(result) {
window.alert(result.get_message());
}
</script>
Now, let me explain the above JavaScript code. In the function Multiply(), we are creating a new variable named as "service" which
is refering to the MathService service created earlier. Then we use the variable "service" to access the Operation Contract of the WCF service.
We provide 4 parameters to the function, 2 are the values which a user's gonna type in the front-end, while rest 2 are further JavaScript functions which define,
as to what will happen if the operation succeeds or not. Hence functions are called as onSuccess and onFailure.
You can give whatever name you desire, but please remember to implement them.
On the successful implementation of the operation contract, I have tried to encode a message on to the "new" div, while onFailure alerts the alert message,
if the implementation fails. The code itself is almost self-explanatory.
- Build the solution, see for any errors, and then start debugging the project. It should happen something like below:
Thus, we have seen how to create a AJAX enabled WCF service and how to call it from an ASP.NET client by using JavaScript.
Well, guess it
is time to wrap up the article. In this article, we have learnt:
- How to consume a WCF service via an ASP.NET WebSite.
- How to code an AJAX enabled WCF Service and consume it in an ASP.NET Web Site
Points of Interest
I learnt a lot while writing this article.
I would like to share with the readers that we can't directly use a DataTable to bind data in a WCF service.It's actually bad practice.
If we are returning a DataTable from a WCF service, we are actually messing up with service-oriented architecture. The contract doesn't define what columns the DataTable contains.
So if in future, the columns change, the client will be in problem, because the columns have changed but not the contract.
Provided that it isn't a good practice, we still can use a DataTable in a WCF service, by providing a TableName.
DataTable dt=new DataTable();
dt.TableName="newTestTable";
return dt;
I have attached the codes in the zipped folder. It has three projects basically, NewService, SampleWeb and AJAX.
NewService is the WCF service project, SampleWeb is the ASP.NET website project which is consuming the NewService. AJAX has the implementation of the AJAX enabled WCF service
and its consumption via a web app. Make full use of the code and enjoy.
History
- 2 April,2013: Version 1.0