Introduction
In the previous article we saw a WCF Authentication and Authorization example using a Windows Client. In the distributed world we often end up with multiple consumers of the same service. But the same client code won't be enough to run on the new client platforms, especially in Silverlight.
In this article we can explore using the same WCF service using a Silverlight client.
The core aspects we cover here are:
Following are the activities involved:
Open the existing WCF service application |
Create Silverlight application |
Add Service References |
Enable Cookie Container |
Invoke Authentication Service |
Invoke Utility Service |
Run the Application |
Create Service Client Factories |
So now we can start with the above steps.
Step 1: Open the existing WCF service application
Open the previous WCF service application solution.
Step 2: Create Silverlight application
Now add a new Silverlight Application into it and name it SilverlightClient.
Click Ok and in the next page use the same WCF application for hosing our Silverlight client.
The hosting in same WCF service discards the chance of Cross Domain policy error.
Please note that we are using Silverlight 4
Step 3: Add Service References
Now we need to add references to the following services:
1) Authentication Service (http://localhost:54332/AuthenticationService.svc)
2) Utility Service (http://localhost:54332/UtilityService.svc)
Step 4: Enable Cookie Container
Since Silverlight does not support Behavior Configuration, we need to use an alternative solution. We can use Cookie Container which acts as the holder for cookie while communication with WCF services.
In the ServiceReferences.ClientConfigadd the tag enableHttpCookieContainer for both the services as shown below.
We are also adding a new class named Globals to store the CookieContainer globally.
namespace SilverlightClient
{
public class Globals
{
public static CookieContainer CookieContainer
{
get;
set;
}
}
|}
As in Silverlight an application needs only one authentication cookie to be stored in the client side.
Step 5: Invoke Authentication Service
Now we can start by invoking the Authentication Service. The Service, on successful Login, returns the cookie in the message header. This cookie will be stored in the Global Cookie Container.
Place a button on the main form and add the code in button click handler.
private void AuthenticateButton_Click(object sender, RoutedEventArgs e)
{
bool httpResult = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
Globals.CookieContainer = new CookieContainer();
AuthSvc.AuthenticationServiceClient authClient = new AuthSvc.AuthenticationServiceClient();
using (new OperationContextScope(authClient.InnerChannel))
{
HttpRequestMessageProperty property = new HttpRequestMessageProperty();
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = property;
authClient.CookieContainer = Globals.CookieContainer;
authClient.LoginCompleted += (object sender2, AuthSvc.LoginCompletedEventArgs e2) =>
{
if (e2.Result)
MessageBox.Show("Authentication Success!");
else
MessageBox.Show("Authentication Failure!");
};
authClient.LoginAsync("tom", "chicago12", string.Empty, true);
}
}
The Authentication Service was invoked after setting the cookie container to global cookie container. This ensures the cookie will br stored globally.
Step 6: Invoke Utility Service
Now that we have the cookie inside Global.CookieContainer we can invoke the Utility Service by setting the cookie container property.
Place a new button and add the following code inside the click handler.
private void InvokeButton_Click(object sender, RoutedEventArgs e)
{
Uri authUri = new Uri("http://localhost:54332/AuthenticationService.svc");
Uri utilUri = new Uri("http://localhost:54332/UtilityService.svc");
Globals.CookieContainer.SetCookies(utilUri, Globals.CookieContainer.GetCookieHeader(authUri));
UtilSvc.UtilityServiceClient utilClient = new UtilSvc.UtilityServiceClient();
utilClient.CookieContainer = Globals.CookieContainer;
utilClient.GetDataCompleted += (object sender2, UtilSvc.GetDataCompletedEventArgs e2) =>
{
MessageBox.Show("Data: " + e2.Result);
};
utilClient.GetDataAsync(100);
}
Step 7: Run the Application
Now you can run the application and use the buttons to play around with Authentication and Utility services.
Click on the first button to get Authenticated and you should get the following message:
Now click on the second button and you will get the data message as shown below:
If you are able to see the above message then the Authentication and Authorization is working fine with your Silverlight application. Good Job!
Step 8: Create Service Client Factories
You have probably observed that the Utility Invocation is little tedious than the ordinary way. We can make a lot of code to the background by using the ServiceClientFactory class.
The source code of the above class can be found in the attachment. The Service Client Factory performs the following activities:
-
Ensures on single instance of the class through Singleton design pattern
-
Create properties for all services using Factory Method design pattern
-
Performs the Authentication on first call
-
Sets the Cookie Container for all Utility Service client instances
After having the service factory class the code for invoking Utility Service is simplified as below:
ServiceClientFactory.Insance.UtilityServiceClient.GetDataCompleted += (object sender2, UtilSvc.GetDataCompletedEventArgs e2) =>
{
MessageBox.Show(e2.Result.ToString());
};
ServiceClientFactory.Insance.UtilityServiceClient.GetDataAsync(1000);
The application looks like below with the new features enabled.
Summary
In this article we have seen how to use the WCF Authentication and Authorization from a Silverlight client application.