Monday, October 10, 2011

Keyboard selection on Silverlight ListBox and ComboBox

By default Silverlight combo box and list box does not support keyboard selection, so we need custom solution, “Mr Fons Sonnemans”  has done a fantastic job of achieving the behavior with adding behavior  to the controls.

Here is the original post “Keyboard selection on Silverlight ListBox and ComboBox

There is a sample project added with the post. its totally reusable and fantastic. We have used it in our project and also recommend that people should use it.

Thumbs Up  “Mr Fons Sonnemans” .

Monday, October 3, 2011

Add New Package source to NuGet Package Manager.

NuGet has surely reduced the maintaining the library package to some extent, we are using NuGet package manager quite often in our project. Recently I Needed a package which is not part of the NuGet Official package source. After a small research I found the solution and its been already published in many blogs in the internet.

Still sharing it, by default we have “https://go.microsoft.com/fwlink/?LinkID=206669” as a default NuGet Official package source. If you want to add additional repository you can always add it by adding more source in Package Sources, user can find this on Visual Studio 2010->Tools->Options-> Package Manager tab.

image

Above we have the option page where additional source can be added, just add a name and source url where the nuget package is published for a particular library.

Now you go to your project and right click on project reference and select manage nuget package, and a package manager will popup.

imageIn the above window you can see that I have added First Floor Software package as additional source.

Its truly a nice feature and making the management of software library a piece of cake.

Https with IIS 7~7.5, Testing asp.net application in https protocol

In this short blog I am going to share a pretty simple information and which can be very useful in some cases, and it is running asp.net application in https and testing it in locally.

Of Couse we have the option to use IIS Express and web matrix for that purpose. But I am going to share how we can do it using IIS.

First thing is that we have to transfer whole default web application’s binding to https.

image

Right click on the default Web site of  and select edit bindings, this will bring out the following window.

image

We can see where that https is already been configured, its because I have already configured it.  How click on add to add a new binding. This will bring another modal window.

image

In this window you have to select type == “Https” and select SSL certificate, we have used IIS Express Development Certificate, for testing but you can add your own certificate. How you can also choose to view the certificate information.

image

That’s it now click on ok to apply and dismiss the window. click on to ok to other opened window to apply the changes.

image

Now try browsing the same site using https protocol, for instance https://localhost/myapplication where my application is a normal asp.net application. And you would see the browser warning for the first time. Its because we have used a development certificate. click “Continue to this website” to continue.

Sunday, October 2, 2011

“Silverlight SPY” for firebug or snoop like tool for Silverlight

In this blog I am going to share one yet another interesting tool developed by “firstfloorsoftware”, and the tool is “Silverlight SPY” It’s a simple wonderful tool for UI debug, in fact you can see the dom and highlight particular section.

image

One demoralizing thing is that this is not a free tool, its available only in commercial tool. Its available for only evaluation.

But if we don’t need for debug the UI rather need to watch the inner anatomy of controls and customize it, I would say Expression blend is also handy.  But again expression blend is also not free Open-mouthed smile. In fact to be frank Visual Studio is also not free Open-mouthed smile.

Tell Next time. Me “Munna” Signing out.

Display XPS document In Silverlight

Today I am going to share a very useful tool named “DocumentViewer”, it’s a Silverlight control which allow users to display documents as XPS document. There are lots of supporting control associated with “DocumentViewer”, for instance view mode which deals with document’s zoom factor, navigation and off course thumb nail view, etc.

image

One key thing is that this control is commercial, so we need to pay for using it. But its free to try. We have developed a application with shows different types of document via this control, and so far the impression is very satisfactory.

I wonder whey some thing would be available with built in Silverlight control set.

Saturday, October 1, 2011

Using WCF Service with Silverlight

Introduction

In one of our products, we had to use WCF service with Silverlight. While working on Silverlight and WCF, I found out some very interesting things and I feel that those are worth sharing. Whenever we want to work with Silverlight and need some kind of service communication, we would encounter those common problems. In this article, we are going to discuss a few interesting findings about WCF and Silverlight Bridge.

For the purpose of demonstration, we are going to use a demo application with some simple class. Let's say we have an expense management application and we have a client build with Silverlight. And the client communicated to server via WCF. Let's take this example to fit our explanation process.

Using WCF with Silverlight

In this section, we will see how we can use WCF service with Silverlight. I am sure every reader has a nice grip on what is WCF and how we can use it in web applications. Some of the stuff is repeated and discussed again and may sound familiar. But as we need some parts as a subset, I am discussing it again. First, we would look at the basics and then we would see some other relevant tricks and information.

The WCF Basics

WCF has three basic building blocks. Those are called A,B,C of WCF. A stands for Address, B stands for Binding and C stands for contract. In a later section, we would see the most common knowledge that is necessary to work with WCF, of course communication with Silverlight context. WCF can be hosted in several ways. Most common ones are given below:

  • Hosting in Internet Information Services
  • Hosting in Windows Process Activation Service
  • Hosting in a Windows Service Application
  • Hosting in a Managed Application

We are not going to discuss about the above hosting options in this article as those need further study, and assumes to not be the focused area of the article. I would recommend that you spend some time on MSDN or Google to learn more about WCF hosting process.

The Service Contract and Operation Contract

I am sure we all know what a service contract is, but I am still discussing it as it is a beginner article. We make any class a service contract by adding one simple class attribute "[ServiceContract]" but it's better to declare an interface first and then apply class attribute to that interface and then implement class in a derived class. Now the methods that we would want to expose as part of the service need to be decorated with a method attribute named "[OperationContract]".

Below we have a code block with an interface that has been declared as a service contract and then we have implemented a derived class from the interface to define the methods that would be invoked via clients.

Service Contract

[ServiceContract]
public interface IMoneyService
{
[OperationContract]
ServiceResponse AddExpense(Expense expense);
[OperationContract]
ServiceResponse UpdateExpense(Expense expense);
[OperationContract]
ServiceResponse DeleteExpense(Expense expense);
[OperationContract]
ServiceResponse GetExpenseByID(int expenseId);
[OperationContract]
ServiceResponse AddCategory(Category category);
[OperationContract]
ServiceResponse UpdateCategory(Category category);
[OperationContract]
ServiceResponse DeleteCategory(Category category);
[OperationContract]
ServiceResponse GetCategoryByID(int categoryId);
}

Implementation of the Contract

[AspNetCompatibilityRequirements
(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MoneyService : IMoneyService
{
public ServiceResponse AddExpense(Expense expense)
{
var response = new ServiceResponse();
using (var manager = new ExpenseManager())
{
try
{
response.Result = manager.AddExpense(expense);
response.IsSuccess = true;
}
catch (Exception exception)
{
response.ServiceException = exception;
response.IsSuccess = false;
response.ErrorMessage = "Unable to add Expense";
}
}
return response;
}

///Other method's implementation.... goes bellow
///....
}

In the above example, we didn't put down all the implementation in one method to demonstrate the idea.


The Data Contract


If we want to transfer custom data via WCF from server to client, we have to apply "[DataContract]" class attribute on the custom data type. Besides, all primitive datatypes can be used as a transferable data. Below we have added a simple class that we have used as our custom type to transfer data from service to client.


You might need to use KnownType attribute in case you have nested custom type in your data contract.

[KnownType(<span style="COLOR: blue">typeof</span>(your-custom-type))]

Below, a sample Data contract implementation is given.

[DataContract]
public class ServiceResponse
{
private string _errorMessage;
[DataMember]
public string ErrorMessage
{
get { return _errorMessage; }
set { _errorMessage = value; }
}
private object _result;
[DataMember]
public object Result
{
get { return _result; }
set { _result = value; }
}
private bool _isSuccess;
[DataMember]
public bool IsSuccess
{
get { return _isSuccess; }
set { _isSuccess = value; }
}
private Exception _serviceException;
[DataMember]
public Exception ServiceException
{
get { return _serviceException; }
set { _serviceException = value; }
}
}

ASP.NET Compatibility


This particular scenario is very useful if we host the WCF service in the IIS environment. The idea is to share the same HttpContext in service methods and inner methods so that we can access session and application data of the web application where the WCF service is being exposed.

var context = HttpContext.Current;
var path = context.Server.MapPath("~/MyPics");

if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}

var userFolder = string.Format("{0}\\{1}", path, userId);

if (!Directory.Exists(userFolder))
{
Directory.CreateDirectory(userFolder);
}

In the above example, we want to find a folder name "MyPics" where the pictures of a particular user will be saved. So we need the httpContext where the service is running.


Below, the service configuration is given. The key stuff is the tag "serviceHostingEnvironment" we have to set the attribute aspNetCompatibilityEnabled="true".

    <system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="PEM.MoneyTrackingServiceAspNetAjaxBehavior">
<enableWebScript />

</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />

<services>
<service name="PEM.MoneyTrackingService">
<endpoint address=""
behaviorConfiguration="PEM.MoneyTrackingServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="PEM.MoneyTrackingService" />

</service>
</services>
</system.serviceModel>

After that, we have to put the AspNetCompatibilityRequirements class attribute with value RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed to the desired service contract implementation. Note that this attribute cannot be added before the interface which is the contract. We have to add it before the service contract implementation.

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements
(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MoneyTrackingService
{
[OperationContract]
public void DoWork()
{
return;
}
}

Adding Service Reference to Silverlight


Alright. We have the basics on our finger tip, now it's time to make the service workable. Here are the steps we have to do.



  • Step 1: Define Data Contract that we want to transmit via service. Add "[DataContract]" class attribute to class and "[DataMember]" property attribute to properties. If we have any enum in the DataContract we have to apply EnumMember attribute.
  • Step 2: Define interface for ServiceContract with methods, add service contract attribute. mark each method that we want to expose to OperationContract.
  • Step 3: Define a derived class for ServiceContract implementation. Add the necessary class attribute if we need ASP.NET compatibility.
    In our case, we have defined those classes and interface in a separate project named MoneyTracking.Service.
  • Step 4: Add a reference to the project where we defined the classes. If we defined all the classes and interfaces in the web project, then no worries.
  • Step 5: Add a svc file. Get rid of the "cs" file. Modify the XML for the .svc file. put down the proper service name.
     <%@ ServiceHost Language="C#" Debug="true" 
    Service="full Qualified name goes here" %>

  • Step 6: Define proper service definition in service model tag of web.config. We have defined the XML in the previous section, we can also copy from there. Note that we should at mex binding as well.
  • Step 7: Browser the service to see if everything is working fine or not.
  • Step 8: Go to the Silverlight project where we want to consume the service, right click on the project's reference node and select add Service Reference, which will bring the configure add service reference wizard. Rest of the work is self explanatory in the wizard.

When you finished adding the service, you will have a service reference node where the service will be added. Visual Studio also adds lots of code behind the scenes, an also a ServiceReferences.ClientConfig file. We will see the uses in later sections.


ServiceReferences.ClientConfig

<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>

<binding name="BasicHttpBinding_IMoneyService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />

</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/MoneyTrackingService.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IMoneyService"

contract="MoneyTrackingServiceReference.IMoneyService"
name="BasicHttpBinding_IMoneyService" />
</client>
</system.serviceModel>
</configuration>

Using the Channel Factory


So far, we have three ways to use a WCF service in Silverlight:



  • Using a service reference
  • Using chanel Factory
  • Using Client base

Below, we have explained how the chanel factory can be used to define a WCF service in Silverlight side. Note that in this case, we don't have to use any sort of reference for the service. But how? Silverlight only allows asynchronous model of service method call, so we cannot use the same OperationContract. We can copy all the classes that are DataContract as a link and use in the Silverlight project, for the service contract we have to define a new class with ServiceContract attribute. Note that the methods need to have [OperationContract(AsyncPattern = true)] method attribute. For each method in the ServiceContract in server, we have to define two methods with pre-fix "Begin" and "End" so if we have a method named "AddExpense" in server, in the client class we have to define two methods named "BeginAddExpense" and "EndAddExpense". Below, a complete code has been given for the class IMoneyService of client.


Example of AnyncPattern Contract

namespace MoneyTracking.Service
{
[ServiceContract]
public interface IMoneyService
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginAddExpense
(Expense expense, AsyncCallback callback, object state);

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginUpdateExpense
(Expense expense, AsyncCallback callback, object state);

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginDeleteExpense
(Expense expense, AsyncCallback callback, object state);

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginGetExpenseByID
(int expenseId, AsyncCallback callback, object state);

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginAddCategory
(Category category, AsyncCallback callback, object state);

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginUpdateCategory
(Category category, AsyncCallback callback, object state);

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginDeleteCategory
(Category category, AsyncCallback callback, object state);

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginGetCategoryByID
(int categoryId, AsyncCallback callback, object state);

ServiceResponse EndAddExpense(IAsyncResult result);

ServiceResponse EndUpdateExpense(IAsyncResult result);

ServiceResponse EndDeleteExpense(IAsyncResult result);

ServiceResponse EndGetExpenseByID(IAsyncResult result);

ServiceResponse EndAddCategory(IAsyncResult result);

ServiceResponse EndUpdateCategory(IAsyncResult result);

ServiceResponse EndDeleteCategory(IAsyncResult result);

ServiceResponse EndGetCategoryByID(IAsyncResult result);
}
}

Example of chanelFactory


Now we have defined the interface. It's time to build the service using ChanelFactory. Below a simple code is given to demonstrate how we can create a service client and invoke a method.

private void UsingChanelFactory(object sender, RoutedEventArgs e)
{
var basicHttpBinding = new BasicHttpBinding();
var endpointAddress = new EndpointAddress
("http://localhost/MoneyTrackingWeb/MoneyTrackingService.svc");
var moneyService = new ChannelFactory
<moneytracking.service.imoneyservice>

(basicHttpBinding, endpointAddress).CreateChannel();
moneyService.BeginAddCategory
(new MoneyTracking.Common.Category(), ASyncronousCallBack, moneyService);
}

private void ASyncronousCallBack(IAsyncResult ar)
{
if(ar.IsCompleted)
{
MoneyTracking.Common.ServiceResponse serviceResponse =
((MoneyTracking.Service.IMoneyService)ar.AsyncState).EndAddCategory(ar);
if(serviceResponse.IsSuccess)
{
//do your work here
}
}
}

Making Synchronous Call


By default, the methods that we have in service client in Silverlight are asynchronous method calls. A simple code is given below to demonstrate the idea. A Client has been initiated and then a completed event has been subscribed to and then call the asynchronous method.


Example of Asynchronous call

public void AddExpense()
{
var client = new MoneyServiceClient();
var category = new Category();
//fill category attributes here
client.AddCategoryCompleted += ClientAddCategoryCompleted;
client.AddCategoryAsync(category);
}

void ClientAddCategoryCompleted(object sender, AddCategoryCompletedEventArgs e)
{
ServiceResponse serviceResponse = e.Result;
if(serviceResponse.IsSuccess)
Categories.Add((Category) serviceResponse.Result);
}

Example of Synchronous Call


In some scenarios, we need to have a synchronous call, since Silverlight does not allow the synchronous call we can always bypass and use the same system in such a way so that we have a synchronous call, the idea is to stop the current code execution until the completed event is been fired.


We have defined a custom class AsyncCallStatus<T> a custom status which will be passed via Async Method. But the magic class which make all this possible is "AutoResetEvent", we have the current execution freeze using _autoResetEvent.WaitOne(). When in completed event, we get the result back we simply set the  _autoResetEvent.Set(); which again resumes the process.


Note that in Silverlight 4, we have to use ThreadPool.QueueUserWorkItem(MethodNameGoesHere); to start the process otherwise AutoResetEvent.WaitOne() will stop the current tread execution, and completed event won't fire at all, in fact call the server will never be invoked. Below, we have put down the complete listing of a method called synchronously.

private void SyncronousCall(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem(AddExpenseInServer);

}

private void AddExpenseInServer(object state)
{
Expense addedExpense = AddExpense();
Dispatcher.BeginInvoke(() =>
{
StatusMessage.Content = "Expense is been Added";
Expenses.Add(addedExpense);
});
}

private Expense AddExpense()
{
var asyncCallStatus = new AsyncCallStatus<AddExpenseCompletedEventArgs>();
var client = new MoneyServiceClient();
client.AddExpenseCompleted += ClientAddExpenseCompleted;
client.AddExpenseAsync(new Expense(),asyncCallStatus);
_autoResetEvent.WaitOne();
if (asyncCallStatus.CompletedEventArgs.Error != null)
{
throw asyncCallStatus.CompletedEventArgs.Error;
}
var serviceResponse = asyncCallStatus.CompletedEventArgs.Result;
if (serviceResponse.IsSuccess)
{
return serviceResponse.Result as Expense;
}
else
return null;
}

void ClientAddExpenseCompleted(object sender, AddExpenseCompletedEventArgs e)
{
var status = e.UserState as AsyncCallStatus<AddExpenseCompletedEventArgs>;
if (status != null) status.CompletedEventArgs = e;
_autoResetEvent.Set();
}

private readonly AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

public class AsyncCallStatus<T>

{
public T CompletedEventArgs { get; set; }
}

Cross Domain Service Call


By default, Silverlight can invoke any method from the originator site. So if the Silverlight component is invoked from "http://mytestside.com/silverlightTestPage.aspx", the component can call any WCF service hosted in "http://mytestside.com/testservice.svc". But let's say we want to call a WCF service which is hosted on "http://myotherside.com/otherservice.svc", we would encounter an error something like this:


The way to archive cross domain service call in Silverlight is pretty simple in fact. We have to put two XML files named "clientaccesspolicy.xml" and "crossdomain.xml" file in root folder of the service. So if we have a service named "http://mytestserver.com/myservice.svc", we need to put down those two files in "http://mytestserver.com/clientaccesspolicy.xml". Both the file and its content are given below.


clientaccesspolicy.xml

<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
<cross-domain-access>

<policy>
<allow-from http-request-headers="SOAPAction">
<domain uri="*"/>
</allow-from>
<grant-to>

<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>

</access-policy>

crossdomain.xml

<?xml version="1.0" ?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="SOAPAction,Content-Type"/>

</cross-domain-policy>

You can simulate the crossdomain class in the local environment also. For this, modify the host file:

127.0.0.1 testserver.com 
127.0.0.1 testclient.com

Now you can run your project from testclient and service will be consumed from testserver.


Transfer Large Data


In this section, we would see how we can customize the WCF service so that we can transfer large amount of data. We often encounter an error while communicating that max limit of array size has been crossed or perhaps an exception that endpoint not found, it's simply because there could be a size issue. Note that the endpoint not found exception can occur for many reasons.


To overcome the limitation, we need to customize the basicHttpBinding. We have to define a bindings section under <system.servicemodel> and under that we would customize the basicHttpBinding. For this, we have to create another sub section under binding named "<basicHttpBinding>". Here we can put multiple bindings and of course we can set all the advanced attributes.


Below, we have put down both client and server configuration.


Service Configuration on Server

<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true"/>

<bindings>
<basicHttpBinding>
<binding name="MoneyTrackingServiceBinding" maxBufferPoolSize="2147483647"
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">

<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647">
</readerQuotas>

</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MoneyTrackingServiceBehavior">

<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>

</behaviors>
<services>
<service name="MoneyTracking.Service.MoneyService"
behaviorConfiguration="MoneyTrackingServiceBehavior">
<endpoint address="" binding="basicHttpBinding"

bindingConfiguration="MoneyTrackingServiceBinding"
contract="MoneyTracking.Service.IMoneyService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

</service>
</services>
</system.serviceModel>

Here under service, we have added behaviorConfiguration to "" in service and under that in endpoint section we have also set "bindingConfiguration" to our desired configuration name.


Client Side Configuration

<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MoneyTrackingServiceBinding" maxBufferSize="2147483647"

maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
</bindings>
<client>

<endpoint address="http://localhost/MoneyTrackingWeb/MoneyTrackingService.svc"
binding="basicHttpBinding"
bindingConfiguration="MoneyTrackingServiceBinding"
contract="MoneyTrackingServiceReference.IMoneyService"
name="BasicHttpBinding_IMoneyService" />

</client>
</system.serviceModel>
</configuration>

The above service configuration section is for the client, note that both server and client binding configuration name should match and the value should also match. In client service configuration fine we don't have to define the "readerQuotas", infact that would give you an exception. And we don't need behaviour configuration. You guys can also copy and paste the above configurations in your context, while doing so you have to fix the contract names and service names.


Summary


In this short article, we have seen the basics of WCF service. We have discussed only those parts that are necessary to build a simple WCF service that can be consumed by a Silverlight client. Then we have seen two ways of creating a client proxy for Silverlight. We can add service reference and also can use chanel factory to build client. Chanel factory gives more control over client proxy.


After that, we have seen how we can use some small policy XML files to extend the service so that it can be consumed via Silverlight components running in a different domain. Lastly, we have seen how we can customize the binding to support large amount of data transfer. There are lots of challenges in real life development regarding WCF and Silverlight. I hope to put together more content in a future article.


References



History



  • 29th September, 2011: Initial version